1 /* ieee802154_rf2xx_iface.c - ATMEL RF2XX IEEE 802.15.4 Interface */
2
3 /*
4 * Copyright (c) 2019-2020 Gerson Fernando Budke
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define LOG_MODULE_NAME ieee802154_rf2xx_iface
10 #define LOG_LEVEL CONFIG_IEEE802154_DRIVER_LOG_LEVEL
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
14
15 #include <errno.h>
16
17 #include <zephyr/device.h>
18 #include <zephyr/drivers/spi.h>
19 #include <zephyr/drivers/gpio.h>
20
21 #include <zephyr/net/ieee802154_radio.h>
22
23 #include "ieee802154_rf2xx.h"
24 #include "ieee802154_rf2xx_regs.h"
25 #include "ieee802154_rf2xx_iface.h"
26
rf2xx_iface_phy_rst(const struct device * dev)27 void rf2xx_iface_phy_rst(const struct device *dev)
28 {
29 const struct rf2xx_config *conf = dev->config;
30
31 /* Ensure control lines have correct levels. */
32 gpio_pin_set_dt(&conf->reset_gpio, 0);
33 gpio_pin_set_dt(&conf->slptr_gpio, 0);
34
35 /* Wait typical time of timer TR1. */
36 k_busy_wait(330);
37
38 gpio_pin_set_dt(&conf->reset_gpio, 1);
39 k_busy_wait(10);
40 gpio_pin_set_dt(&conf->reset_gpio, 0);
41 }
rf2xx_iface_phy_tx_start(const struct device * dev)42 void rf2xx_iface_phy_tx_start(const struct device *dev)
43 {
44 const struct rf2xx_config *conf = dev->config;
45
46 /* Start TX transmission at rise edge */
47 gpio_pin_set_dt(&conf->slptr_gpio, 1);
48 /* 16.125[μs] delay to detect signal */
49 k_busy_wait(20);
50 /* restore initial pin state */
51 gpio_pin_set_dt(&conf->slptr_gpio, 0);
52 }
53
rf2xx_iface_reg_read(const struct device * dev,uint8_t addr)54 uint8_t rf2xx_iface_reg_read(const struct device *dev,
55 uint8_t addr)
56 {
57 const struct rf2xx_config *conf = dev->config;
58 uint8_t status;
59 uint8_t regval = 0;
60
61 addr |= RF2XX_RF_CMD_REG_R;
62
63 const struct spi_buf tx_buf = {
64 .buf = &addr,
65 .len = 1
66 };
67 const struct spi_buf_set tx = {
68 .buffers = &tx_buf,
69 .count = 1
70 };
71 const struct spi_buf rx_buf[2] = {
72 {
73 .buf = &status,
74 .len = 1
75 },
76 {
77 .buf = ®val,
78 .len = 1
79 },
80 };
81 const struct spi_buf_set rx = {
82 .buffers = rx_buf,
83 .count = 2
84 };
85
86 if (spi_transceive_dt(&conf->spi, &tx, &rx) != 0) {
87 LOG_ERR("Failed to exec rf2xx_reg_read CMD at address %d",
88 addr);
89 }
90
91 LOG_DBG("Read Address: %02X, PhyStatus: %02X, RegVal: %02X",
92 (addr & ~(RF2XX_RF_CMD_REG_R)), status, regval);
93
94 return regval;
95 }
96
rf2xx_iface_reg_write(const struct device * dev,uint8_t addr,uint8_t data)97 void rf2xx_iface_reg_write(const struct device *dev,
98 uint8_t addr,
99 uint8_t data)
100 {
101 const struct rf2xx_config *conf = dev->config;
102 uint8_t status;
103
104 addr |= RF2XX_RF_CMD_REG_W;
105
106 const struct spi_buf tx_buf[2] = {
107 {
108 .buf = &addr,
109 .len = 1
110 },
111 {
112 .buf = &data,
113 .len = 1
114 }
115 };
116 const struct spi_buf_set tx = {
117 .buffers = tx_buf,
118 .count = 2
119 };
120 const struct spi_buf rx_buf = {
121 .buf = &status,
122 .len = 1
123 };
124 const struct spi_buf_set rx = {
125 .buffers = &rx_buf,
126 .count = 1
127 };
128
129 if (spi_transceive_dt(&conf->spi, &tx, &rx) != 0) {
130 LOG_ERR("Failed to exec rf2xx_reg_write at address %d",
131 addr);
132 }
133
134 LOG_DBG("Write Address: %02X, PhyStatus: %02X, RegVal: %02X",
135 (addr & ~(RF2XX_RF_CMD_REG_W)), status, data);
136 }
137
rf2xx_iface_bit_read(const struct device * dev,uint8_t addr,uint8_t mask,uint8_t pos)138 uint8_t rf2xx_iface_bit_read(const struct device *dev,
139 uint8_t addr,
140 uint8_t mask,
141 uint8_t pos)
142 {
143 uint8_t ret;
144
145 ret = rf2xx_iface_reg_read(dev, addr);
146 ret &= mask;
147 ret >>= pos;
148
149 return ret;
150 }
151
rf2xx_iface_bit_write(const struct device * dev,uint8_t reg_addr,uint8_t mask,uint8_t pos,uint8_t new_value)152 void rf2xx_iface_bit_write(const struct device *dev,
153 uint8_t reg_addr,
154 uint8_t mask,
155 uint8_t pos,
156 uint8_t new_value)
157 {
158 uint8_t current_reg_value;
159
160 current_reg_value = rf2xx_iface_reg_read(dev, reg_addr);
161 current_reg_value &= ~mask;
162 new_value <<= pos;
163 new_value &= mask;
164 new_value |= current_reg_value;
165 rf2xx_iface_reg_write(dev, reg_addr, new_value);
166 }
167
rf2xx_iface_frame_read(const struct device * dev,uint8_t * data,uint8_t length)168 void rf2xx_iface_frame_read(const struct device *dev,
169 uint8_t *data,
170 uint8_t length)
171 {
172 const struct rf2xx_config *conf = dev->config;
173 uint8_t cmd = RF2XX_RF_CMD_FRAME_R;
174
175 const struct spi_buf tx_buf = {
176 .buf = &cmd,
177 .len = 1
178 };
179 const struct spi_buf_set tx = {
180 .buffers = &tx_buf,
181 .count = 1
182 };
183 const struct spi_buf rx_buf = {
184 .buf = data,
185 .len = length
186 };
187 const struct spi_buf_set rx = {
188 .buffers = &rx_buf,
189 .count = 1
190 };
191
192 if (spi_transceive_dt(&conf->spi, &tx, &rx) != 0) {
193 LOG_ERR("Failed to exec rf2xx_frame_read PHR");
194 }
195
196 LOG_DBG("Frame R: PhyStatus: %02X. length: %02X", data[0], length);
197 LOG_HEXDUMP_DBG(data + RX2XX_FRAME_HEADER_SIZE, length, "payload");
198 }
199
rf2xx_iface_frame_write(const struct device * dev,uint8_t * data,uint8_t length)200 void rf2xx_iface_frame_write(const struct device *dev,
201 uint8_t *data,
202 uint8_t length)
203 {
204 const struct rf2xx_config *conf = dev->config;
205 uint8_t cmd = RF2XX_RF_CMD_FRAME_W;
206 uint8_t status;
207 uint8_t phr;
208
209 /* Sanity check */
210 if (length > 125) {
211 length = 125;
212 }
213
214 phr = length + RX2XX_FRAME_FCS_LENGTH;
215
216 const struct spi_buf tx_buf[3] = {
217 {
218 .buf = &cmd,
219 .len = 1
220 },
221 {
222 .buf = &phr, /* PHR */
223 .len = 1
224 },
225 {
226 .buf = data, /* PSDU */
227 .len = length
228 },
229 };
230 const struct spi_buf_set tx = {
231 .buffers = tx_buf,
232 .count = 3
233 };
234 const struct spi_buf rx_buf = {
235 .buf = &status,
236 .len = 1
237 };
238 const struct spi_buf_set rx = {
239 .buffers = &rx_buf,
240 .count = 1
241 };
242
243 if (spi_transceive_dt(&conf->spi, &tx, &rx) != 0) {
244 LOG_ERR("Failed to exec rf2xx_frame_write");
245 }
246
247 LOG_DBG("Frame W: PhyStatus: %02X. length: %02X", status, length);
248 LOG_HEXDUMP_DBG(data, length, "payload");
249 }
250
rf2xx_iface_sram_read(const struct device * dev,uint8_t address,uint8_t * data,uint8_t length)251 void rf2xx_iface_sram_read(const struct device *dev,
252 uint8_t address,
253 uint8_t *data,
254 uint8_t length)
255 {
256 const struct rf2xx_config *conf = dev->config;
257 uint8_t cmd = RF2XX_RF_CMD_SRAM_R;
258 uint8_t status[2];
259
260 const struct spi_buf tx_buf[2] = {
261 {
262 .buf = &cmd,
263 .len = 1
264 },
265 {
266 .buf = &address,
267 .len = 1
268 },
269 };
270 const struct spi_buf_set tx = {
271 .buffers = tx_buf,
272 .count = 2
273 };
274 const struct spi_buf rx_buf[2] = {
275 {
276 .buf = status,
277 .len = 2
278 },
279 {
280 .buf = data,
281 .len = length
282 },
283 };
284 const struct spi_buf_set rx = {
285 .buffers = rx_buf,
286 .count = 2
287 };
288
289 if (spi_transceive_dt(&conf->spi, &tx, &rx) != 0) {
290 LOG_ERR("Failed to exec rf2xx_sram_read");
291 }
292
293 LOG_DBG("SRAM R: length: %02X, status: %02X", length, status[0]);
294 LOG_HEXDUMP_DBG(data, length, "content");
295 }
296