]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
385c9ef5 HS |
2 | /* |
3 | * Copyright (C) 2009 Sergey Kubushyn <[email protected]> | |
4 | * | |
5 | * (C) Copyright 2012 | |
6 | * Heiko Schocher, DENX Software Engineering, [email protected]. | |
7 | * | |
8 | * Multibus/multiadapter I2C core functions (wrappers) | |
385c9ef5 | 9 | */ |
03de305e | 10 | #include <config.h> |
385c9ef5 | 11 | #include <i2c.h> |
f7ae49fc | 12 | #include <linker_lists.h> |
401d1c4f | 13 | #include <asm/global_data.h> |
385c9ef5 HS |
14 | |
15 | struct 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 | ||
385c9ef5 HS |
36 | DECLARE_GLOBAL_DATA_PTR; |
37 | ||
385c9ef5 HS |
38 | /* |
39 | * i2c_init_bus(): | |
40 | * --------------- | |
41 | * | |
42 | * Initializes one bus. Will initialize the parent adapter. No current bus | |
43 | * changes, no mux (if any) setup. | |
44 | */ | |
45 | static void i2c_init_bus(unsigned int bus_no, int speed, int slaveaddr) | |
46 | { | |
cdc5ed8f | 47 | if (bus_no >= CFG_SYS_NUM_I2C_BUSES) |
385c9ef5 HS |
48 | return; |
49 | ||
50 | I2C_ADAP->init(I2C_ADAP, speed, slaveaddr); | |
51 | ||
52 | if (gd->flags & GD_FLG_RELOC) { | |
53 | I2C_ADAP->init_done = 1; | |
54 | I2C_ADAP->speed = speed; | |
55 | I2C_ADAP->slaveaddr = slaveaddr; | |
56 | } | |
57 | } | |
58 | ||
59 | /* implement possible board specific board init */ | |
13a8b7ae | 60 | __weak void i2c_init_board(void) |
385c9ef5 HS |
61 | { |
62 | } | |
385c9ef5 HS |
63 | |
64 | /* | |
65 | * i2c_init_all(): | |
66 | * | |
67 | * not longer needed, will deleted. Actual init the SPD_BUS | |
68 | * for compatibility. | |
69 | * i2c_adap[] must be initialized beforehead with function pointers and | |
70 | * data, including speed and slaveaddr. | |
71 | */ | |
72 | void i2c_init_all(void) | |
73 | { | |
74 | i2c_init_board(); | |
75 | i2c_set_bus_num(CONFIG_SYS_SPD_BUS_NUM); | |
76 | return; | |
77 | } | |
78 | ||
79 | /* | |
80 | * i2c_get_bus_num(): | |
81 | * ------------------ | |
82 | * | |
83 | * Returns index of currently active I2C bus. Zero-based. | |
84 | */ | |
85 | unsigned int i2c_get_bus_num(void) | |
86 | { | |
87 | return gd->cur_i2c_bus; | |
88 | } | |
89 | ||
90 | /* | |
91 | * i2c_set_bus_num(): | |
92 | * ------------------ | |
93 | * | |
94 | * Change the active I2C bus. Subsequent read/write calls will | |
95 | * go to this one. Sets all of the muxes in a proper condition | |
96 | * if that bus is behind muxes. | |
97 | * If previously selected bus is behind the muxes turns off all the | |
98 | * muxes along the path to that bus. | |
99 | * | |
100 | * bus - bus index, zero based | |
101 | * | |
102 | * Returns: 0 on success, not 0 on failure | |
103 | */ | |
104 | int i2c_set_bus_num(unsigned int bus) | |
105 | { | |
13c2433c HS |
106 | int max; |
107 | ||
108 | if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0)) | |
109 | return 0; | |
385c9ef5 | 110 | |
13c2433c HS |
111 | max = ll_entry_count(struct i2c_adapter, i2c); |
112 | if (I2C_ADAPTER(bus) >= max) { | |
113 | printf("Error, wrong i2c adapter %d max %d possible\n", | |
114 | I2C_ADAPTER(bus), max); | |
115 | return -2; | |
116 | } | |
385c9ef5 | 117 | |
385c9ef5 HS |
118 | gd->cur_i2c_bus = bus; |
119 | if (I2C_ADAP->init_done == 0) | |
120 | i2c_init_bus(bus, I2C_ADAP->speed, I2C_ADAP->slaveaddr); | |
121 | ||
385c9ef5 HS |
122 | return 0; |
123 | } | |
124 | ||
125 | /* | |
126 | * Probe the given I2C chip address. Returns 0 if a chip responded, | |
127 | * not 0 on failure. | |
128 | */ | |
129 | int i2c_probe(uint8_t chip) | |
130 | { | |
131 | return I2C_ADAP->probe(I2C_ADAP, chip); | |
132 | } | |
133 | ||
134 | /* | |
135 | * Read/Write interface: | |
136 | * chip: I2C chip address, range 0..127 | |
137 | * addr: Memory (register) address within the chip | |
138 | * alen: Number of bytes to use for addr (typically 1, 2 for larger | |
139 | * memories, 0 for register type devices with only one | |
140 | * register) | |
141 | * buffer: Where to read/write the data | |
142 | * len: How many bytes to read/write | |
143 | * | |
144 | * Returns: 0 on success, not 0 on failure | |
145 | */ | |
146 | int i2c_read(uint8_t chip, unsigned int addr, int alen, | |
147 | uint8_t *buffer, int len) | |
148 | { | |
149 | return I2C_ADAP->read(I2C_ADAP, chip, addr, alen, buffer, len); | |
150 | } | |
151 | ||
152 | int i2c_write(uint8_t chip, unsigned int addr, int alen, | |
153 | uint8_t *buffer, int len) | |
154 | { | |
155 | return I2C_ADAP->write(I2C_ADAP, chip, addr, alen, buffer, len); | |
156 | } | |
157 | ||
158 | unsigned int i2c_set_bus_speed(unsigned int speed) | |
159 | { | |
160 | unsigned int ret; | |
161 | ||
162 | if (I2C_ADAP->set_bus_speed == NULL) | |
163 | return 0; | |
164 | ret = I2C_ADAP->set_bus_speed(I2C_ADAP, speed); | |
165 | if (gd->flags & GD_FLG_RELOC) | |
7cc1b02f | 166 | I2C_ADAP->speed = (ret == 0) ? speed : 0; |
385c9ef5 HS |
167 | |
168 | return ret; | |
169 | } | |
170 | ||
171 | unsigned int i2c_get_bus_speed(void) | |
172 | { | |
173 | struct i2c_adapter *cur = I2C_ADAP; | |
174 | return cur->speed; | |
175 | } | |
176 | ||
177 | uint8_t i2c_reg_read(uint8_t addr, uint8_t reg) | |
178 | { | |
179 | uint8_t buf; | |
180 | ||
385c9ef5 HS |
181 | i2c_read(addr, reg, 1, &buf, 1); |
182 | ||
183 | #ifdef DEBUG | |
184 | printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", | |
185 | __func__, i2c_get_bus_num(), addr, reg, buf); | |
186 | #endif | |
187 | ||
188 | return buf; | |
189 | } | |
190 | ||
191 | void i2c_reg_write(uint8_t addr, uint8_t reg, uint8_t val) | |
192 | { | |
385c9ef5 HS |
193 | #ifdef DEBUG |
194 | printf("%s: bus=%d addr=0x%02x, reg=0x%02x, val=0x%02x\n", | |
195 | __func__, i2c_get_bus_num(), addr, reg, val); | |
196 | #endif | |
197 | ||
198 | i2c_write(addr, reg, 1, &val, 1); | |
199 | } | |
200 | ||
13a8b7ae | 201 | __weak void i2c_init(int speed, int slaveaddr) |
385c9ef5 HS |
202 | { |
203 | i2c_init_bus(i2c_get_bus_num(), speed, slaveaddr); | |
204 | } |