1 /*
2 * Copyright (c) 2021 Florin Stancu
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /*
8 * Implements the RF driver callback to configure the on-board antenna
9 * switch.
10 */
11
12 #define DT_DRV_COMPAT skyworks_sky13317
13
14 #include <zephyr/init.h>
15 #include <zephyr/device.h>
16 #include <zephyr/drivers/gpio.h>
17 #include <zephyr/drivers/pinctrl.h>
18
19 #include <ti/drivers/rf/RF.h>
20 #include <driverlib/rom.h>
21 #include <driverlib/interrupt.h>
22
23 /* custom pinctrl states for the antenna mux */
24 #define PINCTRL_STATE_ANT_24G 1
25 #define PINCTRL_STATE_ANT_24G_PA 2
26 #define PINCTRL_STATE_ANT_SUBG 3
27 #define PINCTRL_STATE_ANT_SUBG_PA 4
28
29 #define BOARD_ANT_GPIO_24G 0
30 #define BOARD_ANT_GPIO_PA 1
31 #define BOARD_ANT_GPIO_SUBG 2
32
33 static int board_antenna_init(const struct device *dev);
34 static void board_cc13xx_rf_callback(RF_Handle client, RF_GlobalEvent events, void *arg);
35
36 const RFCC26XX_HWAttrsV2 RFCC26XX_hwAttrs = {
37 .hwiPriority = INT_PRI_LEVEL7,
38 .swiPriority = 0,
39 .xoscHfAlwaysNeeded = true,
40 /* RF driver callback for custom antenna switching */
41 .globalCallback = board_cc13xx_rf_callback,
42 /* Subscribe to events */
43 .globalEventMask = (RF_GlobalEventRadioSetup | RF_GlobalEventRadioPowerDown),
44 };
45
46 PINCTRL_DT_INST_DEFINE(0);
47 DEVICE_DT_INST_DEFINE(0, board_antenna_init, NULL, NULL, NULL, POST_KERNEL,
48 CONFIG_BOARD_ANTENNA_INIT_PRIO, NULL);
49
50 static const struct pinctrl_dev_config *ant_pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0);
51 static const struct gpio_dt_spec ant_gpios[] = {
52 DT_FOREACH_PROP_ELEM_SEP(DT_NODELABEL(antenna_mux0), gpios, GPIO_DT_SPEC_GET_BY_IDX, (,))};
53
54 /**
55 * Antenna switch GPIO init routine.
56 */
board_antenna_init(const struct device * dev)57 static int board_antenna_init(const struct device *dev)
58 {
59 ARG_UNUSED(dev);
60 int i;
61
62 /* default pinctrl configuration: set all antenna mux control pins as GPIOs */
63 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_DEFAULT);
64 /* set all GPIOs to 0 (all RF paths disabled) */
65 for (i = 0; i < ARRAY_SIZE(ant_gpios); i++) {
66 gpio_pin_configure_dt(&ant_gpios[i], 0);
67 }
68 return 0;
69 }
70
71 /**
72 * Custom TI RFCC26XX callback for switching the on-board antenna mux on radio setup.
73 */
board_cc13xx_rf_callback(RF_Handle client,RF_GlobalEvent events,void * arg)74 static void board_cc13xx_rf_callback(RF_Handle client, RF_GlobalEvent events, void *arg)
75 {
76 bool sub1GHz = false;
77 uint8_t loDivider = 0;
78 int i;
79
80 /* Clear all antenna switch GPIOs (for all cases). */
81 for (i = 0; i < ARRAY_SIZE(ant_gpios); i++) {
82 gpio_pin_configure_dt(&ant_gpios[i], 0);
83 }
84
85 if (events & RF_GlobalEventRadioSetup) {
86 /* Decode the current PA configuration. */
87 RF_TxPowerTable_PAType paType =
88 (RF_TxPowerTable_PAType)RF_getTxPower(client).paType;
89 /* Decode the generic argument as a setup command. */
90 RF_RadioSetup *setupCommand = (RF_RadioSetup *)arg;
91
92 switch (setupCommand->common.commandNo) {
93 case CMD_RADIO_SETUP:
94 case CMD_BLE5_RADIO_SETUP:
95 loDivider = RF_LODIVIDER_MASK & setupCommand->common.loDivider;
96 break;
97 case CMD_PROP_RADIO_DIV_SETUP:
98 loDivider = RF_LODIVIDER_MASK & setupCommand->prop_div.loDivider;
99 break;
100 default:
101 break;
102 }
103 sub1GHz = (loDivider != 0);
104
105 if (sub1GHz) {
106 if (paType == RF_TxPowerTable_HighPA) {
107 /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 */
108 /* is sometimes not de-asserted on CC1352 Rev A. */
109 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_ANT_SUBG_PA);
110 } else {
111 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_ANT_SUBG);
112 /* Manually set the sub-GHZ antenna switch DIO */
113 gpio_pin_configure_dt(&ant_gpios[BOARD_ANT_GPIO_SUBG], 1);
114 }
115 } else /* 2.4 GHz */ {
116 if (paType == RF_TxPowerTable_HighPA) {
117 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_ANT_24G_PA);
118 } else {
119 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_ANT_24G);
120 /* Manually set the 2.4GHZ antenna switch DIO */
121 gpio_pin_configure_dt(&ant_gpios[BOARD_ANT_GPIO_24G], 1);
122 }
123 }
124 } else {
125 pinctrl_apply_state(ant_pcfg, PINCTRL_STATE_DEFAULT);
126 }
127 }
128