bsc_devs.c (13333B)
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 * I2C driver for BSC (Broadcom Serial control). This 8 * module provides for discovery and loading of I2C device drivers and 9 * manipulation of I2C device state. 10 * 11 * See also: bus.c 12 */ 13 14 #if defined(INCLUDE_I2C) 15 16 #include <sal/types.h> 17 #include <sal/core/boot.h> 18 #include <soc/debug.h> 19 #include <soc/error.h> 20 #include <soc/drv.h> 21 #include <soc/cmic.h> 22 #include <soc/i2c.h> 23 #include <soc/bsc.h> 24 #include <shared/bsl.h> 25 26 #ifdef INCLUDE_I2C_SFP 27 extern bsc_driver_t _soc_bsc_sfp_driver; 28 #endif 29 30 #ifdef BCM_FE2000_SUPPORT 31 /* Temperature Monitors and PWM Fan Controllers */ 32 extern bsc_driver_t _soc_bsc_max6653_driver; 33 34 /* Digital Power Manager */ 35 extern bsc_driver_t _soc_bsc_zm73xx_driver; 36 37 extern bsc_driver_t _soc_bsc_at24c64_driver; 38 #endif 39 40 /* Data: bsc_devices 41 * Purpose: BSC device descriptor table. 42 * Devices are added to this table, along with their slave 43 * address, a string description, and their driver (if available). 44 */ 45 STATIC bsc_device_t bsc_devices[] = { 46 #ifdef BCM_FE2000_SUPPORT 47 { 48 "max6653_0", /* device name */ 49 BSC_PCA9548_SADDR, /* mux i2c address */ 50 BSC_PCA9548_CHAN_0, /* mux channel for this device */ 51 BSC_MAX6653_SADDR, /* device i2c address */ 52 &_soc_bsc_max6653_driver, /* device driver */ 53 "Temperature and Fan speed sensor" /* description */ 54 }, 55 { 56 "max6653_1", /* device name */ 57 BSC_PCA9548_SADDR, /* mux i2c address */ 58 BSC_PCA9548_CHAN_1, /* mux channel for this device */ 59 BSC_MAX6653_SADDR, /* device i2c address */ 60 &_soc_bsc_max6653_driver, /* device driver */ 61 "Temperature and Fan speed sensor" /* description */ 62 }, 63 { 64 "max6653_2", /* device name */ 65 BSC_PCA9548_SADDR, /* mux i2c address */ 66 BSC_PCA9548_CHAN_2, /* mux channel for this device */ 67 BSC_MAX6653_SADDR, /* device i2c address */ 68 &_soc_bsc_max6653_driver, /* device driver */ 69 "Temperature and Fan speed sensor" /* description */ 70 }, 71 { 72 "max6653_3", /* device name */ 73 BSC_PCA9548_SADDR, /* mux i2c address */ 74 BSC_PCA9548_CHAN_3, /* mux channel for this device */ 75 BSC_MAX6653_SADDR, /* device i2c address */ 76 &_soc_bsc_max6653_driver, /* device driver */ 77 "Temperature and Fan speed sensor" /* description */ 78 }, 79 { 80 "max6653_4", /* device name */ 81 BSC_PCA9548_SADDR, /* mux i2c address */ 82 BSC_PCA9548_CHAN_4, /* mux channel for this device */ 83 BSC_MAX6653_SADDR, /* device i2c address */ 84 &_soc_bsc_max6653_driver, /* device driver */ 85 "Temperature and Fan speed sensor" /* description */ 86 }, 87 { 88 "zm73xx_0", /* device name */ 89 BSC_PCA9548_SADDR, /* mux i2c address */ 90 BSC_PCA9548_CHAN_5, /* mux channel for this device */ 91 BSC_ZM73XX_SADDR, /* device i2c address */ 92 &_soc_bsc_zm73xx_driver, /* device driver */ 93 "Digital Power Manager" /* description */ 94 }, 95 { 96 BSC_AT24C32_NAME, /* device name */ 97 0, /* no mux i2c address */ 98 0, /* no mux channel */ 99 BSC_AT24C32_SADDR, /* device i2c address */ 100 &_soc_bsc_at24c64_driver, /* device driver */ 101 "Atmel 24C64 serial EEPROM" /* description */ 102 }, 103 #endif 104 #ifdef INCLUDE_I2C_SFP 105 { 106 BSC_SFP_00_NAME, /* device name */ 107 BSC_PCA9548_SADDR_1, /* mux i2c address */ 108 BSC_PCA9548_CHAN_0, /* mux channel for this device */ 109 BSC_SFP_SADDR, /* device i2c address */ 110 &_soc_bsc_sfp_driver, /* device driver */ 111 "SFP" /* description */ 112 }, 113 { 114 BSC_SFP_01_NAME, /* device name */ 115 BSC_PCA9548_SADDR_1, /* mux i2c address */ 116 BSC_PCA9548_CHAN_1, /* mux channel for this device */ 117 BSC_SFP_SADDR, /* device i2c address */ 118 &_soc_bsc_sfp_driver, /* device driver */ 119 "SFP" /* description */ 120 }, 121 { 122 BSC_SFP_02_NAME, /* device name */ 123 BSC_PCA9548_SADDR_1, /* mux i2c address */ 124 BSC_PCA9548_CHAN_2, /* mux channel for this device */ 125 BSC_SFP_SADDR, /* device i2c address */ 126 &_soc_bsc_sfp_driver, /* device driver */ 127 "SFP" /* description */ 128 }, 129 { 130 BSC_SFP_03_NAME, /* device name */ 131 BSC_PCA9548_SADDR_1, /* mux i2c address */ 132 BSC_PCA9548_CHAN_3, /* mux channel for this device */ 133 BSC_SFP_SADDR, /* device i2c address */ 134 &_soc_bsc_sfp_driver, /* device driver */ 135 "SFP" /* description */ 136 }, 137 { 138 BSC_SFP_04_NAME, /* device name */ 139 BSC_PCA9548_SADDR_3, /* mux i2c address */ 140 BSC_PCA9548_CHAN_4, /* mux channel for this device */ 141 BSC_SFP_SADDR, /* device i2c address */ 142 &_soc_bsc_sfp_driver, /* device driver */ 143 "SFP" /* description */ 144 }, 145 { 146 BSC_SFP_05_NAME, /* device name */ 147 BSC_PCA9548_SADDR_1, /* mux i2c address */ 148 BSC_PCA9548_CHAN_5, /* mux channel for this device */ 149 BSC_SFP_SADDR, /* device i2c address */ 150 &_soc_bsc_sfp_driver, /* device driver */ 151 "SFP" /* description */ 152 }, 153 { 154 BSC_SFP_06_NAME, /* device name */ 155 BSC_PCA9548_SADDR_1, /* mux i2c address */ 156 BSC_PCA9548_CHAN_6, /* mux channel for this device */ 157 BSC_SFP_SADDR, /* device i2c address */ 158 &_soc_bsc_sfp_driver, /* device driver */ 159 "SFP" /* description */ 160 }, 161 { 162 BSC_SFP_07_NAME, /* device name */ 163 BSC_PCA9548_SADDR_1, /* mux i2c address */ 164 BSC_PCA9548_CHAN_7, /* mux channel for this device */ 165 BSC_SFP_SADDR, /* device i2c address */ 166 &_soc_bsc_sfp_driver, /* device driver */ 167 "SFP" /* description */ 168 }, 169 { 170 BSC_SFP_08_NAME, /* device name */ 171 BSC_PCA9548_SADDR_2, /* mux i2c address */ 172 BSC_PCA9548_CHAN_0, /* mux channel for this device */ 173 BSC_SFP_SADDR, /* device i2c address */ 174 &_soc_bsc_sfp_driver, /* device driver */ 175 "SFP" /* description */ 176 }, 177 { 178 BSC_SFP_09_NAME, /* device name */ 179 BSC_PCA9548_SADDR_2, /* mux i2c address */ 180 BSC_PCA9548_CHAN_1, /* mux channel for this device */ 181 BSC_SFP_SADDR, /* device i2c address */ 182 &_soc_bsc_sfp_driver, /* device driver */ 183 "SFP" /* description */ 184 }, 185 { 186 BSC_SFP_10_NAME, /* device name */ 187 BSC_PCA9548_SADDR_2, /* mux i2c address */ 188 BSC_PCA9548_CHAN_2, /* mux channel for this device */ 189 BSC_SFP_SADDR, /* device i2c address */ 190 &_soc_bsc_sfp_driver, /* device driver */ 191 "SFP" /* description */ 192 }, 193 { 194 BSC_SFP_11_NAME, /* device name */ 195 BSC_PCA9548_SADDR_2, /* mux i2c address */ 196 BSC_PCA9548_CHAN_3, /* mux channel for this device */ 197 BSC_SFP_SADDR, /* device i2c address */ 198 &_soc_bsc_sfp_driver, /* device driver */ 199 "SFP" /* description */ 200 }, 201 #endif 202 { 203 NULL, 204 0, 205 0, 206 0, 207 NULL, 208 NULL /* Dummy entry to circumvent PEDANTIC */ 209 } 210 }; 211 212 #define num_bsc_devices (COUNTOF(bsc_devices) - 1) 213 214 /* 215 * Function: soc_bsc_probe 216 * Purpose: Probe BSC devices on bus, report devices found. 217 * This routine will walk through our internal BSC device driver 218 * tables, attempt to find the device on the BSC bus, and if 219 * successful, register a device driver for that device. 220 * 221 * This allows for the device to be used in an API context as 222 * when the devices are found, the device driver table is filled 223 * with the correct entries for that device (r/w function, etc). 224 * 225 * Parameters: 226 * unit - device number 227 * 228 * Return: 229 * count of found devices or SOC_E_*** 230 */ 231 int 232 soc_bsc_probe(int unit) 233 { 234 int found; 235 soc_bsc_bus_t *bscbus; 236 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 237 int devno, retv; 238 #endif 239 240 /* Make sure that we're already attached, or go get attached */ 241 if (!soc_bsc_is_attached(unit)) { 242 return soc_bsc_attach(unit); 243 } 244 245 bscbus = BSCBUS(unit); 246 found = 0; /* Number of installed BSC devices */ 247 248 COMPILER_REFERENCE(bscbus); 249 250 /* Coverity Fix : We don't need to probe if no devices are supported */ 251 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 252 /* Probe the currently configured (i.e. MUX'd) I2C bus. */ 253 for (devno = 0; devno < num_bsc_devices; devno++) { 254 255 bscbus->devs[devno] = &bsc_devices[devno]; 256 257 /* Check device existence */ 258 retv = bsc_devices[devno].driver->ioctl( 259 unit, devno, BSC_IOCTL_DEVICE_PRESENT, 0, 0); 260 if (!retv) { 261 /* I2C device not present */ 262 bscbus->devs[devno] = NULL; 263 continue; 264 } 265 266 /* set flags, device id, hook up bus, etc */ 267 bsc_devices[devno].driver->devno = devno; 268 269 retv = bsc_devices[devno].driver->init(unit, devno); 270 if (retv < 0) { 271 LOG_INFO(BSL_LS_SOC_I2C, 272 (BSL_META_U(unit, 273 "unit %d i2c 0x%x: init failed %s on channel: 0x%02x\n"), 274 unit, 275 bsc_devices[devno].saddr, 276 bsc_devices[devno].devname, 277 bsc_devices[devno].chan)); 278 } 279 LOG_INFO(BSL_LS_SOC_I2C, 280 (BSL_META_U(unit, 281 "unit %d bsc 0x%x: found %s on channel 0x%02x: %s\n"), 282 unit, 283 bsc_devices[devno].saddr, 284 bsc_devices[devno].devname, 285 bsc_devices[devno].chan, 286 bsc_devices[devno].desc ? 287 bsc_devices[devno].desc : "")); 288 289 found += 1; 290 } 291 #endif 292 return found; 293 } 294 295 void 296 soc_bsc_show(int unit) 297 { 298 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 299 int devno; 300 #endif 301 soc_bsc_bus_t *bscbus; 302 303 /* Make sure that we're already attached, or go get attached */ 304 if (!soc_bsc_is_attached(unit)) { 305 if (soc_bsc_attach(unit) < 0) { 306 return; 307 } 308 } 309 310 bscbus = BSCBUS(unit); 311 312 COMPILER_REFERENCE(bscbus); 313 314 /* Coverity Fix : We don't need to show if no devices are supported */ 315 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 316 /* Show the currently configured (i.e. MUX'd) I2C bus. */ 317 for (devno = 0; devno < num_bsc_devices; devno++) { 318 if (bscbus->devs[devno]) { 319 LOG_CLI((BSL_META_U(unit, 320 "unit: %d devno: %d name: %s saddr: 0x%x " 321 "chan: 0x%02x - %s\n"), 322 unit, 323 devno, 324 bsc_devices[devno].devname, 325 bsc_devices[devno].saddr, 326 bsc_devices[devno].chan, 327 bsc_devices[devno].desc ? 328 bsc_devices[devno].desc : "")); 329 } 330 } 331 #endif 332 } 333 334 int 335 soc_bsc_addr(int unit, int devno) 336 { 337 soc_bsc_bus_t *bscbus; 338 339 bscbus = BSCBUS(unit); 340 if (bscbus && bscbus->devs[devno]) { 341 return bscbus->devs[devno]->saddr; 342 } 343 return 0; 344 } 345 346 const char * 347 soc_bsc_devname(int unit, int devno) 348 { 349 soc_bsc_bus_t *bscbus; 350 351 bscbus = BSCBUS(unit); 352 if (bscbus && bscbus->devs[devno]) { 353 return bscbus->devs[devno]->devname; 354 } 355 return NULL; 356 } 357 358 int 359 soc_bsc_device_count(int unit) 360 { 361 COMPILER_REFERENCE(unit); 362 return num_bsc_devices; 363 } 364 365 int 366 soc_bsc_devdesc_set(int unit, int devno, char *desc) 367 { 368 soc_bsc_bus_t *bscbus; 369 370 bscbus = BSCBUS(unit); 371 if (bscbus && bscbus->devs[devno]) { 372 bscbus->devs[devno]->desc = desc; 373 } 374 return SOC_E_NONE; 375 } 376 377 int 378 soc_bsc_devdesc_get(int unit, int devno, char **desc) 379 { 380 soc_bsc_bus_t *bscbus; 381 382 bscbus = BSCBUS(unit); 383 if (bscbus && bscbus->devs[devno]) { 384 *desc = bscbus->devs[devno]->desc; 385 } else { 386 *desc = ""; 387 } 388 return SOC_E_NONE; 389 } 390 391 bsc_device_t * 392 soc_bsc_device(int unit, int devno) 393 { 394 soc_bsc_bus_t *bscbus; 395 396 bscbus = BSCBUS(unit); 397 if (bscbus && bscbus->devs[devno]) { 398 return bscbus->devs[devno]; 399 } 400 return NULL; 401 } 402 403 int 404 soc_bsc_devopen(int unit, char* devname) 405 { 406 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 407 int devno; 408 #endif 409 soc_bsc_bus_t *bscbus; 410 411 /* Make sure that we're already attached, or go get attached */ 412 if (!soc_bsc_is_attached(unit)) { 413 if (soc_bsc_attach(unit) < 0) { 414 return SOC_E_FAIL; 415 } 416 } 417 bscbus = BSCBUS(unit); 418 419 COMPILER_REFERENCE(bscbus); 420 421 /* Coverity Fix : We don't need to search if no devices are supported */ 422 #if defined(BCM_FE2000_SUPPORT) || defined(INCLUDE_I2C_SFP) 423 for (devno = 0; devno < num_bsc_devices; devno++) { 424 if (bscbus->devs[devno]) { 425 if (sal_strcmp(bscbus->devs[devno]->devname, devname) == 0) { 426 return devno; 427 } 428 } 429 } 430 #endif 431 return SOC_E_NOT_FOUND; 432 } 433 434 int 435 soc_bsc_devtype(int unit, int devno) 436 { 437 soc_bsc_bus_t *bscbus; 438 439 bscbus = BSCBUS(unit); 440 if (bscbus && bscbus->devs[devno] && bscbus->devs[devno]->driver) { 441 return bscbus->devs[devno]->driver->id; 442 } 443 return 0; 444 } 445 446 /* 447 * 448 * Function: soc_i2c_is_attached 449 * 450 * Purpose: Return true if I2C bus driver is attached. 451 * 452 * Parameters: 453 * unit - StrataSwitch device number or I2C bus number 454 * 455 * Returns: 456 * True if the bus driver for I2C is attached. 457 * 458 * Notes: 459 * None 460 */ 461 int 462 soc_bsc_is_attached(int unit) 463 { 464 uint32 dev_idx; 465 uint8 found = 0; 466 soc_bsc_bus_t *bscbus; 467 468 for(dev_idx = 0; dev_idx < soc_ndev ; ++dev_idx) { 469 if(SOC_NDEV_IDX2DEV(dev_idx) == unit) { 470 found = 1; 471 break; 472 } 473 } 474 if (!found) { 475 return 0; 476 } 477 478 bscbus = BSCBUS(unit); 479 if (bscbus == NULL) { 480 return 0; 481 } 482 return (bscbus->flags & SOC_BSC_ATTACHED) != 0; 483 } 484 485 #else /* BCM_FE2000_SUPPORT && INCLUDE_I2C */ 486 int _soc_i2c_bsc_devs_not_empty; 487 #endif /* BCM_FE2000_SUPPORT && INCLUDE_I2C */ 488