1 /*
2  * Copyright (c) 2019 Kwon Tae-young <tykwon@m2i.co.kr>
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT st_stm32_eeprom
8 
9 #include <zephyr/drivers/eeprom.h>
10 #include <soc.h>
11 #include <zephyr/kernel.h>
12 
13 #define LOG_LEVEL CONFIG_EEPROM_LOG_LEVEL
14 #include <zephyr/logging/log.h>
15 LOG_MODULE_REGISTER(eeprom_stm32);
16 
17 K_MUTEX_DEFINE(lock);
18 
19 struct eeprom_stm32_config {
20 	uint32_t addr;
21 	size_t size;
22 };
23 
eeprom_stm32_read(const struct device * dev,off_t offset,void * buf,size_t len)24 static int eeprom_stm32_read(const struct device *dev, off_t offset,
25 				void *buf,
26 				size_t len)
27 {
28 	const struct eeprom_stm32_config *config = dev->config;
29 	uint8_t *pbuf = buf;
30 
31 	if (!len) {
32 		return 0;
33 	}
34 
35 	if ((offset + len) > config->size) {
36 		LOG_WRN("attempt to read past device boundary");
37 		return -EINVAL;
38 	}
39 
40 	k_mutex_lock(&lock, K_FOREVER);
41 
42 	while (len) {
43 		*pbuf = *(__IO uint8_t*)(config->addr + offset);
44 
45 		pbuf++;
46 		offset++;
47 		len--;
48 	}
49 
50 	k_mutex_unlock(&lock);
51 
52 	return 0;
53 }
54 
eeprom_stm32_write(const struct device * dev,off_t offset,const void * buf,size_t len)55 static int eeprom_stm32_write(const struct device *dev, off_t offset,
56 				const void *buf, size_t len)
57 {
58 	const struct eeprom_stm32_config *config = dev->config;
59 	const uint8_t *pbuf = buf;
60 	HAL_StatusTypeDef ret = HAL_OK;
61 
62 	if (!len) {
63 		return 0;
64 	}
65 
66 	if ((offset + len) > config->size) {
67 		LOG_WRN("attempt to write past device boundary");
68 		return -EINVAL;
69 	}
70 
71 	k_mutex_lock(&lock, K_FOREVER);
72 
73 	HAL_FLASHEx_DATAEEPROM_Unlock();
74 
75 	while (len) {
76 		ret = HAL_FLASHEx_DATAEEPROM_Program(
77 						FLASH_TYPEPROGRAMDATA_BYTE,
78 						config->addr + offset, *pbuf);
79 		if (ret) {
80 			LOG_ERR("failed to write to EEPROM (err %d)", ret);
81 			HAL_FLASHEx_DATAEEPROM_Lock();
82 			k_mutex_unlock(&lock);
83 			return ret;
84 		}
85 
86 		pbuf++;
87 		offset++;
88 		len--;
89 	}
90 
91 	ret = HAL_FLASHEx_DATAEEPROM_Lock();
92 	if (ret) {
93 		LOG_ERR("failed to lock EEPROM (err %d)", ret);
94 		k_mutex_unlock(&lock);
95 		return ret;
96 	}
97 
98 	k_mutex_unlock(&lock);
99 
100 	return ret;
101 }
102 
eeprom_stm32_size(const struct device * dev)103 static size_t eeprom_stm32_size(const struct device *dev)
104 {
105 	const struct eeprom_stm32_config *config = dev->config;
106 
107 	return config->size;
108 }
109 
110 static const struct eeprom_driver_api eeprom_stm32_api = {
111 	.read = eeprom_stm32_read,
112 	.write = eeprom_stm32_write,
113 	.size = eeprom_stm32_size,
114 };
115 
116 static const struct eeprom_stm32_config eeprom_config = {
117 	.addr = DT_INST_REG_ADDR(0),
118 	.size = DT_INST_REG_SIZE(0),
119 };
120 
121 DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &eeprom_config, POST_KERNEL,
122 		      CONFIG_EEPROM_INIT_PRIORITY, &eeprom_stm32_api);
123