Skip to content

Commit 072a428

Browse files
talih0carlescufi
authored andcommitted
drivers: flash: Add xmc4xxx flash drivers
Add xmc4xxx flash drivers. Signed-off-by: Andriy Gelman <[email protected]>
1 parent 2c22d7c commit 072a428

File tree

13 files changed

+271
-3
lines changed

13 files changed

+271
-3
lines changed

boards/arm/xmc45_relax_kit/xmc45_relax_kit.dts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,30 @@
3636
zephyr,flash = &flash0;
3737
zephyr,console = &usic1ch1;
3838
zephyr,shell-uart = &usic1ch1;
39+
zephyr,flash-controller = &flash_controller;
40+
zephyr,code-partition = &code_partition;
41+
};
42+
};
43+
44+
&flash_controller {
45+
status = "okay";
46+
};
47+
48+
&flash0 {
49+
partitions {
50+
compatible = "fixed-partitions";
51+
#address-cells = <1>;
52+
#size-cells = <1>;
53+
54+
code_partition: partition@0 {
55+
reg = <0x0 0x80000>;
56+
read-only;
57+
};
58+
59+
storage_partition: partition@80000 {
60+
label = "storage";
61+
reg = <0x80000 0x80000>;
62+
};
3963
};
4064
};
4165

boards/arm/xmc45_relax_kit/xmc45_relax_kit_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ CONFIG_SERIAL=y
1414
# enable console
1515
CONFIG_CONSOLE=y
1616
CONFIG_UART_CONSOLE=y
17+
CONFIG_USE_DT_CODE_PARTITION=y

drivers/flash/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH flash_mcux_fle
2828
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_ESP32 flash_esp32.c)
2929
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SMARTBOND flash_smartbond.c)
3030
zephyr_library_sources_ifdef(CONFIG_FLASH_CAD_QSPI_NOR flash_cadence_qspi_nor.c flash_cadence_qspi_nor_ll.c)
31+
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_XMC4XXX soc_flash_xmc4xxx.c)
3132

3233
if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
3334
dt_chosen(chosen_flash PROPERTY "zephyr,flash")

drivers/flash/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,6 @@ source "drivers/flash/Kconfig.cadence_qspi_nor"
110110

111111
source "drivers/flash/Kconfig.gd32"
112112

113+
source "drivers/flash/Kconfig.xmc4xxx"
114+
113115
endif # FLASH

drivers/flash/Kconfig.xmc4xxx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright (c) 2022 Schlumberger
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config SOC_FLASH_XMC4XXX
5+
bool "XMC4XXX flash driver"
6+
default y
7+
depends on DT_HAS_INFINEON_XMC4XXX_FLASH_CONTROLLER_ENABLED
8+
select FLASH_HAS_PAGE_LAYOUT
9+
select FLASH_HAS_DRIVER_ENABLED
10+
help
11+
Enables XMC4XXX flash driver.

drivers/flash/soc_flash_xmc4xxx.c

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
/*
2+
* Copyright (c) 2022 Schlumberger
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT infineon_xmc4xxx_flash_controller
8+
9+
#define FLASH_WRITE_BLK_SZ DT_PROP(DT_INST(0, infineon_xmc4xxx_nv_flash), write_block_size)
10+
11+
#include <zephyr/device.h>
12+
#include <zephyr/drivers/flash.h>
13+
14+
#include <xmc_flash.h>
15+
16+
struct flash_xmc4xxx_data {
17+
struct k_sem sem;
18+
};
19+
20+
struct flash_xmc4xxx_config {
21+
uint32_t base;
22+
uint32_t size;
23+
struct flash_parameters parameters;
24+
};
25+
26+
static inline bool is_aligned_32(uint32_t data)
27+
{
28+
return (data & 0x3) ? false : true;
29+
}
30+
31+
static int flash_xmc4xxx_init(const struct device *dev)
32+
{
33+
struct flash_xmc4xxx_data *dev_data = dev->data;
34+
35+
k_sem_init(&dev_data->sem, 1, 1);
36+
return 0;
37+
}
38+
39+
#define SET_PAGES(node_id) \
40+
{.pages_count = DT_PROP(node_id, pages_count), .pages_size = DT_PROP(node_id, pages_size)},
41+
42+
#if CONFIG_FLASH_PAGE_LAYOUT
43+
static const struct flash_pages_layout flash_xmc4xxx_pages_layout[] = {
44+
DT_FOREACH_CHILD(DT_NODELABEL(pages_layout), SET_PAGES)};
45+
46+
static void flash_xmc4xxx_page_layout(const struct device *dev,
47+
const struct flash_pages_layout **layout, size_t *layout_size)
48+
{
49+
*layout = &flash_xmc4xxx_pages_layout[0];
50+
*layout_size = ARRAY_SIZE(flash_xmc4xxx_pages_layout);
51+
}
52+
#endif
53+
54+
static int flash_xmc4xxx_read(const struct device *dev, off_t offset, void *data, size_t len)
55+
{
56+
const struct flash_xmc4xxx_config *dev_config = dev->config;
57+
58+
if (offset < 0 || offset + len > dev_config->size) {
59+
return -1;
60+
}
61+
memcpy(data, (void *)(dev_config->base + offset), len);
62+
return 0;
63+
}
64+
65+
static __aligned(4) uint8_t
66+
aligned_page[DT_PROP(DT_INST(0, infineon_xmc4xxx_nv_flash), write_block_size)];
67+
68+
static int flash_xmc4xxx_write(const struct device *dev, off_t offset, const void *data, size_t len)
69+
{
70+
struct flash_xmc4xxx_data *dev_data = dev->data;
71+
const struct flash_xmc4xxx_config *dev_config = dev->config;
72+
uint32_t irq_key;
73+
uint32_t flash_addr = dev_config->base;
74+
const uint8_t *src = data;
75+
int num_pages;
76+
77+
if (offset < 0 || offset + len > dev_config->size) {
78+
return -1;
79+
}
80+
81+
if (len % dev_config->parameters.write_block_size ||
82+
offset % dev_config->parameters.write_block_size > 0) {
83+
return -1;
84+
}
85+
86+
k_sem_take(&dev_data->sem, K_FOREVER);
87+
88+
/* erase and write operations must be on the uncached base address */
89+
flash_addr |= 0xc000000;
90+
flash_addr += offset;
91+
92+
num_pages = len / dev_config->parameters.write_block_size;
93+
for (int i = 0; i < num_pages; i++) {
94+
uint32_t *src_ptr = (uint32_t *)src;
95+
96+
/* XMC_FLASH_ProgramPage() needs a 32 bit aligned input. */
97+
/* Copy the data to an aligned array if needed. */
98+
if (!is_aligned_32((uint32_t)src)) {
99+
memcpy(aligned_page, src, dev_config->parameters.write_block_size);
100+
src_ptr = (uint32_t *)aligned_page;
101+
}
102+
103+
irq_key = irq_lock();
104+
XMC_FLASH_ProgramPage((uint32_t *)flash_addr, src_ptr);
105+
irq_unlock(irq_key);
106+
flash_addr += dev_config->parameters.write_block_size;
107+
src += dev_config->parameters.write_block_size;
108+
}
109+
110+
k_sem_give(&dev_data->sem);
111+
return 0;
112+
}
113+
114+
#if CONFIG_FLASH_PAGE_LAYOUT
115+
static int flash_xmc4xxx_erase(const struct device *dev, off_t offset, size_t size)
116+
{
117+
struct flash_xmc4xxx_data *dev_data = dev->data;
118+
const struct flash_xmc4xxx_config *dev_config = dev->config;
119+
uint32_t irq_key;
120+
uint32_t offset_page = 0;
121+
int ret = 0;
122+
123+
if (offset < 0 || offset > dev_config->size) {
124+
return -1;
125+
}
126+
127+
k_sem_take(&dev_data->sem, K_FOREVER);
128+
129+
for (int i = 0; i < ARRAY_SIZE(flash_xmc4xxx_pages_layout); i++) {
130+
for (int k = 0; k < flash_xmc4xxx_pages_layout[i].pages_count; k++) {
131+
uint32_t pages_size = flash_xmc4xxx_pages_layout[i].pages_size;
132+
/* erase and write operations must be on the uncached base address */
133+
uint32_t flash_addr = dev_config->base | 0xc000000;
134+
135+
if (offset == offset_page && size >= pages_size) {
136+
flash_addr += offset;
137+
irq_key = irq_lock();
138+
XMC_FLASH_EraseSector((uint32_t *)flash_addr);
139+
irq_unlock(irq_key);
140+
141+
size -= pages_size;
142+
offset += pages_size;
143+
}
144+
offset_page += pages_size;
145+
146+
if (size == 0) {
147+
ret = 0;
148+
goto finish;
149+
}
150+
151+
/* page not aligned with offset address */
152+
if (offset_page > offset) {
153+
ret = -1;
154+
goto finish;
155+
}
156+
}
157+
}
158+
159+
finish:
160+
k_sem_give(&dev_data->sem);
161+
return ret;
162+
}
163+
#else
164+
static int flash_xmc4xxx_erase(const struct device *dev, off_t offset, size_t size)
165+
{
166+
ARG_UNUSED(dev);
167+
ARG_UNUSED(offset);
168+
ARG_UNUSED(size);
169+
170+
return -ENOTSUP;
171+
}
172+
#endif
173+
174+
static const struct flash_parameters *flash_xmc4xxx_get_parameters(const struct device *dev)
175+
{
176+
const struct flash_xmc4xxx_config *dev_config = dev->config;
177+
178+
return &dev_config->parameters;
179+
}
180+
181+
static const struct flash_driver_api flash_xmc4xxx_api = {.erase = flash_xmc4xxx_erase,
182+
.write = flash_xmc4xxx_write,
183+
.read = flash_xmc4xxx_read,
184+
#ifdef CONFIG_FLASH_PAGE_LAYOUT
185+
.page_layout = flash_xmc4xxx_page_layout,
186+
#endif
187+
.get_parameters =
188+
flash_xmc4xxx_get_parameters};
189+
190+
static struct flash_xmc4xxx_data flash_xmc4xxx_data_0;
191+
static struct flash_xmc4xxx_config flash_xmc4xxx_cfg_0 = {
192+
.base = DT_REG_ADDR(DT_INST(0, infineon_xmc4xxx_nv_flash)),
193+
.size = DT_REG_SIZE(DT_INST(0, infineon_xmc4xxx_nv_flash)),
194+
.parameters = {.write_block_size = FLASH_WRITE_BLK_SZ, .erase_value = 0}};
195+
196+
DEVICE_DT_INST_DEFINE(0, flash_xmc4xxx_init, NULL, &flash_xmc4xxx_data_0, &flash_xmc4xxx_cfg_0,
197+
POST_KERNEL, CONFIG_FLASH_INIT_PRIORITY, &flash_xmc4xxx_api);

dts/arm/infineon/xmc4500_F100x1024.dtsi

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@
2222

2323
&flash0 {
2424
reg = <0xc000000 DT_SIZE_M(1)>;
25+
pages_layout: pages_layout {
26+
pages_layout_16k: pages_layout_16k {
27+
pages-count = <8>;
28+
pages-size = <DT_SIZE_K(16)>;
29+
};
30+
pages_layout_128k: pages_layout_128k {
31+
pages-count = <1>;
32+
pages-size = <DT_SIZE_K(128)>;
33+
};
34+
pages_layout_256k: pages_layout_256k {
35+
pages-count = <3>;
36+
pages-size = <DT_SIZE_K(256)>;
37+
};
38+
};
2539
};
2640

2741
&gpio0 {

dts/arm/infineon/xmc4xxx.dtsi

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,15 @@
3333
compatible = "mmio-sram";
3434
};
3535

36-
flash0: serial-flash@c000000 {
37-
compatible = "serial-flash";
36+
flash_controller: flash_controller@58001000 {
37+
compatible = "infineon,xmc4xxx-flash-controller";
38+
reg = <0x58001000 0x1400>;
39+
#address-cells = <1>;
40+
#size-cells = <1>;
41+
flash0: flash@c000000 {
42+
compatible = "infineon,xmc4xxx-nv-flash","soc-nv-flash";
43+
write-block-size = <256>;
44+
};
3845
};
3946

4047
sysclk: system-clock {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
description: XMC4XXX flash controller
2+
3+
compatible: "infineon,xmc4xxx-flash-controller"
4+
5+
include: flash-controller.yaml

modules/Kconfig.infineon

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,8 @@ config HAS_XMCLIB_UART
1515
help
1616
Enable XMCLIB Universal asynchronous receiver transmitter (UART)
1717

18+
config HAS_XMCLIB_FLASH
19+
bool
20+
help
21+
Enable XMCLIB Flash
1822
endif # HAS_XMCLIB

0 commit comments

Comments
 (0)