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