1 /*
2 * Copyright (c) 2019 Manivannan Sadhasivam
3 * Copyright (c) 2020 Grinn
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <zephyr/drivers/gpio.h>
9 #include <zephyr/drivers/lora.h>
10 #include <zephyr/drivers/spi.h>
11 #include <zephyr/kernel.h>
12
13 #include "sx12xx_common.h"
14
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(sx127x, CONFIG_LORA_LOG_LEVEL);
17
18 #if DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1272)
19
20 #include <sx1272/sx1272.h>
21
22 #define DT_DRV_COMPAT semtech_sx1272
23
24 #define SX127xCheckRfFrequency SX1272CheckRfFrequency
25 #define SX127xGetBoardTcxoWakeupTime SX1272GetBoardTcxoWakeupTime
26 #define SX127xSetAntSwLowPower SX1272SetAntSwLowPower
27 #define SX127xSetBoardTcxo SX1272SetBoardTcxo
28 #define SX127xSetAntSw SX1272SetAntSw
29 #define SX127xReset SX1272Reset
30 #define SX127xIoIrqInit SX1272IoIrqInit
31 #define SX127xWriteBuffer SX1272WriteBuffer
32 #define SX127xReadBuffer SX1272ReadBuffer
33 #define SX127xSetRfTxPower SX1272SetRfTxPower
34 #define SX127xGetDio1PinState SX1272GetDio1PinState
35 #define SX127xInit SX1272Init
36 #define SX127xGetStatus SX1272GetStatus
37 #define SX127xSetModem SX1272SetModem
38 #define SX127xSetChannel SX1272SetChannel
39 #define SX127xIsChannelFree SX1272IsChannelFree
40 #define SX127xRandom SX1272Random
41 #define SX127xSetRxConfig SX1272SetRxConfig
42 #define SX127xSetTxConfig SX1272SetTxConfig
43 #define SX127xGetTimeOnAir SX1272GetTimeOnAir
44 #define SX127xSend SX1272Send
45 #define SX127xSetSleep SX1272SetSleep
46 #define SX127xSetStby SX1272SetStby
47 #define SX127xSetRx SX1272SetRx
48 #define SX127xWrite SX1272Write
49 #define SX127xRead SX1272Read
50 #define SX127xSetMaxPayloadLength SX1272SetMaxPayloadLength
51 #define SX127xSetPublicNetwork SX1272SetPublicNetwork
52 #define SX127xGetWakeupTime SX1272GetWakeupTime
53 #define SX127xSetTxContinuousWave SX1272SetTxContinuousWave
54
55 #elif DT_HAS_COMPAT_STATUS_OKAY(semtech_sx1276)
56
57 #include <sx1276/sx1276.h>
58
59 #define DT_DRV_COMPAT semtech_sx1276
60
61 #define SX127xCheckRfFrequency SX1276CheckRfFrequency
62 #define SX127xGetBoardTcxoWakeupTime SX1276GetBoardTcxoWakeupTime
63 #define SX127xSetAntSwLowPower SX1276SetAntSwLowPower
64 #define SX127xSetBoardTcxo SX1276SetBoardTcxo
65 #define SX127xSetAntSw SX1276SetAntSw
66 #define SX127xReset SX1276Reset
67 #define SX127xIoIrqInit SX1276IoIrqInit
68 #define SX127xWriteBuffer SX1276WriteBuffer
69 #define SX127xReadBuffer SX1276ReadBuffer
70 #define SX127xSetRfTxPower SX1276SetRfTxPower
71 #define SX127xGetDio1PinState SX1276GetDio1PinState
72 #define SX127xInit SX1276Init
73 #define SX127xGetStatus SX1276GetStatus
74 #define SX127xSetModem SX1276SetModem
75 #define SX127xSetChannel SX1276SetChannel
76 #define SX127xIsChannelFree SX1276IsChannelFree
77 #define SX127xRandom SX1276Random
78 #define SX127xSetRxConfig SX1276SetRxConfig
79 #define SX127xSetTxConfig SX1276SetTxConfig
80 #define SX127xGetTimeOnAir SX1276GetTimeOnAir
81 #define SX127xSend SX1276Send
82 #define SX127xSetSleep SX1276SetSleep
83 #define SX127xSetStby SX1276SetStby
84 #define SX127xSetRx SX1276SetRx
85 #define SX127xWrite SX1276Write
86 #define SX127xRead SX1276Read
87 #define SX127xSetMaxPayloadLength SX1276SetMaxPayloadLength
88 #define SX127xSetPublicNetwork SX1276SetPublicNetwork
89 #define SX127xGetWakeupTime SX1276GetWakeupTime
90 #define SX127xSetTxContinuousWave SX1276SetTxContinuousWave
91
92 #else
93 #error No SX127x instance in device tree.
94 #endif
95
96 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(semtech_sx1272) +
97 DT_NUM_INST_STATUS_OKAY(semtech_sx1276) <= 1,
98 "Multiple SX127x instances in DT");
99
100 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_startup_delay_ms)
101 #define TCXO_POWER_STARTUP_DELAY_MS \
102 DT_INST_PROP(0, tcxo_power_startup_delay_ms)
103 #else
104 #define TCXO_POWER_STARTUP_DELAY_MS 0
105 #endif
106
107 /*
108 * Those macros must be in sync with 'power-amplifier-output' dts property.
109 */
110 #define SX127X_PA_RFO 0
111 #define SX127X_PA_BOOST 1
112
113 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \
114 DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
115 #define SX127X_PA_OUTPUT(power) \
116 ((power) > 14 ? SX127X_PA_BOOST : SX127X_PA_RFO)
117 #elif DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios)
118 #define SX127X_PA_OUTPUT(power) SX127X_PA_RFO
119 #elif DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
120 #define SX127X_PA_OUTPUT(power) SX127X_PA_BOOST
121 #elif DT_INST_NODE_HAS_PROP(0, power_amplifier_output)
122 #define SX127X_PA_OUTPUT(power) \
123 DT_INST_ENUM_IDX(0, power_amplifier_output)
124 #else
125 BUILD_ASSERT(0, "None of rfo-enable-gpios, pa-boost-enable-gpios and "
126 "power-amplifier-output has been specified. "
127 "Look at semtech,sx127x-base.yaml to fix that.");
128 #endif
129
130 #define SX127X_PADAC_20DBM_ON (RF_PADAC_20DBM_ON)
131 #define SX127X_PADAC_20DBM_OFF (RF_PADAC_20DBM_OFF)
132 #define SX127X_PADAC_20DBM_MASK (~RF_PADAC_20DBM_MASK)
133
134 #define SX127X_PACONFIG_PASELECT_PABOOST (RF_PACONFIG_PASELECT_PABOOST)
135 #define SX127X_PACONFIG_OUTPUTPOWER_MASK (~RF_PACONFIG_OUTPUTPOWER_MASK)
136
137 #ifdef RF_PACONFIG_MAX_POWER_MASK
138 #define SX127X_PACONFIG_MAX_POWER_SHIFT 4
139 #endif
140
141 extern DioIrqHandler *DioIrq[];
142
143 /* Helper macro that UTIL_LISTIFY can use and produces an element with comma */
144 #define SX127X_DIO_GPIO_LEN(inst) \
145 DT_INST_PROP_LEN(inst, dio_gpios)
146
147 #define SX127X_DIO_GPIO_ELEM(idx, inst) \
148 GPIO_DT_SPEC_INST_GET_BY_IDX(inst, dio_gpios, idx)
149
150 #define SX127X_DIO_GPIO_INIT(n) \
151 LISTIFY(SX127X_DIO_GPIO_LEN(n), SX127X_DIO_GPIO_ELEM, (,), n)
152
153 static const struct gpio_dt_spec sx127x_dios[] = { SX127X_DIO_GPIO_INIT(0) };
154
155 #define SX127X_MAX_DIO ARRAY_SIZE(sx127x_dios)
156
157 struct sx127x_config {
158 struct spi_dt_spec bus;
159 struct gpio_dt_spec reset;
160 #if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios)
161 struct gpio_dt_spec antenna_enable;
162 #endif
163 #if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios)
164 struct gpio_dt_spec rfi_enable;
165 #endif
166 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios)
167 struct gpio_dt_spec rfo_enable;
168 #endif
169 #if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
170 struct gpio_dt_spec pa_boost_enable;
171 #endif
172 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios)
173 struct gpio_dt_spec tcxo_power;
174 #endif
175 };
176
177 static const struct sx127x_config dev_config = {
178 .bus = SPI_DT_SPEC_INST_GET(0, SPI_WORD_SET(8) | SPI_TRANSFER_MSB, 0),
179 .reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios),
180 #if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios)
181 .antenna_enable = GPIO_DT_SPEC_INST_GET(0, antenna_enable_gpios),
182 #endif
183 #if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios)
184 .rfi_enable = GPIO_DT_SPEC_INST_GET(0, rfi_enable_gpios),
185 #endif
186 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios)
187 .rfo_enable = GPIO_DT_SPEC_INST_GET(0, rfo_enable_gpios),
188 #endif
189 #if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
190 .pa_boost_enable = GPIO_DT_SPEC_INST_GET(0, pa_boost_enable_gpios),
191 #endif
192 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios)
193 .tcxo_power = GPIO_DT_SPEC_INST_GET(0, tcxo_power_gpios),
194 #endif
195 };
196
197 static struct sx127x_data {
198 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \
199 DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
200 uint8_t tx_power;
201 #endif
202 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios)
203 bool tcxo_power_enabled;
204 #endif
205 struct k_work dio_work[SX127X_MAX_DIO];
206 } dev_data;
207
clamp_int8(int8_t x,int8_t min,int8_t max)208 static int8_t clamp_int8(int8_t x, int8_t min, int8_t max)
209 {
210 if (x < min) {
211 return min;
212 } else if (x > max) {
213 return max;
214 } else {
215 return x;
216 }
217 }
218
SX127xCheckRfFrequency(uint32_t frequency)219 bool SX127xCheckRfFrequency(uint32_t frequency)
220 {
221 /* TODO */
222 return true;
223 }
224
SX127xGetBoardTcxoWakeupTime(void)225 uint32_t SX127xGetBoardTcxoWakeupTime(void)
226 {
227 return TCXO_POWER_STARTUP_DELAY_MS;
228 }
229
sx127x_antenna_enable(int val)230 static inline void sx127x_antenna_enable(int val)
231 {
232 #if DT_INST_NODE_HAS_PROP(0, antenna_enable_gpios)
233 gpio_pin_set_dt(&dev_config.antenna_enable, val);
234 #endif
235 }
236
sx127x_rfi_enable(int val)237 static inline void sx127x_rfi_enable(int val)
238 {
239 #if DT_INST_NODE_HAS_PROP(0, rfi_enable_gpios)
240 gpio_pin_set_dt(&dev_config.rfi_enable, val);
241 #endif
242 }
243
sx127x_rfo_enable(int val)244 static inline void sx127x_rfo_enable(int val)
245 {
246 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios)
247 gpio_pin_set_dt(&dev_config.rfo_enable, val);
248 #endif
249 }
250
sx127x_pa_boost_enable(int val)251 static inline void sx127x_pa_boost_enable(int val)
252 {
253 #if DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
254 gpio_pin_set_dt(&dev_config.pa_boost_enable, val);
255 #endif
256 }
257
SX127xSetAntSwLowPower(bool low_power)258 void SX127xSetAntSwLowPower(bool low_power)
259 {
260 if (low_power) {
261 /* force inactive (low power) state of all antenna paths */
262 sx127x_rfi_enable(0);
263 sx127x_rfo_enable(0);
264 sx127x_pa_boost_enable(0);
265
266 sx127x_antenna_enable(0);
267 } else {
268 sx127x_antenna_enable(1);
269
270 /* rely on SX127xSetAntSw() to configure proper antenna path */
271 }
272 }
273
SX127xSetBoardTcxo(uint8_t state)274 void SX127xSetBoardTcxo(uint8_t state)
275 {
276 #if DT_INST_NODE_HAS_PROP(0, tcxo_power_gpios)
277 bool enable = state;
278
279 if (enable == dev_data.tcxo_power_enabled) {
280 return;
281 }
282
283 if (enable) {
284 gpio_pin_set_dt(&dev_config.tcxo_power, 1);
285
286 if (TCXO_POWER_STARTUP_DELAY_MS > 0) {
287 k_sleep(K_MSEC(TCXO_POWER_STARTUP_DELAY_MS));
288 }
289 } else {
290 gpio_pin_set_dt(&dev_config.tcxo_power, 0);
291 }
292
293 dev_data.tcxo_power_enabled = enable;
294 #endif
295 }
296
SX127xSetAntSw(uint8_t opMode)297 void SX127xSetAntSw(uint8_t opMode)
298 {
299 switch (opMode) {
300 case RFLR_OPMODE_TRANSMITTER:
301 sx127x_rfi_enable(0);
302
303 if (SX127X_PA_OUTPUT(dev_data.tx_power) == SX127X_PA_BOOST) {
304 sx127x_rfo_enable(0);
305 sx127x_pa_boost_enable(1);
306 } else {
307 sx127x_pa_boost_enable(0);
308 sx127x_rfo_enable(1);
309 }
310 break;
311 default:
312 sx127x_rfo_enable(0);
313 sx127x_pa_boost_enable(0);
314 sx127x_rfi_enable(1);
315 break;
316 }
317 }
318
SX127xReset(void)319 void SX127xReset(void)
320 {
321 SX127xSetBoardTcxo(true);
322
323 gpio_pin_set_dt(&dev_config.reset, 1);
324
325 k_sleep(K_MSEC(1));
326
327 gpio_pin_set_dt(&dev_config.reset, 0);
328
329 k_sleep(K_MSEC(6));
330 }
331
sx127x_dio_work_handle(struct k_work * work)332 static void sx127x_dio_work_handle(struct k_work *work)
333 {
334 int dio = work - dev_data.dio_work;
335
336 (*DioIrq[dio])(NULL);
337 }
338
sx127x_irq_callback(const struct device * dev,struct gpio_callback * cb,uint32_t pins)339 static void sx127x_irq_callback(const struct device *dev,
340 struct gpio_callback *cb, uint32_t pins)
341 {
342 unsigned int i, pin;
343
344 pin = find_lsb_set(pins) - 1;
345
346 for (i = 0; i < SX127X_MAX_DIO; i++) {
347 if (dev == sx127x_dios[i].port &&
348 pin == sx127x_dios[i].pin) {
349 k_work_submit(&dev_data.dio_work[i]);
350 }
351 }
352 }
353
SX127xIoIrqInit(DioIrqHandler ** irqHandlers)354 void SX127xIoIrqInit(DioIrqHandler **irqHandlers)
355 {
356 unsigned int i;
357 static struct gpio_callback callbacks[SX127X_MAX_DIO];
358
359 /* Setup DIO gpios */
360 for (i = 0; i < SX127X_MAX_DIO; i++) {
361 if (!irqHandlers[i]) {
362 continue;
363 }
364
365 if (!gpio_is_ready_dt(&sx127x_dios[i])) {
366 LOG_ERR("GPIO port %s not ready",
367 sx127x_dios[i].port->name);
368 return;
369 }
370
371 k_work_init(&dev_data.dio_work[i], sx127x_dio_work_handle);
372
373 gpio_pin_configure_dt(&sx127x_dios[i], GPIO_INPUT);
374
375 gpio_init_callback(&callbacks[i],
376 sx127x_irq_callback,
377 BIT(sx127x_dios[i].pin));
378
379 if (gpio_add_callback(sx127x_dios[i].port, &callbacks[i]) < 0) {
380 LOG_ERR("Could not set gpio callback.");
381 return;
382 }
383 gpio_pin_interrupt_configure_dt(&sx127x_dios[i],
384 GPIO_INT_EDGE_TO_ACTIVE);
385 }
386
387 }
388
sx127x_transceive(uint8_t reg,bool write,void * data,size_t length)389 static int sx127x_transceive(uint8_t reg, bool write, void *data, size_t length)
390 {
391 const struct spi_buf buf[2] = {
392 {
393 .buf = ®,
394 .len = sizeof(reg)
395 },
396 {
397 .buf = data,
398 .len = length
399 }
400 };
401
402 struct spi_buf_set tx = {
403 .buffers = buf,
404 .count = ARRAY_SIZE(buf),
405 };
406
407 if (!write) {
408 const struct spi_buf_set rx = {
409 .buffers = buf,
410 .count = ARRAY_SIZE(buf)
411 };
412
413 return spi_transceive_dt(&dev_config.bus, &tx, &rx);
414 }
415
416 return spi_write_dt(&dev_config.bus, &tx);
417 }
418
sx127x_read(uint8_t reg_addr,uint8_t * data,uint8_t len)419 int sx127x_read(uint8_t reg_addr, uint8_t *data, uint8_t len)
420 {
421 return sx127x_transceive(reg_addr, false, data, len);
422 }
423
sx127x_write(uint8_t reg_addr,uint8_t * data,uint8_t len)424 int sx127x_write(uint8_t reg_addr, uint8_t *data, uint8_t len)
425 {
426 return sx127x_transceive(reg_addr | BIT(7), true, data, len);
427 }
428
SX127xWriteBuffer(uint32_t addr,uint8_t * buffer,uint8_t size)429 void SX127xWriteBuffer(uint32_t addr, uint8_t *buffer, uint8_t size)
430 {
431 int ret;
432
433 ret = sx127x_write(addr, buffer, size);
434 if (ret < 0) {
435 LOG_ERR("Unable to write address: 0x%x", addr);
436 }
437 }
438
SX127xReadBuffer(uint32_t addr,uint8_t * buffer,uint8_t size)439 void SX127xReadBuffer(uint32_t addr, uint8_t *buffer, uint8_t size)
440 {
441 int ret;
442
443 ret = sx127x_read(addr, buffer, size);
444 if (ret < 0) {
445 LOG_ERR("Unable to read address: 0x%x", addr);
446 }
447 }
448
SX127xSetRfTxPower(int8_t power)449 void SX127xSetRfTxPower(int8_t power)
450 {
451 int ret;
452 uint8_t pa_config = 0;
453 uint8_t pa_dac = 0;
454
455 ret = sx127x_read(REG_PADAC, &pa_dac, 1);
456 if (ret < 0) {
457 LOG_ERR("Unable to read PA dac");
458 return;
459 }
460
461 pa_dac &= ~SX127X_PADAC_20DBM_MASK;
462
463 if (SX127X_PA_OUTPUT(power) == SX127X_PA_BOOST) {
464 power = clamp_int8(power, 2, 20);
465
466 pa_config |= SX127X_PACONFIG_PASELECT_PABOOST;
467 if (power > 17) {
468 pa_dac |= SX127X_PADAC_20DBM_ON;
469 pa_config |= (power - 5) & SX127X_PACONFIG_OUTPUTPOWER_MASK;
470 } else {
471 pa_dac |= SX127X_PADAC_20DBM_OFF;
472 pa_config |= (power - 2) & SX127X_PACONFIG_OUTPUTPOWER_MASK;
473 }
474 } else {
475 #ifdef SX127X_PACONFIG_MAX_POWER_SHIFT
476 power = clamp_int8(power, -4, 15);
477
478 pa_dac |= SX127X_PADAC_20DBM_OFF;
479 if (power > 0) {
480 /* Set the power range to 0 -- 10.8+0.6*7 dBm */
481 pa_config |= 7 << SX127X_PACONFIG_MAX_POWER_SHIFT;
482 pa_config |= power & SX127X_PACONFIG_OUTPUTPOWER_MASK;
483 } else {
484 /* Set the power range to -4.2 -- 10.8+0.6*0 dBm */
485 pa_config |= (power + 4) & SX127X_PACONFIG_OUTPUTPOWER_MASK;
486 }
487 #else
488 power = clamp_int8(power, -1, 14);
489
490 pa_dac |= SX127X_PADAC_20DBM_OFF;
491 pa_config |= (power + 1) & SX127X_PACONFIG_OUTPUTPOWER_MASK;
492 #endif
493 }
494
495 #if DT_INST_NODE_HAS_PROP(0, rfo_enable_gpios) && \
496 DT_INST_NODE_HAS_PROP(0, pa_boost_enable_gpios)
497 dev_data.tx_power = power;
498 #endif
499
500 ret = sx127x_write(REG_PACONFIG, &pa_config, 1);
501 if (ret < 0) {
502 LOG_ERR("Unable to write PA config");
503 return;
504 }
505
506 ret = sx127x_write(REG_PADAC, &pa_dac, 1);
507 if (ret < 0) {
508 LOG_ERR("Unable to write PA dac");
509 return;
510 }
511 }
512
SX127xGetDio1PinState(void)513 uint32_t SX127xGetDio1PinState(void)
514 {
515 #if SX127X_DIO_GPIO_LEN(0) >= 2
516 if (gpio_pin_get_dt(&sx127x_dios[1]) > 0) {
517 return 1U;
518 }
519 #endif
520
521 return 0U;
522 }
523
524 /* Initialize Radio driver callbacks */
525 const struct Radio_s Radio = {
526 .Init = SX127xInit,
527 .GetStatus = SX127xGetStatus,
528 .SetModem = SX127xSetModem,
529 .SetChannel = SX127xSetChannel,
530 .IsChannelFree = SX127xIsChannelFree,
531 .Random = SX127xRandom,
532 .SetRxConfig = SX127xSetRxConfig,
533 .SetTxConfig = SX127xSetTxConfig,
534 .CheckRfFrequency = SX127xCheckRfFrequency,
535 .TimeOnAir = SX127xGetTimeOnAir,
536 .Send = SX127xSend,
537 .Sleep = SX127xSetSleep,
538 .Standby = SX127xSetStby,
539 .Rx = SX127xSetRx,
540 .Write = SX127xWrite,
541 .Read = SX127xRead,
542 .WriteBuffer = SX127xWriteBuffer,
543 .ReadBuffer = SX127xReadBuffer,
544 .SetMaxPayloadLength = SX127xSetMaxPayloadLength,
545 .SetPublicNetwork = SX127xSetPublicNetwork,
546 .GetWakeupTime = SX127xGetWakeupTime,
547 .IrqProcess = NULL,
548 .RxBoosted = NULL,
549 .SetRxDutyCycle = NULL,
550 .SetTxContinuousWave = SX127xSetTxContinuousWave,
551 };
552
sx127x_antenna_configure(void)553 static int sx127x_antenna_configure(void)
554 {
555 int ret;
556
557 ret = sx12xx_configure_pin(antenna_enable, GPIO_OUTPUT_INACTIVE);
558 if (ret) {
559 return ret;
560 }
561
562 ret = sx12xx_configure_pin(rfi_enable, GPIO_OUTPUT_INACTIVE);
563 if (ret) {
564 return ret;
565 }
566
567 ret = sx12xx_configure_pin(rfo_enable, GPIO_OUTPUT_INACTIVE);
568 if (ret) {
569 return ret;
570 }
571
572 ret = sx12xx_configure_pin(pa_boost_enable, GPIO_OUTPUT_INACTIVE);
573 if (ret) {
574 return ret;
575 }
576
577 return 0;
578 }
579
sx127x_lora_init(const struct device * dev)580 static int sx127x_lora_init(const struct device *dev)
581 {
582 int ret;
583 uint8_t regval;
584
585 if (!spi_is_ready_dt(&dev_config.bus)) {
586 LOG_ERR("SPI device not ready");
587 return -ENODEV;
588 }
589
590 ret = sx12xx_configure_pin(tcxo_power, GPIO_OUTPUT_INACTIVE);
591 if (ret) {
592 return ret;
593 }
594
595 /* Setup Reset gpio and perform soft reset */
596 ret = sx12xx_configure_pin(reset, GPIO_OUTPUT_ACTIVE);
597 if (ret) {
598 return ret;
599 }
600
601 k_sleep(K_MSEC(100));
602 gpio_pin_set_dt(&dev_config.reset, 0);
603 k_sleep(K_MSEC(100));
604
605 ret = sx127x_read(REG_VERSION, ®val, 1);
606 if (ret < 0) {
607 LOG_ERR("Unable to read version info");
608 return -EIO;
609 }
610
611 LOG_INF("SX127x version 0x%02x found", regval);
612
613 ret = sx127x_antenna_configure();
614 if (ret < 0) {
615 LOG_ERR("Unable to configure antenna");
616 return -EIO;
617 }
618
619 ret = sx12xx_init(dev);
620 if (ret < 0) {
621 LOG_ERR("Failed to initialize SX12xx common");
622 return ret;
623 }
624
625 return 0;
626 }
627
628 static const struct lora_driver_api sx127x_lora_api = {
629 .config = sx12xx_lora_config,
630 .send = sx12xx_lora_send,
631 .send_async = sx12xx_lora_send_async,
632 .recv = sx12xx_lora_recv,
633 .recv_async = sx12xx_lora_recv_async,
634 .test_cw = sx12xx_lora_test_cw,
635 };
636
637 DEVICE_DT_INST_DEFINE(0, &sx127x_lora_init, NULL, NULL,
638 NULL, POST_KERNEL, CONFIG_LORA_INIT_PRIORITY,
639 &sx127x_lora_api);
640