blob: 58efc87fe9cbf0f98f8320cca26b315762c1d02c [file] [log] [blame]
Angel Pons8a3453f2020-04-02 23:48:19 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin6f115592016-08-11 18:24:54 -05002
Aaron Durbin6f115592016-08-11 18:24:54 -05003#include <boot_device.h>
4#include <spi_flash.h>
Furquan Shaikhc28984d2016-11-20 21:04:00 -08005#include <spi-generic.h>
Furquan Shaikh30221b42017-05-15 14:35:15 -07006#include <stdint.h>
Aaron Durbin6f115592016-08-11 18:24:54 -05007
Arthur Heymansd20b0a82019-11-20 22:00:57 +01008static struct spi_flash sfg;
9static bool sfg_init_done;
Aaron Durbin6f115592016-08-11 18:24:54 -050010
11static ssize_t spi_readat(const struct region_device *rd, void *b,
12 size_t offset, size_t size)
13{
Arthur Heymansd20b0a82019-11-20 22:00:57 +010014 if (spi_flash_read(&sfg, offset, size, b))
Aaron Durbin6f115592016-08-11 18:24:54 -050015 return -1;
16
17 return size;
18}
19
20static ssize_t spi_writeat(const struct region_device *rd, const void *b,
21 size_t offset, size_t size)
22{
Arthur Heymansd20b0a82019-11-20 22:00:57 +010023 if (spi_flash_write(&sfg, offset, size, b))
Aaron Durbin6f115592016-08-11 18:24:54 -050024 return -1;
25
26 return size;
27}
28
29static ssize_t spi_eraseat(const struct region_device *rd,
30 size_t offset, size_t size)
31{
Arthur Heymansd20b0a82019-11-20 22:00:57 +010032 if (spi_flash_erase(&sfg, offset, size))
Aaron Durbin6f115592016-08-11 18:24:54 -050033 return -1;
34
35 return size;
36}
37
38static const struct region_device_ops spi_ops = {
39 .readat = spi_readat,
40 .writeat = spi_writeat,
41 .eraseat = spi_eraseat,
42};
43
44static const struct region_device spi_rw =
45 REGION_DEV_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
46
Aaron Durbin67e4df82016-08-23 08:45:55 -050047static void boot_device_rw_init(void)
Aaron Durbin6f115592016-08-11 18:24:54 -050048{
49 const int bus = CONFIG_BOOT_DEVICE_SPI_FLASH_BUS;
50 const int cs = 0;
51
Arthur Heymansd20b0a82019-11-20 22:00:57 +010052 if (sfg_init_done == true)
Aaron Durbin6f115592016-08-11 18:24:54 -050053 return;
54
Aaron Durbindf76f892016-08-22 17:41:13 -050055 /* Ensure any necessary setup is performed by the drivers. */
56 spi_init();
57
Arthur Heymansd20b0a82019-11-20 22:00:57 +010058 if (!spi_flash_probe(bus, cs, &sfg))
59 sfg_init_done = true;
Aaron Durbin6f115592016-08-11 18:24:54 -050060}
61
62const struct region_device *boot_device_rw(void)
63{
Aaron Durbin67e4df82016-08-23 08:45:55 -050064 /* Probe for the SPI flash device if not already done. */
65 boot_device_rw_init();
66
Arthur Heymansd20b0a82019-11-20 22:00:57 +010067 if (sfg_init_done != true)
Aaron Durbin6f115592016-08-11 18:24:54 -050068 return NULL;
69
70 return &spi_rw;
71}
Aaron Durbin305c0ca2016-12-03 17:04:06 -060072
73const struct spi_flash *boot_device_spi_flash(void)
74{
75 boot_device_rw_init();
Furquan Shaikh30221b42017-05-15 14:35:15 -070076
Arthur Heymansd20b0a82019-11-20 22:00:57 +010077 if (sfg_init_done != true)
Furquan Shaikh30221b42017-05-15 14:35:15 -070078 return NULL;
79
Arthur Heymansd20b0a82019-11-20 22:00:57 +010080 return &sfg;
Aaron Durbin305c0ca2016-12-03 17:04:06 -060081}
Rizwan Qureshi6d4c1f52018-10-26 16:54:42 +053082
Patrick Rudolph2be0b502019-05-09 13:43:49 +020083int boot_device_wp_region(const struct region_device *rd,
Rizwan Qureshi6d4c1f52018-10-26 16:54:42 +053084 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,
Arthur Heymansd20b0a82019-11-20 22:00:57 +010098 region_device_region(rd)) != 1) {
Daniel Gröber16dbbeb2020-05-26 22:18:44 +020099 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
Rizwan Qureshi6d4c1f52018-10-26 16:54:42 +0530108 return spi_flash_set_write_protected(boot_dev,
Daniel Gröber16dbbeb2020-05-26 22:18:44 +0200109 region_device_region(rd), lock);
Rizwan Qureshi6d4c1f52018-10-26 16:54:42 +0530110 }
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}