Skip to content

Commit eaadea5

Browse files
gmarullcarlescufi
authored andcommitted
drivers: gpio: npm6001: initial driver
Add GPIO driver for the GPIO controller embedded in the nPM6001 PMIC. Signed-off-by: Gerard Marull-Paretas <[email protected]>
1 parent e77e137 commit eaadea5

File tree

6 files changed

+339
-0
lines changed

6 files changed

+339
-0
lines changed

drivers/gpio/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,4 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_TCA6424A gpio_tca6424a.c)
6666
zephyr_library_sources_ifdef(CONFIG_GPIO_SHELL gpio_shell.c)
6767
zephyr_library_sources_ifdef(CONFIG_USERSPACE gpio_handlers.c)
6868
zephyr_library_sources_ifdef(CONFIG_GPIO_XMC4XXX gpio_xmc4xxx.c)
69+
zephyr_library_sources_ifdef(CONFIG_GPIO_NPM6001 gpio_npm6001.c)

drivers/gpio/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,4 +156,6 @@ source "drivers/gpio/Kconfig.s32"
156156

157157
source "drivers/gpio/Kconfig.tca6424a"
158158

159+
source "drivers/gpio/Kconfig.npm6001"
160+
159161
endif # GPIO

drivers/gpio/Kconfig.npm6001

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Copyright (c) 2022 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
config GPIO_NPM6001
5+
bool "nPM6001 GPIO driver"
6+
default y
7+
depends on DT_HAS_NORDIC_NPM6001_GPIO_ENABLED
8+
select I2C
9+
help
10+
Enable the nPM6001 GPIO driver.
11+
12+
config GPIO_NPM6001_INIT_PRIORITY
13+
int "nPM6001 GPIO driver initialization priority"
14+
depends on GPIO_NPM6001
15+
default 60
16+
help
17+
Initialization priority for the nPM6001 GPIO driver. It must be
18+
greater than the I2C controller init priority.

drivers/gpio/gpio_npm6001.c

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#define DT_DRV_COMPAT nordic_npm6001_gpio
7+
8+
#include <errno.h>
9+
10+
#include <zephyr/drivers/gpio.h>
11+
#include <zephyr/drivers/gpio/gpio_utils.h>
12+
#include <zephyr/drivers/i2c.h>
13+
#include <zephyr/dt-bindings/gpio/nordic-npm6001-gpio.h>
14+
#include <zephyr/kernel.h>
15+
#include <zephyr/sys/util_macro.h>
16+
#include <zephyr/toolchain.h>
17+
18+
/* nPM6001 GPIO related registers */
19+
#define NPM6001_GPIOOUTSET 0x69U
20+
#define NPM6001_GPIOOUTCLR 0x6AU
21+
#define NPM6001_GPIOIN 0x6BU
22+
#define NPM6001_GPIO0CONF 0x6CU
23+
#define NPM6001_GPIO1CONF 0x6DU
24+
#define NPM6001_GPIO2CONF 0x6EU
25+
26+
/* GPIO(0|1|2)CONF fields */
27+
#define NPM6001_CONF_DIRECTION_OUTPUT BIT(0)
28+
#define NPM6001_CONF_INPUT_ENABLED BIT(1)
29+
#define NPM6001_CONF_PULLDOWN_ENABLED BIT(2)
30+
#define NPM6001_CONF_DRIVE_HIGH BIT(5)
31+
#define NPM6001_CONF_SENSE_CMOS BIT(6)
32+
33+
#define NPM6001_PIN_MAX 2U
34+
#define NPM6001_PIN_MSK 0x7U
35+
36+
struct gpio_npm6001_config {
37+
struct gpio_driver_config common;
38+
struct i2c_dt_spec bus;
39+
};
40+
41+
struct gpio_npm6001_data {
42+
struct gpio_driver_data common;
43+
};
44+
45+
static int gpio_npm6001_port_get_raw(const struct device *dev, uint32_t *value)
46+
{
47+
const struct gpio_npm6001_config *config = dev->config;
48+
uint8_t reg = NPM6001_GPIOIN;
49+
uint8_t val;
50+
int ret;
51+
52+
if (k_is_in_isr()) {
53+
return -EWOULDBLOCK;
54+
}
55+
56+
ret = i2c_write_read_dt(&config->bus, &reg, sizeof(reg), &val,
57+
sizeof(val));
58+
if (ret < 0) {
59+
return ret;
60+
}
61+
62+
*value = val;
63+
64+
return 0;
65+
}
66+
67+
static int gpio_npm6001_port_set_bits_raw(const struct device *dev,
68+
gpio_port_pins_t pins)
69+
{
70+
const struct gpio_npm6001_config *config = dev->config;
71+
uint8_t buf[2] = {NPM6001_GPIOOUTSET, (uint8_t)pins & NPM6001_PIN_MSK};
72+
73+
if (k_is_in_isr()) {
74+
return -EWOULDBLOCK;
75+
}
76+
77+
return i2c_write_dt(&config->bus, buf, sizeof(buf));
78+
}
79+
80+
static int gpio_npm6001_port_clear_bits_raw(const struct device *dev,
81+
gpio_port_pins_t pins)
82+
{
83+
const struct gpio_npm6001_config *config = dev->config;
84+
uint8_t buf[2] = {NPM6001_GPIOOUTCLR, (uint8_t)pins & NPM6001_PIN_MSK};
85+
86+
if (k_is_in_isr()) {
87+
return -EWOULDBLOCK;
88+
}
89+
90+
return i2c_write_dt(&config->bus, buf, sizeof(buf));
91+
}
92+
93+
static inline int gpio_npm6001_configure(const struct device *dev,
94+
gpio_pin_t pin, gpio_flags_t flags)
95+
{
96+
const struct gpio_npm6001_config *config = dev->config;
97+
uint8_t buf[2] = {NPM6001_GPIO0CONF, 0U};
98+
99+
if (k_is_in_isr()) {
100+
return -EWOULDBLOCK;
101+
}
102+
103+
if (pin > NPM6001_PIN_MAX) {
104+
return -EINVAL;
105+
}
106+
107+
/* select GPIO0CONF/GPIO1CONF/GPIO2CONF */
108+
buf[0] += pin;
109+
110+
if ((flags & GPIO_OUTPUT) != 0U) {
111+
/* input buffer enabled to allow reading output level */
112+
buf[1] |= NPM6001_CONF_DIRECTION_OUTPUT |
113+
NPM6001_CONF_INPUT_ENABLED;
114+
115+
/* open-drain/open-source not supported */
116+
if ((flags & GPIO_SINGLE_ENDED) != 0U) {
117+
return -ENOTSUP;
118+
}
119+
120+
/* drive strength (defaults to normal) */
121+
if ((flags & NPM6001_GPIO_DRIVE_MSK) ==
122+
NPM6001_GPIO_DRIVE_HIGH) {
123+
buf[1] |= NPM6001_CONF_DRIVE_HIGH;
124+
}
125+
126+
if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0U) {
127+
int ret;
128+
129+
ret = gpio_npm6001_port_set_bits_raw(
130+
dev, (gpio_port_pins_t)BIT(pin));
131+
if (ret < 0) {
132+
return ret;
133+
}
134+
} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0U) {
135+
int ret;
136+
137+
ret = gpio_npm6001_port_clear_bits_raw(
138+
dev, (gpio_port_pins_t)BIT(pin));
139+
if (ret < 0) {
140+
return ret;
141+
}
142+
}
143+
} else if ((flags & GPIO_INPUT) != 0U) {
144+
buf[1] |= NPM6001_CONF_INPUT_ENABLED;
145+
146+
/* pull resistor */
147+
if ((flags & GPIO_PULL_DOWN) != 0U) {
148+
buf[1] |= NPM6001_CONF_PULLDOWN_ENABLED;
149+
} else if ((flags & GPIO_PULL_UP) != 0U) {
150+
return -ENOTSUP;
151+
}
152+
153+
/* input type (defaults to schmitt trigger) */
154+
if ((flags & NPM6001_GPIO_SENSE_MSK) ==
155+
NPM6001_GPIO_SENSE_CMOS) {
156+
buf[1] |= NPM6001_CONF_SENSE_CMOS;
157+
}
158+
} else {
159+
return -ENOTSUP;
160+
}
161+
162+
return i2c_write_dt(&config->bus, buf, sizeof(buf));
163+
}
164+
165+
static int gpio_npm6001_port_set_masked_raw(const struct device *dev,
166+
gpio_port_pins_t mask,
167+
gpio_port_value_t value)
168+
{
169+
int ret;
170+
171+
ret = gpio_npm6001_port_set_bits_raw(dev, mask & value);
172+
if (ret < 0) {
173+
return ret;
174+
}
175+
176+
return gpio_npm6001_port_clear_bits_raw(
177+
dev, mask & (~value & NPM6001_PIN_MSK));
178+
}
179+
180+
static int gpio_npm6001_port_toggle_bits(const struct device *dev,
181+
gpio_port_pins_t pins)
182+
{
183+
uint32_t val;
184+
int ret;
185+
186+
ret = gpio_npm6001_port_get_raw(dev, &val);
187+
if (ret < 0) {
188+
return ret;
189+
}
190+
191+
return gpio_npm6001_port_set_masked_raw(dev, pins,
192+
~val & NPM6001_PIN_MSK);
193+
}
194+
195+
static int gpio_npm6001_pin_interrupt_configure(const struct device *dev,
196+
gpio_pin_t pin,
197+
enum gpio_int_mode mode,
198+
enum gpio_int_trig trig)
199+
{
200+
ARG_UNUSED(dev);
201+
ARG_UNUSED(pin);
202+
ARG_UNUSED(mode);
203+
ARG_UNUSED(trig);
204+
205+
return -ENOTSUP;
206+
}
207+
208+
static const struct gpio_driver_api gpio_npm6001_api = {
209+
.pin_configure = gpio_npm6001_configure,
210+
.port_get_raw = gpio_npm6001_port_get_raw,
211+
.port_set_masked_raw = gpio_npm6001_port_set_masked_raw,
212+
.port_set_bits_raw = gpio_npm6001_port_set_bits_raw,
213+
.port_clear_bits_raw = gpio_npm6001_port_clear_bits_raw,
214+
.port_toggle_bits = gpio_npm6001_port_toggle_bits,
215+
.pin_interrupt_configure = gpio_npm6001_pin_interrupt_configure,
216+
};
217+
218+
static int gpio_npm6001_init(const struct device *dev)
219+
{
220+
const struct gpio_npm6001_config *config = dev->config;
221+
222+
if (!device_is_ready(config->bus.bus)) {
223+
return -ENODEV;
224+
}
225+
226+
return 0;
227+
}
228+
229+
#define GPIO_NPM6001_DEFINE(n) \
230+
static const struct gpio_npm6001_config gpio_npm6001_config##n = { \
231+
.common = \
232+
{ \
233+
.port_pin_mask = \
234+
GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \
235+
}, \
236+
.bus = I2C_DT_SPEC_GET(DT_INST_PARENT(n))}; \
237+
\
238+
static struct gpio_npm6001_data gpio_npm6001_data##n; \
239+
\
240+
DEVICE_DT_INST_DEFINE(n, &gpio_npm6001_init, NULL, \
241+
&gpio_npm6001_data##n, &gpio_npm6001_config##n, \
242+
POST_KERNEL, CONFIG_GPIO_NPM6001_INIT_PRIORITY, \
243+
&gpio_npm6001_api);
244+
245+
DT_INST_FOREACH_STATUS_OKAY(GPIO_NPM6001_DEFINE)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) 2022 Nordic Semiconductor ASA
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
description: nPM6001 GPIO Controller
5+
6+
compatible: "nordic,npm6001-gpio"
7+
8+
include: gpio-controller.yaml
9+
10+
gpio-cells:
11+
- pin
12+
- flags
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM6001_GPIO_H_
7+
#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NPM6001_GPIO_H_
8+
9+
/**
10+
* @brief nPM6001-specific GPIO Flags
11+
* @defgroup gpio_interface_npm6001 nPM6001-specific GPIO Flags
12+
*
13+
* The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as
14+
* follows:
15+
*
16+
* - Bit 8: Drive strength (0=NORMAL, 1=HIGH)
17+
* - Bit 9: Input type (0=SCHMITT, 1=CMOS)
18+
*
19+
* @ingroup gpio_interface
20+
* @{
21+
*/
22+
23+
/**
24+
* @name nPM6001 GPIO drive strength flags
25+
* @brief nPM6001 GPIO drive strength flags
26+
* @{
27+
*/
28+
29+
/** @cond INTERNAL_HIDDEN */
30+
/** Drive mode field mask */
31+
#define NPM6001_GPIO_DRIVE_MSK 0x0100U
32+
/** @endcond */
33+
34+
/** Normal drive */
35+
#define NPM6001_GPIO_DRIVE_NORMAL (0U << 8U)
36+
/** High drive */
37+
#define NPM6001_GPIO_DRIVE_HIGH (1U << 8U)
38+
39+
/** @} */
40+
41+
/**
42+
* @name nPM6001 GPIO drive strength flags
43+
* @brief nPM6001 GPIO drive strength flags
44+
* @{
45+
*/
46+
47+
/** @cond INTERNAL_HIDDEN */
48+
/** Input type field mask */
49+
#define NPM6001_GPIO_SENSE_MSK 0x0200U
50+
/** @endcond */
51+
52+
/** Schmitt trigger input type */
53+
#define NPM6001_GPIO_SENSE_SCHMITT (0U << 9U)
54+
/** CMOS input type */
55+
#define NPM6001_GPIO_SENSE_CMOS (1U << 9U)
56+
57+
/** @} */
58+
59+
/** @} */
60+
61+
#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_NORDIC_NRF_GPIO_H_ */

0 commit comments

Comments
 (0)