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