xref: /linux/drivers/mfd/tps6594-i2c.c (revision df34ecc52526480a1a4bb78bc75bfb009c6076a4)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * I2C access driver for the following TI PMICs:
4  *  - LP8764
5  *  - TPS65224
6  *  - TPS652G1
7  *  - TPS6593
8  *  - TPS6594
9  *
10  * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/
11  */
12 
13 #include <linux/crc8.h>
14 #include <linux/i2c.h>
15 #include <linux/module.h>
16 #include <linux/of_device.h>
17 #include <linux/regmap.h>
18 
19 #include <linux/mfd/tps6594.h>
20 
21 static bool enable_crc;
22 module_param(enable_crc, bool, 0444);
23 MODULE_PARM_DESC(enable_crc, "Enable CRC feature for I2C interface");
24 
25 DECLARE_CRC8_TABLE(tps6594_i2c_crc_table);
26 
27 static int tps6594_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
28 {
29 	int ret = i2c_transfer(adap, msgs, num);
30 
31 	if (ret == num)
32 		return 0;
33 	else if (ret < 0)
34 		return ret;
35 	else
36 		return -EIO;
37 }
38 
39 static int tps6594_i2c_reg_read_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 *val)
40 {
41 	struct i2c_msg msgs[2];
42 	u8 buf_rx[] = { 0, 0 };
43 	/* I2C address = I2C base address + Page index */
44 	const u8 addr = client->addr + page;
45 	/*
46 	 * CRC is calculated from every bit included in the protocol
47 	 * except the ACK bits from the target. Byte stream is:
48 	 * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
49 	 * - B1: reg
50 	 * - B2: (I2C_addr_7bits << 1) | RD_bit, with RD_bit = 1
51 	 * - B3: val
52 	 * - B4: CRC from B0-B1-B2-B3
53 	 */
54 	u8 crc_data[] = { addr << 1, reg, addr << 1 | 1, 0 };
55 	int ret;
56 
57 	/* Write register */
58 	msgs[0].addr = addr;
59 	msgs[0].flags = 0;
60 	msgs[0].len = 1;
61 	msgs[0].buf = &reg;
62 
63 	/* Read data and CRC */
64 	msgs[1].addr = msgs[0].addr;
65 	msgs[1].flags = I2C_M_RD;
66 	msgs[1].len = 2;
67 	msgs[1].buf = buf_rx;
68 
69 	ret = tps6594_i2c_transfer(client->adapter, msgs, 2);
70 	if (ret < 0)
71 		return ret;
72 
73 	crc_data[sizeof(crc_data) - 1] = *val = buf_rx[0];
74 	if (buf_rx[1] != crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE))
75 		return -EIO;
76 
77 	return ret;
78 }
79 
80 static int tps6594_i2c_reg_write_with_crc(struct i2c_client *client, u8 page, u8 reg, u8 val)
81 {
82 	struct i2c_msg msg;
83 	u8 buf[] = { reg, val, 0 };
84 	/* I2C address = I2C base address + Page index */
85 	const u8 addr = client->addr + page;
86 	/*
87 	 * CRC is calculated from every bit included in the protocol
88 	 * except the ACK bits from the target. Byte stream is:
89 	 * - B0: (I2C_addr_7bits << 1) | WR_bit, with WR_bit = 0
90 	 * - B1: reg
91 	 * - B2: val
92 	 * - B3: CRC from B0-B1-B2
93 	 */
94 	const u8 crc_data[] = { addr << 1, reg, val };
95 
96 	/* Write register, data and CRC */
97 	msg.addr = addr;
98 	msg.flags = client->flags & I2C_M_TEN;
99 	msg.len = sizeof(buf);
100 	msg.buf = buf;
101 
102 	buf[msg.len - 1] = crc8(tps6594_i2c_crc_table, crc_data, sizeof(crc_data), CRC8_INIT_VALUE);
103 
104 	return tps6594_i2c_transfer(client->adapter, &msg, 1);
105 }
106 
107 static int tps6594_i2c_read(void *context, const void *reg_buf, size_t reg_size,
108 			    void *val_buf, size_t val_size)
109 {
110 	struct i2c_client *client = context;
111 	struct tps6594 *tps = i2c_get_clientdata(client);
112 	struct i2c_msg msgs[2];
113 	const u8 *reg_bytes = reg_buf;
114 	u8 *val_bytes = val_buf;
115 	const u8 page = reg_bytes[1];
116 	u8 reg = reg_bytes[0];
117 	int ret = 0;
118 	int i;
119 
120 	if (tps->use_crc) {
121 		/*
122 		 * Auto-increment feature does not support CRC protocol.
123 		 * Converts the bulk read operation into a series of single read operations.
124 		 */
125 		for (i = 0 ; ret == 0 && i < val_size ; i++)
126 			ret = tps6594_i2c_reg_read_with_crc(client, page, reg + i, val_bytes + i);
127 
128 		return ret;
129 	}
130 
131 	/* Write register: I2C address = I2C base address + Page index */
132 	msgs[0].addr = client->addr + page;
133 	msgs[0].flags = 0;
134 	msgs[0].len = 1;
135 	msgs[0].buf = &reg;
136 
137 	/* Read data */
138 	msgs[1].addr = msgs[0].addr;
139 	msgs[1].flags = I2C_M_RD;
140 	msgs[1].len = val_size;
141 	msgs[1].buf = val_bytes;
142 
143 	return tps6594_i2c_transfer(client->adapter, msgs, 2);
144 }
145 
146 static int tps6594_i2c_write(void *context, const void *data, size_t count)
147 {
148 	struct i2c_client *client = context;
149 	struct tps6594 *tps = i2c_get_clientdata(client);
150 	struct i2c_msg msg;
151 	const u8 *bytes = data;
152 	u8 *buf;
153 	const u8 page = bytes[1];
154 	const u8 reg = bytes[0];
155 	int ret = 0;
156 	int i;
157 
158 	if (tps->use_crc) {
159 		/*
160 		 * Auto-increment feature does not support CRC protocol.
161 		 * Converts the bulk write operation into a series of single write operations.
162 		 */
163 		for (i = 0 ; ret == 0 && i < count - 2 ; i++)
164 			ret = tps6594_i2c_reg_write_with_crc(client, page, reg + i, bytes[i + 2]);
165 
166 		return ret;
167 	}
168 
169 	/* Setup buffer: page byte is not sent */
170 	buf = kzalloc(--count, GFP_KERNEL);
171 	if (!buf)
172 		return -ENOMEM;
173 
174 	buf[0] = reg;
175 	for (i = 0 ; i < count - 1 ; i++)
176 		buf[i + 1] = bytes[i + 2];
177 
178 	/* Write register and data: I2C address = I2C base address + Page index */
179 	msg.addr = client->addr + page;
180 	msg.flags = client->flags & I2C_M_TEN;
181 	msg.len = count;
182 	msg.buf = buf;
183 
184 	ret = tps6594_i2c_transfer(client->adapter, &msg, 1);
185 
186 	kfree(buf);
187 	return ret;
188 }
189 
190 static struct regmap_config tps6594_i2c_regmap_config = {
191 	.reg_bits = 16,
192 	.val_bits = 8,
193 	.max_register = TPS6594_REG_DWD_FAIL_CNT_REG,
194 	.volatile_table = &tps6594_volatile_table,
195 	.read = tps6594_i2c_read,
196 	.write = tps6594_i2c_write,
197 };
198 
199 static const struct of_device_id tps6594_i2c_of_match_table[] = {
200 	{ .compatible = "ti,tps6594-q1", .data = (void *)TPS6594, },
201 	{ .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, },
202 	{ .compatible = "ti,lp8764-q1",  .data = (void *)LP8764,  },
203 	{ .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, },
204 	{ .compatible = "ti,tps652g1", .data = (void *)TPS652G1, },
205 	{}
206 };
207 MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table);
208 
209 static int tps6594_i2c_probe(struct i2c_client *client)
210 {
211 	struct device *dev = &client->dev;
212 	struct tps6594 *tps;
213 	const struct of_device_id *match;
214 
215 	tps = devm_kzalloc(dev, sizeof(*tps), GFP_KERNEL);
216 	if (!tps)
217 		return -ENOMEM;
218 
219 	i2c_set_clientdata(client, tps);
220 
221 	tps->dev = dev;
222 	tps->reg = client->addr;
223 	tps->irq = client->irq;
224 
225 	match = of_match_device(tps6594_i2c_of_match_table, dev);
226 	if (!match)
227 		return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n");
228 	tps->chip_id = (unsigned long)match->data;
229 
230 	if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1)
231 		tps6594_i2c_regmap_config.volatile_table = &tps65224_volatile_table;
232 
233 	tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
234 	if (IS_ERR(tps->regmap))
235 		return dev_err_probe(dev, PTR_ERR(tps->regmap), "Failed to init regmap\n");
236 
237 	crc8_populate_msb(tps6594_i2c_crc_table, TPS6594_CRC8_POLYNOMIAL);
238 
239 	return tps6594_device_init(tps, enable_crc);
240 }
241 
242 static struct i2c_driver tps6594_i2c_driver = {
243 	.driver	= {
244 		.name = "tps6594",
245 		.of_match_table = tps6594_i2c_of_match_table,
246 	},
247 	.probe = tps6594_i2c_probe,
248 };
249 module_i2c_driver(tps6594_i2c_driver);
250 
251 MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
252 MODULE_DESCRIPTION("I2C Interface Driver for TPS65224, TPS6594/3, and LP8764");
253 MODULE_LICENSE("GPL");
254