xref: /openbmc/linux/drivers/gpio/gpio-hlwd.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
18f55fed3SJonathan Neuschäfer // SPDX-License-Identifier: GPL-2.0+
28f55fed3SJonathan Neuschäfer // Copyright (C) 2008-2009 The GameCube Linux Team
38f55fed3SJonathan Neuschäfer // Copyright (C) 2008,2009 Albert Herranz
48f55fed3SJonathan Neuschäfer // Copyright (C) 2017-2018 Jonathan Neuschäfer
58f55fed3SJonathan Neuschäfer //
68f55fed3SJonathan Neuschäfer // Nintendo Wii (Hollywood) GPIO driver
78f55fed3SJonathan Neuschäfer 
88f55fed3SJonathan Neuschäfer #include <linux/gpio/driver.h>
98f55fed3SJonathan Neuschäfer #include <linux/io.h>
108f55fed3SJonathan Neuschäfer #include <linux/kernel.h>
118f55fed3SJonathan Neuschäfer #include <linux/module.h>
128f55fed3SJonathan Neuschäfer #include <linux/of.h>
13*e91d0f05SRob Herring #include <linux/platform_device.h>
14ab42f021SLinus Walleij #include <linux/seq_file.h>
158f55fed3SJonathan Neuschäfer #include <linux/slab.h>
168f55fed3SJonathan Neuschäfer 
178f55fed3SJonathan Neuschäfer /*
188f55fed3SJonathan Neuschäfer  * Register names and offsets courtesy of WiiBrew:
198f55fed3SJonathan Neuschäfer  * https://wiibrew.org/wiki/Hardware/Hollywood_GPIOs
208f55fed3SJonathan Neuschäfer  *
218f55fed3SJonathan Neuschäfer  * Note that for most registers, there are two versions:
228f55fed3SJonathan Neuschäfer  * - HW_GPIOB_* Is always accessible by the Broadway PowerPC core, but does
238f55fed3SJonathan Neuschäfer  *   always give access to all GPIO lines
248f55fed3SJonathan Neuschäfer  * - HW_GPIO_* Is only accessible by the Broadway PowerPC code if the memory
258f55fed3SJonathan Neuschäfer  *   firewall (AHBPROT) in the Hollywood chipset has been configured to allow
268f55fed3SJonathan Neuschäfer  *   such access.
278f55fed3SJonathan Neuschäfer  *
288f55fed3SJonathan Neuschäfer  * The ownership of each GPIO line can be configured in the HW_GPIO_OWNER
298f55fed3SJonathan Neuschäfer  * register: A one bit configures the line for access via the HW_GPIOB_*
308f55fed3SJonathan Neuschäfer  * registers, a zero bit indicates access via HW_GPIO_*. This driver uses
318f55fed3SJonathan Neuschäfer  * HW_GPIOB_*.
328f55fed3SJonathan Neuschäfer  */
338f55fed3SJonathan Neuschäfer #define HW_GPIOB_OUT		0x00
348f55fed3SJonathan Neuschäfer #define HW_GPIOB_DIR		0x04
358f55fed3SJonathan Neuschäfer #define HW_GPIOB_IN		0x08
368f55fed3SJonathan Neuschäfer #define HW_GPIOB_INTLVL		0x0c
378f55fed3SJonathan Neuschäfer #define HW_GPIOB_INTFLAG	0x10
388f55fed3SJonathan Neuschäfer #define HW_GPIOB_INTMASK	0x14
398f55fed3SJonathan Neuschäfer #define HW_GPIOB_INMIR		0x18
408f55fed3SJonathan Neuschäfer #define HW_GPIO_ENABLE		0x1c
418f55fed3SJonathan Neuschäfer #define HW_GPIO_OUT		0x20
428f55fed3SJonathan Neuschäfer #define HW_GPIO_DIR		0x24
438f55fed3SJonathan Neuschäfer #define HW_GPIO_IN		0x28
448f55fed3SJonathan Neuschäfer #define HW_GPIO_INTLVL		0x2c
458f55fed3SJonathan Neuschäfer #define HW_GPIO_INTFLAG		0x30
468f55fed3SJonathan Neuschäfer #define HW_GPIO_INTMASK		0x34
478f55fed3SJonathan Neuschäfer #define HW_GPIO_INMIR		0x38
488f55fed3SJonathan Neuschäfer #define HW_GPIO_OWNER		0x3c
498f55fed3SJonathan Neuschäfer 
508f55fed3SJonathan Neuschäfer struct hlwd_gpio {
518f55fed3SJonathan Neuschäfer 	struct gpio_chip gpioc;
52ab42f021SLinus Walleij 	struct device *dev;
538f55fed3SJonathan Neuschäfer 	void __iomem *regs;
54588de43cSJonathan Neuschäfer 	int irq;
55a7241c1bSJonathan Neuschäfer 	u32 edge_emulation;
56a7241c1bSJonathan Neuschäfer 	u32 rising_edge, falling_edge;
578f55fed3SJonathan Neuschäfer };
588f55fed3SJonathan Neuschäfer 
hlwd_gpio_irqhandler(struct irq_desc * desc)59588de43cSJonathan Neuschäfer static void hlwd_gpio_irqhandler(struct irq_desc *desc)
60588de43cSJonathan Neuschäfer {
61588de43cSJonathan Neuschäfer 	struct hlwd_gpio *hlwd =
62588de43cSJonathan Neuschäfer 		gpiochip_get_data(irq_desc_get_handler_data(desc));
63588de43cSJonathan Neuschäfer 	struct irq_chip *chip = irq_desc_get_chip(desc);
64588de43cSJonathan Neuschäfer 	unsigned long flags;
65588de43cSJonathan Neuschäfer 	unsigned long pending;
66588de43cSJonathan Neuschäfer 	int hwirq;
67a7241c1bSJonathan Neuschäfer 	u32 emulated_pending;
68588de43cSJonathan Neuschäfer 
693c938cc5SSchspa Shi 	raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
70588de43cSJonathan Neuschäfer 	pending = ioread32be(hlwd->regs + HW_GPIOB_INTFLAG);
71588de43cSJonathan Neuschäfer 	pending &= ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
72a7241c1bSJonathan Neuschäfer 
73a7241c1bSJonathan Neuschäfer 	/* Treat interrupts due to edge trigger emulation separately */
74a7241c1bSJonathan Neuschäfer 	emulated_pending = hlwd->edge_emulation & pending;
75a7241c1bSJonathan Neuschäfer 	pending &= ~emulated_pending;
76a7241c1bSJonathan Neuschäfer 	if (emulated_pending) {
77a7241c1bSJonathan Neuschäfer 		u32 level, rising, falling;
78a7241c1bSJonathan Neuschäfer 
79a7241c1bSJonathan Neuschäfer 		level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
80a7241c1bSJonathan Neuschäfer 		rising = level & emulated_pending;
81a7241c1bSJonathan Neuschäfer 		falling = ~level & emulated_pending;
82a7241c1bSJonathan Neuschäfer 
83a7241c1bSJonathan Neuschäfer 		/* Invert the levels */
84a7241c1bSJonathan Neuschäfer 		iowrite32be(level ^ emulated_pending,
85a7241c1bSJonathan Neuschäfer 			    hlwd->regs + HW_GPIOB_INTLVL);
86a7241c1bSJonathan Neuschäfer 
87a7241c1bSJonathan Neuschäfer 		/* Ack all emulated-edge interrupts */
88a7241c1bSJonathan Neuschäfer 		iowrite32be(emulated_pending, hlwd->regs + HW_GPIOB_INTFLAG);
89a7241c1bSJonathan Neuschäfer 
90a7241c1bSJonathan Neuschäfer 		/* Signal interrupts only on the correct edge */
91a7241c1bSJonathan Neuschäfer 		rising &= hlwd->rising_edge;
92a7241c1bSJonathan Neuschäfer 		falling &= hlwd->falling_edge;
93a7241c1bSJonathan Neuschäfer 
94a7241c1bSJonathan Neuschäfer 		/* Mark emulated interrupts as pending */
95a7241c1bSJonathan Neuschäfer 		pending |= rising | falling;
96a7241c1bSJonathan Neuschäfer 	}
973c938cc5SSchspa Shi 	raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
98588de43cSJonathan Neuschäfer 
99588de43cSJonathan Neuschäfer 	chained_irq_enter(chip, desc);
100588de43cSJonathan Neuschäfer 
101dbd1c54fSMarc Zyngier 	for_each_set_bit(hwirq, &pending, 32)
102dbd1c54fSMarc Zyngier 		generic_handle_domain_irq(hlwd->gpioc.irq.domain, hwirq);
103588de43cSJonathan Neuschäfer 
104588de43cSJonathan Neuschäfer 	chained_irq_exit(chip, desc);
105588de43cSJonathan Neuschäfer }
106588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_ack(struct irq_data * data)107588de43cSJonathan Neuschäfer static void hlwd_gpio_irq_ack(struct irq_data *data)
108588de43cSJonathan Neuschäfer {
109588de43cSJonathan Neuschäfer 	struct hlwd_gpio *hlwd =
110588de43cSJonathan Neuschäfer 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
111588de43cSJonathan Neuschäfer 
112588de43cSJonathan Neuschäfer 	iowrite32be(BIT(data->hwirq), hlwd->regs + HW_GPIOB_INTFLAG);
113588de43cSJonathan Neuschäfer }
114588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_mask(struct irq_data * data)115588de43cSJonathan Neuschäfer static void hlwd_gpio_irq_mask(struct irq_data *data)
116588de43cSJonathan Neuschäfer {
117588de43cSJonathan Neuschäfer 	struct hlwd_gpio *hlwd =
118588de43cSJonathan Neuschäfer 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
119588de43cSJonathan Neuschäfer 	unsigned long flags;
120588de43cSJonathan Neuschäfer 	u32 mask;
121588de43cSJonathan Neuschäfer 
1223c938cc5SSchspa Shi 	raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
123588de43cSJonathan Neuschäfer 	mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
124588de43cSJonathan Neuschäfer 	mask &= ~BIT(data->hwirq);
125588de43cSJonathan Neuschäfer 	iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
1263c938cc5SSchspa Shi 	raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
127ab42f021SLinus Walleij 	gpiochip_disable_irq(&hlwd->gpioc, irqd_to_hwirq(data));
128588de43cSJonathan Neuschäfer }
129588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_unmask(struct irq_data * data)130588de43cSJonathan Neuschäfer static void hlwd_gpio_irq_unmask(struct irq_data *data)
131588de43cSJonathan Neuschäfer {
132588de43cSJonathan Neuschäfer 	struct hlwd_gpio *hlwd =
133588de43cSJonathan Neuschäfer 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
134588de43cSJonathan Neuschäfer 	unsigned long flags;
135588de43cSJonathan Neuschäfer 	u32 mask;
136588de43cSJonathan Neuschäfer 
137ab42f021SLinus Walleij 	gpiochip_enable_irq(&hlwd->gpioc, irqd_to_hwirq(data));
1383c938cc5SSchspa Shi 	raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
139588de43cSJonathan Neuschäfer 	mask = ioread32be(hlwd->regs + HW_GPIOB_INTMASK);
140588de43cSJonathan Neuschäfer 	mask |= BIT(data->hwirq);
141588de43cSJonathan Neuschäfer 	iowrite32be(mask, hlwd->regs + HW_GPIOB_INTMASK);
1423c938cc5SSchspa Shi 	raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
143588de43cSJonathan Neuschäfer }
144588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_enable(struct irq_data * data)145588de43cSJonathan Neuschäfer static void hlwd_gpio_irq_enable(struct irq_data *data)
146588de43cSJonathan Neuschäfer {
147588de43cSJonathan Neuschäfer 	hlwd_gpio_irq_ack(data);
148588de43cSJonathan Neuschäfer 	hlwd_gpio_irq_unmask(data);
149588de43cSJonathan Neuschäfer }
150588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_setup_emulation(struct hlwd_gpio * hlwd,int hwirq,unsigned int flow_type)151a7241c1bSJonathan Neuschäfer static void hlwd_gpio_irq_setup_emulation(struct hlwd_gpio *hlwd, int hwirq,
152a7241c1bSJonathan Neuschäfer 					  unsigned int flow_type)
153a7241c1bSJonathan Neuschäfer {
154a7241c1bSJonathan Neuschäfer 	u32 level, state;
155a7241c1bSJonathan Neuschäfer 
156a7241c1bSJonathan Neuschäfer 	/* Set the trigger level to the inactive level */
157a7241c1bSJonathan Neuschäfer 	level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
158a7241c1bSJonathan Neuschäfer 	state = ioread32be(hlwd->regs + HW_GPIOB_IN) & BIT(hwirq);
159a7241c1bSJonathan Neuschäfer 	level &= ~BIT(hwirq);
160a7241c1bSJonathan Neuschäfer 	level |= state ^ BIT(hwirq);
161a7241c1bSJonathan Neuschäfer 	iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
162a7241c1bSJonathan Neuschäfer 
163a7241c1bSJonathan Neuschäfer 	hlwd->edge_emulation |= BIT(hwirq);
164a7241c1bSJonathan Neuschäfer 	hlwd->rising_edge &= ~BIT(hwirq);
165a7241c1bSJonathan Neuschäfer 	hlwd->falling_edge &= ~BIT(hwirq);
166a7241c1bSJonathan Neuschäfer 	if (flow_type & IRQ_TYPE_EDGE_RISING)
167a7241c1bSJonathan Neuschäfer 		hlwd->rising_edge |= BIT(hwirq);
168a7241c1bSJonathan Neuschäfer 	if (flow_type & IRQ_TYPE_EDGE_FALLING)
169a7241c1bSJonathan Neuschäfer 		hlwd->falling_edge |= BIT(hwirq);
170a7241c1bSJonathan Neuschäfer }
171a7241c1bSJonathan Neuschäfer 
hlwd_gpio_irq_set_type(struct irq_data * data,unsigned int flow_type)172588de43cSJonathan Neuschäfer static int hlwd_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
173588de43cSJonathan Neuschäfer {
174588de43cSJonathan Neuschäfer 	struct hlwd_gpio *hlwd =
175588de43cSJonathan Neuschäfer 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
176588de43cSJonathan Neuschäfer 	unsigned long flags;
177588de43cSJonathan Neuschäfer 	u32 level;
178588de43cSJonathan Neuschäfer 
1793c938cc5SSchspa Shi 	raw_spin_lock_irqsave(&hlwd->gpioc.bgpio_lock, flags);
180588de43cSJonathan Neuschäfer 
181a7241c1bSJonathan Neuschäfer 	hlwd->edge_emulation &= ~BIT(data->hwirq);
182a7241c1bSJonathan Neuschäfer 
183588de43cSJonathan Neuschäfer 	switch (flow_type) {
184588de43cSJonathan Neuschäfer 	case IRQ_TYPE_LEVEL_HIGH:
185588de43cSJonathan Neuschäfer 		level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
186588de43cSJonathan Neuschäfer 		level |= BIT(data->hwirq);
187588de43cSJonathan Neuschäfer 		iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
188588de43cSJonathan Neuschäfer 		break;
189588de43cSJonathan Neuschäfer 	case IRQ_TYPE_LEVEL_LOW:
190588de43cSJonathan Neuschäfer 		level = ioread32be(hlwd->regs + HW_GPIOB_INTLVL);
191588de43cSJonathan Neuschäfer 		level &= ~BIT(data->hwirq);
192588de43cSJonathan Neuschäfer 		iowrite32be(level, hlwd->regs + HW_GPIOB_INTLVL);
193588de43cSJonathan Neuschäfer 		break;
194a7241c1bSJonathan Neuschäfer 	case IRQ_TYPE_EDGE_RISING:
195a7241c1bSJonathan Neuschäfer 	case IRQ_TYPE_EDGE_FALLING:
196a7241c1bSJonathan Neuschäfer 	case IRQ_TYPE_EDGE_BOTH:
197a7241c1bSJonathan Neuschäfer 		hlwd_gpio_irq_setup_emulation(hlwd, data->hwirq, flow_type);
198a7241c1bSJonathan Neuschäfer 		break;
199588de43cSJonathan Neuschäfer 	default:
2003c938cc5SSchspa Shi 		raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
201588de43cSJonathan Neuschäfer 		return -EINVAL;
202588de43cSJonathan Neuschäfer 	}
203588de43cSJonathan Neuschäfer 
2043c938cc5SSchspa Shi 	raw_spin_unlock_irqrestore(&hlwd->gpioc.bgpio_lock, flags);
205588de43cSJonathan Neuschäfer 	return 0;
206588de43cSJonathan Neuschäfer }
207588de43cSJonathan Neuschäfer 
hlwd_gpio_irq_print_chip(struct irq_data * data,struct seq_file * p)208ab42f021SLinus Walleij static void hlwd_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
209ab42f021SLinus Walleij {
210ab42f021SLinus Walleij 	struct hlwd_gpio *hlwd =
211ab42f021SLinus Walleij 		gpiochip_get_data(irq_data_get_irq_chip_data(data));
212ab42f021SLinus Walleij 
213ab42f021SLinus Walleij 	seq_printf(p, dev_name(hlwd->dev));
214ab42f021SLinus Walleij }
215ab42f021SLinus Walleij 
216ab42f021SLinus Walleij static const struct irq_chip hlwd_gpio_irq_chip = {
217ab42f021SLinus Walleij 	.irq_mask = hlwd_gpio_irq_mask,
218ab42f021SLinus Walleij 	.irq_unmask = hlwd_gpio_irq_unmask,
219ab42f021SLinus Walleij 	.irq_enable = hlwd_gpio_irq_enable,
220ab42f021SLinus Walleij 	.irq_set_type = hlwd_gpio_irq_set_type,
221ab42f021SLinus Walleij 	.irq_print_chip = hlwd_gpio_irq_print_chip,
222ab42f021SLinus Walleij 	.flags = IRQCHIP_IMMUTABLE,
223ab42f021SLinus Walleij 	GPIOCHIP_IRQ_RESOURCE_HELPERS,
224ab42f021SLinus Walleij };
225ab42f021SLinus Walleij 
hlwd_gpio_probe(struct platform_device * pdev)2268f55fed3SJonathan Neuschäfer static int hlwd_gpio_probe(struct platform_device *pdev)
2278f55fed3SJonathan Neuschäfer {
2288f55fed3SJonathan Neuschäfer 	struct hlwd_gpio *hlwd;
2298f55fed3SJonathan Neuschäfer 	u32 ngpios;
2308f55fed3SJonathan Neuschäfer 	int res;
2318f55fed3SJonathan Neuschäfer 
2328f55fed3SJonathan Neuschäfer 	hlwd = devm_kzalloc(&pdev->dev, sizeof(*hlwd), GFP_KERNEL);
2338f55fed3SJonathan Neuschäfer 	if (!hlwd)
2348f55fed3SJonathan Neuschäfer 		return -ENOMEM;
2358f55fed3SJonathan Neuschäfer 
2368f701e1dSEnrico Weigelt, metux IT consult 	hlwd->regs = devm_platform_ioremap_resource(pdev, 0);
2378f55fed3SJonathan Neuschäfer 	if (IS_ERR(hlwd->regs))
2388f55fed3SJonathan Neuschäfer 		return PTR_ERR(hlwd->regs);
2398f55fed3SJonathan Neuschäfer 
240ab42f021SLinus Walleij 	hlwd->dev = &pdev->dev;
241ab42f021SLinus Walleij 
2428f55fed3SJonathan Neuschäfer 	/*
2438f55fed3SJonathan Neuschäfer 	 * Claim all GPIOs using the OWNER register. This will not work on
2448f55fed3SJonathan Neuschäfer 	 * systems where the AHBPROT memory firewall hasn't been configured to
2458f55fed3SJonathan Neuschäfer 	 * permit PPC access to HW_GPIO_*.
2468f55fed3SJonathan Neuschäfer 	 *
2478f55fed3SJonathan Neuschäfer 	 * Note that this has to happen before bgpio_init reads the
2488f55fed3SJonathan Neuschäfer 	 * HW_GPIOB_OUT and HW_GPIOB_DIR, because otherwise it reads the wrong
2498f55fed3SJonathan Neuschäfer 	 * values.
2508f55fed3SJonathan Neuschäfer 	 */
2518f55fed3SJonathan Neuschäfer 	iowrite32be(0xffffffff, hlwd->regs + HW_GPIO_OWNER);
2528f55fed3SJonathan Neuschäfer 
2538f55fed3SJonathan Neuschäfer 	res = bgpio_init(&hlwd->gpioc, &pdev->dev, 4,
2548f55fed3SJonathan Neuschäfer 			hlwd->regs + HW_GPIOB_IN, hlwd->regs + HW_GPIOB_OUT,
2558f55fed3SJonathan Neuschäfer 			NULL, hlwd->regs + HW_GPIOB_DIR, NULL,
2568f55fed3SJonathan Neuschäfer 			BGPIOF_BIG_ENDIAN_BYTE_ORDER);
2578f55fed3SJonathan Neuschäfer 	if (res < 0) {
2588f55fed3SJonathan Neuschäfer 		dev_warn(&pdev->dev, "bgpio_init failed: %d\n", res);
2598f55fed3SJonathan Neuschäfer 		return res;
2608f55fed3SJonathan Neuschäfer 	}
2618f55fed3SJonathan Neuschäfer 
2628f55fed3SJonathan Neuschäfer 	res = of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios);
2638f55fed3SJonathan Neuschäfer 	if (res)
2648f55fed3SJonathan Neuschäfer 		ngpios = 32;
2658f55fed3SJonathan Neuschäfer 	hlwd->gpioc.ngpio = ngpios;
2668f55fed3SJonathan Neuschäfer 
267588de43cSJonathan Neuschäfer 	/* Mask and ack all interrupts */
268588de43cSJonathan Neuschäfer 	iowrite32be(0, hlwd->regs + HW_GPIOB_INTMASK);
269588de43cSJonathan Neuschäfer 	iowrite32be(0xffffffff, hlwd->regs + HW_GPIOB_INTFLAG);
270588de43cSJonathan Neuschäfer 
271588de43cSJonathan Neuschäfer 	/*
272588de43cSJonathan Neuschäfer 	 * If this GPIO controller is not marked as an interrupt controller in
273a2ac3eb3SLinus Walleij 	 * the DT, skip interrupt support.
274588de43cSJonathan Neuschäfer 	 */
275a2ac3eb3SLinus Walleij 	if (of_property_read_bool(pdev->dev.of_node, "interrupt-controller")) {
276a2ac3eb3SLinus Walleij 		struct gpio_irq_chip *girq;
277588de43cSJonathan Neuschäfer 
278588de43cSJonathan Neuschäfer 		hlwd->irq = platform_get_irq(pdev, 0);
279588de43cSJonathan Neuschäfer 		if (hlwd->irq < 0) {
280588de43cSJonathan Neuschäfer 			dev_info(&pdev->dev, "platform_get_irq returned %d\n",
281588de43cSJonathan Neuschäfer 				 hlwd->irq);
282588de43cSJonathan Neuschäfer 			return hlwd->irq;
283588de43cSJonathan Neuschäfer 		}
284588de43cSJonathan Neuschäfer 
285a2ac3eb3SLinus Walleij 		girq = &hlwd->gpioc.irq;
286ab42f021SLinus Walleij 		gpio_irq_chip_set_chip(girq, &hlwd_gpio_irq_chip);
287a2ac3eb3SLinus Walleij 		girq->parent_handler = hlwd_gpio_irqhandler;
288a2ac3eb3SLinus Walleij 		girq->num_parents = 1;
289a2ac3eb3SLinus Walleij 		girq->parents = devm_kcalloc(&pdev->dev, 1,
290a2ac3eb3SLinus Walleij 					     sizeof(*girq->parents),
291a2ac3eb3SLinus Walleij 					     GFP_KERNEL);
292a2ac3eb3SLinus Walleij 		if (!girq->parents)
293a2ac3eb3SLinus Walleij 			return -ENOMEM;
294a2ac3eb3SLinus Walleij 		girq->parents[0] = hlwd->irq;
295a2ac3eb3SLinus Walleij 		girq->default_type = IRQ_TYPE_NONE;
296a2ac3eb3SLinus Walleij 		girq->handler = handle_level_irq;
297a2ac3eb3SLinus Walleij 	}
298588de43cSJonathan Neuschäfer 
299a2ac3eb3SLinus Walleij 	return devm_gpiochip_add_data(&pdev->dev, &hlwd->gpioc, hlwd);
3008f55fed3SJonathan Neuschäfer }
3018f55fed3SJonathan Neuschäfer 
3028f55fed3SJonathan Neuschäfer static const struct of_device_id hlwd_gpio_match[] = {
3038f55fed3SJonathan Neuschäfer 	{ .compatible = "nintendo,hollywood-gpio", },
3048f55fed3SJonathan Neuschäfer 	{},
3058f55fed3SJonathan Neuschäfer };
3068f55fed3SJonathan Neuschäfer MODULE_DEVICE_TABLE(of, hlwd_gpio_match);
3078f55fed3SJonathan Neuschäfer 
3088f55fed3SJonathan Neuschäfer static struct platform_driver hlwd_gpio_driver = {
3098f55fed3SJonathan Neuschäfer 	.driver	= {
3108f55fed3SJonathan Neuschäfer 		.name		= "gpio-hlwd",
3118f55fed3SJonathan Neuschäfer 		.of_match_table	= hlwd_gpio_match,
3128f55fed3SJonathan Neuschäfer 	},
3138f55fed3SJonathan Neuschäfer 	.probe	= hlwd_gpio_probe,
3148f55fed3SJonathan Neuschäfer };
3158f55fed3SJonathan Neuschäfer module_platform_driver(hlwd_gpio_driver);
3168f55fed3SJonathan Neuschäfer 
3178f55fed3SJonathan Neuschäfer MODULE_AUTHOR("Jonathan Neuschäfer <j.neuschaefer@gmx.net>");
3188f55fed3SJonathan Neuschäfer MODULE_DESCRIPTION("Nintendo Wii GPIO driver");
3198f55fed3SJonathan Neuschäfer MODULE_LICENSE("GPL");
320