1 /*
2  * Copyright (c) 2016 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <errno.h>
8 #include <zephyr/kernel.h>
9 #include <zephyr/sys/printk.h>
10 #include <zephyr/device.h>
11 #include <zephyr/drivers/spi.h>
12 
13 /**
14  * @file Sample app using the Fujitsu MB85RS64V FRAM through SPI.
15  */
16 
17 #define MB85RS64V_MANUFACTURER_ID_CMD 0x9f
18 #define MB85RS64V_WRITE_ENABLE_CMD 0x06
19 #define MB85RS64V_READ_CMD 0x03
20 #define MB85RS64V_WRITE_CMD 0x02
21 #define MAX_USER_DATA_LENGTH 1024
22 
23 static uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH];
24 
mb85rs64v_access(const struct device * spi,struct spi_config * spi_cfg,uint8_t cmd,uint16_t addr,void * data,size_t len)25 static int mb85rs64v_access(const struct device *spi,
26 			    struct spi_config *spi_cfg,
27 			    uint8_t cmd, uint16_t addr, void *data, size_t len)
28 {
29 	uint8_t access[3];
30 	struct spi_buf bufs[] = {
31 		{
32 			.buf = access,
33 		},
34 		{
35 			.buf = data,
36 			.len = len
37 		}
38 	};
39 	struct spi_buf_set tx = {
40 		.buffers = bufs
41 	};
42 
43 	access[0] = cmd;
44 
45 	if (cmd == MB85RS64V_WRITE_CMD || cmd == MB85RS64V_READ_CMD) {
46 		access[1] = (addr >> 8) & 0xFF;
47 		access[2] = addr & 0xFF;
48 
49 		bufs[0].len = 3;
50 		tx.count = 2;
51 
52 		if (cmd == MB85RS64V_READ_CMD) {
53 			struct spi_buf_set rx = {
54 				.buffers = bufs,
55 				.count = 2
56 			};
57 
58 			return spi_transceive(spi, spi_cfg, &tx, &rx);
59 		}
60 	} else {
61 		tx.count = 1;
62 	}
63 
64 	return spi_write(spi, spi_cfg, &tx);
65 }
66 
67 
mb85rs64v_read_id(const struct device * spi,struct spi_config * spi_cfg)68 static int mb85rs64v_read_id(const struct device *spi,
69 			     struct spi_config *spi_cfg)
70 {
71 	uint8_t id[4];
72 	int err;
73 
74 	err = mb85rs64v_access(spi, spi_cfg,
75 			       MB85RS64V_MANUFACTURER_ID_CMD, 0, &id, 4);
76 	if (err) {
77 		printk("Error during ID read\n");
78 		return -EIO;
79 	}
80 
81 	if (id[0] != 0x04) {
82 		return -EIO;
83 	}
84 
85 	if (id[1] != 0x7f) {
86 		return -EIO;
87 	}
88 
89 	if (id[2] != 0x03) {
90 		return -EIO;
91 	}
92 
93 	if (id[3] != 0x02) {
94 		return -EIO;
95 	}
96 
97 	return 0;
98 }
99 
write_bytes(const struct device * spi,struct spi_config * spi_cfg,uint16_t addr,uint8_t * data,uint32_t num_bytes)100 static int write_bytes(const struct device *spi, struct spi_config *spi_cfg,
101 		       uint16_t addr, uint8_t *data, uint32_t num_bytes)
102 {
103 	int err;
104 
105 	/* disable write protect */
106 	err = mb85rs64v_access(spi, spi_cfg,
107 			       MB85RS64V_WRITE_ENABLE_CMD, 0, NULL, 0);
108 	if (err) {
109 		printk("unable to disable write protect\n");
110 		return -EIO;
111 	}
112 
113 	/* write cmd */
114 	err = mb85rs64v_access(spi, spi_cfg,
115 			       MB85RS64V_WRITE_CMD, addr, data, num_bytes);
116 	if (err) {
117 		printk("Error during SPI write\n");
118 		return -EIO;
119 	}
120 
121 	return 0;
122 }
123 
read_bytes(const struct device * spi,struct spi_config * spi_cfg,uint16_t addr,uint8_t * data,uint32_t num_bytes)124 static int read_bytes(const struct device *spi, struct spi_config *spi_cfg,
125 		      uint16_t addr, uint8_t *data, uint32_t num_bytes)
126 {
127 	int err;
128 
129 	/* read cmd */
130 	err = mb85rs64v_access(spi, spi_cfg,
131 			       MB85RS64V_READ_CMD, addr, data, num_bytes);
132 	if (err) {
133 		printk("Error during SPI read\n");
134 		return -EIO;
135 	}
136 
137 	return 0;
138 }
139 
main(void)140 int main(void)
141 {
142 	const struct device *spi;
143 	struct spi_config spi_cfg = {0};
144 	int err;
145 
146 	printk("fujitsu FRAM example application\n");
147 
148 	spi = DEVICE_DT_GET(DT_ALIAS(spi_1));
149 	if (!device_is_ready(spi)) {
150 		printk("SPI device %s is not ready\n", spi->name);
151 		return 0;
152 	}
153 
154 	spi_cfg.operation = SPI_WORD_SET(8);
155 	spi_cfg.frequency = 256000U;
156 
157 
158 	err = mb85rs64v_read_id(spi, &spi_cfg);
159 	if (err) {
160 		printk("Could not verify FRAM ID\n");
161 		return 0;
162 	}
163 
164 	/* Do one-byte read/write */
165 	data[0] = 0xAE;
166 	err = write_bytes(spi, &spi_cfg, 0x00, data, 1);
167 	if (err) {
168 		printk("Error writing to FRAM! error code (%d)\n", err);
169 		return 0;
170 	} else {
171 		printk("Wrote 0xAE to address 0x00.\n");
172 	}
173 
174 	data[0] = 0x86;
175 	err = write_bytes(spi, &spi_cfg, 0x01, data, 1);
176 	if (err) {
177 		printk("Error writing to FRAM! error code (%d)\n", err);
178 		return 0;
179 	} else {
180 		printk("Wrote 0x86 to address 0x01.\n");
181 	}
182 
183 	data[0] = 0x00;
184 	err = read_bytes(spi, &spi_cfg, 0x00, data, 1);
185 	if (err) {
186 		printk("Error reading from FRAM! error code (%d)\n", err);
187 		return 0;
188 	} else {
189 		printk("Read 0x%X from address 0x00.\n", data[0]);
190 	}
191 
192 	data[0] = 0x00;
193 	err = read_bytes(spi, &spi_cfg, 0x01, data, 1);
194 	if (err) {
195 		printk("Error reading from FRAM! error code (%d)\n", err);
196 		return 0;
197 	} else {
198 		printk("Read 0x%X from address 0x01.\n", data[0]);
199 	}
200 
201 	/* Do multi-byte read/write */
202 	/* get some random data, and clear out data[] */
203 	for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
204 		cmp_data[i] = k_cycle_get_32() & 0xFF;
205 		data[i] = 0x00;
206 	}
207 
208 	/* write them to the FRAM */
209 	err = write_bytes(spi, &spi_cfg, 0x00, cmp_data, sizeof(cmp_data));
210 	if (err) {
211 		printk("Error writing to FRAM! error code (%d)\n", err);
212 		return 0;
213 	} else {
214 		printk("Wrote %d bytes to address 0x00.\n",
215 		       (uint32_t) sizeof(cmp_data));
216 	}
217 
218 	err = read_bytes(spi, &spi_cfg, 0x00, data, sizeof(data));
219 	if (err) {
220 		printk("Error reading from FRAM! error code (%d)\n", err);
221 		return 0;
222 	} else {
223 		printk("Read %d bytes from address 0x00.\n",
224 		       (uint32_t) sizeof(data));
225 	}
226 
227 	err = 0;
228 	for (uint32_t i = 0; i < sizeof(cmp_data); i++) {
229 		if (cmp_data[i] != data[i]) {
230 			printk("Data comparison failed @ %d.\n", i);
231 			err = -EIO;
232 		}
233 	}
234 	if (err == 0) {
235 		printk("Data comparison successful.\n");
236 	}
237 	return 0;
238 }
239