1 /*
2  * Copyright (c) 2018-2021 Nordic Semiconductor ASA.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/init.h>
9 #include <zephyr/drivers/gpio.h>
10 #include <zephyr/devicetree.h>
11 #include <zephyr/logging/log.h>
12 #include <soc.h>
13 #include <hal/nrf_gpio.h>
14 
15 LOG_MODULE_REGISTER(board_control, CONFIG_BOARD_NRF9160DK_LOG_LEVEL);
16 
17 #define GET_CTLR(name, prop, idx) \
18 	DT_GPIO_CTLR_BY_IDX(DT_NODELABEL(name), prop, idx)
19 #define GET_PIN(name, prop, idx) \
20 	DT_GPIO_PIN_BY_IDX(DT_NODELABEL(name), prop, idx)
21 #define GET_PORT(name, prop, idx) \
22 	DT_PROP_BY_PHANDLE_IDX(DT_NODELABEL(name), prop, idx, port)
23 #define GET_FLAGS(name, prop, idx) \
24 	DT_GPIO_FLAGS_BY_IDX(DT_NODELABEL(name), prop, idx)
25 #define GET_DEV(name, prop, idx) DEVICE_DT_GET(GET_CTLR(name, prop, idx))
26 
27 /* If the GPIO pin selected to be the reset line is actually the pin that
28  * exposes the nRESET function (P0.18 in nRF52840), there is no need to
29  * provide any additional GPIO configuration for it.
30  */
31 #define RESET_INPUT_IS_PINRESET (DT_PROP(DT_NODELABEL(uicr), gpio_as_nreset) && \
32 				 GET_PORT(reset_input, gpios, 0) == 0 && \
33 				 GET_PIN(reset_input, gpios, 0) == 18)
34 #define USE_RESET_GPIO \
35 	(DT_NODE_HAS_STATUS(DT_NODELABEL(reset_input), okay) && \
36 	 !RESET_INPUT_IS_PINRESET)
37 
38 struct switch_cfg {
39 	const struct device *gpio;
40 	gpio_pin_t pin;
41 	gpio_dt_flags_t flags;
42 	bool on;
43 #if defined(CONFIG_LOG)
44 	uint8_t port;
45 	bool info;
46 	const char *name;
47 #endif
48 };
49 
50 #define ROUTING_ENABLED(_name) DT_NODE_HAS_STATUS(DT_NODELABEL(_name), okay)
51 #define SWITCH_CFG(_name, _idx)					\
52 {								\
53 	.gpio  = GET_DEV(_name, control_gpios, _idx),		\
54 	.pin   = GET_PIN(_name, control_gpios, _idx),		\
55 	.flags = GET_FLAGS(_name, control_gpios, _idx),		\
56 	.on    = ROUTING_ENABLED(_name),			\
57 	COND_CODE_1(CONFIG_LOG,					\
58 	(							\
59 		.port = GET_PORT(_name, control_gpios, _idx),	\
60 		.info = (_idx == 0),				\
61 		.name = #_name,					\
62 	), ())							\
63 }
64 #define HAS_TWO_PINS(_name) \
65 	DT_PHA_HAS_CELL_AT_IDX(DT_NODELABEL(_name), control_gpios, 1, pin)
66 
67 #define ROUTING_SWITCH(_name)					\
68 	COND_CODE_1(DT_NODE_EXISTS(DT_NODELABEL(_name)),	\
69 	(							\
70 		COND_CODE_1(HAS_TWO_PINS(_name),		\
71 		(						\
72 			SWITCH_CFG(_name, 1),			\
73 		), ())						\
74 		SWITCH_CFG(_name, 0),				\
75 	), ())
76 
77 static const struct switch_cfg routing_switches[] = {
78 	ROUTING_SWITCH(vcom0_pins_routing)
79 	ROUTING_SWITCH(vcom2_pins_routing)
80 	ROUTING_SWITCH(led1_pin_routing)
81 	ROUTING_SWITCH(led2_pin_routing)
82 	ROUTING_SWITCH(led3_pin_routing)
83 	ROUTING_SWITCH(led4_pin_routing)
84 	ROUTING_SWITCH(switch1_pin_routing)
85 	ROUTING_SWITCH(switch2_pin_routing)
86 	ROUTING_SWITCH(button1_pin_routing)
87 	ROUTING_SWITCH(button2_pin_routing)
88 	ROUTING_SWITCH(nrf_interface_pins_0_2_routing)
89 	ROUTING_SWITCH(nrf_interface_pins_3_5_routing)
90 	ROUTING_SWITCH(nrf_interface_pins_6_8_routing)
91 	ROUTING_SWITCH(nrf_interface_pin_9_routing)
92 	ROUTING_SWITCH(io_expander_pins_routing)
93 	ROUTING_SWITCH(external_flash_pins_routing)
94 };
95 
96 #if USE_RESET_GPIO
chip_reset(const struct device * gpio,struct gpio_callback * cb,uint32_t pins)97 static void chip_reset(const struct device *gpio,
98 		       struct gpio_callback *cb, uint32_t pins)
99 {
100 	const uint32_t stamp = k_cycle_get_32();
101 
102 	printk("GPIO reset line asserted, device reset.\n");
103 	printk("Bye @ cycle32 %u\n", stamp);
104 
105 	NVIC_SystemReset();
106 }
107 
reset_pin_wait_inactive(const struct device * gpio,uint32_t pin)108 static void reset_pin_wait_inactive(const struct device *gpio, uint32_t pin)
109 {
110 	int val;
111 
112 	/* Wait until the pin becomes inactive. */
113 	do {
114 		val = gpio_pin_get(gpio, pin);
115 	} while (val > 0);
116 }
117 
reset_pin_configure(void)118 static int reset_pin_configure(void)
119 {
120 	int rc;
121 	static struct gpio_callback gpio_ctx;
122 
123 	const struct device *gpio = GET_DEV(reset_input, gpios, 0);
124 	gpio_pin_t pin = GET_PIN(reset_input, gpios, 0);
125 	gpio_dt_flags_t flags = GET_FLAGS(reset_input, gpios, 0);
126 
127 	if (!device_is_ready(gpio)) {
128 		LOG_ERR("%s is not ready", gpio->name);
129 		return -ENODEV;
130 	}
131 
132 	rc = gpio_pin_configure(gpio, pin, flags | GPIO_INPUT);
133 	if (rc) {
134 		LOG_ERR("Error %d while configuring pin P%d.%02d",
135 			rc, GET_PORT(reset_input, gpios, 0), pin);
136 		return rc;
137 	}
138 
139 	gpio_init_callback(&gpio_ctx, chip_reset, BIT(pin));
140 
141 	rc = gpio_add_callback(gpio, &gpio_ctx);
142 	if (rc) {
143 		return rc;
144 	}
145 
146 	rc = gpio_pin_interrupt_configure(gpio, pin, GPIO_INT_EDGE_TO_ACTIVE);
147 	if (rc) {
148 		return rc;
149 	}
150 
151 	LOG_INF("GPIO reset line enabled on pin P%d.%02d, holding...",
152 		GET_PORT(reset_input, gpios, 0), pin);
153 
154 	/* Wait until the pin becomes inactive before continuing.
155 	 * This lets the other side ensure that they are ready.
156 	 */
157 	reset_pin_wait_inactive(gpio, pin);
158 
159 	return 0;
160 }
161 #endif /* USE_RESET_GPIO */
162 
init(void)163 static int init(void)
164 {
165 	int rc;
166 
167 	for (int i = 0; i < ARRAY_SIZE(routing_switches); ++i) {
168 		const struct switch_cfg *cfg = &routing_switches[i];
169 		gpio_flags_t flags = cfg->flags;
170 
171 		if (!device_is_ready(cfg->gpio)) {
172 			LOG_ERR("%s is not ready", cfg->gpio->name);
173 			return -ENODEV;
174 		}
175 
176 		flags |= (cfg->on ? GPIO_OUTPUT_ACTIVE
177 				  : GPIO_OUTPUT_INACTIVE);
178 		rc = gpio_pin_configure(cfg->gpio, cfg->pin, flags);
179 #if defined(CONFIG_LOG)
180 		LOG_DBG("Configuring P%d.%02d with flags: 0x%08x",
181 			cfg->port, cfg->pin, flags);
182 		if (rc) {
183 			LOG_ERR("Error %d while configuring pin P%d.%02d (%s)",
184 				rc, cfg->port, cfg->pin, cfg->name);
185 		} else if (cfg->info) {
186 			LOG_INF("%s is %s",
187 				cfg->name, cfg->on ? "ENABLED" : "disabled");
188 		}
189 #endif
190 		if (rc) {
191 			return rc;
192 		}
193 	}
194 
195 	/* Make sure to configure the switches before initializing
196 	 * the GPIO reset pin, so that we are connected to
197 	 * the nRF9160 before enabling our interrupt.
198 	 */
199 
200 #if USE_RESET_GPIO
201 	rc = reset_pin_configure();
202 	if (rc) {
203 		LOG_ERR("Unable to configure reset pin, err %d", rc);
204 		return -EIO;
205 	}
206 #endif
207 
208 	LOG_INF("Board configured.");
209 
210 	return 0;
211 }
212 
213 SYS_INIT(init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
214 
215 #define EXT_MEM_CTRL DT_NODELABEL(external_flash_pins_routing)
216 #if DT_NODE_EXISTS(EXT_MEM_CTRL)
217 
early_init(void)218 static int early_init(void)
219 {
220 	/* As soon as possible after the system starts up, enable the analog
221 	 * switch that routes signals to the external flash. Otherwise, the
222 	 * HOLD line in the flash chip may not be properly pulled up internally
223 	 * and consequently the chip will not respond to any command.
224 	 * Later on, during the normal initialization performed above, this
225 	 * analog switch will get configured according to what is selected
226 	 * in devicetree.
227 	 */
228 	uint32_t psel = NRF_DT_GPIOS_TO_PSEL(EXT_MEM_CTRL, control_gpios);
229 	gpio_dt_flags_t flags = DT_GPIO_FLAGS(EXT_MEM_CTRL, control_gpios);
230 
231 	if (flags & GPIO_ACTIVE_LOW) {
232 		nrf_gpio_pin_clear(psel);
233 	} else {
234 		nrf_gpio_pin_set(psel);
235 	}
236 	nrf_gpio_cfg_output(psel);
237 
238 	return 0;
239 }
240 
241 SYS_INIT(early_init, PRE_KERNEL_1, 0);
242 #endif
243