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