Skip to content

Commit d7f482a

Browse files
RuibinChangcarlescufi
authored andcommitted
ITE driver/gpio/it8xxx2: add kscan pins gpio driver
Add kscan pins gpio driver for KSI[7:0], KSO[15:0] pins that they can be configured to gpio mode. These pins registers address, bit fields and function are different from GPIO group, so I create a new compatible driver for these pins. Signed-off-by: Ruibin Chang <[email protected]>
1 parent 931e97a commit d7f482a

File tree

5 files changed

+313
-0
lines changed

5 files changed

+313
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SIFIVE gpio_sifive.c)
1212
zephyr_library_sources_ifdef(CONFIG_GPIO_GECKO gpio_gecko.c)
1313
zephyr_library_sources_ifdef(CONFIG_GPIO_IMX gpio_imx.c)
1414
zephyr_library_sources_ifdef(CONFIG_GPIO_ITE_IT8XXX2 gpio_ite_it8xxx2.c)
15+
zephyr_library_sources_ifdef(CONFIG_GPIO_KSCAN_ITE_IT8XXX2 gpio_kscan_ite_it8xxx2.c)
1516
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23S17 gpio_mcp23s17.c)
1617
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23XXX gpio_mcp23xxx.c)
1718
zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23SXX gpio_mcp23sxx.c)

drivers/gpio/Kconfig.it8xxx2

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,16 @@ config GPIO_ITE_IT8XXX2
77
depends on DT_HAS_ITE_IT8XXX2_GPIO_ENABLED
88
help
99
Enable driver for the ite GPIO controller.
10+
11+
config GPIO_KSCAN_ITE_IT8XXX2
12+
bool "ITE IT8XXX2 GPIO KSCAN driver"
13+
default y
14+
depends on DT_HAS_ITE_IT8XXX2_GPIOKSCAN_ENABLED
15+
help
16+
Enable GPIO KSCAN driver for ITE chip it8xxx2.
17+
IT8XXX2 support 8 KSI pins and 18 KSO pins, all of them can be configured
18+
to GPIO mode.
19+
KSI[7:0] and KSO[15:0] pins are configured to GPIO mode by
20+
this GPIO_KSCAN_ITE_IT8XXX2 driver.
21+
KSO[17:16] corresponds to GPC5 and GPC3 pin, so they can be configured to
22+
gpio mode by original GPIO_ITE_IT8XXX2 driver.
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/*
2+
* Copyright (c) 2022 ITE Corporation.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#define DT_DRV_COMPAT ite_it8xxx2_gpiokscan
8+
9+
#include <errno.h>
10+
#include <zephyr/device.h>
11+
#include <zephyr/drivers/gpio.h>
12+
#include <zephyr/drivers/gpio/gpio_utils.h>
13+
#include <zephyr/dt-bindings/gpio/ite-it8xxx2-gpio.h>
14+
#include <zephyr/sys/util.h>
15+
#include <zephyr/types.h>
16+
17+
struct gpio_kscan_cfg {
18+
/* The gpio_driver_config needs to be first */
19+
struct gpio_driver_config common;
20+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] port gpio output enable register (bit mapping to pin) */
21+
volatile uint8_t *reg_ksi_kso_goen;
22+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] port gpio control register (bit mapping to pin) */
23+
volatile uint8_t *reg_ksi_kso_gctrl;
24+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] port gpio data register (bit mapping to pin) */
25+
volatile uint8_t *reg_ksi_kso_gdat;
26+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] port gpio data mirror register (bit mapping to pin) */
27+
volatile uint8_t *reg_ksi_kso_gdmr;
28+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] port gpio open drain register (bit mapping to pin) */
29+
volatile uint8_t *reg_ksi_kso_gpod;
30+
};
31+
32+
struct gpio_kscan_data {
33+
/* The gpio_driver_data needs to be first */
34+
struct gpio_driver_data common;
35+
};
36+
37+
static int gpio_kscan_it8xxx2_configure(const struct device *dev,
38+
gpio_pin_t pin,
39+
gpio_flags_t flags)
40+
{
41+
const struct gpio_kscan_cfg *const config = dev->config;
42+
volatile uint8_t *reg_ksi_kso_gctrl = config->reg_ksi_kso_gctrl;
43+
volatile uint8_t *reg_ksi_kso_goen = config->reg_ksi_kso_goen;
44+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
45+
volatile uint8_t *reg_ksi_kso_gpod = config->reg_ksi_kso_gpod;
46+
uint8_t mask = BIT(pin);
47+
48+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] pins don't support open source, 1.8V and 5.0V mode */
49+
if ((((flags & GPIO_SINGLE_ENDED) != 0) && ((flags & GPIO_LINE_OPEN_DRAIN) == 0)) ||
50+
((flags & IT8XXX2_GPIO_VOLTAGE_MASK) == IT8XXX2_GPIO_VOLTAGE_1P8) ||
51+
((flags & IT8XXX2_GPIO_VOLTAGE_MASK) == IT8XXX2_GPIO_VOLTAGE_5P0)) {
52+
return -ENOTSUP;
53+
}
54+
55+
/* Set GPIO mode */
56+
*reg_ksi_kso_gctrl |= mask;
57+
58+
if (flags & GPIO_OUTPUT) {
59+
/*
60+
* Select open drain first, so that we don't glitch the signal
61+
* when changing the line to an output.
62+
*/
63+
if (flags & GPIO_OPEN_DRAIN) {
64+
/* Set open-drain and enable internal pullup */
65+
*reg_ksi_kso_gpod |= mask;
66+
} else {
67+
/* Set push-pull and disable internal pullup */
68+
*reg_ksi_kso_gpod &= ~mask;
69+
}
70+
71+
/* Set level before change to output */
72+
if (flags & GPIO_OUTPUT_INIT_HIGH) {
73+
*reg_ksi_kso_gdat |= mask;
74+
} else if (flags & GPIO_OUTPUT_INIT_LOW) {
75+
*reg_ksi_kso_gdat &= ~mask;
76+
}
77+
78+
/* Set output mode */
79+
*reg_ksi_kso_goen |= mask;
80+
} else {
81+
/* Set input mode */
82+
*reg_ksi_kso_goen &= ~mask;
83+
84+
if (flags & GPIO_PULL_UP) {
85+
/* Enable internal pullup */
86+
*reg_ksi_kso_gpod |= mask;
87+
} else {
88+
/* No internal pullup and pulldown */
89+
*reg_ksi_kso_gpod &= ~mask;
90+
}
91+
}
92+
93+
return 0;
94+
}
95+
96+
#ifdef CONFIG_GPIO_GET_CONFIG
97+
static int gpio_kscan_it8xxx2_get_config(const struct device *dev,
98+
gpio_pin_t pin,
99+
gpio_flags_t *out_flags)
100+
{
101+
const struct gpio_kscan_cfg *const config = dev->config;
102+
volatile uint8_t *reg_ksi_kso_goen = config->reg_ksi_kso_goen;
103+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
104+
volatile uint8_t *reg_ksi_kso_gpod = config->reg_ksi_kso_gpod;
105+
uint8_t mask = BIT(pin);
106+
gpio_flags_t flags = 0;
107+
108+
/* KSI[7:0]/KSO[15:8]/KSO[7:0] pins only support 3.3V */
109+
flags |= IT8XXX2_GPIO_VOLTAGE_3P3;
110+
111+
/* Input or output */
112+
if (*reg_ksi_kso_goen & mask) {
113+
flags |= GPIO_OUTPUT;
114+
115+
/* Open-drain or push-pull */
116+
if (*reg_ksi_kso_gpod & mask) {
117+
flags |= GPIO_OPEN_DRAIN;
118+
}
119+
120+
/* High or low */
121+
if (*reg_ksi_kso_gdat & mask) {
122+
flags |= GPIO_OUTPUT_HIGH;
123+
} else {
124+
flags |= GPIO_OUTPUT_LOW;
125+
}
126+
} else {
127+
flags |= GPIO_INPUT;
128+
129+
/* pullup or no pull */
130+
if (*reg_ksi_kso_gpod & mask) {
131+
flags |= GPIO_PULL_UP;
132+
}
133+
}
134+
135+
*out_flags = flags;
136+
137+
return 0;
138+
}
139+
#endif
140+
141+
static int gpio_kscan_it8xxx2_port_get_raw(const struct device *dev,
142+
gpio_port_value_t *value)
143+
{
144+
const struct gpio_kscan_cfg *const config = dev->config;
145+
volatile uint8_t *reg_ksi_kso_gdmr = config->reg_ksi_kso_gdmr;
146+
147+
/* Get physical level from all pins of the port */
148+
*value = *reg_ksi_kso_gdmr;
149+
150+
return 0;
151+
}
152+
153+
static int gpio_kscan_it8xxx2_port_set_masked_raw(const struct device *dev,
154+
gpio_port_pins_t mask,
155+
gpio_port_value_t value)
156+
{
157+
const struct gpio_kscan_cfg *const config = dev->config;
158+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
159+
uint8_t out = *reg_ksi_kso_gdat;
160+
161+
/* Set high/low level to mask pins of the port */
162+
*reg_ksi_kso_gdat = ((out & ~mask) | (value & mask));
163+
164+
return 0;
165+
}
166+
167+
static int gpio_kscan_it8xxx2_port_set_bits_raw(const struct device *dev,
168+
gpio_port_pins_t pins)
169+
{
170+
const struct gpio_kscan_cfg *const config = dev->config;
171+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
172+
173+
/* Set high level to pins of the port */
174+
*reg_ksi_kso_gdat |= pins;
175+
176+
return 0;
177+
}
178+
179+
static int gpio_kscan_it8xxx2_port_clear_bits_raw(const struct device *dev,
180+
gpio_port_pins_t pins)
181+
{
182+
const struct gpio_kscan_cfg *const config = dev->config;
183+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
184+
185+
/* Set low level to pins of the port */
186+
*reg_ksi_kso_gdat &= ~pins;
187+
188+
return 0;
189+
}
190+
191+
static int gpio_kscan_it8xxx2_port_toggle_bits(const struct device *dev,
192+
gpio_port_pins_t pins)
193+
{
194+
const struct gpio_kscan_cfg *const config = dev->config;
195+
volatile uint8_t *reg_ksi_kso_gdat = config->reg_ksi_kso_gdat;
196+
197+
/* Toggle output level to pins of the port */
198+
*reg_ksi_kso_gdat ^= pins;
199+
200+
return 0;
201+
}
202+
203+
static int gpio_kscan_it8xxx2_init(const struct device *dev)
204+
{
205+
return 0;
206+
}
207+
208+
static const struct gpio_driver_api gpio_kscan_it8xxx2_driver_api = {
209+
.pin_configure = gpio_kscan_it8xxx2_configure,
210+
#ifdef CONFIG_GPIO_GET_CONFIG
211+
.pin_get_config = gpio_kscan_it8xxx2_get_config,
212+
#endif
213+
.port_get_raw = gpio_kscan_it8xxx2_port_get_raw,
214+
.port_set_masked_raw = gpio_kscan_it8xxx2_port_set_masked_raw,
215+
.port_set_bits_raw = gpio_kscan_it8xxx2_port_set_bits_raw,
216+
.port_clear_bits_raw = gpio_kscan_it8xxx2_port_clear_bits_raw,
217+
.port_toggle_bits = gpio_kscan_it8xxx2_port_toggle_bits,
218+
};
219+
220+
#define GPIO_KSCAN_IT8XXX2_INIT(inst) \
221+
static const struct gpio_kscan_cfg gpio_kscan_it8xxx2_cfg_##inst = { \
222+
.common = { \
223+
.port_pin_mask = GPIO_PORT_PIN_MASK_FROM_NGPIOS( \
224+
DT_INST_PROP(inst, ngpios)) \
225+
}, \
226+
.reg_ksi_kso_goen = (uint8_t *)DT_INST_REG_ADDR_BY_NAME(inst, goen), \
227+
.reg_ksi_kso_gctrl = (uint8_t *)DT_INST_REG_ADDR_BY_NAME(inst, gctrl), \
228+
.reg_ksi_kso_gdat = (uint8_t *)DT_INST_REG_ADDR_BY_NAME(inst, gdat), \
229+
.reg_ksi_kso_gdmr = (uint8_t *)DT_INST_REG_ADDR_BY_NAME(inst, gdmr), \
230+
.reg_ksi_kso_gpod = (uint8_t *)DT_INST_REG_ADDR_BY_NAME(inst, gpod), \
231+
}; \
232+
\
233+
static struct gpio_kscan_data gpio_kscan_it8xxx2_data_##inst; \
234+
\
235+
DEVICE_DT_INST_DEFINE(inst, \
236+
gpio_kscan_it8xxx2_init, \
237+
NULL, \
238+
&gpio_kscan_it8xxx2_data_##inst, \
239+
&gpio_kscan_it8xxx2_cfg_##inst, \
240+
PRE_KERNEL_1, \
241+
CONFIG_GPIO_INIT_PRIORITY, \
242+
&gpio_kscan_it8xxx2_driver_api);
243+
244+
DT_INST_FOREACH_STATUS_OKAY(GPIO_KSCAN_IT8XXX2_INIT)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Copyright (c) 2022 ITE Corporation. All Rights Reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: This binding gives a base representation of the ITE kscan pins as gpio
5+
6+
compatible: "ite,it8xxx2-gpiokscan"
7+
8+
include: [base.yaml, gpio-controller.yaml]
9+
10+
properties:
11+
reg:
12+
required: true
13+
14+
gpio-cells:
15+
- pin
16+
- flags

dts/riscv/ite/it81xx2.dtsi

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,45 @@
1313
reg = <0x00f01600 0x100>;
1414
};
1515

16+
gpioksi: gpiokscan@f01d07 {
17+
compatible = "ite,it8xxx2-gpiokscan";
18+
reg = <0x00f01d07 1
19+
0x00f01d06 1
20+
0x00f01d08 1
21+
0x00f01d09 1
22+
0x00f01d26 1>;
23+
reg-names = "goen", "gctrl", "gdat", "gdmr", "gpod";
24+
ngpios = <8>;
25+
gpio-controller;
26+
#gpio-cells = <2>;
27+
};
28+
29+
gpioksoh: gpiokscan@f01d0b {
30+
compatible = "ite,it8xxx2-gpiokscan";
31+
reg = <0x00f01d0b 1
32+
0x00f01d0a 1
33+
0x00f01d01 1
34+
0x00f01d0c 1
35+
0x00f01d27 1>;
36+
reg-names = "goen", "gctrl", "gdat", "gdmr", "gpod";
37+
ngpios = <8>;
38+
gpio-controller;
39+
#gpio-cells = <2>;
40+
};
41+
42+
gpioksol: gpiokscan@f01d0e {
43+
compatible = "ite,it8xxx2-gpiokscan";
44+
reg = <0x00f01d0e 1
45+
0x00f01d0d 1
46+
0x00f01d00 1
47+
0x00f01d0f 1
48+
0x00f01d28 1>;
49+
reg-names = "goen", "gctrl", "gdat", "gdmr", "gpod";
50+
ngpios = <8>;
51+
gpio-controller;
52+
#gpio-cells = <2>;
53+
};
54+
1655
pinctrl: pin-controller {
1756
compatible = "ite,it8xxx2-pinctrl";
1857
#address-cells = <1>;

0 commit comments

Comments
 (0)