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