1 /*
2  * Copyright (c) 2022 BrainCo Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT gd_gd32_flash_controller
8 
9 #include "flash_gd32.h"
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/devicetree.h>
13 #include <zephyr/drivers/flash.h>
14 #include <zephyr/logging/log.h>
15 
16 #include <gd32_fmc.h>
17 
18 LOG_MODULE_REGISTER(flash_gd32, CONFIG_FLASH_LOG_LEVEL);
19 
20 struct flash_gd32_data {
21 	struct k_sem mutex;
22 };
23 
24 static struct flash_gd32_data flash_data;
25 
26 static const struct flash_parameters flash_gd32_parameters = {
27 	.write_block_size = SOC_NV_FLASH_PRG_SIZE,
28 	.erase_value = 0xff,
29 };
30 
flash_gd32_read(const struct device * dev,off_t offset,void * data,size_t len)31 static int flash_gd32_read(const struct device *dev, off_t offset,
32 			   void *data, size_t len)
33 {
34 	if ((offset > SOC_NV_FLASH_SIZE) ||
35 	    ((offset + len) > SOC_NV_FLASH_SIZE)) {
36 		return -EINVAL;
37 	}
38 
39 	if (len == 0U) {
40 		return 0;
41 	}
42 
43 	memcpy(data, (uint8_t *)SOC_NV_FLASH_ADDR + offset, len);
44 
45 	return 0;
46 }
47 
flash_gd32_write(const struct device * dev,off_t offset,const void * data,size_t len)48 static int flash_gd32_write(const struct device *dev, off_t offset,
49 			    const void *data, size_t len)
50 {
51 	struct flash_gd32_data *dev_data = dev->data;
52 	int ret = 0;
53 
54 	if (!flash_gd32_valid_range(offset, len, true)) {
55 		return -EINVAL;
56 	}
57 
58 	if (len == 0U) {
59 		return 0;
60 	}
61 
62 	k_sem_take(&dev_data->mutex, K_FOREVER);
63 
64 	ret = flash_gd32_write_range(offset, data, len);
65 
66 	k_sem_give(&dev_data->mutex);
67 
68 	return ret;
69 }
70 
flash_gd32_erase(const struct device * dev,off_t offset,size_t size)71 static int flash_gd32_erase(const struct device *dev, off_t offset, size_t size)
72 {
73 	struct flash_gd32_data *data = dev->data;
74 	int ret = 0;
75 
76 	if (size == 0U) {
77 		return 0;
78 	}
79 
80 	if (!flash_gd32_valid_range(offset, size, false)) {
81 		return -EINVAL;
82 	}
83 
84 	k_sem_take(&data->mutex, K_FOREVER);
85 
86 	ret = flash_gd32_erase_block(offset, size);
87 
88 	k_sem_give(&data->mutex);
89 
90 	return ret;
91 }
92 
93 static const struct flash_parameters*
flash_gd32_get_parameters(const struct device * dev)94 flash_gd32_get_parameters(const struct device *dev)
95 {
96 	ARG_UNUSED(dev);
97 
98 	return &flash_gd32_parameters;
99 }
100 
101 static const struct flash_driver_api flash_gd32_driver_api = {
102 	.read = flash_gd32_read,
103 	.write = flash_gd32_write,
104 	.erase = flash_gd32_erase,
105 	.get_parameters = flash_gd32_get_parameters,
106 #ifdef CONFIG_FLASH_PAGE_LAYOUT
107 	.page_layout = flash_gd32_pages_layout,
108 #endif
109 };
110 
flash_gd32_init(const struct device * dev)111 static int flash_gd32_init(const struct device *dev)
112 {
113 	struct flash_gd32_data *data = dev->data;
114 
115 	k_sem_init(&data->mutex, 1, 1);
116 
117 	return 0;
118 }
119 
120 DEVICE_DT_INST_DEFINE(0, flash_gd32_init, NULL,
121 		      &flash_data, NULL, POST_KERNEL,
122 		      CONFIG_FLASH_INIT_PRIORITY, &flash_gd32_driver_api);
123