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/kernel.h> 16 #include <linux/init.h> 17 #include <linux/module.h> 18 #include <linux/types.h> 19 #include <linux/spinlock.h> 20 #include <linux/io.h> 21 #include <linux/ioport.h> 22 #include <linux/gpio.h> 23 #include <linux/platform_data/gpio-ath79.h> 24 #include <linux/of_device.h> 25 26 #include <asm/mach-ath79/ar71xx_regs.h> 27 28 static void __iomem *ath79_gpio_base; 29 static u32 ath79_gpio_count; 30 static DEFINE_SPINLOCK(ath79_gpio_lock); 31 32 static void __ath79_gpio_set_value(unsigned gpio, int value) 33 { 34 void __iomem *base = ath79_gpio_base; 35 36 if (value) 37 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_SET); 38 else 39 __raw_writel(1 << gpio, base + AR71XX_GPIO_REG_CLEAR); 40 } 41 42 static int __ath79_gpio_get_value(unsigned gpio) 43 { 44 return (__raw_readl(ath79_gpio_base + AR71XX_GPIO_REG_IN) >> gpio) & 1; 45 } 46 47 static int ath79_gpio_get_value(struct gpio_chip *chip, unsigned offset) 48 { 49 return __ath79_gpio_get_value(offset); 50 } 51 52 static void ath79_gpio_set_value(struct gpio_chip *chip, 53 unsigned offset, int value) 54 { 55 __ath79_gpio_set_value(offset, value); 56 } 57 58 static int ath79_gpio_direction_input(struct gpio_chip *chip, 59 unsigned offset) 60 { 61 void __iomem *base = ath79_gpio_base; 62 unsigned long flags; 63 64 spin_lock_irqsave(&ath79_gpio_lock, flags); 65 66 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), 67 base + AR71XX_GPIO_REG_OE); 68 69 spin_unlock_irqrestore(&ath79_gpio_lock, flags); 70 71 return 0; 72 } 73 74 static int ath79_gpio_direction_output(struct gpio_chip *chip, 75 unsigned offset, int value) 76 { 77 void __iomem *base = ath79_gpio_base; 78 unsigned long flags; 79 80 spin_lock_irqsave(&ath79_gpio_lock, flags); 81 82 if (value) 83 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); 84 else 85 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); 86 87 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), 88 base + AR71XX_GPIO_REG_OE); 89 90 spin_unlock_irqrestore(&ath79_gpio_lock, flags); 91 92 return 0; 93 } 94 95 static int ar934x_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 96 { 97 void __iomem *base = ath79_gpio_base; 98 unsigned long flags; 99 100 spin_lock_irqsave(&ath79_gpio_lock, flags); 101 102 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) | (1 << offset), 103 base + AR71XX_GPIO_REG_OE); 104 105 spin_unlock_irqrestore(&ath79_gpio_lock, flags); 106 107 return 0; 108 } 109 110 static int ar934x_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 111 int value) 112 { 113 void __iomem *base = ath79_gpio_base; 114 unsigned long flags; 115 116 spin_lock_irqsave(&ath79_gpio_lock, flags); 117 118 if (value) 119 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_SET); 120 else 121 __raw_writel(1 << offset, base + AR71XX_GPIO_REG_CLEAR); 122 123 __raw_writel(__raw_readl(base + AR71XX_GPIO_REG_OE) & ~(1 << offset), 124 base + AR71XX_GPIO_REG_OE); 125 126 spin_unlock_irqrestore(&ath79_gpio_lock, flags); 127 128 return 0; 129 } 130 131 static struct gpio_chip ath79_gpio_chip = { 132 .label = "ath79", 133 .get = ath79_gpio_get_value, 134 .set = ath79_gpio_set_value, 135 .direction_input = ath79_gpio_direction_input, 136 .direction_output = ath79_gpio_direction_output, 137 .base = 0, 138 }; 139 140 static const struct of_device_id ath79_gpio_of_match[] = { 141 { .compatible = "qca,ar7100-gpio" }, 142 { .compatible = "qca,ar9340-gpio" }, 143 {}, 144 }; 145 146 static int ath79_gpio_probe(struct platform_device *pdev) 147 { 148 struct ath79_gpio_platform_data *pdata = pdev->dev.platform_data; 149 struct device_node *np = pdev->dev.of_node; 150 struct resource *res; 151 bool oe_inverted; 152 int err; 153 154 if (np) { 155 err = of_property_read_u32(np, "ngpios", &ath79_gpio_count); 156 if (err) { 157 dev_err(&pdev->dev, "ngpios property is not valid\n"); 158 return err; 159 } 160 if (ath79_gpio_count >= 32) { 161 dev_err(&pdev->dev, "ngpios must be less than 32\n"); 162 return -EINVAL; 163 } 164 oe_inverted = of_device_is_compatible(np, "qca,ar9340-gpio"); 165 } else if (pdata) { 166 ath79_gpio_count = pdata->ngpios; 167 oe_inverted = pdata->oe_inverted; 168 } else { 169 dev_err(&pdev->dev, "No DT node or platform data found\n"); 170 return -EINVAL; 171 } 172 173 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 174 ath79_gpio_base = devm_ioremap_nocache( 175 &pdev->dev, res->start, resource_size(res)); 176 if (!ath79_gpio_base) 177 return -ENOMEM; 178 179 ath79_gpio_chip.dev = &pdev->dev; 180 ath79_gpio_chip.ngpio = ath79_gpio_count; 181 if (oe_inverted) { 182 ath79_gpio_chip.direction_input = ar934x_gpio_direction_input; 183 ath79_gpio_chip.direction_output = ar934x_gpio_direction_output; 184 } 185 186 err = gpiochip_add(&ath79_gpio_chip); 187 if (err) { 188 dev_err(&pdev->dev, 189 "cannot add AR71xx GPIO chip, error=%d", err); 190 return err; 191 } 192 193 return 0; 194 } 195 196 static struct platform_driver ath79_gpio_driver = { 197 .driver = { 198 .name = "ath79-gpio", 199 .of_match_table = ath79_gpio_of_match, 200 }, 201 .probe = ath79_gpio_probe, 202 }; 203 204 module_platform_driver(ath79_gpio_driver); 205