forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpinmux_mchp_xec.c
151 lines (126 loc) · 3.95 KB
/
pinmux_mchp_xec.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
* Copyright (c) 2019 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/pinmux.h>
#include <soc.h>
#include <sys/printk.h>
#define DT_DRV_COMPAT microchip_xec_pinmux
static const uint32_t valid_ctrl_masks[NUM_MCHP_GPIO_PORTS] = {
(MCHP_GPIO_PORT_A_BITMAP),
(MCHP_GPIO_PORT_B_BITMAP),
(MCHP_GPIO_PORT_C_BITMAP),
(MCHP_GPIO_PORT_D_BITMAP),
(MCHP_GPIO_PORT_E_BITMAP),
(MCHP_GPIO_PORT_F_BITMAP)
};
struct pinmux_xec_config {
uintptr_t pcr1_base;
uint32_t port_num;
};
static int pinmux_xec_set(const struct device *dev, uint32_t pin,
uint32_t func)
{
const struct pinmux_xec_config *config = dev->config;
uintptr_t current_pcr1;
uint32_t pcr1 = 0;
uint32_t mask = 0;
uint32_t temp = 0;
/* Validate pin number in terms of current port */
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0) {
return -EINVAL;
}
mask |= MCHP_GPIO_CTRL_BUFT_MASK | MCHP_GPIO_CTRL_MUX_MASK |
MCHP_GPIO_CTRL_INPAD_DIS_MASK;
/* Check for open drain/push_pull setting */
if (func & MCHP_GPIO_CTRL_BUFT_OPENDRAIN) {
pcr1 |= MCHP_GPIO_CTRL_BUFT_OPENDRAIN;
} else {
pcr1 |= MCHP_GPIO_CTRL_BUFT_PUSHPULL;
}
/* Parse mux mode */
pcr1 |= func & MCHP_GPIO_CTRL_MUX_MASK;
/* Figure out the pullup/pulldown configuration */
mask |= MCHP_GPIO_CTRL_PUD_MASK;
if (func & MCHP_GPIO_CTRL_PUD_PU) {
/* Enable the pull and select the pullup resistor. */
pcr1 |= MCHP_GPIO_CTRL_PUD_PU;
} else if (func & MCHP_GPIO_CTRL_PUD_PD) {
/* Enable the pull and select the pulldown resistor */
pcr1 |= MCHP_GPIO_CTRL_PUD_PD;
} else {
/* None : Pin tristates when no active driver is present
* on the pin. This is the POR setting
*/
pcr1 |= MCHP_GPIO_CTRL_PUD_NONE;
}
/* Make sure gpio isrs are disabled */
pcr1 |= MCHP_GPIO_CTRL_IDET_DISABLE;
mask |= MCHP_GPIO_CTRL_IDET_MASK;
/* Now write contents of pcr1 variable to the PCR1 register that
* corresponds to the pin configured. Each pin control register
* on a 32-bit boundary.
*/
current_pcr1 = config->pcr1_base + pin * 4;
temp = (sys_read32(current_pcr1) & ~mask) | pcr1;
sys_write32(temp, current_pcr1);
return 0;
}
static int pinmux_xec_get(const struct device *dev, uint32_t pin,
uint32_t *func)
{
const struct pinmux_xec_config *config = dev->config;
uintptr_t current_pcr1;
/* Validate pin number in terms of current port */
if ((valid_ctrl_masks[config->port_num] & BIT(pin)) == 0) {
return -EINVAL;
}
current_pcr1 = config->pcr1_base + pin * 4;
*func = sys_read32(current_pcr1) & (MCHP_GPIO_CTRL_BUFT_MASK
| MCHP_GPIO_CTRL_MUX_MASK
| MCHP_GPIO_CTRL_PUD_MASK);
return 0;
}
static int pinmux_xec_pullup(const struct device *dev, uint32_t pin,
uint8_t func)
{
return -ENOTSUP;
}
static int pinmux_xec_input(const struct device *dev, uint32_t pin,
uint8_t func)
{
return -ENOTSUP;
}
static int pinmux_xec_init(const struct device *dev)
{
/* Nothing to do. The PCR clock is enabled at reset. */
return 0;
}
static const struct pinmux_driver_api pinmux_xec_driver_api = {
.set = pinmux_xec_set,
.get = pinmux_xec_get,
.pullup = pinmux_xec_pullup,
.input = pinmux_xec_input,
};
/* Get ph_reg address given a node-id */
#define PINMUX_ADDR(n) DT_REG_ADDR(DT_PHANDLE(n, ph_reg))
/* Get ph_reg address given instance */
#define PINMUX_INST_ADDR(n) DT_REG_ADDR(DT_PHANDLE(DT_NODELABEL(n), ph_reg))
/* Get port-num property */
#define PINMUX_PORT_NUM(n) DT_PROP(DT_NODELABEL(n), port_num)
/* id is a child node-id */
#define PINMUX_XEC_DEVICE(id) \
static const struct pinmux_xec_config pinmux_xec_port_cfg_##id = { \
.pcr1_base = (uintptr_t)PINMUX_ADDR(id), \
.port_num = (uint32_t)DT_PROP(id, port_num), \
}; \
DEVICE_DT_DEFINE(id, &pinmux_xec_init, NULL, NULL, \
&pinmux_xec_port_cfg_##id, \
PRE_KERNEL_1, \
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
&pinmux_xec_driver_api);
DT_FOREACH_CHILD_STATUS_OKAY(DT_NODELABEL(pinmux), PINMUX_XEC_DEVICE)