1 /*
2  * Copyright (c) 2019 Vestas Wind Systems A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @file
9  * @brief GPIO driver for the LMP90xxx AFE.
10  */
11 
12 #define DT_DRV_COMPAT ti_lmp90xxx_gpio
13 
14 #include <zephyr/drivers/gpio.h>
15 #include <zephyr/kernel.h>
16 
17 #define LOG_LEVEL CONFIG_GPIO_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(gpio_lmp90xxx);
20 
21 #include <zephyr/drivers/adc/lmp90xxx.h>
22 
23 #include <zephyr/drivers/gpio/gpio_utils.h>
24 
25 struct gpio_lmp90xxx_config {
26 	/* gpio_driver_config needs to be first */
27 	struct gpio_driver_config common;
28 	const struct device *parent;
29 };
30 
31 struct gpio_lmp90xxx_data {
32 	/* gpio_driver_data needs to be first */
33 	struct gpio_driver_data common;
34 };
35 
gpio_lmp90xxx_config(const struct device * dev,gpio_pin_t pin,gpio_flags_t flags)36 static int gpio_lmp90xxx_config(const struct device *dev,
37 				gpio_pin_t pin, gpio_flags_t flags)
38 {
39 	const struct gpio_lmp90xxx_config *config = dev->config;
40 	int err = 0;
41 
42 	if (pin > LMP90XXX_GPIO_MAX) {
43 		return -EINVAL;
44 	}
45 
46 	if ((flags & GPIO_SINGLE_ENDED) != 0) {
47 		return -ENOTSUP;
48 	}
49 
50 	if ((flags & (GPIO_PULL_UP | GPIO_PULL_DOWN)) != 0) {
51 		return -ENOTSUP;
52 	}
53 
54 	if (flags & GPIO_INT_ENABLE) {
55 		/* LMP90xxx GPIOs do not support interrupts */
56 		return -ENOTSUP;
57 	}
58 
59 	switch (flags & GPIO_DIR_MASK) {
60 	case GPIO_INPUT:
61 		err = lmp90xxx_gpio_set_input(config->parent, pin);
62 		break;
63 	case GPIO_OUTPUT:
64 		if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) {
65 			err = lmp90xxx_gpio_set_pin_value(config->parent, pin,
66 							  true);
67 		} else if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) {
68 			err = lmp90xxx_gpio_set_pin_value(config->parent, pin,
69 							  false);
70 		}
71 
72 		if (err) {
73 			return err;
74 		}
75 		err = lmp90xxx_gpio_set_output(config->parent, pin);
76 		break;
77 	default:
78 		return -ENOTSUP;
79 	}
80 
81 	return err;
82 }
83 
gpio_lmp90xxx_port_get_raw(const struct device * dev,gpio_port_value_t * value)84 static int gpio_lmp90xxx_port_get_raw(const struct device *dev,
85 				      gpio_port_value_t *value)
86 {
87 	const struct gpio_lmp90xxx_config *config = dev->config;
88 
89 	return lmp90xxx_gpio_port_get_raw(config->parent, value);
90 }
91 
gpio_lmp90xxx_port_set_masked_raw(const struct device * dev,gpio_port_pins_t mask,gpio_port_value_t value)92 static int gpio_lmp90xxx_port_set_masked_raw(const struct device *dev,
93 					     gpio_port_pins_t mask,
94 					     gpio_port_value_t value)
95 {
96 	const struct gpio_lmp90xxx_config *config = dev->config;
97 
98 	return lmp90xxx_gpio_port_set_masked_raw(config->parent, mask, value);
99 }
100 
gpio_lmp90xxx_port_set_bits_raw(const struct device * dev,gpio_port_pins_t pins)101 static int gpio_lmp90xxx_port_set_bits_raw(const struct device *dev,
102 					   gpio_port_pins_t pins)
103 {
104 	const struct gpio_lmp90xxx_config *config = dev->config;
105 
106 	return lmp90xxx_gpio_port_set_bits_raw(config->parent, pins);
107 }
108 
gpio_lmp90xxx_port_clear_bits_raw(const struct device * dev,gpio_port_pins_t pins)109 static int gpio_lmp90xxx_port_clear_bits_raw(const struct device *dev,
110 					     gpio_port_pins_t pins)
111 {
112 	const struct gpio_lmp90xxx_config *config = dev->config;
113 
114 	return lmp90xxx_gpio_port_clear_bits_raw(config->parent, pins);
115 }
116 
gpio_lmp90xxx_port_toggle_bits(const struct device * dev,gpio_port_pins_t pins)117 static int gpio_lmp90xxx_port_toggle_bits(const struct device *dev,
118 					  gpio_port_pins_t pins)
119 {
120 	const struct gpio_lmp90xxx_config *config = dev->config;
121 
122 	return lmp90xxx_gpio_port_toggle_bits(config->parent, pins);
123 }
124 
gpio_lmp90xxx_init(const struct device * dev)125 static int gpio_lmp90xxx_init(const struct device *dev)
126 {
127 	const struct gpio_lmp90xxx_config *config = dev->config;
128 
129 	if (!device_is_ready(config->parent)) {
130 		LOG_ERR("parent LMP90xxx device '%s' not ready",
131 			config->parent->name);
132 		return -EINVAL;
133 	}
134 
135 	return 0;
136 }
137 
138 static const struct gpio_driver_api gpio_lmp90xxx_api = {
139 	.pin_configure = gpio_lmp90xxx_config,
140 	.port_set_masked_raw = gpio_lmp90xxx_port_set_masked_raw,
141 	.port_set_bits_raw = gpio_lmp90xxx_port_set_bits_raw,
142 	.port_clear_bits_raw = gpio_lmp90xxx_port_clear_bits_raw,
143 	.port_toggle_bits = gpio_lmp90xxx_port_toggle_bits,
144 	.port_get_raw = gpio_lmp90xxx_port_get_raw,
145 };
146 
147 BUILD_ASSERT(CONFIG_GPIO_LMP90XXX_INIT_PRIORITY >
148 	     CONFIG_ADC_INIT_PRIORITY,
149 	     "LMP90xxx GPIO driver must be initialized after LMP90xxx ADC "
150 	     "driver");
151 
152 #define GPIO_LMP90XXX_DEVICE(id)					\
153 	static const struct gpio_lmp90xxx_config gpio_lmp90xxx_##id##_cfg = {\
154 		.common = {                                             \
155 			.port_pin_mask =                                \
156 				 GPIO_PORT_PIN_MASK_FROM_DT_INST(id)	\
157 		},                                                      \
158 		.parent = DEVICE_DT_GET(DT_INST_BUS(id)),		\
159 	};								\
160 									\
161 	static struct gpio_lmp90xxx_data gpio_lmp90xxx_##id##_data;	\
162 									\
163 	DEVICE_DT_INST_DEFINE(id,					\
164 			    &gpio_lmp90xxx_init,			\
165 			    NULL,					\
166 			    &gpio_lmp90xxx_##id##_data,			\
167 			    &gpio_lmp90xxx_##id##_cfg, POST_KERNEL,	\
168 			    CONFIG_GPIO_LMP90XXX_INIT_PRIORITY,		\
169 			    &gpio_lmp90xxx_api);
170 
171 DT_INST_FOREACH_STATUS_OKAY(GPIO_LMP90XXX_DEVICE)
172