1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2009 Sergey Kubushyn <ksi@koi8.net> 4 * 5 * (C) Copyright 2012 6 * Heiko Schocher, DENX Software Engineering, hs@denx.de. 7 * 8 * Multibus/multiadapter I2C core functions (wrappers) 9 */ 10#include <common.h> 11#include <i2c.h> 12#include <linker_lists.h> 13#include <asm/global_data.h> 14 15struct i2c_adapter *i2c_get_adapter(int index) 16{ 17 struct i2c_adapter *i2c_adap_p = ll_entry_start(struct i2c_adapter, 18 i2c); 19 int max = ll_entry_count(struct i2c_adapter, i2c); 20 int i; 21 22 if (index >= max) { 23 printf("Error, wrong i2c adapter %d max %d possible\n", 24 index, max); 25 return i2c_adap_p; 26 } 27 if (index == 0) 28 return i2c_adap_p; 29 30 for (i = 0; i < index; i++) 31 i2c_adap_p++; 32 33 return i2c_adap_p; 34} 35 36#if !defined(CFG_SYS_I2C_DIRECT_BUS) 37struct i2c_bus_hose i2c_bus[CFG_SYS_NUM_I2C_BUSES] = 38 CFG_SYS_I2C_BUSES; 39#endif 40 41DECLARE_GLOBAL_DATA_PTR; 42 43#ifndef CFG_SYS_I2C_DIRECT_BUS 44/* 45 * i2c_mux_set() 46 * ------------- 47 * 48 * This turns on the given channel on I2C multiplexer chip connected to 49 * a given I2C adapter directly or via other multiplexers. In the latter 50 * case the entire multiplexer chain must be initialized first starting 51 * with the one connected directly to the adapter. When disabling a chain 52 * muxes must be programmed in reverse order, starting with the one 53 * farthest from the adapter. 54 * 55 * mux_id is the multiplexer chip type from defined in i2c.h. So far only 56 * NXP (Philips) PCA954x multiplexers are supported. Switches are NOT 57 * supported (anybody uses them?) 58 */ 59 60static int i2c_mux_set(struct i2c_adapter *adap, int mux_id, int chip, 61 int channel) 62{ 63 uint8_t buf; 64 int ret; 65 66 /* channel < 0 - turn off the mux */ 67 if (channel < 0) { 68 buf = 0; 69 ret = adap->write(adap, chip, 0, 0, &buf, 1); 70 if (ret) 71 printf("%s: Could not turn off the mux.\n", __func__); 72 return ret; 73 } 74 75 switch (mux_id) { 76 case I2C_MUX_PCA9540_ID: 77 case I2C_MUX_PCA9542_ID: 78 if (channel > 1) 79 return -1; 80 buf = (uint8_t)((channel & 0x01) | (1 << 2)); 81 break; 82 case I2C_MUX_PCA9544_ID: 83 if (channel > 3) 84 return -1; 85 buf = (uint8_t)((channel & 0x03) | (1 << 2)); 86 break; 87 case I2C_MUX_PCA9547_ID: 88 if (channel > 7) 89 return -1; 90 buf = (uint8_t)((channel & 0x07) | (1 << 3)); 91 break; 92 case I2C_MUX_PCA9548_ID: 93 if (channel > 7) 94 return -1; 95 buf = (uint8_t)(0x01 << channel); 96 break; 97 default: 98 printf("%s: wrong mux id: %d\n", __func__, mux_id); 99 return -1; 100 } 101 102 ret = adap->write(adap, chip, 0, 0, &buf, 1); 103 if (ret) 104 printf("%s: could not set mux: id: %d chip: %x channel: %d\n", 105 __func__, mux_id, chip, channel); 106 return ret; 107} 108 109static int i2c_mux_set_all(void) 110{ 111 struct i2c_bus_hose *i2c_bus_tmp = &i2c_bus[I2C_BUS]; 112 int i; 113 114 /* Connect requested bus if behind muxes */ 115 if (i2c_bus_tmp->next_hop[0].chip != 0) { 116 /* Set all muxes along the path to that bus */ 117 for (i = 0; i < CFG_SYS_I2C_MAX_HOPS; i++) { 118 int ret; 119 120 if (i2c_bus_tmp->next_hop[i].chip == 0) 121 break; 122 123 ret = i2c_mux_set(I2C_ADAP, 124 i2c_bus_tmp->next_hop[i].mux.id, 125 i2c_bus_tmp->next_hop[i].chip, 126 i2c_bus_tmp->next_hop[i].channel); 127 if (ret != 0) 128 return ret; 129 } 130 } 131 return 0; 132} 133 134static int i2c_mux_disconnect_all(void) 135{ 136 struct i2c_bus_hose *i2c_bus_tmp = &i2c_bus[I2C_BUS]; 137 int i; 138 uint8_t buf = 0; 139 140 if (I2C_ADAP->init_done == 0) 141 return 0; 142 143 /* Disconnect current bus (turn off muxes if any) */ 144 if ((i2c_bus_tmp->next_hop[0].chip != 0) && 145 (I2C_ADAP->init_done != 0)) { 146 i = CFG_SYS_I2C_MAX_HOPS; 147 do { 148 uint8_t chip; 149 int ret; 150 151 chip = i2c_bus_tmp->next_hop[--i].chip; 152 if (chip == 0) 153 continue; 154 155 ret = I2C_ADAP->write(I2C_ADAP, chip, 0, 0, &buf, 1); 156 if (ret != 0) { 157 printf("i2c: mux disconnect error\n"); 158 return ret; 159 } 160 } while (i > 0); 161 } 162 163 return 0; 164} 165#endif 166 167/* 168 * i2c_init_bus(): 169 * --------------- 170 * 171 * Initializes one bus. Will initialize the parent adapter. No current bus 172 * changes, no mux (if any) setup. 173 */ 174static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr) 175{ 176 if (bus_no >= CFG_SYS_NUM_I2C_BUSES) 177 return; 178 179 I2C_ADAP->init(I2C_ADAP, speed, slaveaddr); 180 181 if (gd->flags & GD_FLG_RELOC) { 182 I2C_ADAP->init_done = 1; 183 I2C_ADAP->speed = speed; 184 I2C_ADAP->slaveaddr = slaveaddr; 185 } 186} 187 188/* implement possible board specific board init */ 189__weak void i2c_init_board(void) 190{ 191} 192 193/* 194 * i2c_init_all(): 195 * 196 * not longer needed, will deleted. Actual init the SPD_BUS 197 * for compatibility. 198 * i2c_adap[] must be initialized beforehead with function pointers and 199 * data, including speed and slaveaddr. 200 */ 201void i2c_init_all(void) 202{ 203 i2c_init_board(); 204 i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); 205 return; 206} 207 208/* 209 * i2c_get_bus_num(): 210 * ------------------ 211 * 212 * Returns index of currently active I2C bus. Zero-based. 213 */ 214unsigned int i2c_get_bus_num(void) 215{ 216 return gd->cur_i2c_bus; 217} 218 219/* 220 * i2c_set_bus_num(): 221 * ------------------ 222 * 223 * Change the active I2C bus. Subsequent read/write calls will 224 * go to this one. Sets all of the muxes in a proper condition 225 * if that bus is behind muxes. 226 * If previously selected bus is behind the muxes turns off all the 227 * muxes along the path to that bus. 228 * 229 * bus - bus index, zero based 230 * 231 * Returns: 0 on success, not 0 on failure 232 */ 233int i2c_set_bus_num(unsigned int bus) 234{ 235 int max; 236 237 if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0)) 238 return 0; 239 240#ifndef CFG_SYS_I2C_DIRECT_BUS 241 if (bus >= CFG_SYS_NUM_I2C_BUSES) 242 return -1; 243#endif 244 245 max = ll_entry_count(struct i2c_adapter, i2c); 246 if (I2C_ADAPTER(bus) >= max) { 247 printf("Error, wrong i2c adapter %d max %d possible\n", 248 I2C_ADAPTER(bus), max); 249 return -2; 250 } 251 252#ifndef CFG_SYS_I2C_DIRECT_BUS 253 i2c_mux_disconnect_all(); 254#endif 255 256 gd->cur_i2c_bus = bus; 257 if (I2C_ADAP->init_done == 0) 258 i2c_init_bus(bus, I2C_ADAP->speed, I2C_ADAP->slaveaddr); 259 260#ifndef CFG_SYS_I2C_DIRECT_BUS 261 i2c_mux_set_all(); 262#endif 263 return 0; 264} 265 266/* 267 * Probe the given I2C chip address. Returns 0 if a chip responded, 268 * not 0 on failure. 269 */ 270int i2c_probe(uint8_t chip) 271{ 272 return I2C_ADAP->probe(I2C_ADAP, chip); 273} 274 275/* 276 * Read/Write interface: 277 * chip: I2C chip address, range 0..127 278 * addr: Memory (register) address within the chip 279 * alen: Number of bytes to use for addr (typically 1, 2 for larger 280 * memories, 0 for register type devices with only one 281 * register) 282 * buffer: Where to read/write the data 283 * len: How many bytes to read/write 284 * 285 * Returns: 0 on success, not 0 on failure 286 */ 287int i2c_read(uint8_t chip, unsigned int addr, int alen, 288 uint8_t *buffer, int len) 289{ 290 return I2C_ADAP->read(I2C_ADAP, chip, addr, alen, buffer, len); 291} 292 293int i2c_write(uint8_t chip, unsigned int addr, int alen, 294 uint8_t *buffer, int len) 295{ 296 return I2C_ADAP->write(I2C_ADAP, chip, addr, alen, buffer, len); 297} 298 299unsigned int i2c_set_bus_speed(unsigned int speed) 300{ 301 unsigned int ret; 302 303 if (I2C_ADAP->set_bus_speed == NULL) 304 return 0; 305 ret = I2C_ADAP->set_bus_speed(I2C_ADAP, speed); 306 if (gd->flags & GD_FLG_RELOC) 307 I2C_ADAP->speed = (ret == 0) ? speed : 0; 308 309 return ret; 310} 311 312unsigned int i2c_get_bus_speed(void) 313{ 314 struct i2c_adapter *cur = I2C_ADAP; 315 return cur->speed; 316} 317 318uint8_t i2c_reg_read(uint8_t addr, uint8_t reg) 319{ 320 uint8_t buf; 321 322 i2c_read(addr, reg, 1, &buf, 1); 323 324#ifdef DEBUG 325 printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", 326 __func__, i2c_get_bus_num(), addr, reg, buf); 327#endif 328 329 return buf; 330} 331 332void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val) 333{ 334#ifdef DEBUG 335 printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", 336 __func__, i2c_get_bus_num(), addr, reg, val); 337#endif 338 339 i2c_write(addr, reg, 1, &val, 1); 340} 341 342__weak void i2c_init(int speed, int slaveaddr) 343{ 344 i2c_init_bus(i2c_get_bus_num(), speed, slaveaddr); 345} 346