Skip to content

Commit 6c76b41

Browse files
Yuriy Vynnychekcfriedt
authored andcommitted
drivers: pinmux: introduce new Telink B91 Pinmux driver
Pinmux driver basic support for new Telink B91 platform. Signed-off-by: Yuriy Vynnychek <[email protected]>
1 parent 215cdc7 commit 6c76b41

File tree

5 files changed

+258
-0
lines changed

5 files changed

+258
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@
267267
/drivers/modem/Kconfig.hl7800 @rerickson1
268268
/drivers/pcie/ @dcpleung @nashif @jhedberg
269269
/drivers/peci/ @albertofloyd @franciscomunoz @scottwcpg
270+
/drivers/pinmux/*b91* @yurvyn
270271
/drivers/pinmux/*hsdk* @iriszzw
271272
/drivers/pinmux/*it8xxx2* @ite
272273
/drivers/pm_cpu_ops/ @carlocaione

drivers/pinmux/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
# Board initialization
4+
zephyr_sources_ifdef(CONFIG_PINMUX_TELINK_B91 pinmux_b91.c)
45
zephyr_sources_ifdef(CONFIG_PINMUX_CC13XX_CC26XX pinmux_cc13xx_cc26xx.c)
56
zephyr_sources_ifdef(CONFIG_PINMUX_ESP32 pinmux_esp32.c)
67
zephyr_sources_ifdef(CONFIG_PINMUX_HSDK pinmux_hsdk.c)

drivers/pinmux/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ config PINMUX_INIT_PRIORITY
2424
rule for particular boards. Don't change this value unless you
2525
know what you are doing.
2626

27+
source "drivers/pinmux/Kconfig.b91"
28+
2729
source "drivers/pinmux/Kconfig.beetle"
2830

2931
source "drivers/pinmux/Kconfig.cc13xx_cc26xx"

drivers/pinmux/Kconfig.b91

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright (c) 2021 Telink Semiconductor
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config PINMUX_TELINK_B91
5+
bool "Telink Semiconductor B91 pinmux driver"
6+
depends on SOC_RISCV_TELINK_B91
7+
default y
8+
help
9+
Enables Telink B91 pinmux driver.

drivers/pinmux/pinmux_b91.c

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* Copyright (c) 2021 Telink Semiconductor
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT telink_b91_pinmux
8+
9+
#include "analog.h"
10+
#include <drivers/pinmux.h>
11+
12+
13+
/**
14+
* GPIO Function Enable Register
15+
* ADDR PINS
16+
* gpio_en: PORT_A[0-7]
17+
* gpio_en + 1*8: PORT_B[0-7]
18+
* gpio_en + 2*8: PORT_C[0-7]
19+
* gpio_en + 3*8: PORT_D[0-7]
20+
* gpio_en + 4*8: PORT_E[0-7]
21+
* gpio_en + 5*8: PORT_F[0-7]
22+
*/
23+
#define reg_gpio_en(pin) (*(volatile uint8_t *)((uint32_t)DT_INST_REG_ADDR_BY_NAME(0, gpio_en) + \
24+
((pin >> 8) * 8)))
25+
26+
/**
27+
* Function Multiplexer Register
28+
* ADDR PINS
29+
* pin_mux: PORT_A[0-3]
30+
* pin_mux + 1: PORT_A[4-7]
31+
* pin_mux + 2: PORT_B[0-3]
32+
* pin_mux + 3: PORT_B[4-7]
33+
* pin_mux + 4: PORT_C[0-3]
34+
* pin_mux + 5: PORT_C[4-7]
35+
* pin_mux + 6: PORT_D[0-3]
36+
* pin_mux + 7: PORT_D[4-7]
37+
* pin_mux + 0x20: PORT_E[0-3]
38+
* pin_mux + 0x21: PORT_E[4-7]
39+
* pin_mux + 0x26: PORT_F[0-3]
40+
* pin_mux + 0x27: PORT_F[4-7]
41+
*/
42+
#define reg_pin_mux(pin) (*(volatile uint8_t *)((uint32_t)DT_INST_REG_ADDR_BY_NAME(0, pin_mux) + \
43+
(((pin >> 8) < 4) ? ((pin >> 8) * 2) : 0) + \
44+
(((pin >> 8) == 4) ? 0x20 : 0) + \
45+
(((pin >> 8) == 5) ? 0x26 : 0) + \
46+
((pin & 0x0f0) ? 1 : 0)))
47+
48+
/**
49+
* Pull Up resistors enable
50+
* ADDR PINS
51+
* pull_up_en: PORT_A[0-3]
52+
* pull_up_en + 1: PORT_A[4-7]
53+
* pull_up_en + 2: PORT_B[0-3]
54+
* pull_up_en + 3: PORT_B[4-7]
55+
* pull_up_en + 4: PORT_C[0-3]
56+
* pull_up_en + 5: PORT_C[4-7]
57+
* pull_up_en + 6: PORT_D[0-3]
58+
* pull_up_en + 7: PORT_D[4-7]
59+
* pull_up_en + 8: PORT_E[0-3]
60+
* pull_up_en + 9: PORT_E[4-7]
61+
* pull_up_en + 10: PORT_F[0-3]
62+
* pull_up_en + 11: PORT_F[4-7]
63+
*/
64+
#define reg_pull_up_en(pin) ((uint8_t)(DT_INST_REG_ADDR_BY_NAME(0, pull_up_en) + \
65+
((pin >> 8) * 2) + \
66+
((pin & 0xf0) ? 1 : 0)))
67+
68+
/* GPIO Pull-Up options */
69+
#define PINMUX_B91_PULLUP_DISABLE ((uint8_t)0u)
70+
#define PINMUX_B91_PULLUP_10K ((uint8_t)3u)
71+
72+
/* Get PinMux configuration */
73+
#define GET_CFG(dev) ((const struct pinmux_b91_config *)dev->config)
74+
75+
76+
/* B91 PinMux config structure */
77+
struct pinmux_b91_config {
78+
uint8_t pad_mul_sel;
79+
};
80+
81+
82+
/* Act as GPIO function disable */
83+
static inline void pinmux_b91_gpio_function_disable(uint32_t pin)
84+
{
85+
uint8_t bit = pin & 0xff;
86+
87+
reg_gpio_en(pin) &= ~bit;
88+
}
89+
90+
/* Get function value bits start position (offset) */
91+
static inline int pinmux_b91_get_func_offset(uint32_t pin, uint8_t *offset)
92+
{
93+
switch ((pin & 0x0fu) != 0u ? pin & 0x0fu : (pin & 0xf0u) >> 4u) {
94+
case BIT(0):
95+
*offset = 0u;
96+
break;
97+
case BIT(1):
98+
*offset = 2u;
99+
break;
100+
case BIT(2):
101+
*offset = 4u;
102+
break;
103+
case BIT(3):
104+
*offset = 6u;
105+
break;
106+
107+
default:
108+
return -EINVAL;
109+
}
110+
111+
return 0;
112+
}
113+
114+
/* Set pin's pull-up/down resistor */
115+
static void pinmux_b91_set_pull_up(uint32_t pin, uint8_t val)
116+
{
117+
uint8_t mask = 0;
118+
uint8_t analog_reg = reg_pull_up_en(pin);
119+
120+
if (pin & 0x11) {
121+
val = val;
122+
mask = 0xfc;
123+
} else if (pin & 0x22) {
124+
val = val << 2;
125+
mask = 0xf3;
126+
} else if (pin & 0x44) {
127+
val = val << 4;
128+
mask = 0xcf;
129+
} else if (pin & 0x88) {
130+
val = val << 6;
131+
mask = 0x3f;
132+
} else {
133+
return;
134+
}
135+
136+
analog_write_reg8(analog_reg, (analog_read_reg8(analog_reg) & mask) | val);
137+
}
138+
139+
/* API implementation: init */
140+
static int pinmux_b91_init(const struct device *dev)
141+
{
142+
const struct pinmux_b91_config *cfg = GET_CFG(dev);
143+
144+
reg_gpio_pad_mul_sel |= cfg->pad_mul_sel;
145+
146+
return 0;
147+
}
148+
149+
/* API implementation: set */
150+
static int pinmux_b91_set(const struct device *dev, uint32_t pin, uint32_t func)
151+
{
152+
ARG_UNUSED(dev);
153+
154+
uint8_t mask = 0;
155+
uint8_t offset = 0;
156+
int32_t status = 0;
157+
158+
/* calculate offset and mask for the func value */
159+
status = pinmux_b91_get_func_offset(pin, &offset);
160+
if (status != 0) {
161+
return status;
162+
}
163+
mask = (uint8_t)~(BIT(offset) | BIT(offset + 1));
164+
165+
/* disable GPIO function (can be enabled back by GPIO init using GPIO driver) */
166+
pinmux_b91_gpio_function_disable(pin);
167+
168+
/* set func value */
169+
reg_pin_mux(pin) = (reg_pin_mux(pin) & mask) | (func << offset);
170+
171+
return status;
172+
}
173+
174+
/* API implementation: get */
175+
static int pinmux_b91_get(const struct device *dev, uint32_t pin, uint32_t *func)
176+
{
177+
ARG_UNUSED(dev);
178+
179+
uint8_t mask = 0u;
180+
uint8_t offset = 0;
181+
int32_t status = 0;
182+
183+
/* calculate offset and mask for the func value */
184+
status = pinmux_b91_get_func_offset(pin, &offset);
185+
if (status != 0) {
186+
return status;
187+
}
188+
mask = (uint8_t)(BIT(offset) | BIT(offset + 1));
189+
190+
/* get func value */
191+
*func = (reg_pin_mux(pin) & mask) >> offset;
192+
193+
return status;
194+
}
195+
196+
/* API implementation: pullup */
197+
static int pinmux_b91_pullup(const struct device *dev, uint32_t pin, uint8_t func)
198+
{
199+
ARG_UNUSED(dev);
200+
201+
switch (func) {
202+
case PINMUX_PULLUP_ENABLE:
203+
pinmux_b91_set_pull_up(pin, PINMUX_B91_PULLUP_10K);
204+
break;
205+
206+
case PINMUX_PULLUP_DISABLE:
207+
pinmux_b91_set_pull_up(pin, PINMUX_B91_PULLUP_DISABLE);
208+
break;
209+
210+
default:
211+
return -ENOTSUP;
212+
}
213+
214+
return 0;
215+
}
216+
217+
/* API implementation: input */
218+
static int pinmux_b91_input(const struct device *dev, uint32_t pin, uint8_t func)
219+
{
220+
ARG_UNUSED(dev);
221+
ARG_UNUSED(pin);
222+
ARG_UNUSED(func);
223+
224+
/* Implemented by GPIO driver */
225+
226+
return -ENOTSUP;
227+
}
228+
229+
/* PinMux driver APIs structure */
230+
static const struct pinmux_driver_api pinmux_b91_api = {
231+
.set = pinmux_b91_set,
232+
.get = pinmux_b91_get,
233+
.pullup = pinmux_b91_pullup,
234+
.input = pinmux_b91_input,
235+
};
236+
237+
static const struct pinmux_b91_config pinmux_b91_cfg = {
238+
.pad_mul_sel = DT_INST_PROP(0, pad_mul_sel)
239+
};
240+
241+
/* PinMux driver registration */
242+
DEVICE_DT_INST_DEFINE(0, pinmux_b91_init,
243+
NULL, NULL, &pinmux_b91_cfg, PRE_KERNEL_1,
244+
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
245+
&pinmux_b91_api);

0 commit comments

Comments
 (0)