1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief Driver for Atmel AT24 I2C and Atmel AT25 SPI EEPROMs.
10  */
11 
12 #include <zephyr/drivers/eeprom.h>
13 #include <zephyr/drivers/gpio.h>
14 #include <zephyr/drivers/i2c.h>
15 #include <zephyr/drivers/spi.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/kernel.h>
18 
19 #define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(eeprom_at2x);
22 
23 /* AT25 instruction set */
24 #define EEPROM_AT25_WRSR  0x01U /* Write STATUS register        */
25 #define EEPROM_AT25_WRITE 0x02U /* Write data to memory array   */
26 #define EEPROM_AT25_READ  0x03U /* Read data from memory array  */
27 #define EEPROM_AT25_WRDI  0x04U /* Reset the write enable latch */
28 #define EEPROM_AT25_RDSR  0x05U /* Read STATUS register         */
29 #define EEPROM_AT25_WREN  0x06U /* Set the write enable latch   */
30 
31 /* AT25 status register bits */
32 #define EEPROM_AT25_STATUS_WIP BIT(0) /* Write-In-Process   (RO) */
33 #define EEPROM_AT25_STATUS_WEL BIT(1) /* Write Enable Latch (RO) */
34 #define EEPROM_AT25_STATUS_BP0 BIT(2) /* Block Protection 0 (RW) */
35 #define EEPROM_AT25_STATUS_BP1 BIT(3) /* Block Protection 1 (RW) */
36 
37 #define HAS_WP_OR(id) DT_NODE_HAS_PROP(id, wp_gpios) ||
38 #define ANY_INST_HAS_WP_GPIOS (DT_FOREACH_STATUS_OKAY(atmel_at24, HAS_WP_OR) \
39 			       DT_FOREACH_STATUS_OKAY(atmel_at25, HAS_WP_OR) 0)
40 
41 struct eeprom_at2x_config {
42 	union {
43 #ifdef CONFIG_EEPROM_AT24
44 		struct i2c_dt_spec i2c;
45 #endif /* CONFIG_EEPROM_AT24 */
46 #ifdef CONFIG_EEPROM_AT25
47 		struct spi_dt_spec spi;
48 #endif /* CONFIG_EEPROM_AT25 */
49 	} bus;
50 #if ANY_INST_HAS_WP_GPIOS
51 	struct gpio_dt_spec wp_gpio;
52 #endif /* ANY_INST_HAS_WP_GPIOS */
53 	size_t size;
54 	size_t pagesize;
55 	uint8_t addr_width;
56 	bool readonly;
57 	uint16_t timeout;
58 	bool (*bus_is_ready)(const struct device *dev);
59 	eeprom_api_read read_fn;
60 	eeprom_api_write write_fn;
61 };
62 
63 struct eeprom_at2x_data {
64 	struct k_mutex lock;
65 };
66 
67 #if ANY_INST_HAS_WP_GPIOS
eeprom_at2x_write_protect(const struct device * dev)68 static inline int eeprom_at2x_write_protect(const struct device *dev)
69 {
70 	const struct eeprom_at2x_config *config = dev->config;
71 
72 	if (!config->wp_gpio.port) {
73 		return 0;
74 	}
75 
76 	return gpio_pin_set_dt(&config->wp_gpio, 1);
77 }
78 
eeprom_at2x_write_enable(const struct device * dev)79 static inline int eeprom_at2x_write_enable(const struct device *dev)
80 {
81 	const struct eeprom_at2x_config *config = dev->config;
82 
83 	if (!config->wp_gpio.port) {
84 		return 0;
85 	}
86 
87 	return gpio_pin_set_dt(&config->wp_gpio, 0);
88 }
89 #endif /* ANY_INST_HAS_WP_GPIOS */
90 
eeprom_at2x_read(const struct device * dev,off_t offset,void * buf,size_t len)91 static int eeprom_at2x_read(const struct device *dev, off_t offset, void *buf,
92 			    size_t len)
93 {
94 	const struct eeprom_at2x_config *config = dev->config;
95 	struct eeprom_at2x_data *data = dev->data;
96 	uint8_t *pbuf = buf;
97 	int ret;
98 
99 	if (!len) {
100 		return 0;
101 	}
102 
103 	if ((offset + len) > config->size) {
104 		LOG_WRN("attempt to read past device boundary");
105 		return -EINVAL;
106 	}
107 
108 	k_mutex_lock(&data->lock, K_FOREVER);
109 	while (len) {
110 		ret = config->read_fn(dev, offset, pbuf, len);
111 		if (ret < 0) {
112 			LOG_ERR("failed to read EEPROM (err %d)", ret);
113 			k_mutex_unlock(&data->lock);
114 			return ret;
115 		}
116 
117 		pbuf += ret;
118 		offset += ret;
119 		len -= ret;
120 	}
121 
122 	k_mutex_unlock(&data->lock);
123 
124 	return 0;
125 }
126 
eeprom_at2x_limit_write_count(const struct device * dev,off_t offset,size_t len)127 static size_t eeprom_at2x_limit_write_count(const struct device *dev,
128 					    off_t offset,
129 					    size_t len)
130 {
131 	const struct eeprom_at2x_config *config = dev->config;
132 	size_t count = len;
133 	off_t page_boundary;
134 
135 	/* We can at most write one page at a time */
136 	if (count > config->pagesize) {
137 		count = config->pagesize;
138 	}
139 
140 	/* Writes can not cross a page boundary */
141 	page_boundary = ROUND_UP(offset + 1, config->pagesize);
142 	if (offset + count > page_boundary) {
143 		count = page_boundary - offset;
144 	}
145 
146 	return count;
147 }
148 
eeprom_at2x_write(const struct device * dev,off_t offset,const void * buf,size_t len)149 static int eeprom_at2x_write(const struct device *dev, off_t offset,
150 			     const void *buf,
151 			     size_t len)
152 {
153 	const struct eeprom_at2x_config *config = dev->config;
154 	struct eeprom_at2x_data *data = dev->data;
155 	const uint8_t *pbuf = buf;
156 	int ret;
157 
158 	if (config->readonly) {
159 		LOG_WRN("attempt to write to read-only device");
160 		return -EACCES;
161 	}
162 
163 	if (!len) {
164 		return 0;
165 	}
166 
167 	if ((offset + len) > config->size) {
168 		LOG_WRN("attempt to write past device boundary");
169 		return -EINVAL;
170 	}
171 
172 	k_mutex_lock(&data->lock, K_FOREVER);
173 
174 #if ANY_INST_HAS_WP_GPIOS
175 	ret = eeprom_at2x_write_enable(dev);
176 	if (ret) {
177 		LOG_ERR("failed to write-enable EEPROM (err %d)", ret);
178 		k_mutex_unlock(&data->lock);
179 		return ret;
180 	}
181 #endif /* ANY_INST_HAS_WP_GPIOS */
182 
183 	while (len) {
184 		ret = config->write_fn(dev, offset, pbuf, len);
185 		if (ret < 0) {
186 			LOG_ERR("failed to write to EEPROM (err %d)", ret);
187 #if ANY_INST_HAS_WP_GPIOS
188 			eeprom_at2x_write_protect(dev);
189 #endif /* ANY_INST_HAS_WP_GPIOS */
190 			k_mutex_unlock(&data->lock);
191 			return ret;
192 		}
193 
194 		pbuf += ret;
195 		offset += ret;
196 		len -= ret;
197 	}
198 
199 #if ANY_INST_HAS_WP_GPIOS
200 	ret = eeprom_at2x_write_protect(dev);
201 	if (ret) {
202 		LOG_ERR("failed to write-protect EEPROM (err %d)", ret);
203 	}
204 #else
205 	ret = 0;
206 #endif /* ANY_INST_HAS_WP_GPIOS */
207 
208 	k_mutex_unlock(&data->lock);
209 
210 	return ret;
211 }
212 
eeprom_at2x_size(const struct device * dev)213 static size_t eeprom_at2x_size(const struct device *dev)
214 {
215 	const struct eeprom_at2x_config *config = dev->config;
216 
217 	return config->size;
218 }
219 
220 #ifdef CONFIG_EEPROM_AT24
221 
eeprom_at24_bus_is_ready(const struct device * dev)222 static bool eeprom_at24_bus_is_ready(const struct device *dev)
223 {
224 	const struct eeprom_at2x_config *config = dev->config;
225 
226 	return device_is_ready(config->bus.i2c.bus);
227 }
228 
229 /**
230  * @brief translate an offset to a device address / offset pair
231  *
232  * It allows to address several devices as a continuous memory region
233  * but also to address higher part of eeprom for chips
234  * with more than 2^(addr_width) adressable word.
235  */
eeprom_at24_translate_offset(const struct device * dev,off_t * offset)236 static uint16_t eeprom_at24_translate_offset(const struct device *dev,
237 					     off_t *offset)
238 {
239 	const struct eeprom_at2x_config *config = dev->config;
240 
241 	const uint16_t addr_incr = *offset >> config->addr_width;
242 	*offset &= BIT_MASK(config->addr_width);
243 
244 	return config->bus.i2c.addr + addr_incr;
245 }
246 
eeprom_at24_adjust_read_count(const struct device * dev,off_t offset,size_t len)247 static size_t eeprom_at24_adjust_read_count(const struct device *dev,
248 					    off_t offset, size_t len)
249 {
250 	const struct eeprom_at2x_config *config = dev->config;
251 	const size_t remainder = BIT(config->addr_width) - offset;
252 
253 	if (len > remainder) {
254 		len = remainder;
255 	}
256 
257 	return len;
258 }
259 
eeprom_at24_read(const struct device * dev,off_t offset,void * buf,size_t len)260 static int eeprom_at24_read(const struct device *dev, off_t offset, void *buf,
261 			    size_t len)
262 {
263 	const struct eeprom_at2x_config *config = dev->config;
264 	int64_t timeout;
265 	uint8_t addr[2];
266 	uint16_t bus_addr;
267 	int err;
268 
269 	bus_addr = eeprom_at24_translate_offset(dev, &offset);
270 
271 	if (config->addr_width == 16) {
272 		sys_put_be16(offset, addr);
273 	} else {
274 		addr[0] = offset & BIT_MASK(8);
275 	}
276 
277 	len = eeprom_at24_adjust_read_count(dev, offset, len);
278 
279 	/*
280 	 * A write cycle may be in progress so reads must be attempted
281 	 * until the current write cycle should be completed.
282 	 */
283 	timeout = k_uptime_get() + config->timeout;
284 	while (1) {
285 		int64_t now = k_uptime_get();
286 		err = i2c_write_read(config->bus.i2c.bus, bus_addr,
287 				     addr, config->addr_width / 8,
288 				     buf, len);
289 		if (!err || now > timeout) {
290 			break;
291 		}
292 		k_sleep(K_MSEC(1));
293 	}
294 
295 	if (err < 0) {
296 		return err;
297 	}
298 
299 	return len;
300 }
301 
eeprom_at24_write(const struct device * dev,off_t offset,const void * buf,size_t len)302 static int eeprom_at24_write(const struct device *dev, off_t offset,
303 			     const void *buf, size_t len)
304 {
305 	const struct eeprom_at2x_config *config = dev->config;
306 	int count = eeprom_at2x_limit_write_count(dev, offset, len);
307 	uint8_t block[config->addr_width / 8 + count];
308 	int64_t timeout;
309 	uint16_t bus_addr;
310 	int i = 0;
311 	int err;
312 
313 	bus_addr = eeprom_at24_translate_offset(dev, &offset);
314 
315 	/*
316 	 * Not all I2C EEPROMs support repeated start so the
317 	 * address (offset) and data (buf) must be provided in one
318 	 * write transaction (block).
319 	 */
320 	if (config->addr_width == 16) {
321 		block[i++] = offset >> 8;
322 	}
323 	block[i++] = offset;
324 	memcpy(&block[i], buf, count);
325 
326 	/*
327 	 * A write cycle may already be in progress so writes must be
328 	 * attempted until the previous write cycle should be
329 	 * completed.
330 	 */
331 	timeout = k_uptime_get() + config->timeout;
332 	while (1) {
333 		int64_t now = k_uptime_get();
334 		err = i2c_write(config->bus.i2c.bus, block, sizeof(block),
335 				bus_addr);
336 		if (!err || now > timeout) {
337 			break;
338 		}
339 		k_sleep(K_MSEC(1));
340 	}
341 
342 	if (err < 0) {
343 		return err;
344 	}
345 
346 	return count;
347 }
348 #endif /* CONFIG_EEPROM_AT24 */
349 
350 #ifdef CONFIG_EEPROM_AT25
351 
eeprom_at25_bus_is_ready(const struct device * dev)352 static bool eeprom_at25_bus_is_ready(const struct device *dev)
353 {
354 	const struct eeprom_at2x_config *config = dev->config;
355 
356 	return spi_is_ready_dt(&config->bus.spi);
357 }
358 
eeprom_at25_rdsr(const struct device * dev,uint8_t * status)359 static int eeprom_at25_rdsr(const struct device *dev, uint8_t *status)
360 {
361 	const struct eeprom_at2x_config *config = dev->config;
362 	uint8_t rdsr[2] = { EEPROM_AT25_RDSR, 0 };
363 	uint8_t sr[2];
364 	int err;
365 	const struct spi_buf tx_buf = {
366 		.buf = rdsr,
367 		.len = sizeof(rdsr),
368 	};
369 	const struct spi_buf_set tx = {
370 		.buffers = &tx_buf,
371 		.count = 1,
372 	};
373 	const struct spi_buf rx_buf = {
374 		.buf = sr,
375 		.len = sizeof(sr),
376 	};
377 	const struct spi_buf_set rx = {
378 		.buffers = &rx_buf,
379 		.count = 1,
380 	};
381 
382 	err = spi_transceive_dt(&config->bus.spi, &tx, &rx);
383 	if (!err) {
384 		*status = sr[1];
385 	}
386 
387 	return err;
388 }
389 
eeprom_at25_wait_for_idle(const struct device * dev)390 static int eeprom_at25_wait_for_idle(const struct device *dev)
391 {
392 	const struct eeprom_at2x_config *config = dev->config;
393 	int64_t timeout;
394 	uint8_t status;
395 	int err;
396 
397 	timeout = k_uptime_get() + config->timeout;
398 	while (1) {
399 		int64_t now = k_uptime_get();
400 		err = eeprom_at25_rdsr(dev, &status);
401 		if (err) {
402 			LOG_ERR("Could not read status register (err %d)", err);
403 			return err;
404 		}
405 
406 		if (!(status & EEPROM_AT25_STATUS_WIP)) {
407 			return 0;
408 		}
409 		if (now > timeout) {
410 			break;
411 		}
412 		k_sleep(K_MSEC(1));
413 	}
414 
415 	return -EBUSY;
416 }
417 
eeprom_at25_read(const struct device * dev,off_t offset,void * buf,size_t len)418 static int eeprom_at25_read(const struct device *dev, off_t offset, void *buf,
419 			    size_t len)
420 {
421 	const struct eeprom_at2x_config *config = dev->config;
422 	size_t cmd_len = 1 + config->addr_width / 8;
423 	uint8_t cmd[4] = { EEPROM_AT25_READ, 0, 0, 0 };
424 	uint8_t *paddr;
425 	int err;
426 	const struct spi_buf tx_buf = {
427 		.buf = cmd,
428 		.len = cmd_len,
429 	};
430 	const struct spi_buf_set tx = {
431 		.buffers = &tx_buf,
432 		.count = 1,
433 	};
434 	const struct spi_buf rx_bufs[2] = {
435 		{
436 			.buf = NULL,
437 			.len = cmd_len,
438 		},
439 		{
440 			.buf = buf,
441 			.len = len,
442 		},
443 	};
444 	const struct spi_buf_set rx = {
445 		.buffers = rx_bufs,
446 		.count = ARRAY_SIZE(rx_bufs),
447 	};
448 
449 	if (!len) {
450 		return 0;
451 	}
452 
453 	if ((offset + len) > config->size) {
454 		LOG_WRN("attempt to read past device boundary");
455 		return -EINVAL;
456 	}
457 
458 	paddr = &cmd[1];
459 	switch (config->addr_width) {
460 	case 24:
461 		*paddr++ = offset >> 16;
462 		__fallthrough;
463 	case 16:
464 		*paddr++ = offset >> 8;
465 		__fallthrough;
466 	case 8:
467 		*paddr++ = offset;
468 		break;
469 	default:
470 		__ASSERT(0, "invalid address width");
471 	}
472 
473 	err = eeprom_at25_wait_for_idle(dev);
474 	if (err) {
475 		LOG_ERR("EEPROM idle wait failed (err %d)", err);
476 		return err;
477 	}
478 
479 	err = spi_transceive_dt(&config->bus.spi, &tx, &rx);
480 	if (err < 0) {
481 		return err;
482 	}
483 
484 	return len;
485 }
486 
eeprom_at25_wren(const struct device * dev)487 static int eeprom_at25_wren(const struct device *dev)
488 {
489 	const struct eeprom_at2x_config *config = dev->config;
490 	uint8_t cmd = EEPROM_AT25_WREN;
491 	const struct spi_buf tx_buf = {
492 		.buf = &cmd,
493 		.len = 1,
494 	};
495 	const struct spi_buf_set tx = {
496 		.buffers = &tx_buf,
497 		.count = 1,
498 	};
499 
500 	return spi_write_dt(&config->bus.spi, &tx);
501 }
502 
eeprom_at25_write(const struct device * dev,off_t offset,const void * buf,size_t len)503 static int eeprom_at25_write(const struct device *dev, off_t offset,
504 			     const void *buf, size_t len)
505 {
506 	const struct eeprom_at2x_config *config = dev->config;
507 	int count = eeprom_at2x_limit_write_count(dev, offset, len);
508 	uint8_t cmd[4] = { EEPROM_AT25_WRITE, 0, 0, 0 };
509 	size_t cmd_len = 1 + config->addr_width / 8;
510 	uint8_t *paddr;
511 	int err;
512 	const struct spi_buf tx_bufs[2] = {
513 		{
514 			.buf = cmd,
515 			.len = cmd_len,
516 		},
517 		{
518 			.buf = (void *)buf,
519 			.len = count,
520 		},
521 	};
522 	const struct spi_buf_set tx = {
523 		.buffers = tx_bufs,
524 		.count = ARRAY_SIZE(tx_bufs),
525 	};
526 
527 	paddr = &cmd[1];
528 	switch (config->addr_width) {
529 	case 24:
530 		*paddr++ = offset >> 16;
531 		__fallthrough;
532 	case 16:
533 		*paddr++ = offset >> 8;
534 		__fallthrough;
535 	case 8:
536 		*paddr++ = offset;
537 		break;
538 	default:
539 		__ASSERT(0, "invalid address width");
540 	}
541 
542 	err = eeprom_at25_wait_for_idle(dev);
543 	if (err) {
544 		LOG_ERR("EEPROM idle wait failed (err %d)", err);
545 		return err;
546 	}
547 
548 	err = eeprom_at25_wren(dev);
549 	if (err) {
550 		LOG_ERR("failed to disable write protection (err %d)", err);
551 		return err;
552 	}
553 
554 	err = spi_transceive_dt(&config->bus.spi, &tx, NULL);
555 	if (err) {
556 		return err;
557 	}
558 
559 	return count;
560 }
561 #endif /* CONFIG_EEPROM_AT25 */
562 
eeprom_at2x_init(const struct device * dev)563 static int eeprom_at2x_init(const struct device *dev)
564 {
565 	const struct eeprom_at2x_config *config = dev->config;
566 	struct eeprom_at2x_data *data = dev->data;
567 
568 	k_mutex_init(&data->lock);
569 
570 	if (!config->bus_is_ready(dev)) {
571 		LOG_ERR("parent bus device not ready");
572 		return -EINVAL;
573 	}
574 
575 #if ANY_INST_HAS_WP_GPIOS
576 	if (config->wp_gpio.port) {
577 		int err;
578 		if (!gpio_is_ready_dt(&config->wp_gpio)) {
579 			LOG_ERR("wp gpio device not ready");
580 			return -EINVAL;
581 		}
582 
583 		err = gpio_pin_configure_dt(&config->wp_gpio, GPIO_OUTPUT_ACTIVE);
584 		if (err) {
585 			LOG_ERR("failed to configure WP GPIO pin (err %d)", err);
586 			return err;
587 		}
588 	}
589 #endif /* ANY_INST_HAS_WP_GPIOS */
590 
591 	return 0;
592 }
593 
594 static DEVICE_API(eeprom, eeprom_at2x_api) = {
595 	.read = eeprom_at2x_read,
596 	.write = eeprom_at2x_write,
597 	.size = eeprom_at2x_size,
598 };
599 
600 #define ASSERT_AT24_ADDR_W_VALID(w) \
601 	BUILD_ASSERT(w == 8U || w == 16U,		\
602 		     "Unsupported address width")
603 
604 #define ASSERT_AT25_ADDR_W_VALID(w)			\
605 	BUILD_ASSERT(w == 8U || w == 16U || w == 24U,	\
606 		     "Unsupported address width")
607 
608 #define ASSERT_PAGESIZE_IS_POWER_OF_2(page) \
609 	BUILD_ASSERT((page != 0U) && ((page & (page - 1)) == 0U),	\
610 		     "Page size is not a power of two")
611 
612 #define ASSERT_SIZE_PAGESIZE_VALID(size, page)				\
613 	BUILD_ASSERT(size % page == 0U,					\
614 		     "Size is not an integer multiple of page size")
615 
616 #define INST_DT_AT2X(inst, t) DT_INST(inst, atmel_at##t)
617 
618 #define EEPROM_AT24_BUS(n, t) \
619 	{ .i2c = I2C_DT_SPEC_GET(INST_DT_AT2X(n, t)) }
620 
621 #define EEPROM_AT25_BUS(n, t)						 \
622 	{ .spi = SPI_DT_SPEC_GET(INST_DT_AT2X(n, t),			 \
623 				 SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \
624 				 SPI_WORD_SET(8), 0) }
625 
626 #define EEPROM_AT2X_WP_GPIOS(id)					\
627 	IF_ENABLED(DT_NODE_HAS_PROP(id, wp_gpios),			\
628 		   (.wp_gpio = GPIO_DT_SPEC_GET(id, wp_gpios),))
629 
630 #define EEPROM_AT2X_DEVICE(n, t) \
631 	ASSERT_PAGESIZE_IS_POWER_OF_2(DT_PROP(INST_DT_AT2X(n, t), pagesize)); \
632 	ASSERT_SIZE_PAGESIZE_VALID(DT_PROP(INST_DT_AT2X(n, t), size), \
633 				   DT_PROP(INST_DT_AT2X(n, t), pagesize)); \
634 	ASSERT_AT##t##_ADDR_W_VALID(DT_PROP(INST_DT_AT2X(n, t), \
635 					    address_width)); \
636 	static const struct eeprom_at2x_config eeprom_at##t##_config_##n = { \
637 		.bus = EEPROM_AT##t##_BUS(n, t), \
638 		EEPROM_AT2X_WP_GPIOS(INST_DT_AT2X(n, t)) \
639 		.size = DT_PROP(INST_DT_AT2X(n, t), size), \
640 		.pagesize = DT_PROP(INST_DT_AT2X(n, t), pagesize), \
641 		.addr_width = DT_PROP(INST_DT_AT2X(n, t), address_width), \
642 		.readonly = DT_PROP(INST_DT_AT2X(n, t), read_only), \
643 		.timeout = DT_PROP(INST_DT_AT2X(n, t), timeout), \
644 		.bus_is_ready = eeprom_at##t##_bus_is_ready, \
645 		.read_fn = eeprom_at##t##_read, \
646 		.write_fn = eeprom_at##t##_write, \
647 	}; \
648 	static struct eeprom_at2x_data eeprom_at##t##_data_##n; \
649 	DEVICE_DT_DEFINE(INST_DT_AT2X(n, t), eeprom_at2x_init, \
650 			    NULL, &eeprom_at##t##_data_##n, \
651 			    &eeprom_at##t##_config_##n, POST_KERNEL, \
652 			    CONFIG_EEPROM_AT2X_INIT_PRIORITY, \
653 			    &eeprom_at2x_api)
654 
655 #define EEPROM_AT24_DEVICE(n) EEPROM_AT2X_DEVICE(n, 24)
656 #define EEPROM_AT25_DEVICE(n) EEPROM_AT2X_DEVICE(n, 25)
657 
658 #define CALL_WITH_ARG(arg, expr) expr(arg);
659 
660 #define INST_DT_AT2X_FOREACH(t, inst_expr) \
661 	LISTIFY(DT_NUM_INST_STATUS_OKAY(atmel_at##t),	\
662 		CALL_WITH_ARG, (), inst_expr)
663 
664 #ifdef CONFIG_EEPROM_AT24
665 INST_DT_AT2X_FOREACH(24, EEPROM_AT24_DEVICE);
666 #endif
667 
668 #ifdef CONFIG_EEPROM_AT25
669 INST_DT_AT2X_FOREACH(25, EEPROM_AT25_DEVICE);
670 #endif
671