root/drivers/gpio/gpio-vx855.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gpi_i_bit
  2. gpo_o_bit
  3. gpio_i_bit
  4. gpio_o_bit
  5. vx855gpio_direction_input
  6. vx855gpio_get
  7. vx855gpio_set
  8. vx855gpio_direction_output
  9. vx855gpio_set_config
  10. vx855gpio_gpio_setup
  11. vx855gpio_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Linux GPIOlib driver for the VIA VX855 integrated southbridge GPIO
   4  *
   5  * Copyright (C) 2009 VIA Technologies, Inc.
   6  * Copyright (C) 2010 One Laptop per Child
   7  * Author: Harald Welte <HaraldWelte@viatech.com>
   8  * All rights reserved.
   9  */
  10 #include <linux/kernel.h>
  11 #include <linux/module.h>
  12 #include <linux/gpio/driver.h>
  13 #include <linux/slab.h>
  14 #include <linux/device.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/pci.h>
  17 #include <linux/io.h>
  18 
  19 #define MODULE_NAME "vx855_gpio"
  20 
  21 /* The VX855 south bridge has the following GPIO pins:
  22  *      GPI 0...13      General Purpose Input
  23  *      GPO 0...12      General Purpose Output
  24  *      GPIO 0...14     General Purpose I/O (Open-Drain)
  25  */
  26 
  27 #define NR_VX855_GPI    14
  28 #define NR_VX855_GPO    13
  29 #define NR_VX855_GPIO   15
  30 
  31 #define NR_VX855_GPInO  (NR_VX855_GPI + NR_VX855_GPO)
  32 #define NR_VX855_GP     (NR_VX855_GPI + NR_VX855_GPO + NR_VX855_GPIO)
  33 
  34 struct vx855_gpio {
  35         struct gpio_chip gpio;
  36         spinlock_t lock;
  37         u32 io_gpi;
  38         u32 io_gpo;
  39 };
  40 
  41 /* resolve a GPIx into the corresponding bit position */
  42 static inline u_int32_t gpi_i_bit(int i)
  43 {
  44         if (i < 10)
  45                 return 1 << i;
  46         else
  47                 return 1 << (i + 14);
  48 }
  49 
  50 static inline u_int32_t gpo_o_bit(int i)
  51 {
  52         if (i < 11)
  53                 return 1 << i;
  54         else
  55                 return 1 << (i + 14);
  56 }
  57 
  58 static inline u_int32_t gpio_i_bit(int i)
  59 {
  60         if (i < 14)
  61                 return 1 << (i + 10);
  62         else
  63                 return 1 << (i + 14);
  64 }
  65 
  66 static inline u_int32_t gpio_o_bit(int i)
  67 {
  68         if (i < 14)
  69                 return 1 << (i + 11);
  70         else
  71                 return 1 << (i + 13);
  72 }
  73 
  74 /* Mapping betwee numeric GPIO ID and the actual GPIO hardware numbering:
  75  * 0..13        GPI 0..13
  76  * 14..26       GPO 0..12
  77  * 27..41       GPIO 0..14
  78  */
  79 
  80 static int vx855gpio_direction_input(struct gpio_chip *gpio,
  81                                      unsigned int nr)
  82 {
  83         struct vx855_gpio *vg = gpiochip_get_data(gpio);
  84         unsigned long flags;
  85         u_int32_t reg_out;
  86 
  87         /* Real GPI bits are always in input direction */
  88         if (nr < NR_VX855_GPI)
  89                 return 0;
  90 
  91         /* Real GPO bits cannot be put in output direction */
  92         if (nr < NR_VX855_GPInO)
  93                 return -EINVAL;
  94 
  95         /* Open Drain GPIO have to be set to one */
  96         spin_lock_irqsave(&vg->lock, flags);
  97         reg_out = inl(vg->io_gpo);
  98         reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
  99         outl(reg_out, vg->io_gpo);
 100         spin_unlock_irqrestore(&vg->lock, flags);
 101 
 102         return 0;
 103 }
 104 
 105 static int vx855gpio_get(struct gpio_chip *gpio, unsigned int nr)
 106 {
 107         struct vx855_gpio *vg = gpiochip_get_data(gpio);
 108         u_int32_t reg_in;
 109         int ret = 0;
 110 
 111         if (nr < NR_VX855_GPI) {
 112                 reg_in = inl(vg->io_gpi);
 113                 if (reg_in & gpi_i_bit(nr))
 114                         ret = 1;
 115         } else if (nr < NR_VX855_GPInO) {
 116                 /* GPO don't have an input bit, we need to read it
 117                  * back from the output register */
 118                 reg_in = inl(vg->io_gpo);
 119                 if (reg_in & gpo_o_bit(nr - NR_VX855_GPI))
 120                         ret = 1;
 121         } else {
 122                 reg_in = inl(vg->io_gpi);
 123                 if (reg_in & gpio_i_bit(nr - NR_VX855_GPInO))
 124                         ret = 1;
 125         }
 126 
 127         return ret;
 128 }
 129 
 130 static void vx855gpio_set(struct gpio_chip *gpio, unsigned int nr,
 131                           int val)
 132 {
 133         struct vx855_gpio *vg = gpiochip_get_data(gpio);
 134         unsigned long flags;
 135         u_int32_t reg_out;
 136 
 137         /* True GPI cannot be switched to output mode */
 138         if (nr < NR_VX855_GPI)
 139                 return;
 140 
 141         spin_lock_irqsave(&vg->lock, flags);
 142         reg_out = inl(vg->io_gpo);
 143         if (nr < NR_VX855_GPInO) {
 144                 if (val)
 145                         reg_out |= gpo_o_bit(nr - NR_VX855_GPI);
 146                 else
 147                         reg_out &= ~gpo_o_bit(nr - NR_VX855_GPI);
 148         } else {
 149                 if (val)
 150                         reg_out |= gpio_o_bit(nr - NR_VX855_GPInO);
 151                 else
 152                         reg_out &= ~gpio_o_bit(nr - NR_VX855_GPInO);
 153         }
 154         outl(reg_out, vg->io_gpo);
 155         spin_unlock_irqrestore(&vg->lock, flags);
 156 }
 157 
 158 static int vx855gpio_direction_output(struct gpio_chip *gpio,
 159                                       unsigned int nr, int val)
 160 {
 161         /* True GPI cannot be switched to output mode */
 162         if (nr < NR_VX855_GPI)
 163                 return -EINVAL;
 164 
 165         /* True GPO don't need to be switched to output mode,
 166          * and GPIO are open-drain, i.e. also need no switching,
 167          * so all we do is set the level */
 168         vx855gpio_set(gpio, nr, val);
 169 
 170         return 0;
 171 }
 172 
 173 static int vx855gpio_set_config(struct gpio_chip *gpio, unsigned int nr,
 174                                 unsigned long config)
 175 {
 176         enum pin_config_param param = pinconf_to_config_param(config);
 177 
 178         /* The GPI cannot be single-ended */
 179         if (nr < NR_VX855_GPI)
 180                 return -EINVAL;
 181 
 182         /* The GPO's are push-pull */
 183         if (nr < NR_VX855_GPInO) {
 184                 if (param != PIN_CONFIG_DRIVE_PUSH_PULL)
 185                         return -ENOTSUPP;
 186                 return 0;
 187         }
 188 
 189         /* The GPIO's are open drain */
 190         if (param != PIN_CONFIG_DRIVE_OPEN_DRAIN)
 191                 return -ENOTSUPP;
 192 
 193         return 0;
 194 }
 195 
 196 static const char *vx855gpio_names[NR_VX855_GP] = {
 197         "VX855_GPI0", "VX855_GPI1", "VX855_GPI2", "VX855_GPI3", "VX855_GPI4",
 198         "VX855_GPI5", "VX855_GPI6", "VX855_GPI7", "VX855_GPI8", "VX855_GPI9",
 199         "VX855_GPI10", "VX855_GPI11", "VX855_GPI12", "VX855_GPI13",
 200         "VX855_GPO0", "VX855_GPO1", "VX855_GPO2", "VX855_GPO3", "VX855_GPO4",
 201         "VX855_GPO5", "VX855_GPO6", "VX855_GPO7", "VX855_GPO8", "VX855_GPO9",
 202         "VX855_GPO10", "VX855_GPO11", "VX855_GPO12",
 203         "VX855_GPIO0", "VX855_GPIO1", "VX855_GPIO2", "VX855_GPIO3",
 204         "VX855_GPIO4", "VX855_GPIO5", "VX855_GPIO6", "VX855_GPIO7",
 205         "VX855_GPIO8", "VX855_GPIO9", "VX855_GPIO10", "VX855_GPIO11",
 206         "VX855_GPIO12", "VX855_GPIO13", "VX855_GPIO14"
 207 };
 208 
 209 static void vx855gpio_gpio_setup(struct vx855_gpio *vg)
 210 {
 211         struct gpio_chip *c = &vg->gpio;
 212 
 213         c->label = "VX855 South Bridge";
 214         c->owner = THIS_MODULE;
 215         c->direction_input = vx855gpio_direction_input;
 216         c->direction_output = vx855gpio_direction_output;
 217         c->get = vx855gpio_get;
 218         c->set = vx855gpio_set;
 219         c->set_config = vx855gpio_set_config,
 220         c->dbg_show = NULL;
 221         c->base = 0;
 222         c->ngpio = NR_VX855_GP;
 223         c->can_sleep = false;
 224         c->names = vx855gpio_names;
 225 }
 226 
 227 /* This platform device is ordinarily registered by the vx855 mfd driver */
 228 static int vx855gpio_probe(struct platform_device *pdev)
 229 {
 230         struct resource *res_gpi;
 231         struct resource *res_gpo;
 232         struct vx855_gpio *vg;
 233 
 234         res_gpi = platform_get_resource(pdev, IORESOURCE_IO, 0);
 235         res_gpo = platform_get_resource(pdev, IORESOURCE_IO, 1);
 236         if (!res_gpi || !res_gpo)
 237                 return -EBUSY;
 238 
 239         vg = devm_kzalloc(&pdev->dev, sizeof(*vg), GFP_KERNEL);
 240         if (!vg)
 241                 return -ENOMEM;
 242 
 243         platform_set_drvdata(pdev, vg);
 244 
 245         dev_info(&pdev->dev, "found VX855 GPIO controller\n");
 246         vg->io_gpi = res_gpi->start;
 247         vg->io_gpo = res_gpo->start;
 248         spin_lock_init(&vg->lock);
 249 
 250         /*
 251          * A single byte is used to control various GPIO ports on the VX855,
 252          * and in the case of the OLPC XO-1.5, some of those ports are used
 253          * for switches that are interpreted and exposed through ACPI. ACPI
 254          * will have reserved the region, so our own reservation will not
 255          * succeed. Ignore and continue.
 256          */
 257 
 258         if (!devm_request_region(&pdev->dev, res_gpi->start,
 259                                  resource_size(res_gpi), MODULE_NAME "_gpi"))
 260                 dev_warn(&pdev->dev,
 261                         "GPI I/O resource busy, probably claimed by ACPI\n");
 262 
 263         if (!devm_request_region(&pdev->dev, res_gpo->start,
 264                                  resource_size(res_gpo), MODULE_NAME "_gpo"))
 265                 dev_warn(&pdev->dev,
 266                         "GPO I/O resource busy, probably claimed by ACPI\n");
 267 
 268         vx855gpio_gpio_setup(vg);
 269 
 270         return devm_gpiochip_add_data(&pdev->dev, &vg->gpio, vg);
 271 }
 272 
 273 static struct platform_driver vx855gpio_driver = {
 274         .driver = {
 275                 .name   = MODULE_NAME,
 276         },
 277         .probe          = vx855gpio_probe,
 278 };
 279 
 280 module_platform_driver(vx855gpio_driver);
 281 
 282 MODULE_LICENSE("GPL");
 283 MODULE_AUTHOR("Harald Welte <HaraldWelte@viatech.com>");
 284 MODULE_DESCRIPTION("GPIO driver for the VIA VX855 chipset");
 285 MODULE_ALIAS("platform:vx855_gpio");

/* [<][>][^][v][top][bottom][index][help] */