openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

cy22150.c (8490B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *    _____   _____________________
      7  *   / __\ \ / / _ \ _ \ __/ __/ __|
      8  *  | (__ \ ^ /|  _/   / _|\__ \__ \
      9  *   \___| |_| |_| |_|_\___|___/___/ TIMING TECHNOLOGY
     10  *   ==================================================
     11  * Generated by CyClocksRT R1.05.00
     12  *
     13  * Modification Date: 8/12/02
     14  * Comments:
     15  * Customer:
     16  * FAE:
     17  * License #:
     18  * Part Number:  CY22150
     19  *                      ______________
     20  *                    _|     \__/     |_
     21  *               XIN |_| 1         16 |_| XOUT
     22  *                    _|              |_
     23  *               VDD |_| 2         15 |_| CLK6
     24  *                    _|              |_
     25  *              AVDD |_| 3         14 |_| CLK5
     26  *                    _|              |_
     27  *               SDA |_| 4         13 |_| VSS
     28  *                    _|   CY22150    |_
     29  *              AVSS |_| 5         12 |_| LCLK4
     30  *                    _|              |_
     31  *              VSSL |_| 6         11 |_| VDDL
     32  *                    _|              |_
     33  *             LCLK1 |_| 7         10 |_| SCL
     34  *                    _|              |_
     35  *             LCLK2 |_| 8          9 |_| LCLK3
     36  *                     |______________|
     37  *
     38  *
     39  * Reference Input:   25.000000 MHz External
     40  * Target VCO:  314.000000 MHz
     41  * Actual VCO:  314.000000 MHz    PPM:      0.0
     42  *
     43  * P value:  314  MSB 0100111010 LSB
     44  * Q vaule:  25  MSB 0011001 LSB
     45  * Charge Pump Setting:  4
     46  * Divider 1-X:  4   VCO
     47  * Divider 2-X:  9   VCO
     48  *
     49  * Clock Output
     50  * ====================================================================
     51  * |Output|  Source  |  Desired   |   Actual   |    PPM     | Voltage |
     52  * ====================================================================
     53  * | CLK1 |  Pll/2   | 157.000000 | 157.000000 |       0.0  |   2.5V  |
     54  * | CLK2 |  Pll/2   | 157.000000 | 157.000000 |       0.0  |   2.5V  |
     55  * | CLK3 |    Off   |    Off     |    Off     |    - -     |   2.5V  |
     56  * | CLK4 |    Off   |    Off     |    Off     |    - -     |   2.5V  |
     57  * | CLK5 |  Pll/  9 |  34.888889 |  34.888889 |       0.0  |   3.3V  |
     58  * | CLK6 |  Pll/  9 |  34.888889 |  34.888889 |       0.0  |   3.3V  |
     59  * ====================================================================
     60  *
     61  *
     62  *
     63  * Programming Algorithm
     64  *
     65  *  For Core (Outputs AB, PLL3): NOTE: Q defaults to 25 so no adjustmnt
     66  *  is necessary.
     67  *
     68  * 1. Adjust Q to desired value (25).  Default so no action necessary!!!
     69  * 2. Adjust P to desired value 3. Adjust output divider to desired value
     70  * (2) - default is 3 for core and SDRAM 4. Adjust LF
     71  *
     72  * For SDRAM (Outputs CD, PLL2):
     73  *
     74  * 1. Adjust Q to desired value (25)
     75  * 2. Adjust P to desired value
     76  * 3. Adjust output divider to desired value (2) - default is 3 for core and
     77  *    SDRAM
     78  * 4. Adjust LF
     79  *
     80  * For PCI/CPU clock  (OUTPUT E, PLL1)
     81  *
     82  * 1. Adjust Q to desired value (25).  Default so no action necessary!!!
     83  * 2. Adjust P to desired value
     84  * 3. Adjust output divider to desired value (4) - Default so no action
     85  *    necessary!!!
     86  * 4. Adjust LF.
     87  * 5. Compensate as necessary for baud rate or other parameters affected by
     88  *    changing the PCI or CPU frequency!!!!!!
     89  *
     90  *
     91  * See the Cypress W22393 Clock chip data sheet(s) for more details.
     92  * See also: http://www.cypress.com/clock/datasheets.html
     93  */
     94 
     95 #include <sal/types.h>
     96 #include <soc/drv.h>
     97 #include <soc/error.h>
     98 #include <soc/i2c.h>
     99 #include <shared/bsl.h>
    100 
    101 #define MHZ(x)    ((x)*1000000)
    102 
    103 /* FRef = 25MHz */
    104 #define    CY22150_REF_CLK    MHZ(25)
    105 #define    CY22150_DIV_CORE   2
    106 #define    CY22150_DIV_SDRAM  2
    107 #define    CY22150_DIV_PCI    4
    108 #define CY_DEBUG(x) do { \
    109         LOG_CLI((BSL_META(x);                                  \
    110         sal_usleep(1000);                               \
    111     } while (0)
    112 
    113 /*
    114  * Charge Pump : Computed based on Ptotal
    115  * See datasheet for more info.
    116  */
    117 STATIC uint8
    118 cy22150_charge_pump(int val)
    119 {
    120     uint8 tmp;
    121 
    122     /* Convert from MHz if required */
    123     if (val > MHZ(1)) {
    124 	val /= MHZ(1);
    125     }
    126     if (val >= 16 && val <= 44) {
    127 	tmp = 0;
    128     } else if (val >= 45 && val <= 479) {
    129 	tmp = 1;
    130     } else if (val >= 480 && val <= 639) {
    131 	tmp = 2;
    132     } else if (val >= 640 && val <= 799) {
    133 	tmp = 3;
    134     } else if (val >= 800 && val <= 1023) {
    135 	tmp = 4;
    136     } else {
    137 	tmp = 0;
    138     }
    139     return tmp;
    140 }
    141 
    142 STATIC int
    143 cy22150_ioctl(int unit, int devno,
    144               int opcode, void *data, int len)
    145 {
    146 #ifdef COMPILER_HAS_DOUBLE
    147     double clk, qt;
    148 #else
    149     int qt;
    150 #endif
    151     int iclk, P0, ip, iq;
    152     uint8 tmp, lf, saddr = soc_i2c_addr(unit, devno);
    153 
    154     if ( I2C_XPLL_SET_PCI == opcode ) {
    155         /* Not implemented, but report success */
    156     } else if ( I2C_XPLL_GET_PCI == opcode ) {
    157         /* Not implemented, but report success */
    158     } else if ( I2C_XPLL_SET_CORE == opcode ) {
    159 #ifdef COMPILER_HAS_DOUBLE
    160 	clk = *((double *)data);
    161 
    162 	/* Convert from MHz if required */
    163 	if( clk < MHZ(1))
    164 	    clk *= MHZ(1);
    165 
    166 	/* Setup new core clock */
    167 	iclk = (int) clk;
    168 #else
    169 	iclk = *((int *)data);
    170 #endif
    171         /* Compute actual frequency in MHz */
    172         iclk = (CY22150_DIV_CORE * iclk) / MHZ(1);
    173 
    174         /* This is set only on an odd clock freq */
    175  	P0 = iclk % 2;
    176 
    177 	/* Compute Qt and convert to byte value (in MHz)*/
    178 	qt = CY22150_REF_CLK - MHZ(2);
    179 	qt = qt / MHZ(1);
    180 
    181 	/* Compute P/Q (integer format) */
    182 	ip = ((iclk - P0) / 2) - 4;
    183 	iq = (int) qt;
    184 
    185         /* Bit 8 of Q (0x42) is PNot */
    186 	iq |= (P0 << 8);
    187 
    188 	/* Compute Charge Pump setting */
    189 	lf = cy22150_charge_pump(iclk);
    190 
    191         /* Bits 7-5 fixed at 110b */
    192         tmp = 0xC0;
    193 
    194 	/* Add upper P bits */
    195 	tmp |= (ip >> 8);
    196 
    197 	/* Add Charge Pump bits */
    198 	tmp |= (lf << 2);
    199 
    200 	/* Configure new clock setting */
    201 	soc_i2c_write_byte_data(unit, saddr, 0x40, tmp);
    202 	soc_i2c_write_byte_data(unit, saddr, 0x41, (uint8)ip);
    203 	soc_i2c_write_byte_data(unit, saddr, 0x42, (uint8)iq);
    204 
    205     } else if ( I2C_XPLL_GET_CORE == opcode) {
    206 	uint8 p_l, p_h, q, pNot;
    207 	uint16 p;
    208 
    209 	soc_i2c_read_byte_data(unit, saddr, 0x41, &p_l);
    210 	soc_i2c_read_byte_data(unit, saddr, 0x40, &p_h);
    211 	soc_i2c_read_byte_data(unit, saddr, 0x42, &q);
    212 	pNot = ((p_h & 0x04) >> 2); /* Bit 2 of 0x57 */
    213 	p_h &= 0x03; /* Clear all bits except bits 0-1 */
    214 	p = (p_h << 8) | p_l; /* 10 bits of p value */
    215 #ifdef COMPILER_HAS_DOUBLE
    216 	clk =   2 * ( p + 4 )  + pNot ;
    217 	clk *= CY22150_REF_CLK;
    218 	clk /= (q+2);
    219 	clk /= 2;
    220 	clk /= MHZ(1);
    221 	*((double *)data) = clk;
    222 #else
    223 	iclk = 2 * (p + 4) + pNot;
    224 	iclk *= CY22150_REF_CLK / (q + 2);
    225 	iclk /= 2;
    226 	*((int *)data) = iclk;
    227 #endif
    228     } else if ( I2C_XPLL_SET_SDRAM == opcode) {
    229         /* Not implemented, but report success */
    230     } else if ( I2C_XPLL_GET_SDRAM == opcode) {
    231         /* Not implemented, but report success */
    232     } else {
    233 	return SOC_E_PARAM;
    234     }
    235 
    236     return SOC_E_NONE;
    237 }
    238 
    239 /*
    240  * Function: cy22150_init
    241  *
    242  * Purpose:
    243  *    Initialize the CY22150 clock chip
    244  * Parameters:
    245  *    unit - StrataSwitch device number or I2C bus number
    246  *    devno - chip device id
    247  *    data - not used
    248  *    len - not used
    249  * Returns:
    250  *    SOC_E_NONE - no failure
    251  */
    252 STATIC int
    253 cy22150_init(int unit, int devno, 
    254              void *data, int len)
    255 {
    256 #if 0
    257     int i;
    258     uint8 x;
    259     uint8 saddr = soc_i2c_addr(unit, devno);
    260 
    261     /* Dump register values */
    262     for (i = 0x08; i <= 0x17; i++) {
    263         soc_i2c_read_byte_data(unit, saddr, (uint8)i, &x);
    264         LOG_CLI((BSL_META_U(unit,
    265                             "pll[%x] = 0x%x\n"), i, x));
    266     }
    267     for (i = 0x40; i <= 0x57; i++) {
    268         soc_i2c_read_byte_data(unit, saddr, (uint8)i, &x);
    269         LOG_CLI((BSL_META_U(unit,
    270                             "pll[%x] = 0x%x\n"), i, x));
    271     }
    272 #endif
    273     soc_i2c_devdesc_set(unit, devno, "Cypress W22150 clock Chip");
    274     return SOC_E_NONE;
    275 }
    276 
    277 STATIC int
    278 cy22150_read(int unit, int devno,
    279 	     uint16 addr, uint8 *data, uint32 *len)
    280 {
    281     *len = 1; /* Byte-write mode */
    282     return soc_i2c_read_byte_data(unit,
    283 				  soc_i2c_addr(unit, devno),
    284 				  (uint8)addr, data);
    285 }
    286 
    287 STATIC int
    288 cy22150_write(int unit, int devno,
    289               uint16 addr, uint8 *data, uint32 len)
    290 {
    291     return soc_i2c_write_byte_data(unit,
    292 				   soc_i2c_addr(unit, devno),
    293 				   (uint8)addr, *data);
    294 }
    295 
    296 /* CY22150/W311 Clock Chip Driver callout */
    297 i2c_driver_t _soc_i2c_cy22150_driver = {
    298     0x0, 0x0, /* System assigned bytes */
    299     CY22150_DEVICE_TYPE,
    300     cy22150_read,
    301     cy22150_write,
    302     cy22150_ioctl,
    303     cy22150_init,
    304     NULL,
    305 };