1813e7d36SLinus Walleij // SPDX-License-Identifier: GPL-2.0
2813e7d36SLinus Walleij //
3813e7d36SLinus Walleij // IXP4 GPIO driver
4813e7d36SLinus Walleij // Copyright (C) 2019 Linus Walleij <linus.walleij@linaro.org>
5813e7d36SLinus Walleij //
6813e7d36SLinus Walleij // based on previous work and know-how from:
7813e7d36SLinus Walleij // Deepak Saxena <dsaxena@plexity.net>
8813e7d36SLinus Walleij
9*1e3d42f5SAndy Shevchenko #include <linux/bitops.h>
10813e7d36SLinus Walleij #include <linux/gpio/driver.h>
11813e7d36SLinus Walleij #include <linux/io.h>
12813e7d36SLinus Walleij #include <linux/irq.h>
13813e7d36SLinus Walleij #include <linux/irqdomain.h>
14813e7d36SLinus Walleij #include <linux/irqchip.h>
15e4bfb0ffSLinus Walleij #include <linux/of_irq.h>
16813e7d36SLinus Walleij #include <linux/platform_device.h>
17*1e3d42f5SAndy Shevchenko #include <linux/property.h>
18813e7d36SLinus Walleij
19813e7d36SLinus Walleij #define IXP4XX_REG_GPOUT 0x00
20813e7d36SLinus Walleij #define IXP4XX_REG_GPOE 0x04
21813e7d36SLinus Walleij #define IXP4XX_REG_GPIN 0x08
22813e7d36SLinus Walleij #define IXP4XX_REG_GPIS 0x0C
23813e7d36SLinus Walleij #define IXP4XX_REG_GPIT1 0x10
24813e7d36SLinus Walleij #define IXP4XX_REG_GPIT2 0x14
25813e7d36SLinus Walleij #define IXP4XX_REG_GPCLK 0x18
26813e7d36SLinus Walleij #define IXP4XX_REG_GPDBSEL 0x1C
27813e7d36SLinus Walleij
28813e7d36SLinus Walleij /*
29813e7d36SLinus Walleij * The hardware uses 3 bits to indicate interrupt "style".
30813e7d36SLinus Walleij * we clear and set these three bits accordingly. The lower 24
31813e7d36SLinus Walleij * bits in two registers (GPIT1 and GPIT2) are used to set up
32813e7d36SLinus Walleij * the style for 8 lines each for a total of 16 GPIO lines.
33813e7d36SLinus Walleij */
34813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_ACTIVE_HIGH 0x0
35813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_ACTIVE_LOW 0x1
36813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_RISING_EDGE 0x2
37813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_FALLING_EDGE 0x3
38813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_TRANSITIONAL 0x4
39813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_MASK GENMASK(2, 0)
40813e7d36SLinus Walleij #define IXP4XX_GPIO_STYLE_SIZE 3
41813e7d36SLinus Walleij
429a9429b9SLinus Walleij /*
439a9429b9SLinus Walleij * Clock output control register defines.
449a9429b9SLinus Walleij */
459a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK0DC_SHIFT 0
469a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK0TC_SHIFT 4
479a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK0_MASK GENMASK(7, 0)
489a9429b9SLinus Walleij #define IXP4XX_GPCLK_MUX14 BIT(8)
499a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK1DC_SHIFT 16
509a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK1TC_SHIFT 20
519a9429b9SLinus Walleij #define IXP4XX_GPCLK_CLK1_MASK GENMASK(23, 16)
529a9429b9SLinus Walleij #define IXP4XX_GPCLK_MUX15 BIT(24)
539a9429b9SLinus Walleij
54813e7d36SLinus Walleij /**
55813e7d36SLinus Walleij * struct ixp4xx_gpio - IXP4 GPIO state container
56813e7d36SLinus Walleij * @dev: containing device for this instance
57813e7d36SLinus Walleij * @gc: gpiochip for this instance
58813e7d36SLinus Walleij * @base: remapped I/O-memory base
59813e7d36SLinus Walleij * @irq_edge: Each bit represents an IRQ: 1: edge-triggered,
60813e7d36SLinus Walleij * 0: level triggered
61813e7d36SLinus Walleij */
62813e7d36SLinus Walleij struct ixp4xx_gpio {
63813e7d36SLinus Walleij struct gpio_chip gc;
64*1e3d42f5SAndy Shevchenko struct device *dev;
65813e7d36SLinus Walleij void __iomem *base;
66813e7d36SLinus Walleij unsigned long long irq_edge;
67813e7d36SLinus Walleij };
68813e7d36SLinus Walleij
ixp4xx_gpio_irq_ack(struct irq_data * d)69813e7d36SLinus Walleij static void ixp4xx_gpio_irq_ack(struct irq_data *d)
70813e7d36SLinus Walleij {
71aa7d618aSLinus Walleij struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
72aa7d618aSLinus Walleij struct ixp4xx_gpio *g = gpiochip_get_data(gc);
73813e7d36SLinus Walleij
74813e7d36SLinus Walleij __raw_writel(BIT(d->hwirq), g->base + IXP4XX_REG_GPIS);
75813e7d36SLinus Walleij }
76813e7d36SLinus Walleij
ixp4xx_gpio_mask_irq(struct irq_data * d)7794e9bc73SLinus Walleij static void ixp4xx_gpio_mask_irq(struct irq_data *d)
7894e9bc73SLinus Walleij {
7994e9bc73SLinus Walleij struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
8094e9bc73SLinus Walleij
8194e9bc73SLinus Walleij irq_chip_mask_parent(d);
8294e9bc73SLinus Walleij gpiochip_disable_irq(gc, d->hwirq);
8394e9bc73SLinus Walleij }
8494e9bc73SLinus Walleij
ixp4xx_gpio_irq_unmask(struct irq_data * d)85813e7d36SLinus Walleij static void ixp4xx_gpio_irq_unmask(struct irq_data *d)
86813e7d36SLinus Walleij {
87aa7d618aSLinus Walleij struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
88aa7d618aSLinus Walleij struct ixp4xx_gpio *g = gpiochip_get_data(gc);
89813e7d36SLinus Walleij
90813e7d36SLinus Walleij /* ACK when unmasking if not edge-triggered */
91813e7d36SLinus Walleij if (!(g->irq_edge & BIT(d->hwirq)))
92813e7d36SLinus Walleij ixp4xx_gpio_irq_ack(d);
93813e7d36SLinus Walleij
9494e9bc73SLinus Walleij gpiochip_enable_irq(gc, d->hwirq);
95813e7d36SLinus Walleij irq_chip_unmask_parent(d);
96813e7d36SLinus Walleij }
97813e7d36SLinus Walleij
ixp4xx_gpio_irq_set_type(struct irq_data * d,unsigned int type)98813e7d36SLinus Walleij static int ixp4xx_gpio_irq_set_type(struct irq_data *d, unsigned int type)
99813e7d36SLinus Walleij {
100aa7d618aSLinus Walleij struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
101aa7d618aSLinus Walleij struct ixp4xx_gpio *g = gpiochip_get_data(gc);
102813e7d36SLinus Walleij int line = d->hwirq;
103813e7d36SLinus Walleij unsigned long flags;
104813e7d36SLinus Walleij u32 int_style;
105813e7d36SLinus Walleij u32 int_reg;
106813e7d36SLinus Walleij u32 val;
107813e7d36SLinus Walleij
108813e7d36SLinus Walleij switch (type) {
109813e7d36SLinus Walleij case IRQ_TYPE_EDGE_BOTH:
110813e7d36SLinus Walleij irq_set_handler_locked(d, handle_edge_irq);
111813e7d36SLinus Walleij int_style = IXP4XX_GPIO_STYLE_TRANSITIONAL;
112813e7d36SLinus Walleij g->irq_edge |= BIT(d->hwirq);
113813e7d36SLinus Walleij break;
114813e7d36SLinus Walleij case IRQ_TYPE_EDGE_RISING:
115813e7d36SLinus Walleij irq_set_handler_locked(d, handle_edge_irq);
116813e7d36SLinus Walleij int_style = IXP4XX_GPIO_STYLE_RISING_EDGE;
117813e7d36SLinus Walleij g->irq_edge |= BIT(d->hwirq);
118813e7d36SLinus Walleij break;
119813e7d36SLinus Walleij case IRQ_TYPE_EDGE_FALLING:
120813e7d36SLinus Walleij irq_set_handler_locked(d, handle_edge_irq);
121813e7d36SLinus Walleij int_style = IXP4XX_GPIO_STYLE_FALLING_EDGE;
122813e7d36SLinus Walleij g->irq_edge |= BIT(d->hwirq);
123813e7d36SLinus Walleij break;
124813e7d36SLinus Walleij case IRQ_TYPE_LEVEL_HIGH:
125813e7d36SLinus Walleij irq_set_handler_locked(d, handle_level_irq);
126813e7d36SLinus Walleij int_style = IXP4XX_GPIO_STYLE_ACTIVE_HIGH;
127813e7d36SLinus Walleij g->irq_edge &= ~BIT(d->hwirq);
128813e7d36SLinus Walleij break;
129813e7d36SLinus Walleij case IRQ_TYPE_LEVEL_LOW:
130813e7d36SLinus Walleij irq_set_handler_locked(d, handle_level_irq);
131813e7d36SLinus Walleij int_style = IXP4XX_GPIO_STYLE_ACTIVE_LOW;
132813e7d36SLinus Walleij g->irq_edge &= ~BIT(d->hwirq);
133813e7d36SLinus Walleij break;
134813e7d36SLinus Walleij default:
135813e7d36SLinus Walleij return -EINVAL;
136813e7d36SLinus Walleij }
137813e7d36SLinus Walleij
138813e7d36SLinus Walleij if (line >= 8) {
139813e7d36SLinus Walleij /* pins 8-15 */
140813e7d36SLinus Walleij line -= 8;
141813e7d36SLinus Walleij int_reg = IXP4XX_REG_GPIT2;
142813e7d36SLinus Walleij } else {
143813e7d36SLinus Walleij /* pins 0-7 */
144813e7d36SLinus Walleij int_reg = IXP4XX_REG_GPIT1;
145813e7d36SLinus Walleij }
146813e7d36SLinus Walleij
1473c938cc5SSchspa Shi raw_spin_lock_irqsave(&g->gc.bgpio_lock, flags);
148813e7d36SLinus Walleij
149813e7d36SLinus Walleij /* Clear the style for the appropriate pin */
150813e7d36SLinus Walleij val = __raw_readl(g->base + int_reg);
151813e7d36SLinus Walleij val &= ~(IXP4XX_GPIO_STYLE_MASK << (line * IXP4XX_GPIO_STYLE_SIZE));
152813e7d36SLinus Walleij __raw_writel(val, g->base + int_reg);
153813e7d36SLinus Walleij
154813e7d36SLinus Walleij __raw_writel(BIT(line), g->base + IXP4XX_REG_GPIS);
155813e7d36SLinus Walleij
156813e7d36SLinus Walleij /* Set the new style */
157813e7d36SLinus Walleij val = __raw_readl(g->base + int_reg);
158813e7d36SLinus Walleij val |= (int_style << (line * IXP4XX_GPIO_STYLE_SIZE));
159813e7d36SLinus Walleij __raw_writel(val, g->base + int_reg);
160813e7d36SLinus Walleij
161813e7d36SLinus Walleij /* Force-configure this line as an input */
162813e7d36SLinus Walleij val = __raw_readl(g->base + IXP4XX_REG_GPOE);
163813e7d36SLinus Walleij val |= BIT(d->hwirq);
164813e7d36SLinus Walleij __raw_writel(val, g->base + IXP4XX_REG_GPOE);
165813e7d36SLinus Walleij
1663c938cc5SSchspa Shi raw_spin_unlock_irqrestore(&g->gc.bgpio_lock, flags);
167813e7d36SLinus Walleij
168813e7d36SLinus Walleij /* This parent only accept level high (asserted) */
169813e7d36SLinus Walleij return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
170813e7d36SLinus Walleij }
171813e7d36SLinus Walleij
17294e9bc73SLinus Walleij static const struct irq_chip ixp4xx_gpio_irqchip = {
173813e7d36SLinus Walleij .name = "IXP4GPIO",
174813e7d36SLinus Walleij .irq_ack = ixp4xx_gpio_irq_ack,
17594e9bc73SLinus Walleij .irq_mask = ixp4xx_gpio_mask_irq,
176813e7d36SLinus Walleij .irq_unmask = ixp4xx_gpio_irq_unmask,
177813e7d36SLinus Walleij .irq_set_type = ixp4xx_gpio_irq_set_type,
17894e9bc73SLinus Walleij .flags = IRQCHIP_IMMUTABLE,
17994e9bc73SLinus Walleij GPIOCHIP_IRQ_RESOURCE_HELPERS,
180813e7d36SLinus Walleij };
181813e7d36SLinus Walleij
ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip * gc,unsigned int child,unsigned int child_type,unsigned int * parent,unsigned int * parent_type)182aa7d618aSLinus Walleij static int ixp4xx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
183aa7d618aSLinus Walleij unsigned int child,
184aa7d618aSLinus Walleij unsigned int child_type,
185aa7d618aSLinus Walleij unsigned int *parent,
186aa7d618aSLinus Walleij unsigned int *parent_type)
187813e7d36SLinus Walleij {
188aa7d618aSLinus Walleij /* All these interrupts are level high in the CPU */
189aa7d618aSLinus Walleij *parent_type = IRQ_TYPE_LEVEL_HIGH;
190813e7d36SLinus Walleij
191aa7d618aSLinus Walleij /* GPIO lines 0..12 have dedicated IRQs */
192aa7d618aSLinus Walleij if (child == 0) {
193aa7d618aSLinus Walleij *parent = 6;
194aa7d618aSLinus Walleij return 0;
195813e7d36SLinus Walleij }
196aa7d618aSLinus Walleij if (child == 1) {
197aa7d618aSLinus Walleij *parent = 7;
198aa7d618aSLinus Walleij return 0;
199813e7d36SLinus Walleij }
200aa7d618aSLinus Walleij if (child >= 2 && child <= 12) {
201aa7d618aSLinus Walleij *parent = child + 17;
202813e7d36SLinus Walleij return 0;
203813e7d36SLinus Walleij }
204813e7d36SLinus Walleij return -EINVAL;
205813e7d36SLinus Walleij }
206813e7d36SLinus Walleij
ixp4xx_gpio_probe(struct platform_device * pdev)207813e7d36SLinus Walleij static int ixp4xx_gpio_probe(struct platform_device *pdev)
208813e7d36SLinus Walleij {
209813e7d36SLinus Walleij unsigned long flags;
210813e7d36SLinus Walleij struct device *dev = &pdev->dev;
211e4bfb0ffSLinus Walleij struct device_node *np = dev->of_node;
212813e7d36SLinus Walleij struct irq_domain *parent;
213813e7d36SLinus Walleij struct ixp4xx_gpio *g;
214aa7d618aSLinus Walleij struct gpio_irq_chip *girq;
215c83227a5SLinus Walleij struct device_node *irq_parent;
2169a9429b9SLinus Walleij bool clk_14, clk_15;
2179a9429b9SLinus Walleij u32 val;
218813e7d36SLinus Walleij int ret;
219813e7d36SLinus Walleij
220813e7d36SLinus Walleij g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL);
221813e7d36SLinus Walleij if (!g)
222813e7d36SLinus Walleij return -ENOMEM;
223813e7d36SLinus Walleij g->dev = dev;
224813e7d36SLinus Walleij
225f8d1af24SYang Li g->base = devm_platform_ioremap_resource(pdev, 0);
22661059b70SDing Xiang if (IS_ERR(g->base))
227813e7d36SLinus Walleij return PTR_ERR(g->base);
228813e7d36SLinus Walleij
229aa7d618aSLinus Walleij irq_parent = of_irq_find_parent(np);
230aa7d618aSLinus Walleij if (!irq_parent) {
231aa7d618aSLinus Walleij dev_err(dev, "no IRQ parent node\n");
232aa7d618aSLinus Walleij return -ENODEV;
233aa7d618aSLinus Walleij }
234aa7d618aSLinus Walleij parent = irq_find_host(irq_parent);
235aa7d618aSLinus Walleij if (!parent) {
236aa7d618aSLinus Walleij dev_err(dev, "no IRQ parent domain\n");
237aa7d618aSLinus Walleij return -ENODEV;
238aa7d618aSLinus Walleij }
239aa7d618aSLinus Walleij
240aa7d618aSLinus Walleij /*
2419a9429b9SLinus Walleij * If either clock output is enabled explicitly in the device tree
2429a9429b9SLinus Walleij * we take full control of the clock by masking off all bits for
2439a9429b9SLinus Walleij * the clock control and selectively enabling them. Otherwise
2449a9429b9SLinus Walleij * we leave the hardware default settings.
2459a9429b9SLinus Walleij *
2469a9429b9SLinus Walleij * Enable clock outputs with default timings of requested clock.
2479a9429b9SLinus Walleij * If you need control over TC and DC, add these to the device
2489a9429b9SLinus Walleij * tree bindings and use them here.
2499a9429b9SLinus Walleij */
2509a9429b9SLinus Walleij clk_14 = of_property_read_bool(np, "intel,ixp4xx-gpio14-clkout");
2519a9429b9SLinus Walleij clk_15 = of_property_read_bool(np, "intel,ixp4xx-gpio15-clkout");
2529a9429b9SLinus Walleij
2539a9429b9SLinus Walleij /*
254813e7d36SLinus Walleij * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on
255813e7d36SLinus Walleij * specific machines.
256813e7d36SLinus Walleij */
2574f3e79b3SLinus Walleij if (of_machine_is_compatible("dlink,dsm-g600-a") ||
2584f3e79b3SLinus Walleij of_machine_is_compatible("iom,nas-100d"))
2599a9429b9SLinus Walleij val = 0;
2609a9429b9SLinus Walleij else {
2619a9429b9SLinus Walleij val = __raw_readl(g->base + IXP4XX_REG_GPCLK);
2629a9429b9SLinus Walleij
2639a9429b9SLinus Walleij if (clk_14 || clk_15) {
2649a9429b9SLinus Walleij val &= ~(IXP4XX_GPCLK_MUX14 | IXP4XX_GPCLK_MUX15);
2659a9429b9SLinus Walleij val &= ~IXP4XX_GPCLK_CLK0_MASK;
2669a9429b9SLinus Walleij val &= ~IXP4XX_GPCLK_CLK1_MASK;
2679a9429b9SLinus Walleij if (clk_14) {
2689a9429b9SLinus Walleij /* IXP4XX_GPCLK_CLK0DC implicit low */
2699a9429b9SLinus Walleij val |= (1 << IXP4XX_GPCLK_CLK0TC_SHIFT);
2709a9429b9SLinus Walleij val |= IXP4XX_GPCLK_MUX14;
2719a9429b9SLinus Walleij }
2729a9429b9SLinus Walleij
2739a9429b9SLinus Walleij if (clk_15) {
2749a9429b9SLinus Walleij /* IXP4XX_GPCLK_CLK1DC implicit low */
2759a9429b9SLinus Walleij val |= (1 << IXP4XX_GPCLK_CLK1TC_SHIFT);
2769a9429b9SLinus Walleij val |= IXP4XX_GPCLK_MUX15;
2779a9429b9SLinus Walleij }
2789a9429b9SLinus Walleij }
2799a9429b9SLinus Walleij }
2809a9429b9SLinus Walleij
2819a9429b9SLinus Walleij __raw_writel(val, g->base + IXP4XX_REG_GPCLK);
282813e7d36SLinus Walleij
283813e7d36SLinus Walleij /*
284813e7d36SLinus Walleij * This is a very special big-endian ARM issue: when the IXP4xx is
285813e7d36SLinus Walleij * run in big endian mode, all registers in the machine are switched
286813e7d36SLinus Walleij * around to the CPU-native endianness. As you see mostly in the
287813e7d36SLinus Walleij * driver we use __raw_readl()/__raw_writel() to access the registers
288813e7d36SLinus Walleij * in the appropriate order. With the GPIO library we need to specify
289813e7d36SLinus Walleij * byte order explicitly, so this flag needs to be set when compiling
290813e7d36SLinus Walleij * for big endian.
291813e7d36SLinus Walleij */
292813e7d36SLinus Walleij #if defined(CONFIG_CPU_BIG_ENDIAN)
293813e7d36SLinus Walleij flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
294813e7d36SLinus Walleij #else
295813e7d36SLinus Walleij flags = 0;
296813e7d36SLinus Walleij #endif
297813e7d36SLinus Walleij
298813e7d36SLinus Walleij /* Populate and register gpio chip */
299813e7d36SLinus Walleij ret = bgpio_init(&g->gc, dev, 4,
300813e7d36SLinus Walleij g->base + IXP4XX_REG_GPIN,
301813e7d36SLinus Walleij g->base + IXP4XX_REG_GPOUT,
302813e7d36SLinus Walleij NULL,
303813e7d36SLinus Walleij NULL,
304813e7d36SLinus Walleij g->base + IXP4XX_REG_GPOE,
305813e7d36SLinus Walleij flags);
306813e7d36SLinus Walleij if (ret) {
307813e7d36SLinus Walleij dev_err(dev, "unable to init generic GPIO\n");
308813e7d36SLinus Walleij return ret;
309813e7d36SLinus Walleij }
310813e7d36SLinus Walleij g->gc.ngpio = 16;
311813e7d36SLinus Walleij g->gc.label = "IXP4XX_GPIO_CHIP";
312813e7d36SLinus Walleij /*
313813e7d36SLinus Walleij * TODO: when we have migrated to device tree and all GPIOs
314813e7d36SLinus Walleij * are fetched using phandles, set this to -1 to get rid of
315813e7d36SLinus Walleij * the fixed gpiochip base.
316813e7d36SLinus Walleij */
317813e7d36SLinus Walleij g->gc.base = 0;
318813e7d36SLinus Walleij g->gc.parent = &pdev->dev;
319813e7d36SLinus Walleij g->gc.owner = THIS_MODULE;
320813e7d36SLinus Walleij
321aa7d618aSLinus Walleij girq = &g->gc.irq;
32294e9bc73SLinus Walleij gpio_irq_chip_set_chip(girq, &ixp4xx_gpio_irqchip);
323*1e3d42f5SAndy Shevchenko girq->fwnode = dev_fwnode(dev);
324aa7d618aSLinus Walleij girq->parent_domain = parent;
325aa7d618aSLinus Walleij girq->child_to_parent_hwirq = ixp4xx_gpio_child_to_parent_hwirq;
326aa7d618aSLinus Walleij girq->handler = handle_bad_irq;
327aa7d618aSLinus Walleij girq->default_type = IRQ_TYPE_NONE;
328aa7d618aSLinus Walleij
329813e7d36SLinus Walleij ret = devm_gpiochip_add_data(dev, &g->gc, g);
330813e7d36SLinus Walleij if (ret) {
331813e7d36SLinus Walleij dev_err(dev, "failed to add SoC gpiochip\n");
332813e7d36SLinus Walleij return ret;
333813e7d36SLinus Walleij }
334813e7d36SLinus Walleij
335813e7d36SLinus Walleij platform_set_drvdata(pdev, g);
336aa7d618aSLinus Walleij dev_info(dev, "IXP4 GPIO registered\n");
337813e7d36SLinus Walleij
338813e7d36SLinus Walleij return 0;
339813e7d36SLinus Walleij }
340813e7d36SLinus Walleij
341e4bfb0ffSLinus Walleij static const struct of_device_id ixp4xx_gpio_of_match[] = {
342e4bfb0ffSLinus Walleij {
343e4bfb0ffSLinus Walleij .compatible = "intel,ixp4xx-gpio",
344e4bfb0ffSLinus Walleij },
345e4bfb0ffSLinus Walleij {},
346e4bfb0ffSLinus Walleij };
347e4bfb0ffSLinus Walleij
348e4bfb0ffSLinus Walleij
349813e7d36SLinus Walleij static struct platform_driver ixp4xx_gpio_driver = {
350813e7d36SLinus Walleij .driver = {
351813e7d36SLinus Walleij .name = "ixp4xx-gpio",
35207d93cbbSZhu Wang .of_match_table = ixp4xx_gpio_of_match,
353813e7d36SLinus Walleij },
354813e7d36SLinus Walleij .probe = ixp4xx_gpio_probe,
355813e7d36SLinus Walleij };
356813e7d36SLinus Walleij builtin_platform_driver(ixp4xx_gpio_driver);
357