16e75fc04SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2c103de24SGrant Likely /* 374600ee0SMichal Simek * Xilinx gpio driver for xps/axi_gpio IP. 4c103de24SGrant Likely * 574600ee0SMichal Simek * Copyright 2008 - 2013 Xilinx, Inc. 6c103de24SGrant Likely */ 7c103de24SGrant Likely 874600ee0SMichal Simek #include <linux/bitops.h> 965bbe531SSrinivas Neeli #include <linux/clk.h> 10c103de24SGrant Likely #include <linux/errno.h> 118c669fe6SSrinivas Neeli #include <linux/gpio/driver.h> 128c669fe6SSrinivas Neeli #include <linux/init.h> 138c669fe6SSrinivas Neeli #include <linux/io.h> 14bb207ef1SPaul Gortmaker #include <linux/module.h> 15c103de24SGrant Likely #include <linux/of_device.h> 16c103de24SGrant Likely #include <linux/of_platform.h> 17c103de24SGrant Likely #include <linux/slab.h> 18c103de24SGrant Likely 19c103de24SGrant Likely /* Register Offset Definitions */ 20c103de24SGrant Likely #define XGPIO_DATA_OFFSET (0x0) /* Data register */ 21c103de24SGrant Likely #define XGPIO_TRI_OFFSET (0x4) /* I/O direction register */ 22c103de24SGrant Likely 2374600ee0SMichal Simek #define XGPIO_CHANNEL_OFFSET 0x8 2474600ee0SMichal Simek 2574600ee0SMichal Simek /* Read/Write access to the GPIO registers */ 26c54c58baSRicardo Ribalda Delgado #if defined(CONFIG_ARCH_ZYNQ) || defined(CONFIG_X86) 27cc090d61SMichal Simek # define xgpio_readreg(offset) readl(offset) 28cc090d61SMichal Simek # define xgpio_writereg(offset, val) writel(val, offset) 29cc090d61SMichal Simek #else 30cc090d61SMichal Simek # define xgpio_readreg(offset) __raw_readl(offset) 31cc090d61SMichal Simek # define xgpio_writereg(offset, val) __raw_writel(val, offset) 32cc090d61SMichal Simek #endif 3374600ee0SMichal Simek 3474600ee0SMichal Simek /** 3574600ee0SMichal Simek * struct xgpio_instance - Stores information about GPIO device 361ebd0687SRobert Hancock * @gc: GPIO chip 371ebd0687SRobert Hancock * @regs: register block 383c1b5c9bSMichal Simek * @gpio_width: GPIO width for every channel 394ae798faSRicardo Ribalda Delgado * @gpio_state: GPIO state shadow register 404ae798faSRicardo Ribalda Delgado * @gpio_dir: GPIO direction shadow register 414ae798faSRicardo Ribalda Delgado * @gpio_lock: Lock used for synchronization 4265bbe531SSrinivas Neeli * @clk: clock resource for this driver 4374600ee0SMichal Simek */ 44c103de24SGrant Likely struct xgpio_instance { 451ebd0687SRobert Hancock struct gpio_chip gc; 461ebd0687SRobert Hancock void __iomem *regs; 471d6902d3SRicardo Ribalda Delgado unsigned int gpio_width[2]; 481d6902d3SRicardo Ribalda Delgado u32 gpio_state[2]; 491d6902d3SRicardo Ribalda Delgado u32 gpio_dir[2]; 501d6902d3SRicardo Ribalda Delgado spinlock_t gpio_lock[2]; 5165bbe531SSrinivas Neeli struct clk *clk; 52749564ffSRicardo Ribalda Delgado }; 53749564ffSRicardo Ribalda Delgado 541d6902d3SRicardo Ribalda Delgado static inline int xgpio_index(struct xgpio_instance *chip, int gpio) 551d6902d3SRicardo Ribalda Delgado { 561d6902d3SRicardo Ribalda Delgado if (gpio >= chip->gpio_width[0]) 571d6902d3SRicardo Ribalda Delgado return 1; 581d6902d3SRicardo Ribalda Delgado 591d6902d3SRicardo Ribalda Delgado return 0; 601d6902d3SRicardo Ribalda Delgado } 611d6902d3SRicardo Ribalda Delgado 621d6902d3SRicardo Ribalda Delgado static inline int xgpio_regoffset(struct xgpio_instance *chip, int gpio) 631d6902d3SRicardo Ribalda Delgado { 641d6902d3SRicardo Ribalda Delgado if (xgpio_index(chip, gpio)) 651d6902d3SRicardo Ribalda Delgado return XGPIO_CHANNEL_OFFSET; 661d6902d3SRicardo Ribalda Delgado 671d6902d3SRicardo Ribalda Delgado return 0; 681d6902d3SRicardo Ribalda Delgado } 691d6902d3SRicardo Ribalda Delgado 701d6902d3SRicardo Ribalda Delgado static inline int xgpio_offset(struct xgpio_instance *chip, int gpio) 711d6902d3SRicardo Ribalda Delgado { 721d6902d3SRicardo Ribalda Delgado if (xgpio_index(chip, gpio)) 731d6902d3SRicardo Ribalda Delgado return gpio - chip->gpio_width[0]; 741d6902d3SRicardo Ribalda Delgado 751d6902d3SRicardo Ribalda Delgado return gpio; 761d6902d3SRicardo Ribalda Delgado } 77c103de24SGrant Likely 78c103de24SGrant Likely /** 79c103de24SGrant Likely * xgpio_get - Read the specified signal of the GPIO device. 80c103de24SGrant Likely * @gc: Pointer to gpio_chip device structure. 81c103de24SGrant Likely * @gpio: GPIO signal number. 82c103de24SGrant Likely * 834ae798faSRicardo Ribalda Delgado * This function reads the specified signal of the GPIO device. 844ae798faSRicardo Ribalda Delgado * 854ae798faSRicardo Ribalda Delgado * Return: 864ae798faSRicardo Ribalda Delgado * 0 if direction of GPIO signals is set as input otherwise it 874ae798faSRicardo Ribalda Delgado * returns negative error value. 88c103de24SGrant Likely */ 89c103de24SGrant Likely static int xgpio_get(struct gpio_chip *gc, unsigned int gpio) 90c103de24SGrant Likely { 91097d88e9SLinus Walleij struct xgpio_instance *chip = gpiochip_get_data(gc); 921d6902d3SRicardo Ribalda Delgado u32 val; 93c103de24SGrant Likely 941ebd0687SRobert Hancock val = xgpio_readreg(chip->regs + XGPIO_DATA_OFFSET + 951d6902d3SRicardo Ribalda Delgado xgpio_regoffset(chip, gpio)); 961d6902d3SRicardo Ribalda Delgado 971d6902d3SRicardo Ribalda Delgado return !!(val & BIT(xgpio_offset(chip, gpio))); 98c103de24SGrant Likely } 99c103de24SGrant Likely 100c103de24SGrant Likely /** 101c103de24SGrant Likely * xgpio_set - Write the specified signal of the GPIO device. 102c103de24SGrant Likely * @gc: Pointer to gpio_chip device structure. 103c103de24SGrant Likely * @gpio: GPIO signal number. 104c103de24SGrant Likely * @val: Value to be written to specified signal. 105c103de24SGrant Likely * 106c103de24SGrant Likely * This function writes the specified value in to the specified signal of the 107c103de24SGrant Likely * GPIO device. 108c103de24SGrant Likely */ 109c103de24SGrant Likely static void xgpio_set(struct gpio_chip *gc, unsigned int gpio, int val) 110c103de24SGrant Likely { 111c103de24SGrant Likely unsigned long flags; 112097d88e9SLinus Walleij struct xgpio_instance *chip = gpiochip_get_data(gc); 1131d6902d3SRicardo Ribalda Delgado int index = xgpio_index(chip, gpio); 1141d6902d3SRicardo Ribalda Delgado int offset = xgpio_offset(chip, gpio); 115c103de24SGrant Likely 1161d6902d3SRicardo Ribalda Delgado spin_lock_irqsave(&chip->gpio_lock[index], flags); 117c103de24SGrant Likely 118c103de24SGrant Likely /* Write to GPIO signal and set its direction to output */ 119c103de24SGrant Likely if (val) 1201d6902d3SRicardo Ribalda Delgado chip->gpio_state[index] |= BIT(offset); 121c103de24SGrant Likely else 1221d6902d3SRicardo Ribalda Delgado chip->gpio_state[index] &= ~BIT(offset); 12374600ee0SMichal Simek 1241ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + 1251d6902d3SRicardo Ribalda Delgado xgpio_regoffset(chip, gpio), chip->gpio_state[index]); 126c103de24SGrant Likely 1271d6902d3SRicardo Ribalda Delgado spin_unlock_irqrestore(&chip->gpio_lock[index], flags); 128c103de24SGrant Likely } 129c103de24SGrant Likely 130c103de24SGrant Likely /** 1318e7c1b80SIban Rodriguez * xgpio_set_multiple - Write the specified signals of the GPIO device. 1328e7c1b80SIban Rodriguez * @gc: Pointer to gpio_chip device structure. 1338e7c1b80SIban Rodriguez * @mask: Mask of the GPIOS to modify. 1348e7c1b80SIban Rodriguez * @bits: Value to be wrote on each GPIO 1358e7c1b80SIban Rodriguez * 1368e7c1b80SIban Rodriguez * This function writes the specified values into the specified signals of the 1378e7c1b80SIban Rodriguez * GPIO devices. 1388e7c1b80SIban Rodriguez */ 1398e7c1b80SIban Rodriguez static void xgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask, 1408e7c1b80SIban Rodriguez unsigned long *bits) 1418e7c1b80SIban Rodriguez { 1428e7c1b80SIban Rodriguez unsigned long flags; 1438e7c1b80SIban Rodriguez struct xgpio_instance *chip = gpiochip_get_data(gc); 1448e7c1b80SIban Rodriguez int index = xgpio_index(chip, 0); 1458e7c1b80SIban Rodriguez int offset, i; 1468e7c1b80SIban Rodriguez 1478e7c1b80SIban Rodriguez spin_lock_irqsave(&chip->gpio_lock[index], flags); 1488e7c1b80SIban Rodriguez 1498e7c1b80SIban Rodriguez /* Write to GPIO signals */ 1508e7c1b80SIban Rodriguez for (i = 0; i < gc->ngpio; i++) { 1518e7c1b80SIban Rodriguez if (*mask == 0) 1528e7c1b80SIban Rodriguez break; 153c3afa804SPaul Thomas /* Once finished with an index write it out to the register */ 1548e7c1b80SIban Rodriguez if (index != xgpio_index(chip, i)) { 1551ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + 156c3afa804SPaul Thomas index * XGPIO_CHANNEL_OFFSET, 1578e7c1b80SIban Rodriguez chip->gpio_state[index]); 1588e7c1b80SIban Rodriguez spin_unlock_irqrestore(&chip->gpio_lock[index], flags); 1598e7c1b80SIban Rodriguez index = xgpio_index(chip, i); 1608e7c1b80SIban Rodriguez spin_lock_irqsave(&chip->gpio_lock[index], flags); 1618e7c1b80SIban Rodriguez } 1628e7c1b80SIban Rodriguez if (__test_and_clear_bit(i, mask)) { 1638e7c1b80SIban Rodriguez offset = xgpio_offset(chip, i); 1648e7c1b80SIban Rodriguez if (test_bit(i, bits)) 1658e7c1b80SIban Rodriguez chip->gpio_state[index] |= BIT(offset); 1668e7c1b80SIban Rodriguez else 1678e7c1b80SIban Rodriguez chip->gpio_state[index] &= ~BIT(offset); 1688e7c1b80SIban Rodriguez } 1698e7c1b80SIban Rodriguez } 1708e7c1b80SIban Rodriguez 1711ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + 172c3afa804SPaul Thomas index * XGPIO_CHANNEL_OFFSET, chip->gpio_state[index]); 1738e7c1b80SIban Rodriguez 1748e7c1b80SIban Rodriguez spin_unlock_irqrestore(&chip->gpio_lock[index], flags); 1758e7c1b80SIban Rodriguez } 1768e7c1b80SIban Rodriguez 1778e7c1b80SIban Rodriguez /** 178c103de24SGrant Likely * xgpio_dir_in - Set the direction of the specified GPIO signal as input. 179c103de24SGrant Likely * @gc: Pointer to gpio_chip device structure. 180c103de24SGrant Likely * @gpio: GPIO signal number. 181c103de24SGrant Likely * 1824ae798faSRicardo Ribalda Delgado * Return: 1834ae798faSRicardo Ribalda Delgado * 0 - if direction of GPIO signals is set as input 1844ae798faSRicardo Ribalda Delgado * otherwise it returns negative error value. 185c103de24SGrant Likely */ 186c103de24SGrant Likely static int xgpio_dir_in(struct gpio_chip *gc, unsigned int gpio) 187c103de24SGrant Likely { 188c103de24SGrant Likely unsigned long flags; 189097d88e9SLinus Walleij struct xgpio_instance *chip = gpiochip_get_data(gc); 1901d6902d3SRicardo Ribalda Delgado int index = xgpio_index(chip, gpio); 1911d6902d3SRicardo Ribalda Delgado int offset = xgpio_offset(chip, gpio); 192c103de24SGrant Likely 1931d6902d3SRicardo Ribalda Delgado spin_lock_irqsave(&chip->gpio_lock[index], flags); 194c103de24SGrant Likely 195c103de24SGrant Likely /* Set the GPIO bit in shadow register and set direction as input */ 1961d6902d3SRicardo Ribalda Delgado chip->gpio_dir[index] |= BIT(offset); 1971ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + 1981d6902d3SRicardo Ribalda Delgado xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); 199c103de24SGrant Likely 2001d6902d3SRicardo Ribalda Delgado spin_unlock_irqrestore(&chip->gpio_lock[index], flags); 201c103de24SGrant Likely 202c103de24SGrant Likely return 0; 203c103de24SGrant Likely } 204c103de24SGrant Likely 205c103de24SGrant Likely /** 206c103de24SGrant Likely * xgpio_dir_out - Set the direction of the specified GPIO signal as output. 207c103de24SGrant Likely * @gc: Pointer to gpio_chip device structure. 208c103de24SGrant Likely * @gpio: GPIO signal number. 209c103de24SGrant Likely * @val: Value to be written to specified signal. 210c103de24SGrant Likely * 2114ae798faSRicardo Ribalda Delgado * This function sets the direction of specified GPIO signal as output. 2124ae798faSRicardo Ribalda Delgado * 2134ae798faSRicardo Ribalda Delgado * Return: 2144ae798faSRicardo Ribalda Delgado * If all GPIO signals of GPIO chip is configured as input then it returns 215c103de24SGrant Likely * error otherwise it returns 0. 216c103de24SGrant Likely */ 217c103de24SGrant Likely static int xgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) 218c103de24SGrant Likely { 219c103de24SGrant Likely unsigned long flags; 220097d88e9SLinus Walleij struct xgpio_instance *chip = gpiochip_get_data(gc); 2211d6902d3SRicardo Ribalda Delgado int index = xgpio_index(chip, gpio); 2221d6902d3SRicardo Ribalda Delgado int offset = xgpio_offset(chip, gpio); 223c103de24SGrant Likely 2241d6902d3SRicardo Ribalda Delgado spin_lock_irqsave(&chip->gpio_lock[index], flags); 225c103de24SGrant Likely 226c103de24SGrant Likely /* Write state of GPIO signal */ 227c103de24SGrant Likely if (val) 2281d6902d3SRicardo Ribalda Delgado chip->gpio_state[index] |= BIT(offset); 229c103de24SGrant Likely else 2301d6902d3SRicardo Ribalda Delgado chip->gpio_state[index] &= ~BIT(offset); 2311ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + 2321d6902d3SRicardo Ribalda Delgado xgpio_regoffset(chip, gpio), chip->gpio_state[index]); 233c103de24SGrant Likely 234c103de24SGrant Likely /* Clear the GPIO bit in shadow register and set direction as output */ 2351d6902d3SRicardo Ribalda Delgado chip->gpio_dir[index] &= ~BIT(offset); 2361ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + 2371d6902d3SRicardo Ribalda Delgado xgpio_regoffset(chip, gpio), chip->gpio_dir[index]); 238c103de24SGrant Likely 2391d6902d3SRicardo Ribalda Delgado spin_unlock_irqrestore(&chip->gpio_lock[index], flags); 240c103de24SGrant Likely 241c103de24SGrant Likely return 0; 242c103de24SGrant Likely } 243c103de24SGrant Likely 244c103de24SGrant Likely /** 245c103de24SGrant Likely * xgpio_save_regs - Set initial values of GPIO pins 2461ebd0687SRobert Hancock * @chip: Pointer to GPIO instance 247c103de24SGrant Likely */ 2481ebd0687SRobert Hancock static void xgpio_save_regs(struct xgpio_instance *chip) 249c103de24SGrant Likely { 2501ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET, chip->gpio_state[0]); 2511ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET, chip->gpio_dir[0]); 2521d6902d3SRicardo Ribalda Delgado 2531d6902d3SRicardo Ribalda Delgado if (!chip->gpio_width[1]) 2541d6902d3SRicardo Ribalda Delgado return; 2551d6902d3SRicardo Ribalda Delgado 2561ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_DATA_OFFSET + XGPIO_CHANNEL_OFFSET, 2571d6902d3SRicardo Ribalda Delgado chip->gpio_state[1]); 2581ebd0687SRobert Hancock xgpio_writereg(chip->regs + XGPIO_TRI_OFFSET + XGPIO_CHANNEL_OFFSET, 2591d6902d3SRicardo Ribalda Delgado chip->gpio_dir[1]); 260c103de24SGrant Likely } 261c103de24SGrant Likely 262c103de24SGrant Likely /** 263*0230a41eSSrinivas Neeli * xgpio_remove - Remove method for the GPIO device. 264*0230a41eSSrinivas Neeli * @pdev: pointer to the platform device 265*0230a41eSSrinivas Neeli * 266*0230a41eSSrinivas Neeli * This function remove gpiochips and frees all the allocated resources. 267*0230a41eSSrinivas Neeli * 268*0230a41eSSrinivas Neeli * Return: 0 always 269*0230a41eSSrinivas Neeli */ 270*0230a41eSSrinivas Neeli static int xgpio_remove(struct platform_device *pdev) 271*0230a41eSSrinivas Neeli { 272*0230a41eSSrinivas Neeli struct xgpio_instance *gpio = platform_get_drvdata(pdev); 273*0230a41eSSrinivas Neeli 274*0230a41eSSrinivas Neeli clk_disable_unprepare(gpio->clk); 275*0230a41eSSrinivas Neeli 276*0230a41eSSrinivas Neeli return 0; 277*0230a41eSSrinivas Neeli } 278*0230a41eSSrinivas Neeli 279*0230a41eSSrinivas Neeli /** 280c103de24SGrant Likely * xgpio_of_probe - Probe method for the GPIO device. 281749564ffSRicardo Ribalda Delgado * @pdev: pointer to the platform device 282c103de24SGrant Likely * 2834ae798faSRicardo Ribalda Delgado * Return: 2844ae798faSRicardo Ribalda Delgado * It returns 0, if the driver is bound to the GPIO device, or 2854ae798faSRicardo Ribalda Delgado * a negative value if there is an error. 286c103de24SGrant Likely */ 287749564ffSRicardo Ribalda Delgado static int xgpio_probe(struct platform_device *pdev) 288c103de24SGrant Likely { 289c103de24SGrant Likely struct xgpio_instance *chip; 290c103de24SGrant Likely int status = 0; 291749564ffSRicardo Ribalda Delgado struct device_node *np = pdev->dev.of_node; 2921d6902d3SRicardo Ribalda Delgado u32 is_dual; 293c103de24SGrant Likely 2941d6902d3SRicardo Ribalda Delgado chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); 2951d6902d3SRicardo Ribalda Delgado if (!chip) 296c103de24SGrant Likely return -ENOMEM; 297c103de24SGrant Likely 2981d6902d3SRicardo Ribalda Delgado platform_set_drvdata(pdev, chip); 299749564ffSRicardo Ribalda Delgado 300c103de24SGrant Likely /* Update GPIO state shadow register with default value */ 3011d6902d3SRicardo Ribalda Delgado of_property_read_u32(np, "xlnx,dout-default", &chip->gpio_state[0]); 302c103de24SGrant Likely 303c103de24SGrant Likely /* Update GPIO direction shadow register with default value */ 3041d6902d3SRicardo Ribalda Delgado if (of_property_read_u32(np, "xlnx,tri-default", &chip->gpio_dir[0])) 3051d6902d3SRicardo Ribalda Delgado chip->gpio_dir[0] = 0xFFFFFFFF; 3066f8bf500SMichal Simek 3071b4c5a6eSGernot Vormayr /* 3081b4c5a6eSGernot Vormayr * Check device node and parent device node for device width 3091b4c5a6eSGernot Vormayr * and assume default width of 32 3101b4c5a6eSGernot Vormayr */ 3111d6902d3SRicardo Ribalda Delgado if (of_property_read_u32(np, "xlnx,gpio-width", &chip->gpio_width[0])) 3121d6902d3SRicardo Ribalda Delgado chip->gpio_width[0] = 32; 313c103de24SGrant Likely 3141d6902d3SRicardo Ribalda Delgado spin_lock_init(&chip->gpio_lock[0]); 315c103de24SGrant Likely 3161d6902d3SRicardo Ribalda Delgado if (of_property_read_u32(np, "xlnx,is-dual", &is_dual)) 3171d6902d3SRicardo Ribalda Delgado is_dual = 0; 3181d6902d3SRicardo Ribalda Delgado 3191d6902d3SRicardo Ribalda Delgado if (is_dual) { 3201d6902d3SRicardo Ribalda Delgado /* Update GPIO state shadow register with default value */ 3211d6902d3SRicardo Ribalda Delgado of_property_read_u32(np, "xlnx,dout-default-2", 3221d6902d3SRicardo Ribalda Delgado &chip->gpio_state[1]); 3231d6902d3SRicardo Ribalda Delgado 3241d6902d3SRicardo Ribalda Delgado /* Update GPIO direction shadow register with default value */ 3251d6902d3SRicardo Ribalda Delgado if (of_property_read_u32(np, "xlnx,tri-default-2", 3261d6902d3SRicardo Ribalda Delgado &chip->gpio_dir[1])) 3271d6902d3SRicardo Ribalda Delgado chip->gpio_dir[1] = 0xFFFFFFFF; 3281d6902d3SRicardo Ribalda Delgado 3291d6902d3SRicardo Ribalda Delgado /* 3301d6902d3SRicardo Ribalda Delgado * Check device node and parent device node for device width 3311d6902d3SRicardo Ribalda Delgado * and assume default width of 32 3321d6902d3SRicardo Ribalda Delgado */ 3331d6902d3SRicardo Ribalda Delgado if (of_property_read_u32(np, "xlnx,gpio2-width", 3341d6902d3SRicardo Ribalda Delgado &chip->gpio_width[1])) 3351d6902d3SRicardo Ribalda Delgado chip->gpio_width[1] = 32; 3361d6902d3SRicardo Ribalda Delgado 3371d6902d3SRicardo Ribalda Delgado spin_lock_init(&chip->gpio_lock[1]); 3381d6902d3SRicardo Ribalda Delgado } 3391d6902d3SRicardo Ribalda Delgado 3401ebd0687SRobert Hancock chip->gc.base = -1; 3411ebd0687SRobert Hancock chip->gc.ngpio = chip->gpio_width[0] + chip->gpio_width[1]; 3421ebd0687SRobert Hancock chip->gc.parent = &pdev->dev; 3431ebd0687SRobert Hancock chip->gc.direction_input = xgpio_dir_in; 3441ebd0687SRobert Hancock chip->gc.direction_output = xgpio_dir_out; 3451ebd0687SRobert Hancock chip->gc.get = xgpio_get; 3461ebd0687SRobert Hancock chip->gc.set = xgpio_set; 3471ebd0687SRobert Hancock chip->gc.set_multiple = xgpio_set_multiple; 348c103de24SGrant Likely 3491ebd0687SRobert Hancock chip->gc.label = dev_name(&pdev->dev); 350c103de24SGrant Likely 3511ebd0687SRobert Hancock chip->regs = devm_platform_ioremap_resource(pdev, 0); 3521ebd0687SRobert Hancock if (IS_ERR(chip->regs)) { 3531ebd0687SRobert Hancock dev_err(&pdev->dev, "failed to ioremap memory resource\n"); 3541ebd0687SRobert Hancock return PTR_ERR(chip->regs); 3551ebd0687SRobert Hancock } 3561ebd0687SRobert Hancock 35765bbe531SSrinivas Neeli chip->clk = devm_clk_get_optional(&pdev->dev, NULL); 35865bbe531SSrinivas Neeli if (IS_ERR(chip->clk)) { 35965bbe531SSrinivas Neeli if (PTR_ERR(chip->clk) != -EPROBE_DEFER) 36065bbe531SSrinivas Neeli dev_dbg(&pdev->dev, "Input clock not found\n"); 36165bbe531SSrinivas Neeli return PTR_ERR(chip->clk); 36265bbe531SSrinivas Neeli } 36365bbe531SSrinivas Neeli 36465bbe531SSrinivas Neeli status = clk_prepare_enable(chip->clk); 36565bbe531SSrinivas Neeli if (status < 0) { 36665bbe531SSrinivas Neeli dev_err(&pdev->dev, "Failed to prepare clk\n"); 36765bbe531SSrinivas Neeli return status; 36865bbe531SSrinivas Neeli } 36965bbe531SSrinivas Neeli 3701ebd0687SRobert Hancock xgpio_save_regs(chip); 3711ebd0687SRobert Hancock 3721ebd0687SRobert Hancock status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); 373c103de24SGrant Likely if (status) { 3741ebd0687SRobert Hancock dev_err(&pdev->dev, "failed to add GPIO chip\n"); 37565bbe531SSrinivas Neeli clk_disable_unprepare(chip->clk); 376c103de24SGrant Likely return status; 377c103de24SGrant Likely } 37874600ee0SMichal Simek 379c103de24SGrant Likely return 0; 380c103de24SGrant Likely } 381c103de24SGrant Likely 3829992bc95SJingoo Han static const struct of_device_id xgpio_of_match[] = { 383c103de24SGrant Likely { .compatible = "xlnx,xps-gpio-1.00.a", }, 384c103de24SGrant Likely { /* end of list */ }, 385c103de24SGrant Likely }; 386c103de24SGrant Likely 387749564ffSRicardo Ribalda Delgado MODULE_DEVICE_TABLE(of, xgpio_of_match); 388749564ffSRicardo Ribalda Delgado 389749564ffSRicardo Ribalda Delgado static struct platform_driver xgpio_plat_driver = { 390749564ffSRicardo Ribalda Delgado .probe = xgpio_probe, 391*0230a41eSSrinivas Neeli .remove = xgpio_remove, 392749564ffSRicardo Ribalda Delgado .driver = { 393749564ffSRicardo Ribalda Delgado .name = "gpio-xilinx", 394749564ffSRicardo Ribalda Delgado .of_match_table = xgpio_of_match, 395749564ffSRicardo Ribalda Delgado }, 396749564ffSRicardo Ribalda Delgado }; 397749564ffSRicardo Ribalda Delgado 398c103de24SGrant Likely static int __init xgpio_init(void) 399c103de24SGrant Likely { 400749564ffSRicardo Ribalda Delgado return platform_driver_register(&xgpio_plat_driver); 401c103de24SGrant Likely } 402c103de24SGrant Likely 403c103de24SGrant Likely subsys_initcall(xgpio_init); 404749564ffSRicardo Ribalda Delgado 405749564ffSRicardo Ribalda Delgado static void __exit xgpio_exit(void) 406749564ffSRicardo Ribalda Delgado { 407749564ffSRicardo Ribalda Delgado platform_driver_unregister(&xgpio_plat_driver); 408749564ffSRicardo Ribalda Delgado } 409749564ffSRicardo Ribalda Delgado module_exit(xgpio_exit); 410c103de24SGrant Likely 411c103de24SGrant Likely MODULE_AUTHOR("Xilinx, Inc."); 412c103de24SGrant Likely MODULE_DESCRIPTION("Xilinx GPIO driver"); 413c103de24SGrant Likely MODULE_LICENSE("GPL"); 414