linux/drivers/gpio/gpio-vt8500.c
<<
>>
Prefs
   1/* drivers/gpio/gpio-vt8500.c
   2 *
   3 * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
   4 * Based on arch/arm/mach-vt8500/gpio.c:
   5 * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
   6 *
   7 * This software is licensed under the terms of the GNU General Public
   8 * License version 2, as published by the Free Software Foundation, and
   9 * may be copied, distributed, and modified under those terms.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/err.h>
  20#include <linux/io.h>
  21#include <linux/gpio.h>
  22#include <linux/platform_device.h>
  23#include <linux/bitops.h>
  24#include <linux/of.h>
  25#include <linux/of_address.h>
  26#include <linux/of_irq.h>
  27#include <linux/of_device.h>
  28
  29/*
  30        We handle GPIOs by bank, each bank containing up to 32 GPIOs covered
  31        by one set of registers (although not all may be valid).
  32
  33        Because different SoC's have different register offsets, we pass the
  34        register offsets as data in vt8500_gpio_dt_ids[].
  35
  36        A value of NO_REG is used to indicate that this register is not
  37        supported. Only used for ->en at the moment.
  38*/
  39
  40#define NO_REG  0xFFFF
  41
  42/*
  43 * struct vt8500_gpio_bank_regoffsets
  44 * @en: offset to enable register of the bank
  45 * @dir: offset to direction register of the bank
  46 * @data_out: offset to the data out register of the bank
  47 * @data_in: offset to the data in register of the bank
  48 * @ngpio: highest valid pin in this bank
  49 */
  50
  51struct vt8500_gpio_bank_regoffsets {
  52        unsigned int    en;
  53        unsigned int    dir;
  54        unsigned int    data_out;
  55        unsigned int    data_in;
  56        unsigned char   ngpio;
  57};
  58
  59struct vt8500_gpio_data {
  60        unsigned int                            num_banks;
  61        struct vt8500_gpio_bank_regoffsets      banks[];
  62};
  63
  64#define VT8500_BANK(__en, __dir, __out, __in, __ngpio)          \
  65{                                                               \
  66        .en = __en,                                             \
  67        .dir = __dir,                                           \
  68        .data_out = __out,                                      \
  69        .data_in = __in,                                        \
  70        .ngpio = __ngpio,                                       \
  71}
  72
  73static struct vt8500_gpio_data vt8500_data = {
  74        .num_banks      = 7,
  75        .banks  = {
  76                VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
  77                VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
  78                VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
  79                VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
  80                VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
  81                VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
  82                VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
  83        },
  84};
  85
  86static struct vt8500_gpio_data wm8505_data = {
  87        .num_banks      = 10,
  88        .banks  = {
  89                VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
  90                VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
  91                VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
  92                VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
  93                VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16),
  94                VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25),
  95                VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5),
  96                VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
  97                VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
  98                VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
  99                VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 100        },
 101};
 102
 103/*
 104 * No information about which bits are valid so we just make
 105 * them all available until its figured out.
 106 */
 107static struct vt8500_gpio_data wm8650_data = {
 108        .num_banks      = 9,
 109        .banks  = {
 110                VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32),
 111                VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32),
 112                VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32),
 113                VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32),
 114                VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32),
 115                VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32),
 116                VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
 117                VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
 118                VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
 119                VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
 120        },
 121};
 122
 123struct vt8500_gpio_chip {
 124        struct gpio_chip                chip;
 125
 126        const struct vt8500_gpio_bank_regoffsets *regs;
 127        void __iomem    *base;
 128};
 129
 130struct vt8500_data {
 131        struct vt8500_gpio_chip *chip;
 132        void __iomem *iobase;
 133        int num_banks;
 134};
 135
 136
 137#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
 138
 139static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset)
 140{
 141        u32 val;
 142        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 143
 144        if (vt8500_chip->regs->en == NO_REG)
 145                return 0;
 146
 147        val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
 148        val |= BIT(offset);
 149        writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
 150
 151        return 0;
 152}
 153
 154static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset)
 155{
 156        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 157        u32 val;
 158
 159        if (vt8500_chip->regs->en == NO_REG)
 160                return;
 161
 162        val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
 163        val &= ~BIT(offset);
 164        writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
 165}
 166
 167static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 168{
 169        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 170
 171        u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
 172        val &= ~BIT(offset);
 173        writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
 174
 175        return 0;
 176}
 177
 178static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 179                                                                int value)
 180{
 181        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 182
 183        u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
 184        val |= BIT(offset);
 185        writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
 186
 187        if (value) {
 188                val = readl_relaxed(vt8500_chip->base +
 189                                                vt8500_chip->regs->data_out);
 190                val |= BIT(offset);
 191                writel_relaxed(val, vt8500_chip->base +
 192                                                vt8500_chip->regs->data_out);
 193        }
 194        return 0;
 195}
 196
 197static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset)
 198{
 199        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 200
 201        return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >>
 202                                                                offset) & 1;
 203}
 204
 205static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset,
 206                                                                int value)
 207{
 208        struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
 209
 210        u32 val = readl_relaxed(vt8500_chip->base +
 211                                                vt8500_chip->regs->data_out);
 212        if (value)
 213                val |= BIT(offset);
 214        else
 215                val &= ~BIT(offset);
 216
 217        writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
 218}
 219
 220static int vt8500_of_xlate(struct gpio_chip *gc,
 221                            const struct of_phandle_args *gpiospec, u32 *flags)
 222{
 223        /* bank if specificed in gpiospec->args[0] */
 224        if (flags)
 225                *flags = gpiospec->args[2];
 226
 227        return gpiospec->args[1];
 228}
 229
 230static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
 231                                const struct vt8500_gpio_data *data)
 232{
 233        struct vt8500_data *priv;
 234        struct vt8500_gpio_chip *vtchip;
 235        struct gpio_chip *chip;
 236        int i;
 237        int pin_cnt = 0;
 238
 239        priv = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_data), GFP_KERNEL);
 240        if (!priv) {
 241                dev_err(&pdev->dev, "failed to allocate memory\n");
 242                return -ENOMEM;
 243        }
 244
 245        priv->chip = devm_kzalloc(&pdev->dev,
 246                        sizeof(struct vt8500_gpio_chip) * data->num_banks,
 247                        GFP_KERNEL);
 248        if (!priv->chip) {
 249                dev_err(&pdev->dev, "failed to allocate chip memory\n");
 250                return -ENOMEM;
 251        }
 252
 253        priv->iobase = base;
 254        priv->num_banks = data->num_banks;
 255        platform_set_drvdata(pdev, priv);
 256
 257        vtchip = priv->chip;
 258
 259        for (i = 0; i < data->num_banks; i++) {
 260                vtchip[i].base = base;
 261                vtchip[i].regs = &data->banks[i];
 262
 263                chip = &vtchip[i].chip;
 264
 265                chip->of_xlate = vt8500_of_xlate;
 266                chip->of_gpio_n_cells = 3;
 267                chip->of_node = pdev->dev.of_node;
 268
 269                chip->request = vt8500_gpio_request;
 270                chip->free = vt8500_gpio_free;
 271                chip->direction_input = vt8500_gpio_direction_input;
 272                chip->direction_output = vt8500_gpio_direction_output;
 273                chip->get = vt8500_gpio_get_value;
 274                chip->set = vt8500_gpio_set_value;
 275                chip->can_sleep = 0;
 276                chip->base = pin_cnt;
 277                chip->ngpio = data->banks[i].ngpio;
 278
 279                pin_cnt += data->banks[i].ngpio;
 280
 281                gpiochip_add(chip);
 282        }
 283        return 0;
 284}
 285
 286static struct of_device_id vt8500_gpio_dt_ids[] = {
 287        { .compatible = "via,vt8500-gpio", .data = &vt8500_data, },
 288        { .compatible = "wm,wm8505-gpio", .data = &wm8505_data, },
 289        { .compatible = "wm,wm8650-gpio", .data = &wm8650_data, },
 290        { /* Sentinel */ },
 291};
 292
 293static int vt8500_gpio_probe(struct platform_device *pdev)
 294{
 295        int ret;
 296        void __iomem *gpio_base;
 297        struct resource *res;
 298        const struct of_device_id *of_id =
 299                                of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
 300
 301        if (!of_id) {
 302                dev_err(&pdev->dev, "No matching driver data\n");
 303                return -ENODEV;
 304        }
 305
 306        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 307        if (!res) {
 308                dev_err(&pdev->dev, "Unable to get IO resource\n");
 309                return -ENODEV;
 310        }
 311
 312        gpio_base = devm_request_and_ioremap(&pdev->dev, res);
 313        if (!gpio_base) {
 314                dev_err(&pdev->dev, "Unable to map GPIO registers\n");
 315                return -ENOMEM;
 316        }
 317
 318        ret = vt8500_add_chips(pdev, gpio_base, of_id->data);
 319
 320        return ret;
 321}
 322
 323static int vt8500_gpio_remove(struct platform_device *pdev)
 324{
 325        int i;
 326        int ret;
 327        struct vt8500_data *priv = platform_get_drvdata(pdev);
 328        struct vt8500_gpio_chip *vtchip = priv->chip;
 329
 330        for (i = 0; i < priv->num_banks; i++) {
 331                ret = gpiochip_remove(&vtchip[i].chip);
 332                if (ret)
 333                        dev_warn(&pdev->dev, "gpiochip_remove returned %d\n",
 334                                 ret);
 335        }
 336
 337        return 0;
 338}
 339
 340static struct platform_driver vt8500_gpio_driver = {
 341        .probe          = vt8500_gpio_probe,
 342        .remove         = vt8500_gpio_remove,
 343        .driver         = {
 344                .name   = "vt8500-gpio",
 345                .owner  = THIS_MODULE,
 346                .of_match_table = vt8500_gpio_dt_ids,
 347        },
 348};
 349
 350module_platform_driver(vt8500_gpio_driver);
 351
 352MODULE_DESCRIPTION("VT8500 GPIO Driver");
 353MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
 354MODULE_LICENSE("GPL v2");
 355MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids);
 356
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.