xref: /openbmc/u-boot/drivers/misc/i2c_eeprom.c (revision 8b21180f7db21629cb029461ced1b578e4eb8d0e)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2014 Google, Inc
4  */
5 
6 #include <common.h>
7 #include <eeprom.h>
8 #include <linux/err.h>
9 #include <linux/kernel.h>
10 #include <dm.h>
11 #include <dm/device-internal.h>
12 #include <i2c.h>
13 #include <i2c_eeprom.h>
14 
15 struct i2c_eeprom_drv_data {
16 	u32 size; /* size in bytes */
17 	u32 pagesize; /* page size in bytes */
18 	u32 addr_offset_mask; /* bits in addr used for offset overflow */
19 	u32 offset_len; /* size in bytes of offset */
20 	u32 start_offset; /* valid start offset inside memory, by default 0 */
21 };
22 
i2c_eeprom_read(struct udevice * dev,int offset,uint8_t * buf,int size)23 int i2c_eeprom_read(struct udevice *dev, int offset, uint8_t *buf, int size)
24 {
25 	const struct i2c_eeprom_ops *ops = device_get_ops(dev);
26 
27 	if (!ops->read)
28 		return -ENOSYS;
29 
30 	return ops->read(dev, offset, buf, size);
31 }
32 
i2c_eeprom_write(struct udevice * dev,int offset,uint8_t * buf,int size)33 int i2c_eeprom_write(struct udevice *dev, int offset, uint8_t *buf, int size)
34 {
35 	const struct i2c_eeprom_ops *ops = device_get_ops(dev);
36 
37 	if (!ops->write)
38 		return -ENOSYS;
39 
40 	return ops->write(dev, offset, buf, size);
41 }
42 
i2c_eeprom_size(struct udevice * dev)43 int i2c_eeprom_size(struct udevice *dev)
44 {
45 	const struct i2c_eeprom_ops *ops = device_get_ops(dev);
46 
47 	if (!ops->size)
48 		return -ENOSYS;
49 
50 	return ops->size(dev);
51 }
52 
i2c_eeprom_std_read(struct udevice * dev,int offset,uint8_t * buf,int size)53 static int i2c_eeprom_std_read(struct udevice *dev, int offset, uint8_t *buf,
54 			       int size)
55 {
56 	return dm_i2c_read(dev, offset, buf, size);
57 }
58 
i2c_eeprom_std_write(struct udevice * dev,int offset,const uint8_t * buf,int size)59 static int i2c_eeprom_std_write(struct udevice *dev, int offset,
60 				const uint8_t *buf, int size)
61 {
62 	struct i2c_eeprom *priv = dev_get_priv(dev);
63 	int ret;
64 
65 	while (size > 0) {
66 		int write_size = min_t(int, size, priv->pagesize);
67 
68 		ret = dm_i2c_write(dev, offset, buf, write_size);
69 		if (ret)
70 			return ret;
71 
72 		offset += write_size;
73 		buf += write_size;
74 		size -= write_size;
75 
76 		udelay(10000);
77 	}
78 
79 	return 0;
80 }
81 
i2c_eeprom_std_size(struct udevice * dev)82 static int i2c_eeprom_std_size(struct udevice *dev)
83 {
84 	struct i2c_eeprom *priv = dev_get_priv(dev);
85 
86 	return priv->size;
87 }
88 
89 static const struct i2c_eeprom_ops i2c_eeprom_std_ops = {
90 	.read	= i2c_eeprom_std_read,
91 	.write	= i2c_eeprom_std_write,
92 	.size	= i2c_eeprom_std_size,
93 };
94 
i2c_eeprom_std_ofdata_to_platdata(struct udevice * dev)95 static int i2c_eeprom_std_ofdata_to_platdata(struct udevice *dev)
96 {
97 	struct i2c_eeprom *priv = dev_get_priv(dev);
98 	struct i2c_eeprom_drv_data *data =
99 		(struct i2c_eeprom_drv_data *)dev_get_driver_data(dev);
100 	u32 pagesize;
101 	u32 size;
102 
103 	if (dev_read_u32(dev, "pagesize", &pagesize) == 0)
104 		priv->pagesize = pagesize;
105 	else
106 		/* 6 bit -> page size of up to 2^63 (should be sufficient) */
107 		priv->pagesize = data->pagesize;
108 
109 	if (dev_read_u32(dev, "size", &size) == 0)
110 		priv->size = size;
111 	else
112 		priv->size = data->size;
113 
114 	return 0;
115 }
116 
i2c_eeprom_std_bind(struct udevice * dev)117 static int i2c_eeprom_std_bind(struct udevice *dev)
118 {
119 	ofnode partitions = ofnode_find_subnode(dev_ofnode(dev), "partitions");
120 	ofnode partition;
121 	const char *name;
122 
123 	if (!ofnode_valid(partitions))
124 		return 0;
125 	if (!ofnode_device_is_compatible(partitions, "fixed-partitions"))
126 		return -ENOTSUPP;
127 
128 	ofnode_for_each_subnode(partition, partitions) {
129 		name = ofnode_get_name(partition);
130 		if (!name)
131 			continue;
132 
133 		device_bind_ofnode(dev, DM_GET_DRIVER(i2c_eeprom_partition),
134 				   name, NULL, partition, NULL);
135 	}
136 
137 	return 0;
138 }
139 
i2c_eeprom_std_probe(struct udevice * dev)140 static int i2c_eeprom_std_probe(struct udevice *dev)
141 {
142 	u8 test_byte;
143 	int ret;
144 	struct i2c_eeprom_drv_data *data =
145 		(struct i2c_eeprom_drv_data *)dev_get_driver_data(dev);
146 
147 	i2c_set_chip_offset_len(dev, data->offset_len);
148 	i2c_set_chip_addr_offset_mask(dev, data->addr_offset_mask);
149 
150 	/* Verify that the chip is functional */
151 	/*
152 	 * Not all eeproms start from offset 0. Valid offset is available
153 	 * in the platform data struct.
154 	 */
155 	ret = i2c_eeprom_read(dev, data->start_offset, &test_byte, 1);
156 	if (ret)
157 		return -ENODEV;
158 
159 	return 0;
160 }
161 
162 static const struct i2c_eeprom_drv_data eeprom_data = {
163 	.size = 0,
164 	.pagesize = 1,
165 	.addr_offset_mask = 0,
166 	.offset_len = 1,
167 };
168 
169 static const struct i2c_eeprom_drv_data mc24aa02e48_data = {
170 	.size = 256,
171 	.pagesize = 8,
172 	.addr_offset_mask = 0,
173 	.offset_len = 1,
174 };
175 
176 static const struct i2c_eeprom_drv_data atmel24c01a_data = {
177 	.size = 128,
178 	.pagesize = 8,
179 	.addr_offset_mask = 0,
180 	.offset_len = 1,
181 };
182 
183 static const struct i2c_eeprom_drv_data atmel24c02_data = {
184 	.size = 256,
185 	.pagesize = 8,
186 	.addr_offset_mask = 0,
187 	.offset_len = 1,
188 };
189 
190 static const struct i2c_eeprom_drv_data atmel24c04_data = {
191 	.size = 512,
192 	.pagesize = 16,
193 	.addr_offset_mask = 0x1,
194 	.offset_len = 1,
195 };
196 
197 static const struct i2c_eeprom_drv_data atmel24c08_data = {
198 	.size = 1024,
199 	.pagesize = 16,
200 	.addr_offset_mask = 0x3,
201 	.offset_len = 1,
202 };
203 
204 static const struct i2c_eeprom_drv_data atmel24c08a_data = {
205 	.size = 1024,
206 	.pagesize = 16,
207 	.addr_offset_mask = 0x3,
208 	.offset_len = 1,
209 };
210 
211 static const struct i2c_eeprom_drv_data atmel24c16a_data = {
212 	.size = 2048,
213 	.pagesize = 16,
214 	.addr_offset_mask = 0x7,
215 	.offset_len = 1,
216 };
217 
218 static const struct i2c_eeprom_drv_data atmel24mac402_data = {
219 	.size = 256,
220 	.pagesize = 16,
221 	.addr_offset_mask = 0,
222 	.offset_len = 1,
223 	.start_offset = 0x80,
224 };
225 
226 static const struct i2c_eeprom_drv_data atmel24c32_data = {
227 	.size = 4096,
228 	.pagesize = 32,
229 	.addr_offset_mask = 0,
230 	.offset_len = 2,
231 };
232 
233 static const struct i2c_eeprom_drv_data atmel24c64_data = {
234 	.size = 8192,
235 	.pagesize = 32,
236 	.addr_offset_mask = 0,
237 	.offset_len = 2,
238 };
239 
240 static const struct i2c_eeprom_drv_data atmel24c128_data = {
241 	.size = 16384,
242 	.pagesize = 64,
243 	.addr_offset_mask = 0,
244 	.offset_len = 2,
245 };
246 
247 static const struct i2c_eeprom_drv_data atmel24c256_data = {
248 	.size = 32768,
249 	.pagesize = 64,
250 	.addr_offset_mask = 0,
251 	.offset_len = 2,
252 };
253 
254 static const struct i2c_eeprom_drv_data atmel24c512_data = {
255 	.size = 65536,
256 	.pagesize = 64,
257 	.addr_offset_mask = 0,
258 	.offset_len = 2,
259 };
260 
261 static const struct udevice_id i2c_eeprom_std_ids[] = {
262 	{ .compatible = "i2c-eeprom", (ulong)&eeprom_data },
263 	{ .compatible = "microchip,24aa02e48", (ulong)&mc24aa02e48_data },
264 	{ .compatible = "atmel,24c01a", (ulong)&atmel24c01a_data },
265 	{ .compatible = "atmel,24c02", (ulong)&atmel24c02_data },
266 	{ .compatible = "atmel,24c04", (ulong)&atmel24c04_data },
267 	{ .compatible = "atmel,24c08", (ulong)&atmel24c08_data },
268 	{ .compatible = "atmel,24c08a", (ulong)&atmel24c08a_data },
269 	{ .compatible = "atmel,24c16a", (ulong)&atmel24c16a_data },
270 	{ .compatible = "atmel,24mac402", (ulong)&atmel24mac402_data },
271 	{ .compatible = "atmel,24c32", (ulong)&atmel24c32_data },
272 	{ .compatible = "atmel,24c64", (ulong)&atmel24c64_data },
273 	{ .compatible = "atmel,24c128", (ulong)&atmel24c128_data },
274 	{ .compatible = "atmel,24c256", (ulong)&atmel24c256_data },
275 	{ .compatible = "atmel,24c512", (ulong)&atmel24c512_data },
276 	{ }
277 };
278 
279 U_BOOT_DRIVER(i2c_eeprom_std) = {
280 	.name			= "i2c_eeprom",
281 	.id			= UCLASS_I2C_EEPROM,
282 	.of_match		= i2c_eeprom_std_ids,
283 	.bind			= i2c_eeprom_std_bind,
284 	.probe			= i2c_eeprom_std_probe,
285 	.ofdata_to_platdata	= i2c_eeprom_std_ofdata_to_platdata,
286 	.priv_auto_alloc_size	= sizeof(struct i2c_eeprom),
287 	.ops			= &i2c_eeprom_std_ops,
288 };
289 
290 struct i2c_eeprom_partition {
291 	u32 offset;
292 	u32 size;
293 };
294 
i2c_eeprom_partition_probe(struct udevice * dev)295 static int i2c_eeprom_partition_probe(struct udevice *dev)
296 {
297 	return 0;
298 }
299 
i2c_eeprom_partition_ofdata_to_platdata(struct udevice * dev)300 static int i2c_eeprom_partition_ofdata_to_platdata(struct udevice *dev)
301 {
302 	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
303 	u32 reg[2];
304 	int ret;
305 
306 	ret = dev_read_u32_array(dev, "reg", reg, 2);
307 	if (ret)
308 		return ret;
309 
310 	if (!reg[1])
311 		return -EINVAL;
312 
313 	priv->offset = reg[0];
314 	priv->size = reg[1];
315 
316 	debug("%s: base %x, size %x\n", __func__, priv->offset, priv->size);
317 
318 	return 0;
319 }
320 
i2c_eeprom_partition_read(struct udevice * dev,int offset,u8 * buf,int size)321 static int i2c_eeprom_partition_read(struct udevice *dev, int offset,
322 				     u8 *buf, int size)
323 {
324 	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
325 	struct udevice *parent = dev_get_parent(dev);
326 
327 	if (!parent)
328 		return -ENODEV;
329 	if (offset + size > priv->size)
330 		return -EINVAL;
331 
332 	return i2c_eeprom_read(parent, offset + priv->offset, buf, size);
333 }
334 
i2c_eeprom_partition_write(struct udevice * dev,int offset,const u8 * buf,int size)335 static int i2c_eeprom_partition_write(struct udevice *dev, int offset,
336 				      const u8 *buf, int size)
337 {
338 	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
339 	struct udevice *parent = dev_get_parent(dev);
340 
341 	if (!parent)
342 		return -ENODEV;
343 	if (offset + size > priv->size)
344 		return -EINVAL;
345 
346 	return i2c_eeprom_write(parent, offset + priv->offset, (uint8_t *)buf,
347 				size);
348 }
349 
i2c_eeprom_partition_size(struct udevice * dev)350 static int i2c_eeprom_partition_size(struct udevice *dev)
351 {
352 	struct i2c_eeprom_partition *priv = dev_get_priv(dev);
353 
354 	return priv->size;
355 }
356 
357 static const struct i2c_eeprom_ops i2c_eeprom_partition_ops = {
358 	.read	= i2c_eeprom_partition_read,
359 	.write	= i2c_eeprom_partition_write,
360 	.size	= i2c_eeprom_partition_size,
361 };
362 
363 U_BOOT_DRIVER(i2c_eeprom_partition) = {
364 	.name			= "i2c_eeprom_partition",
365 	.id			= UCLASS_I2C_EEPROM,
366 	.probe			= i2c_eeprom_partition_probe,
367 	.ofdata_to_platdata	= i2c_eeprom_partition_ofdata_to_platdata,
368 	.priv_auto_alloc_size	= sizeof(struct i2c_eeprom_partition),
369 	.ops			= &i2c_eeprom_partition_ops,
370 };
371 
372 UCLASS_DRIVER(i2c_eeprom) = {
373 	.id		= UCLASS_I2C_EEPROM,
374 	.name		= "i2c_eeprom",
375 };
376