From: John Linn <john.linn@xxxxxxxxxx> Date: Fri, 29 Jun 2012 11:27:45 -0700 Driver names were changed to match the kernel. Signed-off-by: John Linn <john.linn@xxxxxxxxxx> Signed-off-by: Alexander Hedges <ahedges@xxxxxxx> (cherry picked from commit e9a98626baf3b31fa6a699576d8d089c5df10f35) --- drivers/gpio/gpio-xilinx.c | 305 +++++++++++++++++++++++-------------- 1 file changed, 193 insertions(+), 112 deletions(-) diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index e8ec0e33a0a9..4fd15f537b90 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -47,37 +47,17 @@ * @gpio_lock: Lock used for synchronization */ struct xgpio_instance { +#ifdef CONFIG_OF struct of_mm_gpio_chip mmchip; - unsigned int gpio_width[2]; - u32 gpio_state[2]; - u32 gpio_dir[2]; - spinlock_t gpio_lock[2]; +#else + struct gpio_chip gc; + void __iomem *regs; +#endif + u32 gpio_state; /* GPIO state shadow register */ + u32 gpio_dir; /* GPIO direction shadow register */ + spinlock_t gpio_lock; /* Lock used for synchronization */ }; -static inline int xgpio_index(struct xgpio_instance *chip, int gpio) -{ - if (gpio >= chip->gpio_width[0]) - return 1; - - return 0; -} - -static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) -{ - if (xgpio_index(chip, gpio)) - return XGPIO_CHANNEL_OFFSET; - - return 0; -} - -static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) -{ - if (xgpio_index(chip, gpio)) - return gpio - chip->gpio_width[0]; - - return gpio; -} - /** * xgpio_get - Read the specified signal of the GPIO device. * @gc: Pointer to gpio_chip device structure. @@ -91,14 +71,15 @@ static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) */ static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) { +#ifdef CONFIG_OF struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = gpiochip_get_data(gc); - u32 val; - - val = xgpio_readreg(mm_gc->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio)); - - return !!(val & BIT(xgpio_offset(chip, gpio))); + void __iomem *regs = mm_gc->regs; +#else + struct xgpio_instance *chip = container_of(gc, struct xgpio_instance, + gc); + void __iomem *regs = chip->regs; +#endif + return (xgpio_readreg(regs + XGPIO_DATA_OFFSET) >> gpio) & 1; } /** @@ -113,23 +94,28 @@ static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; +#ifdef CONFIG_OF struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + void __iomem *regs = mm_gc->regs; +#else + struct xgpio_instance *chip = container_of(gc, struct xgpio_instance, + gc); + void __iomem *regs = chip->regs; +#endif - spin_lock_irqsave(&chip->gpio_lock[index], flags); + spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signal and set its direction to output */ if (val) - chip->gpio_state[index] |= BIT(offset); + chip->gpio_state |= BIT(gpio); else - chip->gpio_state[index] &= ~BIT(offset); + chip->gpio_state &= ~BIT(gpio); - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + xgpio_writereg(regs + XGPIO_DATA_OFFSET, chip->gpio_state); - spin_unlock_irqrestore(&chip->gpio_lock[index], flags); + spin_unlock_irqrestore(&chip->gpio_lock, flags); } /** @@ -147,36 +133,26 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, unsigned long flags; struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, 0); - int offset, i; + int i; - spin_lock_irqsave(&chip->gpio_lock[index], flags); + spin_lock_irqsave(&chip->gpio_lock, flags); /* Write to GPIO signals */ for (i = 0; i < gc->ngpio; i++) { if (*mask == 0) break; - if (index != xgpio_index(chip, i)) { - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, i), - chip->gpio_state[index]); - spin_unlock_irqrestore(&chip->gpio_lock[index], flags); - index = xgpio_index(chip, i); - spin_lock_irqsave(&chip->gpio_lock[index], flags); - } if (__test_and_clear_bit(i, mask)) { - offset = xgpio_offset(chip, i); if (test_bit(i, bits)) - chip->gpio_state[index] |= BIT(offset); + chip->gpio_state |= BIT(i); else - chip->gpio_state[index] &= ~BIT(offset); + chip->gpio_state &= ~BIT(i); } } - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, i), chip->gpio_state[index]); + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, + chip->gpio_state); - spin_unlock_irqrestore(&chip->gpio_lock[index], flags); + spin_unlock_irqrestore(&chip->gpio_lock, flags); } /** @@ -191,19 +167,24 @@ static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) { unsigned long flags; +#ifdef CONFIG_OF struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); - struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + struct xgpio_instance *chip = + container_of(mm_gc, struct xgpio_instance, mmchip); + void __iomem *regs = mm_gc->regs; +#else + struct xgpio_instance *chip = container_of(gc, struct xgpio_instance, + gc); + void __iomem *regs = chip->regs; +#endif - spin_lock_irqsave(&chip->gpio_lock[index], flags); + spin_lock_irqsave(&chip->gpio_lock, flags); /* Set the GPIO bit in shadow register and set direction as input */ - chip->gpio_dir[index] |= BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + chip->gpio_dir |= (1 << gpio); + xgpio_writereg(regs + XGPIO_TRI_OFFSET, chip->gpio_dir); - spin_unlock_irqrestore(&chip->gpio_lock[index], flags); + spin_unlock_irqrestore(&chip->gpio_lock, flags); return 0; } @@ -223,31 +204,35 @@ static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) { unsigned long flags; +#ifdef CONFIG_OF struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); struct xgpio_instance *chip = gpiochip_get_data(gc); - int index = xgpio_index(chip, gpio); - int offset = xgpio_offset(chip, gpio); + void __iomem *regs = mm_gc->regs; +#else + struct xgpio_instance *chip = container_of(gc, struct xgpio_instance, + gc); + void __iomem *regs = chip->regs; +#endif - spin_lock_irqsave(&chip->gpio_lock[index], flags); + spin_lock_irqsave(&chip->gpio_lock, flags); /* Write state of GPIO signal */ if (val) - chip->gpio_state[index] |= BIT(offset); + chip->gpio_state |= BIT(gpio); else - chip->gpio_state[index] &= ~BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_state[index]); + chip->gpio_state &= ~(1 << gpio); + xgpio_writereg(regs + XGPIO_DATA_OFFSET, chip->gpio_state); /* Clear the GPIO bit in shadow register and set direction as output */ - chip->gpio_dir[index] &= ~BIT(offset); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + - xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); + chip->gpio_dir &= (~(1 << gpio)); + xgpio_writereg(regs + XGPIO_TRI_OFFSET, chip->gpio_dir); - spin_unlock_irqrestore(&chip->gpio_lock[index], flags); + spin_unlock_irqrestore(&chip->gpio_lock, flags); return 0; } +#ifdef CONFIG_OF /** * xgpio_save_regs - Set initial values of GPIO pins * @mm_gc: Pointer to memory mapped GPIO chip structure @@ -257,16 +242,8 @@ static void xgpio_save_regs(struct of_mm_gpio_chip *mm_gc) struct xgpio_instance *chip = container_of(mm_gc, struct xgpio_instance, mmchip); - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); - - if (!chip->gpio_width[1]) - return; - - xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_state[1]); - xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, - chip->gpio_dir[1]); + xgpio_writereg(mm_gc->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + xgpio_writereg(mm_gc->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); } /** @@ -298,8 +275,9 @@ static int xgpio_probe(struct platform_device *pdev) { struct xgpio_instance *chip; int status = 0; - struct device_node *np = pdev->dev.of_node; u32 is_dual; + struct device_node *np = pdev->dev.of_node; + u32 ngpio; chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -308,20 +286,20 @@ static int xgpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); /* Update GPIO state shadow register with default value */ - of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]); + of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state); + chip->gpio_dir = 0xFFFFFFFF; /* Update GPIO direction shadow register with default value */ - if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) - chip->gpio_dir[0] = 0xFFFFFFFF; + of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir); /* * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) - chip->gpio_width[0] = 32; + if (of_property_read_u32(np, "xlnx,gpio-width", &ngpio)) + ngpio = 32; - spin_lock_init(&chip->gpio_lock[0]); + spin_lock_init(&chip->gpio_lock); if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) is_dual = 0; @@ -329,25 +307,25 @@ static int xgpio_probe(struct platform_device *pdev) if (is_dual) { /* Update GPIO state shadow register with default value */ of_property_read_u32(np, "xlnx,dout-default-2", - &chip->gpio_state[1]); + &chip->gpio_state); /* Update GPIO direction shadow register with default value */ if (of_property_read_u32(np, "xlnx,tri-default-2", - &chip->gpio_dir[1])) - chip->gpio_dir[1] = 0xFFFFFFFF; + &chip->gpio_dir)) + chip->gpio_dir = 0xFFFFFFFF; /* * Check device node and parent device node for device width * and assume default width of 32 */ if (of_property_read_u32(np, "xlnx,gpio2-width", - &chip->gpio_width[1])) - chip->gpio_width[1] = 32; + &ngpio)) + ngpio = 32; - spin_lock_init(&chip->gpio_lock[1]); + spin_lock_init(&chip->gpio_lock); } - chip->mmchip.gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; + chip->mmchip.gc.ngpio = (u16)ngpio;; chip->mmchip.gc.parent = &pdev->dev; chip->mmchip.gc.direction_input = xgpio_dir_in; chip->mmchip.gc.direction_output = xgpio_dir_out; @@ -364,7 +342,7 @@ static int xgpio_probe(struct platform_device *pdev) np, status); return status; } - + pr_info("XGpio: %s: registered\n", np->full_name); return 0; } @@ -373,27 +351,130 @@ static const struct of_device_id xgpio_of_match[] = { { /* end of list */ }, }; -MODULE_DEVICE_TABLE(of, xgpio_of_match); +#else + +/** + * xgpio_probe - Probe method for the GPIO device + * @pdev: platform device instance + * + * This function allocates memory resources for the xgpio device and initializes + * the driver structures. + * + * Return: 0 on success, negative error otherwise. + */ +static int __init xgpio_probe(struct platform_device *pdev) +{ + int ret; + struct xgpio_instance *chip; + struct gpio_chip *gc; + struct resource *mem_res = NULL; + struct xgpio_platform_data *pdata; + + chip = kzalloc(sizeof(struct xgpio_instance), GFP_KERNEL); + if (!chip) { + dev_err(&pdev->dev, "couldn't allocate memory for gpio private " + "data\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, chip); + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + dev_err(&pdev->dev, "No memory resource\n"); + ret = -ENODEV; + goto err_free_gpio; + } + + if (!request_mem_region(mem_res->start, resource_size(mem_res), + pdev->name)) { + dev_err(&pdev->dev, "Cannot request IO\n"); + ret = -ENXIO; + goto err_free_gpio; + } + + pdata = pdev->dev.platform_data; + if (pdata == NULL) { + dev_err(&pdev->dev, "Cannot find platform data\n"); + return -ENODEV; + } + + chip->regs = ioremap(mem_res->start, resource_size(mem_res)); + if (chip->regs == NULL) { + dev_err(&pdev->dev, "Couldn't ioremap memory at 0x%08lx\n", + (unsigned long)mem_res->start); + ret = -ENOMEM; + goto err_release_region; + } + + chip->gpio_state = pdata->state; + chip->gpio_dir = pdata->dir; + + xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state); + xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir); + + /* configure the gpio chip */ + gc = &chip->gc; + gc->label = "xgpio"; + gc->owner = THIS_MODULE; + gc->dev = &pdev->dev; + gc->get = xgpio_get; + gc->set = xgpio_set; + gc->direction_input = xgpio_dir_in; + gc->direction_output = xgpio_dir_out; + gc->dbg_show = NULL; + gc->base = 0; /* default pin base */ + gc->ngpio = pdata->width; + gc->can_sleep = 0; + + ret = gpiochip_add(gc); + if (ret < 0) { + dev_err(&pdev->dev, "gpio gc registration failed\n"); + goto err_iounmap; + } else + dev_info(&pdev->dev, "gpio at 0x%08lx mapped to 0x%08lx\n", + (unsigned long)mem_res->start, + (unsigned long)chip->regs); + + return 0; -static struct platform_driver xgpio_plat_driver = { +err_iounmap: + iounmap(chip->regs); +err_release_region: + release_mem_region(mem_res->start, resource_size(mem_res)); +err_free_gpio: + platform_set_drvdata(pdev, NULL); + kfree(chip); + + return ret; +} + +#endif /* CONFIG_OF */ + + +static struct platform_driver xgpio_driver = { .probe = xgpio_probe, .remove = xgpio_remove, - .driver = { - .name = "gpio-xilinx", - .of_match_table = xgpio_of_match, + .driver = { + .name = "xilinx_gpio", + .owner = THIS_MODULE, }, }; static int __init xgpio_init(void) { - return platform_driver_register(&xgpio_plat_driver); +#ifdef CONFIG_OF + return 0; +#else + return platform_driver_register(&xgpio_driver); +#endif } subsys_initcall(xgpio_init); static void __exit xgpio_exit(void) { - platform_driver_unregister(&xgpio_plat_driver); + platform_driver_unregister(&xgpio_driver); } module_exit(xgpio_exit); -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-gpio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html