1 /*
2 * Copyright (c) 2022 Telink Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "analog.h"
8 #include <zephyr/drivers/pinctrl.h>
9 #include <zephyr/dt-bindings/pinctrl/b91-pinctrl.h>
10 #include <zephyr/init.h>
11
12 #define DT_DRV_COMPAT telink_b91_pinctrl
13
14 /**
15 * GPIO Function Enable Register
16 * ADDR PINS
17 * gpio_en: PORT_A[0-7]
18 * gpio_en + 1*8: PORT_B[0-7]
19 * gpio_en + 2*8: PORT_C[0-7]
20 * gpio_en + 3*8: PORT_D[0-7]
21 * gpio_en + 4*8: PORT_E[0-7]
22 * gpio_en + 5*8: PORT_F[0-7]
23 */
24 #define reg_gpio_en(pin) (*(volatile uint8_t *)((uint32_t)DT_INST_REG_ADDR_BY_NAME(0, gpio_en) + \
25 ((pin >> 8) * 8)))
26
27 /**
28 * Function Multiplexer Register
29 * ADDR PINS
30 * pin_mux: PORT_A[0-3]
31 * pin_mux + 1: PORT_A[4-7]
32 * pin_mux + 2: PORT_B[0-3]
33 * pin_mux + 3: PORT_B[4-7]
34 * pin_mux + 4: PORT_C[0-3]
35 * pin_mux + 5: PORT_C[4-7]
36 * pin_mux + 6: PORT_D[0-3]
37 * pin_mux + 7: PORT_D[4-7]
38 * pin_mux + 0x20: PORT_E[0-3]
39 * pin_mux + 0x21: PORT_E[4-7]
40 * pin_mux + 0x26: PORT_F[0-3]
41 * pin_mux + 0x27: PORT_F[4-7]
42 */
43 #define reg_pin_mux(pin) (*(volatile uint8_t *)((uint32_t)DT_INST_REG_ADDR_BY_NAME(0, pin_mux) + \
44 (((pin >> 8) < 4) ? ((pin >> 8) * 2) : 0) + \
45 (((pin >> 8) == 4) ? 0x20 : 0) + \
46 (((pin >> 8) == 5) ? 0x26 : 0) + \
47 ((pin & 0x0f0) ? 1 : 0)))
48
49 /**
50 * Pull Up resistors enable
51 * ADDR PINS
52 * pull_up_en: PORT_A[0-3]
53 * pull_up_en + 1: PORT_A[4-7]
54 * pull_up_en + 2: PORT_B[0-3]
55 * pull_up_en + 3: PORT_B[4-7]
56 * pull_up_en + 4: PORT_C[0-3]
57 * pull_up_en + 5: PORT_C[4-7]
58 * pull_up_en + 6: PORT_D[0-3]
59 * pull_up_en + 7: PORT_D[4-7]
60 * pull_up_en + 8: PORT_E[0-3]
61 * pull_up_en + 9: PORT_E[4-7]
62 * pull_up_en + 10: PORT_F[0-3]
63 * pull_up_en + 11: PORT_F[4-7]
64 */
65 #define reg_pull_up_en(pin) ((uint8_t)(DT_INST_REG_ADDR_BY_NAME(0, pull_up_en) + \
66 ((pin >> 8) * 2) + \
67 ((pin & 0xf0) ? 1 : 0)))
68
69 /* Pinctrl driver initialization */
pinctrl_b91_init(void)70 static int pinctrl_b91_init(void)
71 {
72
73 /* set pad_mul_sel register value from dts */
74 reg_gpio_pad_mul_sel |= DT_INST_PROP(0, pad_mul_sel);
75
76 return 0;
77 }
78
79 SYS_INIT(pinctrl_b91_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
80
81 /* Act as GPIO function disable */
pinctrl_b91_gpio_function_disable(uint32_t pin)82 static inline void pinctrl_b91_gpio_function_disable(uint32_t pin)
83 {
84 uint8_t bit = pin & 0xff;
85
86 reg_gpio_en(pin) &= ~bit;
87 }
88
89 /* Get function value bits start position (offset) */
pinctrl_b91_get_offset(uint32_t pin,uint8_t * offset)90 static inline int pinctrl_b91_get_offset(uint32_t pin, uint8_t *offset)
91 {
92 switch (B91_PINMUX_GET_PIN_ID(pin)) {
93 case B91_PIN_0:
94 *offset = B91_PIN_0_FUNC_POS;
95 break;
96 case B91_PIN_1:
97 *offset = B91_PIN_1_FUNC_POS;
98 break;
99 case B91_PIN_2:
100 *offset = B91_PIN_2_FUNC_POS;
101 break;
102 case B91_PIN_3:
103 *offset = B91_PIN_3_FUNC_POS;
104 break;
105 case B91_PIN_4:
106 *offset = B91_PIN_4_FUNC_POS;
107 break;
108 case B91_PIN_5:
109 *offset = B91_PIN_5_FUNC_POS;
110 break;
111 case B91_PIN_6:
112 *offset = B91_PIN_6_FUNC_POS;
113 break;
114 case B91_PIN_7:
115 *offset = B91_PIN_7_FUNC_POS;
116 break;
117
118 default:
119 return -EINVAL;
120 }
121
122 return 0;
123 }
124
125 /* Set pin's function */
pinctrl_configure_pin(const pinctrl_soc_pin_t * pinctrl)126 static int pinctrl_configure_pin(const pinctrl_soc_pin_t *pinctrl)
127 {
128 int status;
129 uint8_t mask;
130 uint8_t offset = 0;
131 uint8_t pull = B91_PINMUX_GET_PULL(*pinctrl);
132 uint8_t func = B91_PINMUX_GET_FUNC(*pinctrl);
133 uint32_t pin = B91_PINMUX_GET_PIN(*pinctrl);
134 uint8_t pull_up_en_addr = reg_pull_up_en(pin);
135
136 /* calculate offset and mask for the func and pull values */
137 status = pinctrl_b91_get_offset(pin, &offset);
138 if (status != 0) {
139 return status;
140 }
141 mask = (uint8_t) ~(BIT(offset) | BIT(offset + 1));
142
143 /* disable GPIO function (can be enabled back by GPIO init using GPIO driver) */
144 pinctrl_b91_gpio_function_disable(pin);
145
146 /* set func value */
147 func = func << offset;
148 reg_pin_mux(pin) = (reg_pin_mux(pin) & mask) | func;
149
150 /* set pull value */
151 pull = pull << offset;
152 analog_write_reg8(pull_up_en_addr, (analog_read_reg8(pull_up_en_addr) & mask) | pull);
153
154 return status;
155 }
156
157 /* API implementation: configure_pins */
pinctrl_configure_pins(const pinctrl_soc_pin_t * pins,uint8_t pin_cnt,uintptr_t reg)158 int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg)
159 {
160 ARG_UNUSED(reg);
161
162 int status = 0;
163
164 for (uint8_t i = 0; i < pin_cnt; i++) {
165 status = pinctrl_configure_pin(pins++);
166 if (status < 0) {
167 break;
168 }
169 }
170
171 return status;
172 }
173