1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <drivers/flash.h>
8 #include <drivers/spi.h>
9 #include <sys/byteorder.h>
10 #include <logging/log.h>
11
12 LOG_MODULE_REGISTER(spi_flash_at45, CONFIG_FLASH_LOG_LEVEL);
13
14 #define DT_DRV_COMPAT atmel_at45
15
16 /* AT45 commands used by this driver: */
17 /* - Continuous Array Read (Low Power Mode) */
18 #define CMD_READ 0x01
19 /* - Main Memory Byte/Page Program through Buffer 1 without Built-In Erase */
20 #define CMD_WRITE 0x02
21 /* - Read-Modify-Write */
22 #define CMD_MODIFY 0x58
23 /* - Manufacturer and Device ID Read */
24 #define CMD_READ_ID 0x9F
25 /* - Status Register Read */
26 #define CMD_READ_STATUS 0xD7
27 /* - Chip Erase */
28 #define CMD_CHIP_ERASE { 0xC7, 0x94, 0x80, 0x9A }
29 /* - Sector Erase */
30 #define CMD_SECTOR_ERASE 0x7C
31 /* - Block Erase */
32 #define CMD_BLOCK_ERASE 0x50
33 /* - Page Erase */
34 #define CMD_PAGE_ERASE 0x81
35 /* - Deep Power-Down */
36 #define CMD_ENTER_DPD 0xB9
37 /* - Resume from Deep Power-Down */
38 #define CMD_EXIT_DPD 0xAB
39 /* - Ultra-Deep Power-Down */
40 #define CMD_ENTER_UDPD 0x79
41 /* - Buffer and Page Size Configuration, "Power of 2" binary page size */
42 #define CMD_BINARY_PAGE_SIZE { 0x3D, 0x2A, 0x80, 0xA6 }
43
44 #define STATUS_REG_LSB_RDY_BUSY_BIT 0x80
45 #define STATUS_REG_LSB_PAGE_SIZE_BIT 0x01
46
47 #define INST_HAS_WP_OR(inst) DT_INST_NODE_HAS_PROP(inst, wp_gpios) ||
48 #define ANY_INST_HAS_WP_GPIOS DT_INST_FOREACH_STATUS_OKAY(INST_HAS_WP_OR) 0
49
50 #define INST_HAS_RESET_OR(inst) DT_INST_NODE_HAS_PROP(inst, reset_gpios) ||
51 #define ANY_INST_HAS_RESET_GPIOS DT_INST_FOREACH_STATUS_OKAY(INST_HAS_RESET_OR) 0
52
53 #define DEF_BUF_SET(_name, _buf_array) \
54 const struct spi_buf_set _name = { \
55 .buffers = _buf_array, \
56 .count = ARRAY_SIZE(_buf_array), \
57 }
58
59 struct spi_flash_at45_data {
60 const struct device *spi;
61 struct spi_cs_control spi_cs;
62 struct k_sem lock;
63 };
64
65 struct spi_flash_at45_config {
66 const char *spi_bus;
67 struct spi_config spi_cfg;
68 const char *cs_gpio;
69 gpio_pin_t cs_pin;
70 gpio_dt_flags_t cs_dt_flags;
71 #if ANY_INST_HAS_RESET_GPIOS
72 const struct gpio_dt_spec *reset;
73 #endif
74 #if ANY_INST_HAS_WP_GPIOS
75 const struct gpio_dt_spec *wp;
76 #endif
77 #if IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT)
78 struct flash_pages_layout pages_layout;
79 #endif
80 uint32_t chip_size;
81 uint32_t sector_size;
82 uint16_t block_size;
83 uint16_t page_size;
84 uint16_t t_enter_dpd; /* in microseconds */
85 uint16_t t_exit_dpd; /* in microseconds */
86 bool use_udpd;
87 uint8_t jedec_id[3];
88 };
89
90 static const struct flash_parameters flash_at45_parameters = {
91 .write_block_size = 1,
92 .erase_value = 0xff,
93 };
94
get_dev_data(const struct device * dev)95 static struct spi_flash_at45_data *get_dev_data(const struct device *dev)
96 {
97 return dev->data;
98 }
99
get_dev_config(const struct device * dev)100 static const struct spi_flash_at45_config *get_dev_config(const struct device *dev)
101 {
102 return dev->config;
103 }
104
acquire(const struct device * dev)105 static void acquire(const struct device *dev)
106 {
107 k_sem_take(&get_dev_data(dev)->lock, K_FOREVER);
108 }
109
release(const struct device * dev)110 static void release(const struct device *dev)
111 {
112 k_sem_give(&get_dev_data(dev)->lock);
113 }
114
check_jedec_id(const struct device * dev)115 static int check_jedec_id(const struct device *dev)
116 {
117 const struct spi_flash_at45_config *cfg = get_dev_config(dev);
118 int err;
119 uint8_t const *expected_id = cfg->jedec_id;
120 uint8_t read_id[sizeof(cfg->jedec_id)];
121 const uint8_t opcode = CMD_READ_ID;
122 const struct spi_buf tx_buf[] = {
123 {
124 .buf = (void *)&opcode,
125 .len = sizeof(opcode),
126 }
127 };
128 const struct spi_buf rx_buf[] = {
129 {
130 .len = sizeof(opcode),
131 },
132 {
133 .buf = read_id,
134 .len = sizeof(read_id),
135 }
136 };
137 DEF_BUF_SET(tx_buf_set, tx_buf);
138 DEF_BUF_SET(rx_buf_set, rx_buf);
139
140 err = spi_transceive(get_dev_data(dev)->spi,
141 &cfg->spi_cfg,
142 &tx_buf_set, &rx_buf_set);
143 if (err != 0) {
144 LOG_ERR("SPI transaction failed with code: %d/%u",
145 err, __LINE__);
146 return -EIO;
147 }
148
149 if (memcmp(expected_id, read_id, sizeof(read_id)) != 0) {
150 LOG_ERR("Wrong JEDEC ID: %02X %02X %02X, "
151 "expected: %02X %02X %02X",
152 read_id[0], read_id[1], read_id[2],
153 expected_id[0], expected_id[1], expected_id[2]);
154 return -ENODEV;
155 }
156
157 return 0;
158 }
159
160 /*
161 * Reads 2-byte Status Register:
162 * - Byte 0 to LSB
163 * - Byte 1 to MSB
164 * of the pointed parameter.
165 */
read_status_register(const struct device * dev,uint16_t * status)166 static int read_status_register(const struct device *dev, uint16_t *status)
167 {
168 int err;
169 const uint8_t opcode = CMD_READ_STATUS;
170 const struct spi_buf tx_buf[] = {
171 {
172 .buf = (void *)&opcode,
173 .len = sizeof(opcode),
174 }
175 };
176 const struct spi_buf rx_buf[] = {
177 {
178 .len = sizeof(opcode),
179 },
180 {
181 .buf = status,
182 .len = sizeof(uint16_t),
183 }
184 };
185 DEF_BUF_SET(tx_buf_set, tx_buf);
186 DEF_BUF_SET(rx_buf_set, rx_buf);
187
188 err = spi_transceive(get_dev_data(dev)->spi,
189 &get_dev_config(dev)->spi_cfg,
190 &tx_buf_set, &rx_buf_set);
191 if (err != 0) {
192 LOG_ERR("SPI transaction failed with code: %d/%u",
193 err, __LINE__);
194 return -EIO;
195 }
196
197 *status = sys_le16_to_cpu(*status);
198 return 0;
199 }
200
wait_until_ready(const struct device * dev)201 static int wait_until_ready(const struct device *dev)
202 {
203 int err;
204 uint16_t status;
205
206 do {
207 err = read_status_register(dev, &status);
208 } while (err == 0 && !(status & STATUS_REG_LSB_RDY_BUSY_BIT));
209
210 return err;
211 }
212
configure_page_size(const struct device * dev)213 static int configure_page_size(const struct device *dev)
214 {
215 int err;
216 uint16_t status;
217 uint8_t const conf_binary_page_size[] = CMD_BINARY_PAGE_SIZE;
218 const struct spi_buf tx_buf[] = {
219 {
220 .buf = (void *)conf_binary_page_size,
221 .len = sizeof(conf_binary_page_size),
222 }
223 };
224 DEF_BUF_SET(tx_buf_set, tx_buf);
225
226 err = read_status_register(dev, &status);
227 if (err != 0) {
228 return err;
229 }
230
231 /* If the device is already configured for "power of 2" binary
232 * page size, there is nothing more to do.
233 */
234 if (status & STATUS_REG_LSB_PAGE_SIZE_BIT) {
235 return 0;
236 }
237
238 err = spi_write(get_dev_data(dev)->spi,
239 &get_dev_config(dev)->spi_cfg,
240 &tx_buf_set);
241 if (err != 0) {
242 LOG_ERR("SPI transaction failed with code: %d/%u",
243 err, __LINE__);
244 } else {
245 err = wait_until_ready(dev);
246 }
247
248 return (err != 0) ? -EIO : 0;
249 }
250
is_valid_request(off_t addr,size_t size,size_t chip_size)251 static bool is_valid_request(off_t addr, size_t size, size_t chip_size)
252 {
253 return (addr >= 0 && (addr + size) <= chip_size);
254 }
255
spi_flash_at45_read(const struct device * dev,off_t offset,void * data,size_t len)256 static int spi_flash_at45_read(const struct device *dev, off_t offset,
257 void *data, size_t len)
258 {
259 const struct spi_flash_at45_config *cfg = get_dev_config(dev);
260 int err;
261
262 if (!is_valid_request(offset, len, cfg->chip_size)) {
263 return -ENODEV;
264 }
265
266 uint8_t const op_and_addr[] = {
267 CMD_READ,
268 (offset >> 16) & 0xFF,
269 (offset >> 8) & 0xFF,
270 (offset >> 0) & 0xFF,
271 };
272 const struct spi_buf tx_buf[] = {
273 {
274 .buf = (void *)&op_and_addr,
275 .len = sizeof(op_and_addr),
276 }
277 };
278 const struct spi_buf rx_buf[] = {
279 {
280 .len = sizeof(op_and_addr),
281 },
282 {
283 .buf = data,
284 .len = len,
285 }
286 };
287 DEF_BUF_SET(tx_buf_set, tx_buf);
288 DEF_BUF_SET(rx_buf_set, rx_buf);
289
290 acquire(dev);
291 err = spi_transceive(get_dev_data(dev)->spi,
292 &cfg->spi_cfg,
293 &tx_buf_set, &rx_buf_set);
294 release(dev);
295
296 if (err != 0) {
297 LOG_ERR("SPI transaction failed with code: %d/%u",
298 err, __LINE__);
299 }
300
301 return (err != 0) ? -EIO : 0;
302 }
303
perform_write(const struct device * dev,off_t offset,const void * data,size_t len)304 static int perform_write(const struct device *dev, off_t offset,
305 const void *data, size_t len)
306 {
307 int err;
308 uint8_t const op_and_addr[] = {
309 IS_ENABLED(CONFIG_SPI_FLASH_AT45_USE_READ_MODIFY_WRITE)
310 ? CMD_MODIFY
311 : CMD_WRITE,
312 (offset >> 16) & 0xFF,
313 (offset >> 8) & 0xFF,
314 (offset >> 0) & 0xFF,
315 };
316 const struct spi_buf tx_buf[] = {
317 {
318 .buf = (void *)&op_and_addr,
319 .len = sizeof(op_and_addr),
320 },
321 {
322 .buf = (void *)data,
323 .len = len,
324 }
325 };
326 DEF_BUF_SET(tx_buf_set, tx_buf);
327
328 err = spi_write(get_dev_data(dev)->spi,
329 &get_dev_config(dev)->spi_cfg,
330 &tx_buf_set);
331 if (err != 0) {
332 LOG_ERR("SPI transaction failed with code: %d/%u",
333 err, __LINE__);
334 } else {
335 err = wait_until_ready(dev);
336 }
337
338 return (err != 0) ? -EIO : 0;
339 }
340
spi_flash_at45_write(const struct device * dev,off_t offset,const void * data,size_t len)341 static int spi_flash_at45_write(const struct device *dev, off_t offset,
342 const void *data, size_t len)
343 {
344 const struct spi_flash_at45_config *cfg = get_dev_config(dev);
345 int err = 0;
346
347 if (!is_valid_request(offset, len, cfg->chip_size)) {
348 return -ENODEV;
349 }
350
351 acquire(dev);
352
353 #if ANY_INST_HAS_WP_GPIOS
354 if (cfg->wp) {
355 gpio_pin_set(cfg->wp->port, cfg->wp->pin, 0);
356 }
357 #endif
358
359 while (len) {
360 size_t chunk_len = len;
361 off_t current_page_start =
362 offset - (offset & (cfg->page_size - 1));
363 off_t current_page_end = current_page_start + cfg->page_size;
364
365 if (chunk_len > (current_page_end - offset)) {
366 chunk_len = (current_page_end - offset);
367 }
368
369 err = perform_write(dev, offset, data, chunk_len);
370 if (err != 0) {
371 break;
372 }
373
374 data = (uint8_t *)data + chunk_len;
375 offset += chunk_len;
376 len -= chunk_len;
377 }
378
379 #if ANY_INST_HAS_WP_GPIOS
380 if (cfg->wp) {
381 gpio_pin_set(cfg->wp->port, cfg->wp->pin, 1);
382 }
383 #endif
384
385 release(dev);
386
387 return err;
388 }
389
perform_chip_erase(const struct device * dev)390 static int perform_chip_erase(const struct device *dev)
391 {
392 int err;
393 uint8_t const chip_erase_cmd[] = CMD_CHIP_ERASE;
394 const struct spi_buf tx_buf[] = {
395 {
396 .buf = (void *)&chip_erase_cmd,
397 .len = sizeof(chip_erase_cmd),
398 }
399 };
400 DEF_BUF_SET(tx_buf_set, tx_buf);
401
402 err = spi_write(get_dev_data(dev)->spi,
403 &get_dev_config(dev)->spi_cfg,
404 &tx_buf_set);
405 if (err != 0) {
406 LOG_ERR("SPI transaction failed with code: %d/%u",
407 err, __LINE__);
408 } else {
409 err = wait_until_ready(dev);
410 }
411
412 return (err != 0) ? -EIO : 0;
413 }
414
is_erase_possible(size_t entity_size,off_t offset,size_t requested_size)415 static bool is_erase_possible(size_t entity_size,
416 off_t offset, size_t requested_size)
417 {
418 return (requested_size >= entity_size &&
419 (offset & (entity_size - 1)) == 0);
420 }
421
perform_erase_op(const struct device * dev,uint8_t opcode,off_t offset)422 static int perform_erase_op(const struct device *dev, uint8_t opcode,
423 off_t offset)
424 {
425 int err;
426 uint8_t const op_and_addr[] = {
427 opcode,
428 (offset >> 16) & 0xFF,
429 (offset >> 8) & 0xFF,
430 (offset >> 0) & 0xFF,
431 };
432 const struct spi_buf tx_buf[] = {
433 {
434 .buf = (void *)&op_and_addr,
435 .len = sizeof(op_and_addr),
436 }
437 };
438 DEF_BUF_SET(tx_buf_set, tx_buf);
439
440 err = spi_write(get_dev_data(dev)->spi,
441 &get_dev_config(dev)->spi_cfg,
442 &tx_buf_set);
443 if (err != 0) {
444 LOG_ERR("SPI transaction failed with code: %d/%u",
445 err, __LINE__);
446 } else {
447 err = wait_until_ready(dev);
448 }
449
450 return (err != 0) ? -EIO : 0;
451 }
452
spi_flash_at45_erase(const struct device * dev,off_t offset,size_t size)453 static int spi_flash_at45_erase(const struct device *dev, off_t offset,
454 size_t size)
455 {
456 const struct spi_flash_at45_config *cfg = get_dev_config(dev);
457 int err = 0;
458
459 if (!is_valid_request(offset, size, cfg->chip_size)) {
460 return -ENODEV;
461 }
462
463 /* Diagnose region errors before starting to erase. */
464 if (((offset % cfg->page_size) != 0)
465 || ((size % cfg->page_size) != 0)) {
466 return -EINVAL;
467 }
468
469 acquire(dev);
470
471 #if ANY_INST_HAS_WP_GPIOS
472 if (cfg->wp) {
473 gpio_pin_set(cfg->wp->port, cfg->wp->pin, 0);
474 }
475 #endif
476
477 if (size == cfg->chip_size) {
478 err = perform_chip_erase(dev);
479 } else {
480 while (size) {
481 if (is_erase_possible(cfg->sector_size,
482 offset, size)) {
483 err = perform_erase_op(dev, CMD_SECTOR_ERASE,
484 offset);
485 offset += cfg->sector_size;
486 size -= cfg->sector_size;
487 } else if (is_erase_possible(cfg->block_size,
488 offset, size)) {
489 err = perform_erase_op(dev, CMD_BLOCK_ERASE,
490 offset);
491 offset += cfg->block_size;
492 size -= cfg->block_size;
493 } else if (is_erase_possible(cfg->page_size,
494 offset, size)) {
495 err = perform_erase_op(dev, CMD_PAGE_ERASE,
496 offset);
497 offset += cfg->page_size;
498 size -= cfg->page_size;
499 } else {
500 LOG_ERR("Unsupported erase request: "
501 "size %zu at 0x%lx",
502 size, (long)offset);
503 err = -EINVAL;
504 }
505
506 if (err != 0) {
507 break;
508 }
509 }
510 }
511
512 #if ANY_INST_HAS_WP_GPIOS
513 if (cfg->wp) {
514 gpio_pin_set(cfg->wp->port, cfg->wp->pin, 1);
515 }
516 #endif
517
518 release(dev);
519
520 return err;
521 }
522
523 #if IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT)
spi_flash_at45_pages_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)524 static void spi_flash_at45_pages_layout(const struct device *dev,
525 const struct flash_pages_layout **layout,
526 size_t *layout_size)
527 {
528 *layout = &get_dev_config(dev)->pages_layout;
529 *layout_size = 1;
530 }
531 #endif /* IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT) */
532
power_down_op(const struct device * dev,uint8_t opcode,uint32_t delay)533 static int power_down_op(const struct device *dev, uint8_t opcode,
534 uint32_t delay)
535 {
536 int err = 0;
537 const struct spi_buf tx_buf[] = {
538 {
539 .buf = (void *)&opcode,
540 .len = sizeof(opcode),
541 }
542 };
543 DEF_BUF_SET(tx_buf_set, tx_buf);
544
545 err = spi_write(get_dev_data(dev)->spi,
546 &get_dev_config(dev)->spi_cfg,
547 &tx_buf_set);
548 if (err != 0) {
549 LOG_ERR("SPI transaction failed with code: %d/%u",
550 err, __LINE__);
551 return -EIO;
552 }
553
554
555 k_busy_wait(delay);
556 return 0;
557 }
558
spi_flash_at45_init(const struct device * dev)559 static int spi_flash_at45_init(const struct device *dev)
560 {
561 struct spi_flash_at45_data *dev_data = get_dev_data(dev);
562 const struct spi_flash_at45_config *dev_config = get_dev_config(dev);
563 int err;
564
565 dev_data->spi = device_get_binding(dev_config->spi_bus);
566 if (!dev_data->spi) {
567 LOG_ERR("Cannot find %s", dev_config->spi_bus);
568 return -ENODEV;
569 }
570
571 #if ANY_INST_HAS_RESET_GPIOS
572 if (dev_config->reset) {
573 if (gpio_pin_configure_dt(dev_config->reset,
574 GPIO_OUTPUT_ACTIVE)) {
575 LOG_ERR("Couldn't configure reset pin");
576 return -ENODEV;
577 }
578 gpio_pin_set(dev_config->reset->port, dev_config->reset->pin, 0);
579 }
580 #endif
581
582 #if ANY_INST_HAS_WP_GPIOS
583 if (dev_config->wp) {
584 if (gpio_pin_configure_dt(dev_config->wp,
585 GPIO_OUTPUT_ACTIVE)) {
586 LOG_ERR("Couldn't configure write protect pin");
587 return -ENODEV;
588 }
589 gpio_pin_set(dev_config->wp->port, dev_config->wp->pin, 1);
590 }
591 #endif
592
593 if (dev_config->cs_gpio) {
594 dev_data->spi_cs.gpio_dev =
595 device_get_binding(dev_config->cs_gpio);
596 if (!dev_data->spi_cs.gpio_dev) {
597 LOG_ERR("Cannot find %s", dev_config->cs_gpio);
598 return -ENODEV;
599 }
600
601 dev_data->spi_cs.gpio_pin = dev_config->cs_pin;
602 dev_data->spi_cs.gpio_dt_flags = dev_config->cs_dt_flags;
603 dev_data->spi_cs.delay = 0;
604 }
605
606 acquire(dev);
607
608 /* Just in case the chip was in the Deep (or Ultra-Deep) Power-Down
609 * mode, issue the command to bring it back to normal operation.
610 * Exiting from the Ultra-Deep mode requires only that the CS line
611 * is asserted for a certain time, so issuing the Resume from Deep
612 * Power-Down command will work in both cases.
613 */
614 power_down_op(dev, CMD_EXIT_DPD, dev_config->t_exit_dpd);
615
616 err = check_jedec_id(dev);
617 if (err == 0) {
618 err = configure_page_size(dev);
619 }
620
621 release(dev);
622
623 return err;
624 }
625
626 #if IS_ENABLED(CONFIG_PM_DEVICE)
spi_flash_at45_pm_control(const struct device * dev,enum pm_device_action action)627 static int spi_flash_at45_pm_control(const struct device *dev,
628 enum pm_device_action action)
629 {
630 const struct spi_flash_at45_config *dev_config = get_dev_config(dev);
631
632 switch (action) {
633 case PM_DEVICE_ACTION_RESUME:
634 acquire(dev);
635 power_down_op(dev, CMD_EXIT_DPD, dev_config->t_exit_dpd);
636 release(dev);
637 break;
638
639 case PM_DEVICE_ACTION_SUSPEND:
640 acquire(dev);
641 power_down_op(dev,
642 dev_config->use_udpd ? CMD_ENTER_UDPD : CMD_ENTER_DPD,
643 dev_config->t_enter_dpd);
644 release(dev);
645 break;
646
647 default:
648 return -ENOTSUP;
649 }
650
651 return 0;
652 }
653 #endif /* IS_ENABLED(CONFIG_PM_DEVICE) */
654
655 static const struct flash_parameters *
flash_at45_get_parameters(const struct device * dev)656 flash_at45_get_parameters(const struct device *dev)
657 {
658 ARG_UNUSED(dev);
659
660 return &flash_at45_parameters;
661 }
662
663 static const struct flash_driver_api spi_flash_at45_api = {
664 .read = spi_flash_at45_read,
665 .write = spi_flash_at45_write,
666 .erase = spi_flash_at45_erase,
667 .get_parameters = flash_at45_get_parameters,
668 #if IS_ENABLED(CONFIG_FLASH_PAGE_LAYOUT)
669 .page_layout = spi_flash_at45_pages_layout,
670 #endif
671 };
672
673 #define INST_HAS_RESET_GPIO(idx) \
674 DT_NODE_HAS_PROP(DT_DRV_INST(idx), reset_gpios)
675
676 #define INST_RESET_GPIO_SPEC(idx) \
677 IF_ENABLED(INST_HAS_RESET_GPIO(idx), \
678 (static const struct gpio_dt_spec reset_##idx = \
679 GPIO_DT_SPEC_GET(DT_DRV_INST(idx), reset_gpios);))
680
681 #define INST_HAS_WP_GPIO(idx) \
682 DT_NODE_HAS_PROP(DT_DRV_INST(idx), wp_gpios)
683
684 #define INST_WP_GPIO_SPEC(idx) \
685 IF_ENABLED(INST_HAS_WP_GPIO(idx), \
686 (static const struct gpio_dt_spec wp_##idx = \
687 GPIO_DT_SPEC_GET(DT_DRV_INST(idx), wp_gpios);))
688
689 #define SPI_FLASH_AT45_INST(idx) \
690 enum { \
691 INST_##idx##_BYTES = (DT_INST_PROP(idx, size) / 8), \
692 INST_##idx##_PAGES = (INST_##idx##_BYTES / \
693 DT_INST_PROP(idx, page_size)), \
694 }; \
695 static struct spi_flash_at45_data inst_##idx##_data = { \
696 .lock = Z_SEM_INITIALIZER(inst_##idx##_data.lock, 1, 1), \
697 }; \
698 INST_RESET_GPIO_SPEC(idx) \
699 INST_WP_GPIO_SPEC(idx) \
700 static const struct spi_flash_at45_config inst_##idx##_config = { \
701 .spi_bus = DT_INST_BUS_LABEL(idx), \
702 .spi_cfg = { \
703 .frequency = DT_INST_PROP(idx, spi_max_frequency), \
704 .operation = SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | \
705 SPI_WORD_SET(8) | SPI_LINES_SINGLE, \
706 .slave = DT_INST_REG_ADDR(idx), \
707 .cs = &inst_##idx##_data.spi_cs, \
708 }, \
709 IF_ENABLED(DT_INST_SPI_DEV_HAS_CS_GPIOS(idx), ( \
710 .cs_gpio = DT_INST_SPI_DEV_CS_GPIOS_LABEL(idx), \
711 .cs_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(idx), \
712 .cs_dt_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(idx),)) \
713 IF_ENABLED(INST_HAS_RESET_GPIO(idx), \
714 (.reset = &reset_##idx,)) \
715 IF_ENABLED(INST_HAS_WP_GPIO(idx), \
716 (.wp = &wp_##idx,)) \
717 IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT, ( \
718 .pages_layout = { \
719 .pages_count = INST_##idx##_PAGES, \
720 .pages_size = DT_INST_PROP(idx, page_size), \
721 },)) \
722 .chip_size = INST_##idx##_BYTES, \
723 .sector_size = DT_INST_PROP(idx, sector_size), \
724 .block_size = DT_INST_PROP(idx, block_size), \
725 .page_size = DT_INST_PROP(idx, page_size), \
726 .t_enter_dpd = ceiling_fraction( \
727 DT_INST_PROP(idx, enter_dpd_delay), \
728 NSEC_PER_USEC), \
729 .t_exit_dpd = ceiling_fraction( \
730 DT_INST_PROP(idx, exit_dpd_delay), \
731 NSEC_PER_USEC), \
732 .use_udpd = DT_INST_PROP(idx, use_udpd), \
733 .jedec_id = DT_INST_PROP(idx, jedec_id), \
734 }; \
735 IF_ENABLED(CONFIG_FLASH_PAGE_LAYOUT, ( \
736 BUILD_ASSERT( \
737 (INST_##idx##_PAGES * DT_INST_PROP(idx, page_size)) \
738 == INST_##idx##_BYTES, \
739 "Page size specified for instance " #idx " of " \
740 "atmel,at45 is not compatible with its " \
741 "total size");)) \
742 DEVICE_DT_INST_DEFINE(idx, \
743 spi_flash_at45_init, spi_flash_at45_pm_control, \
744 &inst_##idx##_data, &inst_##idx##_config, \
745 POST_KERNEL, CONFIG_SPI_FLASH_AT45_INIT_PRIORITY, \
746 &spi_flash_at45_api);
747
748 DT_INST_FOREACH_STATUS_OKAY(SPI_FLASH_AT45_INST)
749