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