xref: /openbmc/linux/drivers/gpio/gpio-mlxbf3.c (revision 52acfebc)
11d2a22faSKrzysztof Kozlowski // SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
2cd33f216SAsmaa Mnebhi /* Copyright (C) 2022 NVIDIA CORPORATION & AFFILIATES */
3cd33f216SAsmaa Mnebhi 
4cd33f216SAsmaa Mnebhi #include <linux/bitfield.h>
5cd33f216SAsmaa Mnebhi #include <linux/bitops.h>
6cd33f216SAsmaa Mnebhi #include <linux/device.h>
7cd33f216SAsmaa Mnebhi #include <linux/err.h>
8cd33f216SAsmaa Mnebhi #include <linux/gpio/driver.h>
9cd33f216SAsmaa Mnebhi #include <linux/interrupt.h>
10cd33f216SAsmaa Mnebhi #include <linux/io.h>
11cd33f216SAsmaa Mnebhi #include <linux/module.h>
12cd33f216SAsmaa Mnebhi #include <linux/platform_device.h>
13cd33f216SAsmaa Mnebhi #include <linux/spinlock.h>
14cd33f216SAsmaa Mnebhi #include <linux/types.h>
15cd33f216SAsmaa Mnebhi 
16cd33f216SAsmaa Mnebhi /*
17cd33f216SAsmaa Mnebhi  * There are 2 YU GPIO blocks:
18cd33f216SAsmaa Mnebhi  * gpio[0]: HOST_GPIO0->HOST_GPIO31
19cd33f216SAsmaa Mnebhi  * gpio[1]: HOST_GPIO32->HOST_GPIO55
20cd33f216SAsmaa Mnebhi  */
21cd33f216SAsmaa Mnebhi #define MLXBF3_GPIO_MAX_PINS_PER_BLOCK 32
2238a700efSAsmaa Mnebhi #define MLXBF3_GPIO_MAX_PINS_BLOCK0    32
2338a700efSAsmaa Mnebhi #define MLXBF3_GPIO_MAX_PINS_BLOCK1    24
24cd33f216SAsmaa Mnebhi 
25cd33f216SAsmaa Mnebhi /*
26cd33f216SAsmaa Mnebhi  * fw_gpio[x] block registers and their offset
27cd33f216SAsmaa Mnebhi  */
28cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_OUTPUT_ENABLE_SET	  0x00
29cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_DATA_OUT_SET        0x04
30cd33f216SAsmaa Mnebhi 
31cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR 0x00
32cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_FW_DATA_OUT_CLEAR      0x04
33cd33f216SAsmaa Mnebhi 
34cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_RISE_EN          0x00
35cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_FALL_EN          0x04
36cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_READ_DATA_IN           0x08
37cd33f216SAsmaa Mnebhi 
38cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0  0x00
39cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_EVTEN0        0x14
40cd33f216SAsmaa Mnebhi #define MLXBF_GPIO_CAUSE_OR_CLRCAUSE      0x18
41cd33f216SAsmaa Mnebhi 
42cd33f216SAsmaa Mnebhi struct mlxbf3_gpio_context {
43cd33f216SAsmaa Mnebhi 	struct gpio_chip gc;
44cd33f216SAsmaa Mnebhi 
45cd33f216SAsmaa Mnebhi 	/* YU GPIO block address */
46cd33f216SAsmaa Mnebhi 	void __iomem *gpio_set_io;
47cd33f216SAsmaa Mnebhi 	void __iomem *gpio_clr_io;
48cd33f216SAsmaa Mnebhi 	void __iomem *gpio_io;
49cd33f216SAsmaa Mnebhi 
50cd33f216SAsmaa Mnebhi 	/* YU GPIO cause block address */
51cd33f216SAsmaa Mnebhi 	void __iomem *gpio_cause_io;
52cd33f216SAsmaa Mnebhi };
53cd33f216SAsmaa Mnebhi 
mlxbf3_gpio_irq_enable(struct irq_data * irqd)54cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_enable(struct irq_data *irqd)
55cd33f216SAsmaa Mnebhi {
56cd33f216SAsmaa Mnebhi 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
57cd33f216SAsmaa Mnebhi 	struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
58cd33f216SAsmaa Mnebhi 	irq_hw_number_t offset = irqd_to_hwirq(irqd);
59cd33f216SAsmaa Mnebhi 	unsigned long flags;
60cd33f216SAsmaa Mnebhi 	u32 val;
61cd33f216SAsmaa Mnebhi 
62cd33f216SAsmaa Mnebhi 	gpiochip_enable_irq(gc, offset);
63cd33f216SAsmaa Mnebhi 
64cd33f216SAsmaa Mnebhi 	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
65cd33f216SAsmaa Mnebhi 	writel(BIT(offset), gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE);
66cd33f216SAsmaa Mnebhi 
67cd33f216SAsmaa Mnebhi 	val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
68cd33f216SAsmaa Mnebhi 	val |= BIT(offset);
69cd33f216SAsmaa Mnebhi 	writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
70cd33f216SAsmaa Mnebhi 	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
71cd33f216SAsmaa Mnebhi }
72cd33f216SAsmaa Mnebhi 
mlxbf3_gpio_irq_disable(struct irq_data * irqd)73cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_disable(struct irq_data *irqd)
74cd33f216SAsmaa Mnebhi {
75cd33f216SAsmaa Mnebhi 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
76cd33f216SAsmaa Mnebhi 	struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
77cd33f216SAsmaa Mnebhi 	irq_hw_number_t offset = irqd_to_hwirq(irqd);
78cd33f216SAsmaa Mnebhi 	unsigned long flags;
79cd33f216SAsmaa Mnebhi 	u32 val;
80cd33f216SAsmaa Mnebhi 
81cd33f216SAsmaa Mnebhi 	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
82cd33f216SAsmaa Mnebhi 	val = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
83cd33f216SAsmaa Mnebhi 	val &= ~BIT(offset);
84cd33f216SAsmaa Mnebhi 	writel(val, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_EVTEN0);
85cd33f216SAsmaa Mnebhi 	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
86cd33f216SAsmaa Mnebhi 
87cd33f216SAsmaa Mnebhi 	gpiochip_disable_irq(gc, offset);
88cd33f216SAsmaa Mnebhi }
89cd33f216SAsmaa Mnebhi 
mlxbf3_gpio_irq_handler(int irq,void * ptr)90cd33f216SAsmaa Mnebhi static irqreturn_t mlxbf3_gpio_irq_handler(int irq, void *ptr)
91cd33f216SAsmaa Mnebhi {
92cd33f216SAsmaa Mnebhi 	struct mlxbf3_gpio_context *gs = ptr;
93cd33f216SAsmaa Mnebhi 	struct gpio_chip *gc = &gs->gc;
94cd33f216SAsmaa Mnebhi 	unsigned long pending;
95cd33f216SAsmaa Mnebhi 	u32 level;
96cd33f216SAsmaa Mnebhi 
97cd33f216SAsmaa Mnebhi 	pending = readl(gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CAUSE_EVTEN0);
98cd33f216SAsmaa Mnebhi 	writel(pending, gs->gpio_cause_io + MLXBF_GPIO_CAUSE_OR_CLRCAUSE);
99cd33f216SAsmaa Mnebhi 
100cd33f216SAsmaa Mnebhi 	for_each_set_bit(level, &pending, gc->ngpio)
101cd33f216SAsmaa Mnebhi 		generic_handle_domain_irq(gc->irq.domain, level);
102cd33f216SAsmaa Mnebhi 
103cd33f216SAsmaa Mnebhi 	return IRQ_RETVAL(pending);
104cd33f216SAsmaa Mnebhi }
105cd33f216SAsmaa Mnebhi 
106cd33f216SAsmaa Mnebhi static int
mlxbf3_gpio_irq_set_type(struct irq_data * irqd,unsigned int type)107cd33f216SAsmaa Mnebhi mlxbf3_gpio_irq_set_type(struct irq_data *irqd, unsigned int type)
108cd33f216SAsmaa Mnebhi {
109cd33f216SAsmaa Mnebhi 	struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
110cd33f216SAsmaa Mnebhi 	struct mlxbf3_gpio_context *gs = gpiochip_get_data(gc);
111cd33f216SAsmaa Mnebhi 	irq_hw_number_t offset = irqd_to_hwirq(irqd);
112cd33f216SAsmaa Mnebhi 	unsigned long flags;
113cd33f216SAsmaa Mnebhi 	u32 val;
114cd33f216SAsmaa Mnebhi 
115cd33f216SAsmaa Mnebhi 	raw_spin_lock_irqsave(&gs->gc.bgpio_lock, flags);
116cd33f216SAsmaa Mnebhi 
117cd33f216SAsmaa Mnebhi 	switch (type & IRQ_TYPE_SENSE_MASK) {
118cd33f216SAsmaa Mnebhi 	case IRQ_TYPE_EDGE_BOTH:
119cd33f216SAsmaa Mnebhi 		val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
120cd33f216SAsmaa Mnebhi 		val |= BIT(offset);
121cd33f216SAsmaa Mnebhi 		writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
122cd33f216SAsmaa Mnebhi 		val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
123cd33f216SAsmaa Mnebhi 		val |= BIT(offset);
124cd33f216SAsmaa Mnebhi 		writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
125cd33f216SAsmaa Mnebhi 		break;
126cd33f216SAsmaa Mnebhi 	case IRQ_TYPE_EDGE_RISING:
127cd33f216SAsmaa Mnebhi 		val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
128cd33f216SAsmaa Mnebhi 		val |= BIT(offset);
129cd33f216SAsmaa Mnebhi 		writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_RISE_EN);
130cd33f216SAsmaa Mnebhi 		break;
131cd33f216SAsmaa Mnebhi 	case IRQ_TYPE_EDGE_FALLING:
132cd33f216SAsmaa Mnebhi 		val = readl(gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
133cd33f216SAsmaa Mnebhi 		val |= BIT(offset);
134cd33f216SAsmaa Mnebhi 		writel(val, gs->gpio_io + MLXBF_GPIO_CAUSE_FALL_EN);
135cd33f216SAsmaa Mnebhi 		break;
136cd33f216SAsmaa Mnebhi 	default:
137cd33f216SAsmaa Mnebhi 		raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
138cd33f216SAsmaa Mnebhi 		return -EINVAL;
139cd33f216SAsmaa Mnebhi 	}
140cd33f216SAsmaa Mnebhi 
141cd33f216SAsmaa Mnebhi 	raw_spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags);
142cd33f216SAsmaa Mnebhi 
143cd33f216SAsmaa Mnebhi 	irq_set_handler_locked(irqd, handle_edge_irq);
144cd33f216SAsmaa Mnebhi 
145cd33f216SAsmaa Mnebhi 	return 0;
146cd33f216SAsmaa Mnebhi }
147cd33f216SAsmaa Mnebhi 
148cd33f216SAsmaa Mnebhi /* This function needs to be defined for handle_edge_irq() */
mlxbf3_gpio_irq_ack(struct irq_data * data)149cd33f216SAsmaa Mnebhi static void mlxbf3_gpio_irq_ack(struct irq_data *data)
150cd33f216SAsmaa Mnebhi {
151cd33f216SAsmaa Mnebhi }
152cd33f216SAsmaa Mnebhi 
153cd33f216SAsmaa Mnebhi static const struct irq_chip gpio_mlxbf3_irqchip = {
154cd33f216SAsmaa Mnebhi 	.name = "MLNXBF33",
155cd33f216SAsmaa Mnebhi 	.irq_ack = mlxbf3_gpio_irq_ack,
156cd33f216SAsmaa Mnebhi 	.irq_set_type = mlxbf3_gpio_irq_set_type,
157cd33f216SAsmaa Mnebhi 	.irq_enable = mlxbf3_gpio_irq_enable,
158cd33f216SAsmaa Mnebhi 	.irq_disable = mlxbf3_gpio_irq_disable,
159cd33f216SAsmaa Mnebhi 	.flags = IRQCHIP_IMMUTABLE,
160cd33f216SAsmaa Mnebhi 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
161cd33f216SAsmaa Mnebhi };
162cd33f216SAsmaa Mnebhi 
mlxbf3_gpio_add_pin_ranges(struct gpio_chip * chip)16338a700efSAsmaa Mnebhi static int mlxbf3_gpio_add_pin_ranges(struct gpio_chip *chip)
16438a700efSAsmaa Mnebhi {
16538a700efSAsmaa Mnebhi 	unsigned int id;
16638a700efSAsmaa Mnebhi 
16738a700efSAsmaa Mnebhi 	switch(chip->ngpio) {
16838a700efSAsmaa Mnebhi 	case MLXBF3_GPIO_MAX_PINS_BLOCK0:
16938a700efSAsmaa Mnebhi 		id = 0;
17038a700efSAsmaa Mnebhi 		break;
17138a700efSAsmaa Mnebhi 	case MLXBF3_GPIO_MAX_PINS_BLOCK1:
17238a700efSAsmaa Mnebhi 		id = 1;
17338a700efSAsmaa Mnebhi 		break;
17438a700efSAsmaa Mnebhi 	default:
17538a700efSAsmaa Mnebhi 		return -EINVAL;
17638a700efSAsmaa Mnebhi 	}
17738a700efSAsmaa Mnebhi 
17838a700efSAsmaa Mnebhi 	return gpiochip_add_pin_range(chip, "MLNXBF34:00",
17938a700efSAsmaa Mnebhi 			chip->base, id * MLXBF3_GPIO_MAX_PINS_PER_BLOCK,
18038a700efSAsmaa Mnebhi 			chip->ngpio);
18138a700efSAsmaa Mnebhi }
18238a700efSAsmaa Mnebhi 
mlxbf3_gpio_probe(struct platform_device * pdev)183cd33f216SAsmaa Mnebhi static int mlxbf3_gpio_probe(struct platform_device *pdev)
184cd33f216SAsmaa Mnebhi {
185cd33f216SAsmaa Mnebhi 	struct device *dev = &pdev->dev;
186cd33f216SAsmaa Mnebhi 	struct mlxbf3_gpio_context *gs;
187cd33f216SAsmaa Mnebhi 	struct gpio_irq_chip *girq;
188cd33f216SAsmaa Mnebhi 	struct gpio_chip *gc;
189cd33f216SAsmaa Mnebhi 	int ret, irq;
190cd33f216SAsmaa Mnebhi 
191cd33f216SAsmaa Mnebhi 	gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL);
192cd33f216SAsmaa Mnebhi 	if (!gs)
193cd33f216SAsmaa Mnebhi 		return -ENOMEM;
194cd33f216SAsmaa Mnebhi 
195cd33f216SAsmaa Mnebhi 	gs->gpio_io = devm_platform_ioremap_resource(pdev, 0);
196cd33f216SAsmaa Mnebhi 	if (IS_ERR(gs->gpio_io))
197cd33f216SAsmaa Mnebhi 		return PTR_ERR(gs->gpio_io);
198cd33f216SAsmaa Mnebhi 
199cd33f216SAsmaa Mnebhi 	gs->gpio_cause_io = devm_platform_ioremap_resource(pdev, 1);
200cd33f216SAsmaa Mnebhi 	if (IS_ERR(gs->gpio_cause_io))
201cd33f216SAsmaa Mnebhi 		return PTR_ERR(gs->gpio_cause_io);
202cd33f216SAsmaa Mnebhi 
203cd33f216SAsmaa Mnebhi 	gs->gpio_set_io = devm_platform_ioremap_resource(pdev, 2);
204cd33f216SAsmaa Mnebhi 	if (IS_ERR(gs->gpio_set_io))
205cd33f216SAsmaa Mnebhi 		return PTR_ERR(gs->gpio_set_io);
206cd33f216SAsmaa Mnebhi 
207cd33f216SAsmaa Mnebhi 	gs->gpio_clr_io = devm_platform_ioremap_resource(pdev, 3);
208cd33f216SAsmaa Mnebhi 	if (IS_ERR(gs->gpio_clr_io))
209cd33f216SAsmaa Mnebhi 		return PTR_ERR(gs->gpio_clr_io);
210cd33f216SAsmaa Mnebhi 	gc = &gs->gc;
211cd33f216SAsmaa Mnebhi 
212cd33f216SAsmaa Mnebhi 	ret = bgpio_init(gc, dev, 4,
213cd33f216SAsmaa Mnebhi 			gs->gpio_io + MLXBF_GPIO_READ_DATA_IN,
214cd33f216SAsmaa Mnebhi 			gs->gpio_set_io + MLXBF_GPIO_FW_DATA_OUT_SET,
215cd33f216SAsmaa Mnebhi 			gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR,
216cd33f216SAsmaa Mnebhi 			gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET,
217cd33f216SAsmaa Mnebhi 			gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0);
218*52acfebcSSu Hui 	if (ret)
219*52acfebcSSu Hui 		return dev_err_probe(dev, ret, "%s: bgpio_init() failed", __func__);
220cd33f216SAsmaa Mnebhi 
221cd33f216SAsmaa Mnebhi 	gc->request = gpiochip_generic_request;
222cd33f216SAsmaa Mnebhi 	gc->free = gpiochip_generic_free;
223cd33f216SAsmaa Mnebhi 	gc->owner = THIS_MODULE;
22438a700efSAsmaa Mnebhi 	gc->add_pin_ranges = mlxbf3_gpio_add_pin_ranges;
225cd33f216SAsmaa Mnebhi 
226cd33f216SAsmaa Mnebhi 	irq = platform_get_irq(pdev, 0);
227cd33f216SAsmaa Mnebhi 	if (irq >= 0) {
228cd33f216SAsmaa Mnebhi 		girq = &gs->gc.irq;
229cd33f216SAsmaa Mnebhi 		gpio_irq_chip_set_chip(girq, &gpio_mlxbf3_irqchip);
230cd33f216SAsmaa Mnebhi 		girq->default_type = IRQ_TYPE_NONE;
231cd33f216SAsmaa Mnebhi 		/* This will let us handle the parent IRQ in the driver */
232cd33f216SAsmaa Mnebhi 		girq->num_parents = 0;
233cd33f216SAsmaa Mnebhi 		girq->parents = NULL;
234cd33f216SAsmaa Mnebhi 		girq->parent_handler = NULL;
235cd33f216SAsmaa Mnebhi 		girq->handler = handle_bad_irq;
236cd33f216SAsmaa Mnebhi 
237cd33f216SAsmaa Mnebhi 		/*
238cd33f216SAsmaa Mnebhi 		 * Directly request the irq here instead of passing
239cd33f216SAsmaa Mnebhi 		 * a flow-handler because the irq is shared.
240cd33f216SAsmaa Mnebhi 		 */
241cd33f216SAsmaa Mnebhi 		ret = devm_request_irq(dev, irq, mlxbf3_gpio_irq_handler,
242cd33f216SAsmaa Mnebhi 				       IRQF_SHARED, dev_name(dev), gs);
243cd33f216SAsmaa Mnebhi 		if (ret)
244cd33f216SAsmaa Mnebhi 			return dev_err_probe(dev, ret, "failed to request IRQ");
245cd33f216SAsmaa Mnebhi 	}
246cd33f216SAsmaa Mnebhi 
247cd33f216SAsmaa Mnebhi 	platform_set_drvdata(pdev, gs);
248cd33f216SAsmaa Mnebhi 
249cd33f216SAsmaa Mnebhi 	ret = devm_gpiochip_add_data(dev, &gs->gc, gs);
250cd33f216SAsmaa Mnebhi 	if (ret)
251cd33f216SAsmaa Mnebhi 		dev_err_probe(dev, ret, "Failed adding memory mapped gpiochip\n");
252cd33f216SAsmaa Mnebhi 
253cd33f216SAsmaa Mnebhi 	return 0;
254cd33f216SAsmaa Mnebhi }
255cd33f216SAsmaa Mnebhi 
256cd33f216SAsmaa Mnebhi static const struct acpi_device_id mlxbf3_gpio_acpi_match[] = {
257cd33f216SAsmaa Mnebhi 	{ "MLNXBF33", 0 },
258cd33f216SAsmaa Mnebhi 	{}
259cd33f216SAsmaa Mnebhi };
260cd33f216SAsmaa Mnebhi MODULE_DEVICE_TABLE(acpi, mlxbf3_gpio_acpi_match);
261cd33f216SAsmaa Mnebhi 
262cd33f216SAsmaa Mnebhi static struct platform_driver mlxbf3_gpio_driver = {
263cd33f216SAsmaa Mnebhi 	.driver = {
264cd33f216SAsmaa Mnebhi 		.name = "mlxbf3_gpio",
265cd33f216SAsmaa Mnebhi 		.acpi_match_table = mlxbf3_gpio_acpi_match,
266cd33f216SAsmaa Mnebhi 	},
267cd33f216SAsmaa Mnebhi 	.probe    = mlxbf3_gpio_probe,
268cd33f216SAsmaa Mnebhi };
269cd33f216SAsmaa Mnebhi module_platform_driver(mlxbf3_gpio_driver);
270cd33f216SAsmaa Mnebhi 
27138a700efSAsmaa Mnebhi MODULE_SOFTDEP("pre: pinctrl-mlxbf3");
272cd33f216SAsmaa Mnebhi MODULE_DESCRIPTION("NVIDIA BlueField-3 GPIO Driver");
273cd33f216SAsmaa Mnebhi MODULE_AUTHOR("Asmaa Mnebhi <asmaa@nvidia.com>");
274cd33f216SAsmaa Mnebhi MODULE_LICENSE("Dual BSD/GPL");
275