1 /* 2 * Atheros AR71XX/AR724X/AR913X GPIO API support 3 * 4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 5 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 7 * 8 * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 */ 14 15 #include <linux/gpio/driver.h> 16 #include <linux/platform_data/gpio-ath79.h> 17 #include <linux/of_device.h> 18 19 #include <asm/mach-ath79/ar71xx_regs.h> 20 21 struct ath79_gpio_ctrl { 22 struct gpio_chip chip; 23 void __iomem *base; 24 spinlock_t lock; 25 }; 26 27 static void ath79_gpio_set_value(struct gpio_chip *chip, 28 unsigned gpio, int value) 29 { 30 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 31 32 if (value) 33 __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_SET); 34 else 35 __raw_writel(BIT(gpio), ctrl->base + AR71XX_GPIO_REG_CLEAR); 36 } 37 38 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned gpio) 39 { 40 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 41 42 return (__raw_readl(ctrl->base + AR71XX_GPIO_REG_IN) >> gpio) & 1; 43 } 44 45 static int ath79_gpio_direction_input(struct gpio_chip *chip, 46 unsigned offset) 47 { 48 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 49 unsigned long flags; 50 51 spin_lock_irqsave(&ctrl->lock, flags); 52 53 __raw_writel( 54 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset), 55 ctrl->base + AR71XX_GPIO_REG_OE); 56 57 spin_unlock_irqrestore(&ctrl->lock, flags); 58 59 return 0; 60 } 61 62 static int ath79_gpio_direction_output(struct gpio_chip *chip, 63 unsigned offset, int value) 64 { 65 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 66 unsigned long flags; 67 68 spin_lock_irqsave(&ctrl->lock, flags); 69 70 if (value) 71 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); 72 else 73 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); 74 75 __raw_writel( 76 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), 77 ctrl->base + AR71XX_GPIO_REG_OE); 78 79 spin_unlock_irqrestore(&ctrl->lock, flags); 80 81 return 0; 82 } 83 84 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 85 { 86 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 87 unsigned long flags; 88 89 spin_lock_irqsave(&ctrl->lock, flags); 90 91 __raw_writel( 92 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) | BIT(offset), 93 ctrl->base + AR71XX_GPIO_REG_OE); 94 95 spin_unlock_irqrestore(&ctrl->lock, flags); 96 97 return 0; 98 } 99 100 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 101 int value) 102 { 103 struct ath79_gpio_ctrl *ctrl = gpiochip_get_data(chip); 104 unsigned long flags; 105 106 spin_lock_irqsave(&ctrl->lock, flags); 107 108 if (value) 109 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_SET); 110 else 111 __raw_writel(BIT(offset), ctrl->base + AR71XX_GPIO_REG_CLEAR); 112 113 __raw_writel( 114 __raw_readl(ctrl->base + AR71XX_GPIO_REG_OE) & ~BIT(offset), 115 ctrl->base + AR71XX_GPIO_REG_OE); 116 117 spin_unlock_irqrestore(&ctrl->lock, flags); 118 119 return 0; 120 } 121 122 static const struct gpio_chip ath79_gpio_chip = { 123 .label = "ath79", 124 .get = ath79_gpio_get_value, 125 .set = ath79_gpio_set_value, 126 .direction_input = ath79_gpio_direction_input, 127 .direction_output = ath79_gpio_direction_output, 128 .base = 0, 129 }; 130 131 static const struct of_device_id ath79_gpio_of_match[] = { 132 { .compatible = "qca,ar7100-gpio" }, 133 { .compatible = "qca,ar9340-gpio" }, 134 {}, 135 }; 136 137 static int ath79_gpio_probe(struct platform_device *pdev) 138 { 139 struct ath79_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev); 140 struct device_node *np = pdev->dev.of_node; 141 struct ath79_gpio_ctrl *ctrl; 142 struct resource *res; 143 u32 ath79_gpio_count; 144 bool oe_inverted; 145 int err; 146 147 ctrl = devm_kzalloc(&pdev->dev, sizeof(*ctrl), GFP_KERNEL); 148 if (!ctrl) 149 return -ENOMEM; 150 151 if (np) { 152 err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); 153 if (err) { 154 dev_err(&pdev->dev, "ngpios property is not valid\n"); 155 return err; 156 } 157 if (ath79_gpio_count >= 32) { 158 dev_err(&pdev->dev, "ngpios must be less than 32\n"); 159 return -EINVAL; 160 } 161 oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio"); 162 } else if (pdata) { 163 ath79_gpio_count = pdata->ngpios; 164 oe_inverted = pdata->oe_inverted; 165 } else { 166 dev_err(&pdev->dev, "No DT node or platform data found\n"); 167 return -EINVAL; 168 } 169 170 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 171 ctrl->base = devm_ioremap_nocache( 172 &pdev->dev, res->start, resource_size(res)); 173 if (!ctrl->base) 174 return -ENOMEM; 175 176 spin_lock_init(&ctrl->lock); 177 memcpy(&ctrl->chip, &ath79_gpio_chip, sizeof(ctrl->chip)); 178 ctrl->chip.parent = &pdev->dev; 179 ctrl->chip.ngpio = ath79_gpio_count; 180 if (oe_inverted) { 181 ctrl->chip.direction_input = ar934x_gpio_direction_input; 182 ctrl->chip.direction_output = ar934x_gpio_direction_output; 183 } 184 185 err = gpiochip_add_data(&ctrl->chip, ctrl); 186 if (err) { 187 dev_err(&pdev->dev, 188 "cannot add AR71xx GPIO chip, error=%d", err); 189 return err; 190 } 191 192 return 0; 193 } 194 195 static struct platform_driver ath79_gpio_driver = { 196 .driver = { 197 .name = "ath79-gpio", 198 .of_match_table = ath79_gpio_of_match, 199 }, 200 .probe = ath79_gpio_probe, 201 }; 202 203 module_platform_driver(ath79_gpio_driver); 204