1 /* 2 * RDC321x GPIO driver 3 * 4 * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> 5 * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 */ 22 #include <linux/module.h> 23 #include <linux/kernel.h> 24 #include <linux/init.h> 25 #include <linux/spinlock.h> 26 #include <linux/platform_device.h> 27 #include <linux/pci.h> 28 #include <linux/gpio.h> 29 #include <linux/mfd/rdc321x.h> 30 #include <linux/slab.h> 31 32 struct rdc321x_gpio { 33 spinlock_t lock; 34 struct pci_dev *sb_pdev; 35 u32 data_reg[2]; 36 int reg1_ctrl_base; 37 int reg1_data_base; 38 int reg2_ctrl_base; 39 int reg2_data_base; 40 struct gpio_chip chip; 41 }; 42 43 /* read GPIO pin */ 44 static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio) 45 { 46 struct rdc321x_gpio *gpch; 47 u32 value = 0; 48 int reg; 49 50 gpch = container_of(chip, struct rdc321x_gpio, chip); 51 reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base; 52 53 spin_lock(&gpch->lock); 54 pci_write_config_dword(gpch->sb_pdev, reg, 55 gpch->data_reg[gpio < 32 ? 0 : 1]); 56 pci_read_config_dword(gpch->sb_pdev, reg, &value); 57 spin_unlock(&gpch->lock); 58 59 return (1 << (gpio & 0x1f)) & value ? 1 : 0; 60 } 61 62 static void rdc_gpio_set_value_impl(struct gpio_chip *chip, 63 unsigned gpio, int value) 64 { 65 struct rdc321x_gpio *gpch; 66 int reg = (gpio < 32) ? 0 : 1; 67 68 gpch = container_of(chip, struct rdc321x_gpio, chip); 69 70 if (value) 71 gpch->data_reg[reg] |= 1 << (gpio & 0x1f); 72 else 73 gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f)); 74 75 pci_write_config_dword(gpch->sb_pdev, 76 reg ? gpch->reg2_data_base : gpch->reg1_data_base, 77 gpch->data_reg[reg]); 78 } 79 80 /* set GPIO pin to value */ 81 static void rdc_gpio_set_value(struct gpio_chip *chip, 82 unsigned gpio, int value) 83 { 84 struct rdc321x_gpio *gpch; 85 86 gpch = container_of(chip, struct rdc321x_gpio, chip); 87 spin_lock(&gpch->lock); 88 rdc_gpio_set_value_impl(chip, gpio, value); 89 spin_unlock(&gpch->lock); 90 } 91 92 static int rdc_gpio_config(struct gpio_chip *chip, 93 unsigned gpio, int value) 94 { 95 struct rdc321x_gpio *gpch; 96 int err; 97 u32 reg; 98 99 gpch = container_of(chip, struct rdc321x_gpio, chip); 100 101 spin_lock(&gpch->lock); 102 err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ? 103 gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, ®); 104 if (err) 105 goto unlock; 106 107 reg |= 1 << (gpio & 0x1f); 108 109 err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ? 110 gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg); 111 if (err) 112 goto unlock; 113 114 rdc_gpio_set_value_impl(chip, gpio, value); 115 116 unlock: 117 spin_unlock(&gpch->lock); 118 119 return err; 120 } 121 122 /* configure GPIO pin as input */ 123 static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) 124 { 125 return rdc_gpio_config(chip, gpio, 1); 126 } 127 128 /* 129 * Cache the initial value of both GPIO data registers 130 */ 131 static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) 132 { 133 int err; 134 struct resource *r; 135 struct rdc321x_gpio *rdc321x_gpio_dev; 136 struct rdc321x_gpio_pdata *pdata; 137 138 pdata = pdev->dev.platform_data; 139 if (!pdata) { 140 dev_err(&pdev->dev, "no platform data supplied\n"); 141 return -ENODEV; 142 } 143 144 rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL); 145 if (!rdc321x_gpio_dev) { 146 dev_err(&pdev->dev, "failed to allocate private data\n"); 147 return -ENOMEM; 148 } 149 150 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1"); 151 if (!r) { 152 dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n"); 153 err = -ENODEV; 154 goto out_free; 155 } 156 157 spin_lock_init(&rdc321x_gpio_dev->lock); 158 rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev; 159 rdc321x_gpio_dev->reg1_ctrl_base = r->start; 160 rdc321x_gpio_dev->reg1_data_base = r->start + 0x4; 161 162 r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2"); 163 if (!r) { 164 dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n"); 165 err = -ENODEV; 166 goto out_free; 167 } 168 169 rdc321x_gpio_dev->reg2_ctrl_base = r->start; 170 rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; 171 172 rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; 173 rdc321x_gpio_dev->chip.owner = THIS_MODULE; 174 rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; 175 rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; 176 rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; 177 rdc321x_gpio_dev->chip.set = rdc_gpio_set_value; 178 rdc321x_gpio_dev->chip.base = 0; 179 rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios; 180 181 platform_set_drvdata(pdev, rdc321x_gpio_dev); 182 183 /* This might not be, what others (BIOS, bootloader, etc.) 184 wrote to these registers before, but it's a good guess. Still 185 better than just using 0xffffffff. */ 186 err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, 187 rdc321x_gpio_dev->reg1_data_base, 188 &rdc321x_gpio_dev->data_reg[0]); 189 if (err) 190 goto out_drvdata; 191 192 err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, 193 rdc321x_gpio_dev->reg2_data_base, 194 &rdc321x_gpio_dev->data_reg[1]); 195 if (err) 196 goto out_drvdata; 197 198 dev_info(&pdev->dev, "registering %d GPIOs\n", 199 rdc321x_gpio_dev->chip.ngpio); 200 return gpiochip_add(&rdc321x_gpio_dev->chip); 201 202 out_drvdata: 203 platform_set_drvdata(pdev, NULL); 204 out_free: 205 kfree(rdc321x_gpio_dev); 206 return err; 207 } 208 209 static int __devexit rdc321x_gpio_remove(struct platform_device *pdev) 210 { 211 int ret; 212 struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev); 213 214 ret = gpiochip_remove(&rdc321x_gpio_dev->chip); 215 if (ret) 216 dev_err(&pdev->dev, "failed to unregister chip\n"); 217 218 kfree(rdc321x_gpio_dev); 219 platform_set_drvdata(pdev, NULL); 220 221 return ret; 222 } 223 224 static struct platform_driver rdc321x_gpio_driver = { 225 .driver.name = "rdc321x-gpio", 226 .driver.owner = THIS_MODULE, 227 .probe = rdc321x_gpio_probe, 228 .remove = __devexit_p(rdc321x_gpio_remove), 229 }; 230 231 module_platform_driver(rdc321x_gpio_driver); 232 233 MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); 234 MODULE_DESCRIPTION("RDC321x GPIO driver"); 235 MODULE_LICENSE("GPL"); 236 MODULE_ALIAS("platform:rdc321x-gpio"); 237