1// SPDX-License-Identifier: GPL-2.0
2/*
3 * TQ-Systems TQMx86 PLD GPIO driver
4 *
5 * Based on vendor driver by:
6 *   Vadim V.Vlasov <vvlasov@dev.rtsoft.ru>
7 */
8
9#include <linux/bitops.h>
10#include <linux/errno.h>
11#include <linux/gpio/driver.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/pm_runtime.h>
18#include <linux/seq_file.h>
19#include <linux/slab.h>
20
21#define TQMX86_NGPIO	8
22#define TQMX86_NGPO	4	/* 0-3 - output */
23#define TQMX86_NGPI	4	/* 4-7 - input */
24#define TQMX86_DIR_INPUT_MASK	0xf0	/* 0-3 - output, 4-7 - input */
25
26#define TQMX86_GPIODD	0	/* GPIO Data Direction Register */
27#define TQMX86_GPIOD	1	/* GPIO Data Register */
28#define TQMX86_GPIIC	3	/* GPI Interrupt Configuration Register */
29#define TQMX86_GPIIS	4	/* GPI Interrupt Status Register */
30
31#define TQMX86_GPII_FALLING	BIT(0)
32#define TQMX86_GPII_RISING	BIT(1)
33#define TQMX86_GPII_MASK	(BIT(0) | BIT(1))
34#define TQMX86_GPII_BITS	2
35
36struct tqmx86_gpio_data {
37	struct gpio_chip	chip;
38	void __iomem		*io_base;
39	int			irq;
40	raw_spinlock_t		spinlock;
41	u8			irq_type[TQMX86_NGPI];
42};
43
44static u8 tqmx86_gpio_read(struct tqmx86_gpio_data *gd, unsigned int reg)
45{
46	return ioread8(gd->io_base + reg);
47}
48
49static void tqmx86_gpio_write(struct tqmx86_gpio_data *gd, u8 val,
50			      unsigned int reg)
51{
52	iowrite8(val, gd->io_base + reg);
53}
54
55static int tqmx86_gpio_get(struct gpio_chip *chip, unsigned int offset)
56{
57	struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
58
59	return !!(tqmx86_gpio_read(gpio, TQMX86_GPIOD) & BIT(offset));
60}
61
62static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset,
63			    int value)
64{
65	struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
66	unsigned long flags;
67	u8 val;
68
69	raw_spin_lock_irqsave(&gpio->spinlock, flags);
70	val = tqmx86_gpio_read(gpio, TQMX86_GPIOD);
71	if (value)
72		val |= BIT(offset);
73	else
74		val &= ~BIT(offset);
75	tqmx86_gpio_write(gpio, val, TQMX86_GPIOD);
76	raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
77}
78
79static int tqmx86_gpio_direction_input(struct gpio_chip *chip,
80				       unsigned int offset)
81{
82	/* Direction cannot be changed. Validate is an input. */
83	if (BIT(offset) & TQMX86_DIR_INPUT_MASK)
84		return 0;
85	else
86		return -EINVAL;
87}
88
89static int tqmx86_gpio_direction_output(struct gpio_chip *chip,
90					unsigned int offset,
91					int value)
92{
93	/* Direction cannot be changed, validate is an output */
94	if (BIT(offset) & TQMX86_DIR_INPUT_MASK)
95		return -EINVAL;
96
97	tqmx86_gpio_set(chip, offset, value);
98	return 0;
99}
100
101static int tqmx86_gpio_get_direction(struct gpio_chip *chip,
102				     unsigned int offset)
103{
104	if (TQMX86_DIR_INPUT_MASK & BIT(offset))
105		return GPIO_LINE_DIRECTION_IN;
106
107	return GPIO_LINE_DIRECTION_OUT;
108}
109
110static void tqmx86_gpio_irq_mask(struct irq_data *data)
111{
112	unsigned int offset = (data->hwirq - TQMX86_NGPO);
113	struct tqmx86_gpio_data *gpio = gpiochip_get_data(
114		irq_data_get_irq_chip_data(data));
115	unsigned long flags;
116	u8 gpiic, mask;
117
118	mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
119
120	raw_spin_lock_irqsave(&gpio->spinlock, flags);
121	gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
122	gpiic &= ~mask;
123	tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
124	raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
125	gpiochip_disable_irq(&gpio->chip, irqd_to_hwirq(data));
126}
127
128static void tqmx86_gpio_irq_unmask(struct irq_data *data)
129{
130	unsigned int offset = (data->hwirq - TQMX86_NGPO);
131	struct tqmx86_gpio_data *gpio = gpiochip_get_data(
132		irq_data_get_irq_chip_data(data));
133	unsigned long flags;
134	u8 gpiic, mask;
135
136	mask = TQMX86_GPII_MASK << (offset * TQMX86_GPII_BITS);
137
138	gpiochip_enable_irq(&gpio->chip, irqd_to_hwirq(data));
139	raw_spin_lock_irqsave(&gpio->spinlock, flags);
140	gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
141	gpiic &= ~mask;
142	gpiic |= gpio->irq_type[offset] << (offset * TQMX86_GPII_BITS);
143	tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
144	raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
145}
146
147static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)
148{
149	struct tqmx86_gpio_data *gpio = gpiochip_get_data(
150		irq_data_get_irq_chip_data(data));
151	unsigned int offset = (data->hwirq - TQMX86_NGPO);
152	unsigned int edge_type = type & IRQF_TRIGGER_MASK;
153	unsigned long flags;
154	u8 new_type, gpiic;
155
156	switch (edge_type) {
157	case IRQ_TYPE_EDGE_RISING:
158		new_type = TQMX86_GPII_RISING;
159		break;
160	case IRQ_TYPE_EDGE_FALLING:
161		new_type = TQMX86_GPII_FALLING;
162		break;
163	case IRQ_TYPE_EDGE_BOTH:
164		new_type = TQMX86_GPII_FALLING | TQMX86_GPII_RISING;
165		break;
166	default:
167		return -EINVAL; /* not supported */
168	}
169
170	gpio->irq_type[offset] = new_type;
171
172	raw_spin_lock_irqsave(&gpio->spinlock, flags);
173	gpiic = tqmx86_gpio_read(gpio, TQMX86_GPIIC);
174	gpiic &= ~((TQMX86_GPII_MASK) << (offset * TQMX86_GPII_BITS));
175	gpiic |= new_type << (offset * TQMX86_GPII_BITS);
176	tqmx86_gpio_write(gpio, gpiic, TQMX86_GPIIC);
177	raw_spin_unlock_irqrestore(&gpio->spinlock, flags);
178
179	return 0;
180}
181
182static void tqmx86_gpio_irq_handler(struct irq_desc *desc)
183{
184	struct gpio_chip *chip = irq_desc_get_handler_data(desc);
185	struct tqmx86_gpio_data *gpio = gpiochip_get_data(chip);
186	struct irq_chip *irq_chip = irq_desc_get_chip(desc);
187	unsigned long irq_bits;
188	int i = 0;
189	u8 irq_status;
190
191	chained_irq_enter(irq_chip, desc);
192
193	irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
194	tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
195
196	irq_bits = irq_status;
197	for_each_set_bit(i, &irq_bits, TQMX86_NGPI)
198		generic_handle_domain_irq(gpio->chip.irq.domain,
199					  i + TQMX86_NGPO);
200
201	chained_irq_exit(irq_chip, desc);
202}
203
204/* Minimal runtime PM is needed by the IRQ subsystem */
205static int __maybe_unused tqmx86_gpio_runtime_suspend(struct device *dev)
206{
207	return 0;
208}
209
210static int __maybe_unused tqmx86_gpio_runtime_resume(struct device *dev)
211{
212	return 0;
213}
214
215static const struct dev_pm_ops tqmx86_gpio_dev_pm_ops = {
216	SET_RUNTIME_PM_OPS(tqmx86_gpio_runtime_suspend,
217			   tqmx86_gpio_runtime_resume, NULL)
218};
219
220static void tqmx86_init_irq_valid_mask(struct gpio_chip *chip,
221				       unsigned long *valid_mask,
222				       unsigned int ngpios)
223{
224	/* Only GPIOs 4-7 are valid for interrupts. Clear the others */
225	clear_bit(0, valid_mask);
226	clear_bit(1, valid_mask);
227	clear_bit(2, valid_mask);
228	clear_bit(3, valid_mask);
229}
230
231static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
232{
233	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
234
235	seq_printf(p, gc->label);
236}
237
238static const struct irq_chip tqmx86_gpio_irq_chip = {
239	.irq_mask = tqmx86_gpio_irq_mask,
240	.irq_unmask = tqmx86_gpio_irq_unmask,
241	.irq_set_type = tqmx86_gpio_irq_set_type,
242	.irq_print_chip = tqmx86_gpio_irq_print_chip,
243	.flags = IRQCHIP_IMMUTABLE,
244	GPIOCHIP_IRQ_RESOURCE_HELPERS,
245};
246
247static int tqmx86_gpio_probe(struct platform_device *pdev)
248{
249	struct device *dev = &pdev->dev;
250	struct tqmx86_gpio_data *gpio;
251	struct gpio_chip *chip;
252	struct gpio_irq_chip *girq;
253	void __iomem *io_base;
254	struct resource *res;
255	int ret, irq;
256
257	irq = platform_get_irq_optional(pdev, 0);
258	if (irq < 0 && irq != -ENXIO)
259		return irq;
260
261	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
262	if (!res) {
263		dev_err(&pdev->dev, "Cannot get I/O\n");
264		return -ENODEV;
265	}
266
267	io_base = devm_ioport_map(&pdev->dev, res->start, resource_size(res));
268	if (!io_base)
269		return -ENOMEM;
270
271	gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL);
272	if (!gpio)
273		return -ENOMEM;
274
275	raw_spin_lock_init(&gpio->spinlock);
276	gpio->io_base = io_base;
277
278	tqmx86_gpio_write(gpio, (u8)~TQMX86_DIR_INPUT_MASK, TQMX86_GPIODD);
279
280	chip = &gpio->chip;
281	chip->label = "gpio-tqmx86";
282	chip->owner = THIS_MODULE;
283	chip->can_sleep = false;
284	chip->base = -1;
285	chip->direction_input = tqmx86_gpio_direction_input;
286	chip->direction_output = tqmx86_gpio_direction_output;
287	chip->get_direction = tqmx86_gpio_get_direction;
288	chip->get = tqmx86_gpio_get;
289	chip->set = tqmx86_gpio_set;
290	chip->ngpio = TQMX86_NGPIO;
291	chip->parent = pdev->dev.parent;
292
293	pm_runtime_enable(&pdev->dev);
294
295	if (irq > 0) {
296		u8 irq_status;
297
298		/* Mask all interrupts */
299		tqmx86_gpio_write(gpio, 0, TQMX86_GPIIC);
300
301		/* Clear all pending interrupts */
302		irq_status = tqmx86_gpio_read(gpio, TQMX86_GPIIS);
303		tqmx86_gpio_write(gpio, irq_status, TQMX86_GPIIS);
304
305		girq = &chip->irq;
306		gpio_irq_chip_set_chip(girq, &tqmx86_gpio_irq_chip);
307		girq->parent_handler = tqmx86_gpio_irq_handler;
308		girq->num_parents = 1;
309		girq->parents = devm_kcalloc(&pdev->dev, 1,
310					     sizeof(*girq->parents),
311					     GFP_KERNEL);
312		if (!girq->parents) {
313			ret = -ENOMEM;
314			goto out_pm_dis;
315		}
316		girq->parents[0] = irq;
317		girq->default_type = IRQ_TYPE_NONE;
318		girq->handler = handle_simple_irq;
319		girq->init_valid_mask = tqmx86_init_irq_valid_mask;
320
321		irq_domain_set_pm_device(girq->domain, dev);
322	}
323
324	ret = devm_gpiochip_add_data(dev, chip, gpio);
325	if (ret) {
326		dev_err(dev, "Could not register GPIO chip\n");
327		goto out_pm_dis;
328	}
329
330	dev_info(dev, "GPIO functionality initialized with %d pins\n",
331		 chip->ngpio);
332
333	return 0;
334
335out_pm_dis:
336	pm_runtime_disable(&pdev->dev);
337
338	return ret;
339}
340
341static struct platform_driver tqmx86_gpio_driver = {
342	.driver = {
343		.name = "tqmx86-gpio",
344		.pm = &tqmx86_gpio_dev_pm_ops,
345	},
346	.probe		= tqmx86_gpio_probe,
347};
348
349module_platform_driver(tqmx86_gpio_driver);
350
351MODULE_DESCRIPTION("TQMx86 PLD GPIO Driver");
352MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
353MODULE_LICENSE("GPL");
354MODULE_ALIAS("platform:tqmx86-gpio");
355