1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <boot_device.h>
4 #include <spi_flash.h>
5 #include <spi-generic.h>
6 #include <stdint.h>
7
8 static struct spi_flash sfg;
9 static bool sfg_init_done;
10
spi_readat(const struct region_device * rd,void * b,size_t offset,size_t size)11 static ssize_t spi_readat(const struct region_device *rd, void *b,
12 size_t offset, size_t size)
13 {
14 if (spi_flash_read(&sfg, offset, size, b))
15 return -1;
16
17 return size;
18 }
19
spi_writeat(const struct region_device * rd,const void * b,size_t offset,size_t size)20 static ssize_t spi_writeat(const struct region_device *rd, const void *b,
21 size_t offset, size_t size)
22 {
23 if (spi_flash_write(&sfg, offset, size, b))
24 return -1;
25
26 return size;
27 }
28
spi_eraseat(const struct region_device * rd,size_t offset,size_t size)29 static ssize_t spi_eraseat(const struct region_device *rd,
30 size_t offset, size_t size)
31 {
32 if (spi_flash_erase(&sfg, offset, size))
33 return -1;
34
35 return size;
36 }
37
38 static const struct region_device_ops spi_ops = {
39 .readat = spi_readat,
40 .writeat = spi_writeat,
41 .eraseat = spi_eraseat,
42 };
43
44 static const struct region_device spi_rw =
45 REGION_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
46
boot_device_rw_init(void)47 static void boot_device_rw_init(void)
48 {
49 const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
50 const int cs = 0;
51
52 if (sfg_init_done == true)
53 return;
54
55 /* Ensure any necessary setup is performed by the drivers. */
56 spi_init();
57
58 if (!spi_flash_probe(bus, cs, &sfg))
59 sfg_init_done = true;
60 }
61
boot_device_rw(void)62 const struct region_device *boot_device_rw(void)
63 {
64 /* Probe for the SPI flash device if not already done. */
65 boot_device_rw_init();
66
67 if (sfg_init_done != true)
68 return NULL;
69
70 return &spi_rw;
71 }
72
boot_device_spi_flash(void)73 const struct spi_flash *boot_device_spi_flash(void)
74 {
75 boot_device_rw_init();
76
77 if (sfg_init_done != true)
78 return NULL;
79
80 return &sfg;
81 }
82
boot_device_wp_region(const struct region_device * rd,const enum bootdev_prot_type type)83 int boot_device_wp_region(const struct region_device *rd,
84 const enum bootdev_prot_type type)
85 {
86 uint32_t ctrlr_pr;
87
88 /* Ensure boot device has been initialized at least once. */
89 boot_device_init();
90
91 const struct spi_flash *boot_dev = boot_device_spi_flash();
92
93 if (boot_dev == NULL)
94 return -1;
95
96 if (type == MEDIA_WP) {
97 if (spi_flash_is_write_protected(boot_dev,
98 region_device_region(rd)) != 1) {
99 enum spi_flash_status_reg_lockdown lock =
100 SPI_WRITE_PROTECTION_REBOOT;
101 if (CONFIG(BOOTMEDIA_SPI_LOCK_REBOOT))
102 lock = SPI_WRITE_PROTECTION_REBOOT;
103 else if (CONFIG(BOOTMEDIA_SPI_LOCK_PIN))
104 lock = SPI_WRITE_PROTECTION_PIN;
105 else if (CONFIG(BOOTMEDIA_SPI_LOCK_PERMANENT))
106 lock = SPI_WRITE_PROTECTION_PERMANENT;
107
108 return spi_flash_set_write_protected(boot_dev,
109 region_device_region(rd), lock);
110 }
111
112 /* Already write protected */
113 return 0;
114 }
115
116 switch (type) {
117 case CTRLR_WP:
118 ctrlr_pr = WRITE_PROTECT;
119 break;
120 case CTRLR_RP:
121 ctrlr_pr = READ_PROTECT;
122 break;
123 case CTRLR_RWP:
124 ctrlr_pr = READ_WRITE_PROTECT;
125 break;
126 default:
127 return -1;
128 }
129
130 return spi_flash_ctrlr_protect_region(boot_dev,
131 region_device_region(rd), ctrlr_pr);
132 }
133