Lines Matching +full:i2c +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Congatec Board Controller I2C busses driver
9 #include <linux/i2c.h>
15 #define CGBC_I2C_PRIMARY_BUS_ID 0
18 #define CGBC_I2C_CMD_START 0x40
19 #define CGBC_I2C_CMD_STAT 0x48
20 #define CGBC_I2C_CMD_DATA 0x50
21 #define CGBC_I2C_CMD_SPEED 0x58
23 #define CGBC_I2C_STAT_IDL 0x00
24 #define CGBC_I2C_STAT_DAT 0x01
25 #define CGBC_I2C_STAT_BUSY 0x02
27 #define CGBC_I2C_START 0x80
28 #define CGBC_I2C_STOP 0x40
30 #define CGBC_I2C_LAST_ACK 0x80 /* send ACK on last read byte */
41 #define CGBC_I2C_FREQ_UNIT_1KHZ 0x40
42 #define CGBC_I2C_FREQ_UNIT_10KHZ 0x80
43 #define CGBC_I2C_FREQ_UNIT_100KHZ 0xC0
45 #define CGBC_I2C_FREQ_UNIT_MASK 0xC0
46 #define CGBC_I2C_FREQ_VALUE_MASK 0x3F
55 CGBC_I2C_STATE_DONE = 0,
118 struct i2c_algo_cgbc_data *algo_data = adap->algo_data; in cgbc_i2c_get_status()
119 struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap); in cgbc_i2c_get_status() local
120 struct cgbc_device_data *cgbc = i2c->cgbc; in cgbc_i2c_get_status()
121 u8 cmd = CGBC_I2C_CMD_STAT | algo_data->bus_id; in cgbc_i2c_get_status()
125 ret = cgbc_command(cgbc, &cmd, sizeof(cmd), NULL, 0, &status); in cgbc_i2c_get_status()
135 struct i2c_algo_cgbc_data *algo_data = adap->algo_data; in cgbc_i2c_set_frequency()
136 struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap); in cgbc_i2c_set_frequency() local
137 struct cgbc_device_data *cgbc = i2c->cgbc; in cgbc_i2c_set_frequency()
143 dev_info(i2c->dev, "invalid frequency %u, using default\n", bus_frequency); in cgbc_i2c_set_frequency()
147 cmd[0] = CGBC_I2C_CMD_SPEED | algo_data->bus_id; in cgbc_i2c_set_frequency()
152 return dev_err_probe(i2c->dev, ret, in cgbc_i2c_set_frequency()
153 "Failed to initialize I2C bus %s", in cgbc_i2c_set_frequency()
154 adap->name); in cgbc_i2c_set_frequency()
156 cmd[1] = 0x00; in cgbc_i2c_set_frequency()
160 return dev_err_probe(i2c->dev, ret, in cgbc_i2c_set_frequency()
161 "Failed to get I2C bus frequency"); in cgbc_i2c_set_frequency()
165 dev_dbg(i2c->dev, "%s is running at %d Hz\n", adap->name, bus_frequency); in cgbc_i2c_set_frequency()
173 algo_data->read_maxtime_us = (BITS_PER_BYTE + 1) * CGBC_I2C_READ_MAX_LEN in cgbc_i2c_set_frequency()
176 return 0; in cgbc_i2c_set_frequency()
181 int i = 0; in cgbc_i2c_xfer_to_cmd()
185 cmd[i] = (xfer.start) ? CGBC_I2C_START : 0x00; in cgbc_i2c_xfer_to_cmd()
195 if (xfer.write > 0) in cgbc_i2c_xfer_to_cmd()
203 struct i2c_algo_cgbc_data *algo_data = adap->algo_data; in cgbc_i2c_xfer_msg()
204 struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap); in cgbc_i2c_xfer_msg() local
205 struct cgbc_device_data *cgbc = i2c->cgbc; in cgbc_i2c_xfer_msg()
206 struct i2c_msg *msg = i2c->msg; in cgbc_i2c_xfer_msg()
213 .bus_id = algo_data->bus_id, in cgbc_i2c_xfer_msg()
217 if (i2c->state == CGBC_I2C_STATE_DONE) in cgbc_i2c_xfer_msg()
218 return 0; in cgbc_i2c_xfer_msg()
223 return -EBUSY; in cgbc_i2c_xfer_msg()
224 else if (ret < 0) in cgbc_i2c_xfer_msg()
227 if (i2c->state == CGBC_I2C_STATE_INIT || in cgbc_i2c_xfer_msg()
228 (i2c->state == CGBC_I2C_STATE_WRITE && msg->flags & I2C_M_RD)) in cgbc_i2c_xfer_msg()
231 i2c->state = (msg->flags & I2C_M_RD) ? CGBC_I2C_STATE_READ : CGBC_I2C_STATE_WRITE; in cgbc_i2c_xfer_msg()
233 max_len = (i2c->state == CGBC_I2C_STATE_READ) ? in cgbc_i2c_xfer_msg()
236 if (msg->len - i2c->pos > max_len) { in cgbc_i2c_xfer_msg()
239 len = msg->len - i2c->pos; in cgbc_i2c_xfer_msg()
241 if (i2c->nmsgs == 1) in cgbc_i2c_xfer_msg()
245 if (i2c->state == CGBC_I2C_STATE_WRITE) { in cgbc_i2c_xfer_msg()
247 xfer.read = 0; in cgbc_i2c_xfer_msg()
249 for (i = 0; i < len; i++) in cgbc_i2c_xfer_msg()
250 xfer.data[i] = msg->buf[i2c->pos + i]; in cgbc_i2c_xfer_msg()
252 cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]); in cgbc_i2c_xfer_msg()
254 ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL); in cgbc_i2c_xfer_msg()
257 } else if (i2c->state == CGBC_I2C_STATE_READ) { in cgbc_i2c_xfer_msg()
258 xfer.write = 0; in cgbc_i2c_xfer_msg()
261 if (i2c->nmsgs > 1 || msg->len - i2c->pos > max_len) in cgbc_i2c_xfer_msg()
264 cmd_len = cgbc_i2c_xfer_to_cmd(xfer, &cmd[0]); in cgbc_i2c_xfer_msg()
265 ret = cgbc_command(cgbc, &cmd, cmd_len, NULL, 0, NULL); in cgbc_i2c_xfer_msg()
270 ret != CGBC_I2C_STAT_BUSY, 0, in cgbc_i2c_xfer_msg()
271 2 * algo_data->read_maxtime_us, false, adap); in cgbc_i2c_xfer_msg()
272 if (ret < 0) in cgbc_i2c_xfer_msg()
275 cmd_data = CGBC_I2C_CMD_DATA | algo_data->bus_id; in cgbc_i2c_xfer_msg()
277 msg->buf + i2c->pos, len, NULL); in cgbc_i2c_xfer_msg()
282 if (len == (msg->len - i2c->pos)) { in cgbc_i2c_xfer_msg()
283 i2c->msg++; in cgbc_i2c_xfer_msg()
284 i2c->nmsgs--; in cgbc_i2c_xfer_msg()
285 i2c->pos = 0; in cgbc_i2c_xfer_msg()
287 i2c->pos += len; in cgbc_i2c_xfer_msg()
290 if (i2c->nmsgs == 0) in cgbc_i2c_xfer_msg()
291 i2c->state = CGBC_I2C_STATE_DONE; in cgbc_i2c_xfer_msg()
293 return 0; in cgbc_i2c_xfer_msg()
296 i2c->state = CGBC_I2C_STATE_ERROR; in cgbc_i2c_xfer_msg()
303 struct cgbc_i2c_data *i2c = i2c_get_adapdata(adap); in cgbc_i2c_xfer() local
307 i2c->state = CGBC_I2C_STATE_INIT; in cgbc_i2c_xfer()
308 i2c->msg = msgs; in cgbc_i2c_xfer()
309 i2c->nmsgs = num; in cgbc_i2c_xfer()
310 i2c->pos = 0; in cgbc_i2c_xfer()
314 if (i2c->state == CGBC_I2C_STATE_DONE) in cgbc_i2c_xfer()
317 if (i2c->state == CGBC_I2C_STATE_ERROR) in cgbc_i2c_xfer()
320 if (ret == 0) in cgbc_i2c_xfer()
324 i2c->state = CGBC_I2C_STATE_ERROR; in cgbc_i2c_xfer()
325 return -ETIMEDOUT; in cgbc_i2c_xfer()
346 .name = "Congatec General Purpose I2C adapter",
349 .algo_data = &cgbc_i2c_algo_data[0],
350 .nr = -1,
354 .name = "Congatec Power Management I2C adapter",
358 .nr = -1,
364 struct cgbc_device_data *cgbc = dev_get_drvdata(pdev->dev.parent); in cgbc_i2c_probe()
365 struct cgbc_i2c_data *i2c; in cgbc_i2c_probe() local
368 i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); in cgbc_i2c_probe()
369 if (!i2c) in cgbc_i2c_probe()
370 return -ENOMEM; in cgbc_i2c_probe()
372 i2c->cgbc = cgbc; in cgbc_i2c_probe()
373 i2c->dev = &pdev->dev; in cgbc_i2c_probe()
374 i2c->adap = cgbc_i2c_adapter[pdev->id]; in cgbc_i2c_probe()
375 i2c->adap.dev.parent = i2c->dev; in cgbc_i2c_probe()
376 i2c_set_adapdata(&i2c->adap, i2c); in cgbc_i2c_probe()
377 platform_set_drvdata(pdev, i2c); in cgbc_i2c_probe()
379 ret = cgbc_i2c_set_frequency(&i2c->adap, I2C_MAX_STANDARD_MODE_FREQ); in cgbc_i2c_probe()
383 return i2c_add_numbered_adapter(&i2c->adap); in cgbc_i2c_probe()
388 struct cgbc_i2c_data *i2c = platform_get_drvdata(pdev); in cgbc_i2c_remove() local
390 i2c_del_adapter(&i2c->adap); in cgbc_i2c_remove()
395 .name = "cgbc-i2c",
403 MODULE_DESCRIPTION("Congatec Board Controller I2C Driver");