Skip to content

Commit b5c0984

Browse files
jeremydickfabiobaltieri
authored andcommitted
drivers: flash: flash_hp_ra: perform blank check before reading
The value read from unwritten areas of Renesas RAxxx SoCs data flash is undefined. To prevent reading unwritten areas a blank check command is performed first. If the area is blank, we return dummy data so it behaves the same as other flash devices. Signed-off-by: Jeremy Dick <[email protected]>
1 parent 4868029 commit b5c0984

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

drivers/flash/Kconfig.renesas_ra

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,13 @@ config FLASH_RENESAS_RA_HP_BGO
3131
help
3232
Enable Background operations (BGOs)
3333

34+
config FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING
35+
bool "Verify area before reading it"
36+
default $(dt_nodelabel_bool_prop,flash1,erase-value-undefined)
37+
help
38+
Do a blank check flash command before reading an area.
39+
This feature prevents erroneous reading. Values read from an
40+
area of the data flash that has been erased but not programmed
41+
are undefined.
42+
3443
endif # SOC_FLASH_RENESAS_RA_HP

drivers/flash/soc_flash_renesas_ra_hp.c

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,15 @@ void flash_bgo_callback(flash_callback_args_t *p_args)
3434
atomic_or(event_flag, FLASH_FLAG_ERASE_COMPLETE);
3535
} else if (FLASH_EVENT_WRITE_COMPLETE == p_args->event) {
3636
atomic_or(event_flag, FLASH_FLAG_WRITE_COMPLETE);
37-
} else {
37+
}
38+
#if defined(CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING)
39+
else if (FLASH_EVENT_BLANK == p_args->event) {
40+
atomic_or(event_flag, FLASH_FLAG_BLANK);
41+
} else if (FLASH_EVENT_NOT_BLANK == p_args->event) {
42+
atomic_or(event_flag, FLASH_FLAG_NOT_BLANK);
43+
}
44+
#endif /* CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING */
45+
else {
3846
atomic_or(event_flag, FLASH_FLAG_GET_ERROR);
3947
}
4048
}
@@ -50,9 +58,62 @@ static bool flash_ra_valid_range(struct flash_hp_ra_data *flash_data, off_t offs
5058
return true;
5159
}
5260

61+
#if defined(CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING)
62+
/* This feature prevents erroneous reading. Values read from an
63+
* area of the data flash that has been erased but not programmed
64+
* are undefined.
65+
*/
66+
static int is_area_readable(const struct device *dev, off_t offset, size_t len)
67+
{
68+
struct flash_hp_ra_data *flash_data = dev->data;
69+
struct flash_hp_ra_controller *dev_ctrl = flash_data->controller;
70+
int ret = 0;
71+
flash_result_t result = FLASH_RESULT_BGO_ACTIVE;
72+
fsp_err_t err;
73+
74+
k_sem_take(&dev_ctrl->ctrl_sem, K_FOREVER);
75+
76+
err = R_FLASH_HP_BlankCheck(&dev_ctrl->flash_ctrl,
77+
(long)(flash_data->area_address + offset), len, &result);
78+
79+
if (err != FSP_SUCCESS) {
80+
ret = -EIO;
81+
goto end;
82+
}
83+
84+
/* Wait for the blank check result event if BGO is SET */
85+
if (true == dev_ctrl->fsp_config.data_flash_bgo) {
86+
while (!(dev_ctrl->flags & (FLASH_FLAG_BLANK | FLASH_FLAG_NOT_BLANK))) {
87+
if (dev_ctrl->flags & FLASH_FLAG_GET_ERROR) {
88+
ret = -EIO;
89+
atomic_and(&dev_ctrl->flags, ~FLASH_FLAG_GET_ERROR);
90+
break;
91+
}
92+
k_sleep(K_USEC(10));
93+
}
94+
if (dev_ctrl->flags & FLASH_FLAG_BLANK) {
95+
LOG_DBG("read request on erased offset:0x%lx size:%d",
96+
offset, len);
97+
result = FLASH_RESULT_BLANK;
98+
}
99+
atomic_and(&dev_ctrl->flags, ~(FLASH_FLAG_BLANK | FLASH_FLAG_NOT_BLANK));
100+
}
101+
102+
end:
103+
k_sem_give(&dev_ctrl->ctrl_sem);
104+
105+
if (result == FLASH_RESULT_BLANK) {
106+
return -ENODATA;
107+
}
108+
109+
return ret;
110+
}
111+
#endif /* CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING */
112+
53113
static int flash_ra_read(const struct device *dev, off_t offset, void *data, size_t len)
54114
{
55115
struct flash_hp_ra_data *flash_data = dev->data;
116+
int rc = 0;
56117

57118
if (!flash_ra_valid_range(flash_data, offset, len)) {
58119
return -EINVAL;
@@ -64,9 +125,23 @@ static int flash_ra_read(const struct device *dev, off_t offset, void *data, siz
64125

65126
LOG_DBG("flash: read 0x%lx, len: %u", (long)(offset + flash_data->area_address), len);
66127

67-
memcpy(data, (uint8_t *)(offset + flash_data->area_address), len);
128+
#if defined(CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING)
129+
if (flash_data->FlashRegion == DATA_FLASH) {
130+
rc = is_area_readable(dev, offset, len);
131+
}
132+
#endif /* CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING */
133+
134+
if (!rc) {
135+
memcpy(data, (uint8_t *)(offset + flash_data->area_address), len);
136+
#if defined(CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING)
137+
} else if (rc == -ENODATA) {
138+
/* Erased area, return dummy data as an erased page. */
139+
memset(data, 0xFF, len);
140+
rc = 0;
141+
#endif /* CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING */
142+
}
68143

69-
return 0;
144+
return rc;
70145
}
71146

72147
static int flash_ra_erase(const struct device *dev, off_t offset, size_t len)

drivers/flash/soc_flash_renesas_ra_hp.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ enum flash_region {
9090
#define FLASH_FLAG_ERASE_COMPLETE BIT(0)
9191
#define FLASH_FLAG_WRITE_COMPLETE BIT(1)
9292
#define FLASH_FLAG_GET_ERROR BIT(2)
93+
94+
#if defined(CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING)
95+
#define FLASH_FLAG_BLANK BIT(3)
96+
#define FLASH_FLAG_NOT_BLANK BIT(4)
97+
#endif /* CONFIG_FLASH_RENESAS_RA_HP_CHECK_BEFORE_READING */
98+
9399
#endif /* CONFIG_FLASH_RENESAS_RA_HP_BGO */
94100

95101
struct flash_hp_ra_controller {

0 commit comments

Comments
 (0)