1*ff718800SKamlakant Patel /* 2*ff718800SKamlakant Patel * Copyright (C) 2003-2015 Broadcom Corporation 3*ff718800SKamlakant Patel * All Rights Reserved 4*ff718800SKamlakant Patel * 5*ff718800SKamlakant Patel * This program is free software; you can redistribute it and/or modify 6*ff718800SKamlakant Patel * it under the terms of the GNU General Public License version 2 as 7*ff718800SKamlakant Patel * published by the Free Software Foundation. 8*ff718800SKamlakant Patel * 9*ff718800SKamlakant Patel * This program is distributed in the hope that it will be useful, 10*ff718800SKamlakant Patel * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*ff718800SKamlakant Patel * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*ff718800SKamlakant Patel * GNU General Public License for more details. 13*ff718800SKamlakant Patel */ 14*ff718800SKamlakant Patel 15*ff718800SKamlakant Patel #include <linux/gpio.h> 16*ff718800SKamlakant Patel #include <linux/platform_device.h> 17*ff718800SKamlakant Patel #include <linux/of_device.h> 18*ff718800SKamlakant Patel #include <linux/module.h> 19*ff718800SKamlakant Patel #include <linux/irq.h> 20*ff718800SKamlakant Patel #include <linux/interrupt.h> 21*ff718800SKamlakant Patel 22*ff718800SKamlakant Patel /* 23*ff718800SKamlakant Patel * XLP GPIO has multiple 32 bit registers for each feature where each register 24*ff718800SKamlakant Patel * controls 32 pins. So, pins up to 64 require 2 32-bit registers and up to 96 25*ff718800SKamlakant Patel * require 3 32-bit registers for each feature. 26*ff718800SKamlakant Patel * Here we only define offset of the first register for each feature. Offset of 27*ff718800SKamlakant Patel * the registers for pins greater than 32 can be calculated as following(Use 28*ff718800SKamlakant Patel * GPIO_INT_STAT as example): 29*ff718800SKamlakant Patel * 30*ff718800SKamlakant Patel * offset = (gpio / XLP_GPIO_REGSZ) * 4; 31*ff718800SKamlakant Patel * reg_addr = addr + offset; 32*ff718800SKamlakant Patel * 33*ff718800SKamlakant Patel * where addr is base address of the that feature register and gpio is the pin. 34*ff718800SKamlakant Patel */ 35*ff718800SKamlakant Patel #define GPIO_OUTPUT_EN 0x00 36*ff718800SKamlakant Patel #define GPIO_PADDRV 0x08 37*ff718800SKamlakant Patel #define GPIO_INT_EN00 0x18 38*ff718800SKamlakant Patel #define GPIO_INT_EN10 0x20 39*ff718800SKamlakant Patel #define GPIO_INT_EN20 0x28 40*ff718800SKamlakant Patel #define GPIO_INT_EN30 0x30 41*ff718800SKamlakant Patel #define GPIO_INT_POL 0x38 42*ff718800SKamlakant Patel #define GPIO_INT_TYPE 0x40 43*ff718800SKamlakant Patel #define GPIO_INT_STAT 0x48 44*ff718800SKamlakant Patel 45*ff718800SKamlakant Patel #define GPIO_9XX_BYTESWAP 0X00 46*ff718800SKamlakant Patel #define GPIO_9XX_CTRL 0X04 47*ff718800SKamlakant Patel #define GPIO_9XX_OUTPUT_EN 0x14 48*ff718800SKamlakant Patel #define GPIO_9XX_PADDRV 0x24 49*ff718800SKamlakant Patel /* 50*ff718800SKamlakant Patel * Only for 4 interrupt enable reg are defined for now, 51*ff718800SKamlakant Patel * total reg available are 12. 52*ff718800SKamlakant Patel */ 53*ff718800SKamlakant Patel #define GPIO_9XX_INT_EN00 0x44 54*ff718800SKamlakant Patel #define GPIO_9XX_INT_EN10 0x54 55*ff718800SKamlakant Patel #define GPIO_9XX_INT_EN20 0x64 56*ff718800SKamlakant Patel #define GPIO_9XX_INT_EN30 0x74 57*ff718800SKamlakant Patel #define GPIO_9XX_INT_POL 0x104 58*ff718800SKamlakant Patel #define GPIO_9XX_INT_TYPE 0x114 59*ff718800SKamlakant Patel #define GPIO_9XX_INT_STAT 0x124 60*ff718800SKamlakant Patel 61*ff718800SKamlakant Patel #define GPIO_3XX_INT_EN00 0x18 62*ff718800SKamlakant Patel #define GPIO_3XX_INT_EN10 0x20 63*ff718800SKamlakant Patel #define GPIO_3XX_INT_EN20 0x28 64*ff718800SKamlakant Patel #define GPIO_3XX_INT_EN30 0x30 65*ff718800SKamlakant Patel #define GPIO_3XX_INT_POL 0x78 66*ff718800SKamlakant Patel #define GPIO_3XX_INT_TYPE 0x80 67*ff718800SKamlakant Patel #define GPIO_3XX_INT_STAT 0x88 68*ff718800SKamlakant Patel 69*ff718800SKamlakant Patel /* Interrupt type register mask */ 70*ff718800SKamlakant Patel #define XLP_GPIO_IRQ_TYPE_LVL 0x0 71*ff718800SKamlakant Patel #define XLP_GPIO_IRQ_TYPE_EDGE 0x1 72*ff718800SKamlakant Patel 73*ff718800SKamlakant Patel /* Interrupt polarity register mask */ 74*ff718800SKamlakant Patel #define XLP_GPIO_IRQ_POL_HIGH 0x0 75*ff718800SKamlakant Patel #define XLP_GPIO_IRQ_POL_LOW 0x1 76*ff718800SKamlakant Patel 77*ff718800SKamlakant Patel #define XLP_GPIO_REGSZ 32 78*ff718800SKamlakant Patel #define XLP_GPIO_IRQ_BASE 768 79*ff718800SKamlakant Patel #define XLP_MAX_NR_GPIO 96 80*ff718800SKamlakant Patel 81*ff718800SKamlakant Patel /* XLP variants supported by this driver */ 82*ff718800SKamlakant Patel enum { 83*ff718800SKamlakant Patel XLP_GPIO_VARIANT_XLP832 = 1, 84*ff718800SKamlakant Patel XLP_GPIO_VARIANT_XLP316, 85*ff718800SKamlakant Patel XLP_GPIO_VARIANT_XLP208, 86*ff718800SKamlakant Patel XLP_GPIO_VARIANT_XLP980, 87*ff718800SKamlakant Patel XLP_GPIO_VARIANT_XLP532 88*ff718800SKamlakant Patel }; 89*ff718800SKamlakant Patel 90*ff718800SKamlakant Patel struct xlp_gpio_priv { 91*ff718800SKamlakant Patel struct gpio_chip chip; 92*ff718800SKamlakant Patel DECLARE_BITMAP(gpio_enabled_mask, XLP_MAX_NR_GPIO); 93*ff718800SKamlakant Patel void __iomem *gpio_intr_en; /* pointer to first intr enable reg */ 94*ff718800SKamlakant Patel void __iomem *gpio_intr_stat; /* pointer to first intr status reg */ 95*ff718800SKamlakant Patel void __iomem *gpio_intr_type; /* pointer to first intr type reg */ 96*ff718800SKamlakant Patel void __iomem *gpio_intr_pol; /* pointer to first intr polarity reg */ 97*ff718800SKamlakant Patel void __iomem *gpio_out_en; /* pointer to first output enable reg */ 98*ff718800SKamlakant Patel void __iomem *gpio_paddrv; /* pointer to first pad drive reg */ 99*ff718800SKamlakant Patel spinlock_t lock; 100*ff718800SKamlakant Patel }; 101*ff718800SKamlakant Patel 102*ff718800SKamlakant Patel static struct xlp_gpio_priv *gpio_chip_to_xlp_priv(struct gpio_chip *gc) 103*ff718800SKamlakant Patel { 104*ff718800SKamlakant Patel return container_of(gc, struct xlp_gpio_priv, chip); 105*ff718800SKamlakant Patel } 106*ff718800SKamlakant Patel 107*ff718800SKamlakant Patel static int xlp_gpio_get_reg(void __iomem *addr, unsigned gpio) 108*ff718800SKamlakant Patel { 109*ff718800SKamlakant Patel u32 pos, regset; 110*ff718800SKamlakant Patel 111*ff718800SKamlakant Patel pos = gpio % XLP_GPIO_REGSZ; 112*ff718800SKamlakant Patel regset = (gpio / XLP_GPIO_REGSZ) * 4; 113*ff718800SKamlakant Patel return !!(readl(addr + regset) & BIT(pos)); 114*ff718800SKamlakant Patel } 115*ff718800SKamlakant Patel 116*ff718800SKamlakant Patel static void xlp_gpio_set_reg(void __iomem *addr, unsigned gpio, int state) 117*ff718800SKamlakant Patel { 118*ff718800SKamlakant Patel u32 value, pos, regset; 119*ff718800SKamlakant Patel 120*ff718800SKamlakant Patel pos = gpio % XLP_GPIO_REGSZ; 121*ff718800SKamlakant Patel regset = (gpio / XLP_GPIO_REGSZ) * 4; 122*ff718800SKamlakant Patel value = readl(addr + regset); 123*ff718800SKamlakant Patel 124*ff718800SKamlakant Patel if (state) 125*ff718800SKamlakant Patel value |= BIT(pos); 126*ff718800SKamlakant Patel else 127*ff718800SKamlakant Patel value &= ~BIT(pos); 128*ff718800SKamlakant Patel 129*ff718800SKamlakant Patel writel(value, addr + regset); 130*ff718800SKamlakant Patel } 131*ff718800SKamlakant Patel 132*ff718800SKamlakant Patel static void xlp_gpio_irq_disable(struct irq_data *d) 133*ff718800SKamlakant Patel { 134*ff718800SKamlakant Patel struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 135*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 136*ff718800SKamlakant Patel unsigned long flags; 137*ff718800SKamlakant Patel 138*ff718800SKamlakant Patel spin_lock_irqsave(&priv->lock, flags); 139*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_en, d->hwirq, 0x0); 140*ff718800SKamlakant Patel __clear_bit(d->hwirq, priv->gpio_enabled_mask); 141*ff718800SKamlakant Patel spin_unlock_irqrestore(&priv->lock, flags); 142*ff718800SKamlakant Patel } 143*ff718800SKamlakant Patel 144*ff718800SKamlakant Patel static void xlp_gpio_irq_mask_ack(struct irq_data *d) 145*ff718800SKamlakant Patel { 146*ff718800SKamlakant Patel struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 147*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 148*ff718800SKamlakant Patel unsigned long flags; 149*ff718800SKamlakant Patel 150*ff718800SKamlakant Patel spin_lock_irqsave(&priv->lock, flags); 151*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_en, d->hwirq, 0x0); 152*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_stat, d->hwirq, 0x1); 153*ff718800SKamlakant Patel __clear_bit(d->hwirq, priv->gpio_enabled_mask); 154*ff718800SKamlakant Patel spin_unlock_irqrestore(&priv->lock, flags); 155*ff718800SKamlakant Patel } 156*ff718800SKamlakant Patel 157*ff718800SKamlakant Patel static void xlp_gpio_irq_unmask(struct irq_data *d) 158*ff718800SKamlakant Patel { 159*ff718800SKamlakant Patel struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 160*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 161*ff718800SKamlakant Patel unsigned long flags; 162*ff718800SKamlakant Patel 163*ff718800SKamlakant Patel spin_lock_irqsave(&priv->lock, flags); 164*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_en, d->hwirq, 0x1); 165*ff718800SKamlakant Patel __set_bit(d->hwirq, priv->gpio_enabled_mask); 166*ff718800SKamlakant Patel spin_unlock_irqrestore(&priv->lock, flags); 167*ff718800SKamlakant Patel } 168*ff718800SKamlakant Patel 169*ff718800SKamlakant Patel static int xlp_gpio_set_irq_type(struct irq_data *d, unsigned int type) 170*ff718800SKamlakant Patel { 171*ff718800SKamlakant Patel struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 172*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 173*ff718800SKamlakant Patel int pol, irq_type; 174*ff718800SKamlakant Patel 175*ff718800SKamlakant Patel switch (type) { 176*ff718800SKamlakant Patel case IRQ_TYPE_EDGE_RISING: 177*ff718800SKamlakant Patel irq_type = XLP_GPIO_IRQ_TYPE_EDGE; 178*ff718800SKamlakant Patel pol = XLP_GPIO_IRQ_POL_HIGH; 179*ff718800SKamlakant Patel break; 180*ff718800SKamlakant Patel case IRQ_TYPE_EDGE_FALLING: 181*ff718800SKamlakant Patel irq_type = XLP_GPIO_IRQ_TYPE_EDGE; 182*ff718800SKamlakant Patel pol = XLP_GPIO_IRQ_POL_LOW; 183*ff718800SKamlakant Patel break; 184*ff718800SKamlakant Patel case IRQ_TYPE_LEVEL_HIGH: 185*ff718800SKamlakant Patel irq_type = XLP_GPIO_IRQ_TYPE_LVL; 186*ff718800SKamlakant Patel pol = XLP_GPIO_IRQ_POL_HIGH; 187*ff718800SKamlakant Patel break; 188*ff718800SKamlakant Patel case IRQ_TYPE_LEVEL_LOW: 189*ff718800SKamlakant Patel irq_type = XLP_GPIO_IRQ_TYPE_LVL; 190*ff718800SKamlakant Patel pol = XLP_GPIO_IRQ_POL_LOW; 191*ff718800SKamlakant Patel break; 192*ff718800SKamlakant Patel default: 193*ff718800SKamlakant Patel return -EINVAL; 194*ff718800SKamlakant Patel } 195*ff718800SKamlakant Patel 196*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_type, d->hwirq, irq_type); 197*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_intr_pol, d->hwirq, pol); 198*ff718800SKamlakant Patel 199*ff718800SKamlakant Patel return 0; 200*ff718800SKamlakant Patel } 201*ff718800SKamlakant Patel 202*ff718800SKamlakant Patel static struct irq_chip xlp_gpio_irq_chip = { 203*ff718800SKamlakant Patel .name = "XLP-GPIO", 204*ff718800SKamlakant Patel .irq_mask_ack = xlp_gpio_irq_mask_ack, 205*ff718800SKamlakant Patel .irq_disable = xlp_gpio_irq_disable, 206*ff718800SKamlakant Patel .irq_set_type = xlp_gpio_set_irq_type, 207*ff718800SKamlakant Patel .irq_unmask = xlp_gpio_irq_unmask, 208*ff718800SKamlakant Patel .flags = IRQCHIP_ONESHOT_SAFE, 209*ff718800SKamlakant Patel }; 210*ff718800SKamlakant Patel 211*ff718800SKamlakant Patel static irqreturn_t xlp_gpio_generic_handler(int irq, void *data) 212*ff718800SKamlakant Patel { 213*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = data; 214*ff718800SKamlakant Patel int gpio, regoff; 215*ff718800SKamlakant Patel u32 gpio_stat; 216*ff718800SKamlakant Patel 217*ff718800SKamlakant Patel regoff = -1; 218*ff718800SKamlakant Patel gpio_stat = 0; 219*ff718800SKamlakant Patel for_each_set_bit(gpio, priv->gpio_enabled_mask, XLP_MAX_NR_GPIO) { 220*ff718800SKamlakant Patel if (regoff != gpio / XLP_GPIO_REGSZ) { 221*ff718800SKamlakant Patel regoff = gpio / XLP_GPIO_REGSZ; 222*ff718800SKamlakant Patel gpio_stat = readl(priv->gpio_intr_stat + regoff * 4); 223*ff718800SKamlakant Patel } 224*ff718800SKamlakant Patel if (gpio_stat & BIT(gpio % XLP_GPIO_REGSZ)) 225*ff718800SKamlakant Patel generic_handle_irq(irq_find_mapping( 226*ff718800SKamlakant Patel priv->chip.irqdomain, gpio)); 227*ff718800SKamlakant Patel } 228*ff718800SKamlakant Patel 229*ff718800SKamlakant Patel return IRQ_HANDLED; 230*ff718800SKamlakant Patel } 231*ff718800SKamlakant Patel 232*ff718800SKamlakant Patel static int xlp_gpio_dir_output(struct gpio_chip *gc, unsigned gpio, int state) 233*ff718800SKamlakant Patel { 234*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 235*ff718800SKamlakant Patel 236*ff718800SKamlakant Patel BUG_ON(gpio >= gc->ngpio); 237*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_out_en, gpio, 0x1); 238*ff718800SKamlakant Patel 239*ff718800SKamlakant Patel return 0; 240*ff718800SKamlakant Patel } 241*ff718800SKamlakant Patel 242*ff718800SKamlakant Patel static int xlp_gpio_dir_input(struct gpio_chip *gc, unsigned gpio) 243*ff718800SKamlakant Patel { 244*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 245*ff718800SKamlakant Patel 246*ff718800SKamlakant Patel BUG_ON(gpio >= gc->ngpio); 247*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_out_en, gpio, 0x0); 248*ff718800SKamlakant Patel 249*ff718800SKamlakant Patel return 0; 250*ff718800SKamlakant Patel } 251*ff718800SKamlakant Patel 252*ff718800SKamlakant Patel static int xlp_gpio_get(struct gpio_chip *gc, unsigned gpio) 253*ff718800SKamlakant Patel { 254*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 255*ff718800SKamlakant Patel 256*ff718800SKamlakant Patel BUG_ON(gpio >= gc->ngpio); 257*ff718800SKamlakant Patel return xlp_gpio_get_reg(priv->gpio_paddrv, gpio); 258*ff718800SKamlakant Patel } 259*ff718800SKamlakant Patel 260*ff718800SKamlakant Patel static void xlp_gpio_set(struct gpio_chip *gc, unsigned gpio, int state) 261*ff718800SKamlakant Patel { 262*ff718800SKamlakant Patel struct xlp_gpio_priv *priv = gpio_chip_to_xlp_priv(gc); 263*ff718800SKamlakant Patel 264*ff718800SKamlakant Patel BUG_ON(gpio >= gc->ngpio); 265*ff718800SKamlakant Patel xlp_gpio_set_reg(priv->gpio_paddrv, gpio, state); 266*ff718800SKamlakant Patel } 267*ff718800SKamlakant Patel 268*ff718800SKamlakant Patel static const struct of_device_id xlp_gpio_of_ids[] = { 269*ff718800SKamlakant Patel { 270*ff718800SKamlakant Patel .compatible = "netlogic,xlp832-gpio", 271*ff718800SKamlakant Patel .data = (void *)XLP_GPIO_VARIANT_XLP832, 272*ff718800SKamlakant Patel }, 273*ff718800SKamlakant Patel { 274*ff718800SKamlakant Patel .compatible = "netlogic,xlp316-gpio", 275*ff718800SKamlakant Patel .data = (void *)XLP_GPIO_VARIANT_XLP316, 276*ff718800SKamlakant Patel }, 277*ff718800SKamlakant Patel { 278*ff718800SKamlakant Patel .compatible = "netlogic,xlp208-gpio", 279*ff718800SKamlakant Patel .data = (void *)XLP_GPIO_VARIANT_XLP208, 280*ff718800SKamlakant Patel }, 281*ff718800SKamlakant Patel { 282*ff718800SKamlakant Patel .compatible = "netlogic,xlp980-gpio", 283*ff718800SKamlakant Patel .data = (void *)XLP_GPIO_VARIANT_XLP980, 284*ff718800SKamlakant Patel }, 285*ff718800SKamlakant Patel { 286*ff718800SKamlakant Patel .compatible = "netlogic,xlp532-gpio", 287*ff718800SKamlakant Patel .data = (void *)XLP_GPIO_VARIANT_XLP532, 288*ff718800SKamlakant Patel }, 289*ff718800SKamlakant Patel { /* sentinel */ }, 290*ff718800SKamlakant Patel }; 291*ff718800SKamlakant Patel MODULE_DEVICE_TABLE(of, xlp_gpio_of_ids); 292*ff718800SKamlakant Patel 293*ff718800SKamlakant Patel static int xlp_gpio_probe(struct platform_device *pdev) 294*ff718800SKamlakant Patel { 295*ff718800SKamlakant Patel struct gpio_chip *gc; 296*ff718800SKamlakant Patel struct resource *iores; 297*ff718800SKamlakant Patel struct xlp_gpio_priv *priv; 298*ff718800SKamlakant Patel const struct of_device_id *of_id; 299*ff718800SKamlakant Patel void __iomem *gpio_base; 300*ff718800SKamlakant Patel int irq_base, irq, err; 301*ff718800SKamlakant Patel int ngpio; 302*ff718800SKamlakant Patel u32 soc_type; 303*ff718800SKamlakant Patel 304*ff718800SKamlakant Patel iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); 305*ff718800SKamlakant Patel if (!iores) 306*ff718800SKamlakant Patel return -ENODEV; 307*ff718800SKamlakant Patel 308*ff718800SKamlakant Patel priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 309*ff718800SKamlakant Patel if (!priv) 310*ff718800SKamlakant Patel return -ENOMEM; 311*ff718800SKamlakant Patel 312*ff718800SKamlakant Patel gpio_base = devm_ioremap_resource(&pdev->dev, iores); 313*ff718800SKamlakant Patel if (IS_ERR(gpio_base)) 314*ff718800SKamlakant Patel return PTR_ERR(gpio_base); 315*ff718800SKamlakant Patel 316*ff718800SKamlakant Patel irq = platform_get_irq(pdev, 0); 317*ff718800SKamlakant Patel if (irq < 0) 318*ff718800SKamlakant Patel return irq; 319*ff718800SKamlakant Patel 320*ff718800SKamlakant Patel of_id = of_match_device(xlp_gpio_of_ids, &pdev->dev); 321*ff718800SKamlakant Patel if (!of_id) { 322*ff718800SKamlakant Patel dev_err(&pdev->dev, "Failed to get soc type!\n"); 323*ff718800SKamlakant Patel return -ENODEV; 324*ff718800SKamlakant Patel } 325*ff718800SKamlakant Patel 326*ff718800SKamlakant Patel soc_type = (uintptr_t) of_id->data; 327*ff718800SKamlakant Patel 328*ff718800SKamlakant Patel switch (soc_type) { 329*ff718800SKamlakant Patel case XLP_GPIO_VARIANT_XLP832: 330*ff718800SKamlakant Patel priv->gpio_out_en = gpio_base + GPIO_OUTPUT_EN; 331*ff718800SKamlakant Patel priv->gpio_paddrv = gpio_base + GPIO_PADDRV; 332*ff718800SKamlakant Patel priv->gpio_intr_stat = gpio_base + GPIO_INT_STAT; 333*ff718800SKamlakant Patel priv->gpio_intr_type = gpio_base + GPIO_INT_TYPE; 334*ff718800SKamlakant Patel priv->gpio_intr_pol = gpio_base + GPIO_INT_POL; 335*ff718800SKamlakant Patel priv->gpio_intr_en = gpio_base + GPIO_INT_EN00; 336*ff718800SKamlakant Patel ngpio = 41; 337*ff718800SKamlakant Patel break; 338*ff718800SKamlakant Patel case XLP_GPIO_VARIANT_XLP208: 339*ff718800SKamlakant Patel case XLP_GPIO_VARIANT_XLP316: 340*ff718800SKamlakant Patel priv->gpio_out_en = gpio_base + GPIO_OUTPUT_EN; 341*ff718800SKamlakant Patel priv->gpio_paddrv = gpio_base + GPIO_PADDRV; 342*ff718800SKamlakant Patel priv->gpio_intr_stat = gpio_base + GPIO_3XX_INT_STAT; 343*ff718800SKamlakant Patel priv->gpio_intr_type = gpio_base + GPIO_3XX_INT_TYPE; 344*ff718800SKamlakant Patel priv->gpio_intr_pol = gpio_base + GPIO_3XX_INT_POL; 345*ff718800SKamlakant Patel priv->gpio_intr_en = gpio_base + GPIO_3XX_INT_EN00; 346*ff718800SKamlakant Patel 347*ff718800SKamlakant Patel ngpio = (soc_type == XLP_GPIO_VARIANT_XLP208) ? 42 : 57; 348*ff718800SKamlakant Patel break; 349*ff718800SKamlakant Patel case XLP_GPIO_VARIANT_XLP980: 350*ff718800SKamlakant Patel case XLP_GPIO_VARIANT_XLP532: 351*ff718800SKamlakant Patel priv->gpio_out_en = gpio_base + GPIO_9XX_OUTPUT_EN; 352*ff718800SKamlakant Patel priv->gpio_paddrv = gpio_base + GPIO_9XX_PADDRV; 353*ff718800SKamlakant Patel priv->gpio_intr_stat = gpio_base + GPIO_9XX_INT_STAT; 354*ff718800SKamlakant Patel priv->gpio_intr_type = gpio_base + GPIO_9XX_INT_TYPE; 355*ff718800SKamlakant Patel priv->gpio_intr_pol = gpio_base + GPIO_9XX_INT_POL; 356*ff718800SKamlakant Patel priv->gpio_intr_en = gpio_base + GPIO_9XX_INT_EN00; 357*ff718800SKamlakant Patel 358*ff718800SKamlakant Patel ngpio = (soc_type == XLP_GPIO_VARIANT_XLP980) ? 66 : 67; 359*ff718800SKamlakant Patel break; 360*ff718800SKamlakant Patel default: 361*ff718800SKamlakant Patel dev_err(&pdev->dev, "Unknown Processor type!\n"); 362*ff718800SKamlakant Patel return -ENODEV; 363*ff718800SKamlakant Patel } 364*ff718800SKamlakant Patel 365*ff718800SKamlakant Patel bitmap_zero(priv->gpio_enabled_mask, XLP_MAX_NR_GPIO); 366*ff718800SKamlakant Patel 367*ff718800SKamlakant Patel gc = &priv->chip; 368*ff718800SKamlakant Patel 369*ff718800SKamlakant Patel gc->base = 0; 370*ff718800SKamlakant Patel gc->dev = &pdev->dev; 371*ff718800SKamlakant Patel gc->ngpio = ngpio; 372*ff718800SKamlakant Patel gc->of_node = pdev->dev.of_node; 373*ff718800SKamlakant Patel gc->direction_output = xlp_gpio_dir_output; 374*ff718800SKamlakant Patel gc->direction_input = xlp_gpio_dir_input; 375*ff718800SKamlakant Patel gc->set = xlp_gpio_set; 376*ff718800SKamlakant Patel gc->get = xlp_gpio_get; 377*ff718800SKamlakant Patel 378*ff718800SKamlakant Patel spin_lock_init(&priv->lock); 379*ff718800SKamlakant Patel 380*ff718800SKamlakant Patel err = devm_request_irq(&pdev->dev, irq, xlp_gpio_generic_handler, 381*ff718800SKamlakant Patel IRQ_TYPE_NONE, pdev->name, priv); 382*ff718800SKamlakant Patel if (err) 383*ff718800SKamlakant Patel return err; 384*ff718800SKamlakant Patel 385*ff718800SKamlakant Patel irq_base = irq_alloc_descs(-1, XLP_GPIO_IRQ_BASE, gc->ngpio, 0); 386*ff718800SKamlakant Patel if (irq_base < 0) { 387*ff718800SKamlakant Patel dev_err(&pdev->dev, "Failed to allocate IRQ numbers\n"); 388*ff718800SKamlakant Patel return err; 389*ff718800SKamlakant Patel } 390*ff718800SKamlakant Patel 391*ff718800SKamlakant Patel err = gpiochip_add(gc); 392*ff718800SKamlakant Patel if (err < 0) 393*ff718800SKamlakant Patel goto out_free_desc; 394*ff718800SKamlakant Patel 395*ff718800SKamlakant Patel err = gpiochip_irqchip_add(gc, &xlp_gpio_irq_chip, irq_base, 396*ff718800SKamlakant Patel handle_level_irq, IRQ_TYPE_NONE); 397*ff718800SKamlakant Patel if (err) { 398*ff718800SKamlakant Patel dev_err(&pdev->dev, "Could not connect irqchip to gpiochip!\n"); 399*ff718800SKamlakant Patel goto out_gpio_remove; 400*ff718800SKamlakant Patel } 401*ff718800SKamlakant Patel 402*ff718800SKamlakant Patel dev_info(&pdev->dev, "registered %d GPIOs\n", gc->ngpio); 403*ff718800SKamlakant Patel 404*ff718800SKamlakant Patel return 0; 405*ff718800SKamlakant Patel 406*ff718800SKamlakant Patel out_gpio_remove: 407*ff718800SKamlakant Patel gpiochip_remove(gc); 408*ff718800SKamlakant Patel out_free_desc: 409*ff718800SKamlakant Patel irq_free_descs(irq_base, gc->ngpio); 410*ff718800SKamlakant Patel return err; 411*ff718800SKamlakant Patel } 412*ff718800SKamlakant Patel 413*ff718800SKamlakant Patel static struct platform_driver xlp_gpio_driver = { 414*ff718800SKamlakant Patel .driver = { 415*ff718800SKamlakant Patel .name = "xlp-gpio", 416*ff718800SKamlakant Patel .of_match_table = xlp_gpio_of_ids, 417*ff718800SKamlakant Patel }, 418*ff718800SKamlakant Patel .probe = xlp_gpio_probe, 419*ff718800SKamlakant Patel }; 420*ff718800SKamlakant Patel module_platform_driver(xlp_gpio_driver); 421*ff718800SKamlakant Patel 422*ff718800SKamlakant Patel MODULE_AUTHOR("Kamlakant Patel <kamlakant.patel@broadcom.com>"); 423*ff718800SKamlakant Patel MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@broadcom.com>"); 424*ff718800SKamlakant Patel MODULE_DESCRIPTION("Netlogic XLP GPIO Driver"); 425*ff718800SKamlakant Patel MODULE_LICENSE("GPL v2"); 426