bcm59101.c (5534B)
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 * BCM56xx I2C Device Driver for BCM59101 8-bit PoE Microcontroller Unit. 8 * The MCU communicates with message types of 12-byte long packet. 9 */ 10 11 #include <sal/types.h> 12 #include <soc/debug.h> 13 #include <soc/drv.h> 14 #include <soc/error.h> 15 #include <soc/i2c.h> 16 #include <shared/bsl.h> 17 #define BCM59101_CTN 12 18 19 STATIC int 20 bcm59101_read(int unit, int devno, 21 uint16 addr, uint8* data, uint32* len) 22 { 23 int rv = SOC_E_NONE; 24 uint8 saddr_r; 25 uint32 nbytes = 0; 26 27 28 /* Valid address, memory and size must be provided */ 29 if ( ! len || ! data ) 30 return SOC_E_PARAM; 31 32 LOG_INFO(BSL_LS_SOC_I2C, 33 (BSL_META_U(unit, 34 "bcm59101_read: unit: %d devno: %d addr: %d data: %p len: %u\n"), 35 unit, devno, addr, (void *)data, *len)); 36 37 I2C_LOCK(unit); 38 39 saddr_r = SOC_I2C_RX_ADDR(soc_i2c_addr(unit, devno)); 40 41 LOG_INFO(BSL_LS_SOC_I2C, 42 (BSL_META_U(unit, 43 "bcm59101_read: devno=0x%x (data=%p) len=%d\n"), 44 devno, (void *)data, (int)*len)); 45 46 /* Now, we have sent the first and second word addresses, 47 * we then issue a repeated start condition, followed by 48 * the device's read address (note: saddr_r) 49 */ 50 /* Generate Start, for Write address */ 51 if( (rv = soc_i2c_start(unit, saddr_r)) < 0){ 52 LOG_INFO(BSL_LS_SOC_I2C, 53 (BSL_META_U(unit, 54 "bcm59101_write(%d,%d,0x%x,%p,%d): " 55 "failed to gen start\n"), 56 unit, devno, addr, (void *)data, *len)); 57 goto error; 58 } 59 60 nbytes = *len; 61 if ( (rv = soc_i2c_read_bytes(unit, data, (int *)&nbytes, 0) ) < 0 ) { 62 goto error; 63 } 64 *len = nbytes; 65 66 error: 67 68 soc_i2c_stop(unit); 69 70 I2C_UNLOCK(unit); 71 return rv ; 72 73 } 74 75 STATIC int 76 bcm59101_write(int unit, int devno, 77 uint16 addr, uint8* data, uint32 len) 78 { 79 int rv = SOC_E_NONE; 80 uint8 saddr = soc_i2c_addr(unit, devno); 81 uint8 *ptr; 82 uint32 i; 83 84 LOG_INFO(BSL_LS_SOC_I2C, 85 (BSL_META_U(unit, 86 "bcm59101_write: unit: %d devno: %d addr: %d data: %p len: %d\n"), 87 unit, devno, addr, (void *)data, len)); 88 89 if (!data) { 90 return SOC_E_PARAM; 91 } 92 93 I2C_LOCK(unit); 94 95 if ((rv = soc_i2c_start(unit, SOC_I2C_TX_ADDR(saddr))) < 0) { 96 LOG_INFO(BSL_LS_SOC_I2C, 97 (BSL_META_U(unit, 98 "i2c%d: soc_i2c_bcm59101_write: " 99 "failed to generate start.\n"), 100 unit)); 101 I2C_UNLOCK(unit); 102 return rv; 103 } 104 105 ptr = data; 106 for (i = 0; i < len; i++, ptr++) { 107 if ((rv = soc_i2c_write_one_byte(unit, *ptr) ) < 0 ) { 108 LOG_INFO(BSL_LS_SOC_I2C, 109 (BSL_META_U(unit, 110 "i2c%d: soc_i2c_bcm59101_write: " 111 "failed to send byte %d.\n"), 112 unit, i )); 113 break; 114 } 115 soc_i2c_device(unit, devno)->tbyte++; 116 } 117 118 soc_i2c_stop(unit); 119 I2C_UNLOCK(unit); 120 121 return rv; 122 } 123 124 125 126 STATIC int 127 bcm59101_ioctl(int unit, int devno, 128 int opcode, void* data, int len) 129 { 130 return SOC_E_NONE; 131 } 132 133 STATIC int 134 bcm59101_init(int unit, int devno, 135 void* data, int len) 136 { 137 uint8 pkt[BCM59101_CTN]; 138 uint32 l = 2; 139 soc_timeout_t to; 140 int rv = SOC_E_NONE; 141 142 LOG_INFO(BSL_LS_SOC_I2C, 143 (BSL_META_U(unit, 144 "bcm59101_init: unit: %d devno: %d data: %p len: %d\n"), 145 unit, devno, data, len)); 146 /* 147 Request : 148 0x20 0x01 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x18 149 150 Response: 151 0x20 0x01 Rest dont care .. 152 0xAF Rest dont care .. 153 */ 154 155 soc_i2c_devdesc_set(unit, devno, "BCM59101 POE controller"); 156 157 if ((rv = bcm59101_write(unit, devno, 0, data, len)) < 0) { 158 159 LOG_INFO(BSL_LS_SOC_I2C, 160 (BSL_META_U(unit, 161 "i2c%d: soc_i2c_bcm59101_init: " 162 "failed to send power init packet.\n"), unit)); 163 return rv; 164 } 165 166 soc_timeout_init(&to, 100000, 0); 167 for (;;) { 168 if (soc_timeout_check(&to)) { 169 break; 170 } 171 } 172 173 l = BCM59101_CTN; 174 if ((rv = bcm59101_read(unit, devno, 0, pkt, &l)) < 0) { 175 LOG_INFO(BSL_LS_SOC_I2C, 176 (BSL_META_U(unit, 177 "i2c%d: soc_i2c_bcm59101_init: " 178 "failed to read power init packet.\n"), unit)); 179 return rv; 180 } 181 182 LOG_INFO(BSL_LS_SOC_I2C, 183 (BSL_META_U(unit, 184 "bcm59101_init: Signature read %x %x\n"), *pkt, *(pkt+1))); 185 186 if ((*pkt != 0x20 || *(pkt+1) != 0x01) && *pkt != 0xaf) { 187 188 LOG_INFO(BSL_LS_SOC_I2C, 189 (BSL_META_U(unit, 190 "i2c%d: soc_i2c_bcm59101_init: " 191 "bcm5910 not found.\n"), unit)); 192 193 return SOC_E_UNAVAIL; 194 } 195 196 return rv; 197 } 198 199 200 /* BCM59101 Chip Driver callout */ 201 i2c_driver_t _soc_i2c_bcm59101_driver = { 202 0x0, 0x0, /* System assigned bytes */ 203 BCM59101_DEVICE_TYPE, 204 bcm59101_read, 205 bcm59101_write, 206 bcm59101_ioctl, 207 bcm59101_init, 208 NULL, 209 };