1 /*
2  * Copyright (c) 2023-2024 Analog Devices, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT adi_max32_flash_controller
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/init.h>
13 
14 #include "flc.h"
15 
16 struct max32_flash_dev_config {
17 	uint32_t flash_base;
18 	uint32_t flash_erase_blk_sz;
19 	struct flash_parameters parameters;
20 #if CONFIG_FLASH_PAGE_LAYOUT
21 	struct flash_pages_layout pages_layouts;
22 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
23 };
24 
25 struct max32_flash_dev_data {
26 #ifdef CONFIG_MULTITHREADING
27 	struct k_sem sem;
28 #endif
29 };
30 
31 #ifdef CONFIG_MULTITHREADING
max32_sem_take(const struct device * dev)32 static inline void max32_sem_take(const struct device *dev)
33 {
34 	struct max32_flash_dev_data *data = dev->data;
35 
36 	k_sem_take(&data->sem, K_FOREVER);
37 }
38 
max32_sem_give(const struct device * dev)39 static inline void max32_sem_give(const struct device *dev)
40 {
41 	struct max32_flash_dev_data *data = dev->data;
42 
43 	k_sem_give(&data->sem);
44 }
45 #else
46 
47 #define max32_sem_take(dev)
48 #define max32_sem_give(dev)
49 
50 #endif /* CONFIG_MULTITHREADING */
51 
api_read(const struct device * dev,off_t address,void * buffer,size_t length)52 static int api_read(const struct device *dev, off_t address, void *buffer, size_t length)
53 {
54 	const struct max32_flash_dev_config *const cfg = dev->config;
55 
56 	address += cfg->flash_base;
57 	MXC_FLC_Read(address, buffer, length);
58 	return 0;
59 }
60 
api_write(const struct device * dev,off_t address,const void * buffer,size_t length)61 static int api_write(const struct device *dev, off_t address, const void *buffer, size_t length)
62 {
63 	const struct max32_flash_dev_config *const cfg = dev->config;
64 	int ret = 0;
65 
66 	max32_sem_take(dev);
67 
68 	address += cfg->flash_base;
69 	ret = MXC_FLC_Write(address, length, (uint32_t *)buffer);
70 
71 	max32_sem_give(dev);
72 
73 	return ret != 0 ? -EIO : 0;
74 }
75 
api_erase(const struct device * dev,off_t start,size_t len)76 static int api_erase(const struct device *dev, off_t start, size_t len)
77 {
78 	const struct max32_flash_dev_config *const cfg = dev->config;
79 	uint32_t page_size = cfg->flash_erase_blk_sz;
80 	uint32_t addr = (start + cfg->flash_base);
81 	int ret = 0;
82 
83 	max32_sem_take(dev);
84 
85 	while (len) {
86 		ret = MXC_FLC_PageErase(addr);
87 		if (ret) {
88 			break;
89 		}
90 
91 		addr += page_size;
92 		if (len > page_size) {
93 			len -= page_size;
94 		} else {
95 			len = 0;
96 		}
97 	}
98 
99 	max32_sem_give(dev);
100 
101 	return ret != 0 ? -EIO : 0;
102 }
103 
104 #if CONFIG_FLASH_PAGE_LAYOUT
api_page_layout(const struct device * dev,const struct flash_pages_layout ** layout,size_t * layout_size)105 static void api_page_layout(const struct device *dev, const struct flash_pages_layout **layout,
106 			    size_t *layout_size)
107 {
108 	const struct max32_flash_dev_config *const cfg = dev->config;
109 
110 	*layout = &cfg->pages_layouts;
111 	*layout_size = 1;
112 }
113 #endif /* CONFIG_FLASH_PAGE_LAYOUT */
114 
api_get_parameters(const struct device * dev)115 static const struct flash_parameters *api_get_parameters(const struct device *dev)
116 {
117 	const struct max32_flash_dev_config *const cfg = dev->config;
118 
119 	return &cfg->parameters;
120 }
121 
flash_max32_init(const struct device * dev)122 static int flash_max32_init(const struct device *dev)
123 {
124 	int ret = MXC_FLC_Init();
125 
126 #ifdef CONFIG_MULTITHREADING
127 	struct max32_flash_dev_data *data = dev->data;
128 
129 	/* Mutex for flash controller */
130 	k_sem_init(&data->sem, 1, 1);
131 #endif
132 	return ret != 0 ? -EIO : 0;
133 }
134 
135 static DEVICE_API(flash, flash_max32_driver_api) = {
136 	.read = api_read,
137 	.write = api_write,
138 	.erase = api_erase,
139 	.get_parameters = api_get_parameters,
140 #ifdef CONFIG_FLASH_PAGE_LAYOUT
141 	.page_layout = api_page_layout,
142 #endif
143 };
144 
145 #if CONFIG_FLASH_PAGE_LAYOUT
146 #define FLASH_MAX32_CONFIG_PAGE_LAYOUT(n)                                                          \
147 	.pages_layouts = {                                                                         \
148 		.pages_count = DT_INST_FOREACH_CHILD(n, GET_FLASH_SIZE) /                          \
149 			       DT_INST_FOREACH_CHILD(n, GET_ERASE_BLOCK_SIZE),                     \
150 		.pages_size = DT_INST_FOREACH_CHILD(n, GET_ERASE_BLOCK_SIZE),                      \
151 	},
152 #else
153 #define FLASH_MAX32_CONFIG_PAGE_LAYOUT(n)
154 #endif
155 
156 #define GET_WRITE_BLOCK_SIZE(n) DT_PROP(n, write_block_size)
157 #define GET_ERASE_BLOCK_SIZE(n) DT_PROP(n, erase_block_size)
158 #define GET_FLASH_BASE(n)       DT_REG_ADDR(n)
159 #define GET_FLASH_SIZE(n)       DT_REG_SIZE(n)
160 
161 #define DEFINE_FLASH_MAX32(_num)                                                                   \
162 	static const struct max32_flash_dev_config max32_flash_dev_cfg_##_num = {                  \
163 		.flash_base = DT_INST_FOREACH_CHILD(_num, GET_FLASH_BASE),                         \
164 		.flash_erase_blk_sz = DT_INST_FOREACH_CHILD(_num, GET_ERASE_BLOCK_SIZE),           \
165 		.parameters =                                                                      \
166 			{                                                                          \
167 				.write_block_size =                                                \
168 					DT_INST_FOREACH_CHILD(_num, GET_WRITE_BLOCK_SIZE),         \
169 				.erase_value = 0xFF,                                               \
170 			},                                                                         \
171 		FLASH_MAX32_CONFIG_PAGE_LAYOUT(_num)};                                             \
172 	static struct max32_flash_dev_data max32_flash_dev_data_##_num;                            \
173 	DEVICE_DT_INST_DEFINE(_num, flash_max32_init, NULL, &max32_flash_dev_data_##_num,          \
174 			      &max32_flash_dev_cfg_##_num, POST_KERNEL,                            \
175 			      CONFIG_FLASH_INIT_PRIORITY, &flash_max32_driver_api);
176 
177 DT_INST_FOREACH_STATUS_OKAY(DEFINE_FLASH_MAX32)
178