linux/drivers/gpio/gpio-menz127.c
<<
>>
Prefs
   1/*
   2 * MEN 16Z127 GPIO driver
   3 *
   4 * Copyright (C) 2016 MEN Mikroelektronik GmbH (www.men.de)
   5 *
   6 * This program is free software; you can redistribute it and/or modify it
   7 * under the terms of the GNU General Public License as published by the Free
   8 * Software Foundation; version 2 of the License.
   9 */
  10
  11#include <linux/kernel.h>
  12#include <linux/module.h>
  13#include <linux/io.h>
  14#include <linux/err.h>
  15#include <linux/mcb.h>
  16#include <linux/bitops.h>
  17#include <linux/gpio/driver.h>
  18
  19#define MEN_Z127_CTRL   0x00
  20#define MEN_Z127_PSR    0x04
  21#define MEN_Z127_IRQR   0x08
  22#define MEN_Z127_GPIODR 0x0c
  23#define MEN_Z127_IER1   0x10
  24#define MEN_Z127_IER2   0x14
  25#define MEN_Z127_DBER   0x18
  26#define MEN_Z127_ODER   0x1C
  27#define GPIO_TO_DBCNT_REG(gpio) ((gpio * 4) + 0x80)
  28
  29#define MEN_Z127_DB_MIN_US      50
  30/* 16 bit compare register. Each bit represents 50us */
  31#define MEN_Z127_DB_MAX_US      (0xffff * MEN_Z127_DB_MIN_US)
  32#define MEN_Z127_DB_IN_RANGE(db)        ((db >= MEN_Z127_DB_MIN_US) && \
  33                                         (db <= MEN_Z127_DB_MAX_US))
  34
  35struct men_z127_gpio {
  36        struct gpio_chip gc;
  37        void __iomem *reg_base;
  38        struct resource *mem;
  39};
  40
  41static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio,
  42                             unsigned debounce)
  43{
  44        struct men_z127_gpio *priv = gpiochip_get_data(gc);
  45        struct device *dev = gc->parent;
  46        unsigned int rnd;
  47        u32 db_en, db_cnt;
  48
  49        if (!MEN_Z127_DB_IN_RANGE(debounce)) {
  50                dev_err(dev, "debounce value %u out of range", debounce);
  51                return -EINVAL;
  52        }
  53
  54        if (debounce > 0) {
  55                /* round up or down depending on MSB-1 */
  56                rnd = fls(debounce) - 1;
  57
  58                if (rnd && (debounce & BIT(rnd - 1)))
  59                        debounce = round_up(debounce, MEN_Z127_DB_MIN_US);
  60                else
  61                        debounce = round_down(debounce, MEN_Z127_DB_MIN_US);
  62
  63                if (debounce > MEN_Z127_DB_MAX_US)
  64                        debounce = MEN_Z127_DB_MAX_US;
  65
  66                /* 50us per register unit */
  67                debounce /= 50;
  68        }
  69
  70        spin_lock(&gc->bgpio_lock);
  71
  72        db_en = readl(priv->reg_base + MEN_Z127_DBER);
  73
  74        if (debounce == 0) {
  75                db_en &= ~BIT(gpio);
  76                db_cnt = 0;
  77        } else {
  78                db_en |= BIT(gpio);
  79                db_cnt = debounce;
  80        }
  81
  82        writel(db_en, priv->reg_base + MEN_Z127_DBER);
  83        writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio));
  84
  85        spin_unlock(&gc->bgpio_lock);
  86
  87        return 0;
  88}
  89
  90static int men_z127_set_single_ended(struct gpio_chip *gc,
  91                                     unsigned offset,
  92                                     enum pin_config_param param)
  93{
  94        struct men_z127_gpio *priv = gpiochip_get_data(gc);
  95        u32 od_en;
  96
  97        spin_lock(&gc->bgpio_lock);
  98        od_en = readl(priv->reg_base + MEN_Z127_ODER);
  99
 100        if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN)
 101                od_en |= BIT(offset);
 102        else
 103                /* Implicitly PIN_CONFIG_DRIVE_PUSH_PULL */
 104                od_en &= ~BIT(offset);
 105
 106        writel(od_en, priv->reg_base + MEN_Z127_ODER);
 107        spin_unlock(&gc->bgpio_lock);
 108
 109        return 0;
 110}
 111
 112static int men_z127_set_config(struct gpio_chip *gc, unsigned offset,
 113                               unsigned long config)
 114{
 115        enum pin_config_param param = pinconf_to_config_param(config);
 116
 117        switch (param) {
 118        case PIN_CONFIG_DRIVE_OPEN_DRAIN:
 119        case PIN_CONFIG_DRIVE_PUSH_PULL:
 120                return men_z127_set_single_ended(gc, offset, param);
 121
 122        case PIN_CONFIG_INPUT_DEBOUNCE:
 123                return men_z127_debounce(gc, offset,
 124                        pinconf_to_config_argument(config));
 125
 126        default:
 127                break;
 128        }
 129
 130        return -ENOTSUPP;
 131}
 132
 133static int men_z127_probe(struct mcb_device *mdev,
 134                          const struct mcb_device_id *id)
 135{
 136        struct men_z127_gpio *men_z127_gpio;
 137        struct device *dev = &mdev->dev;
 138        int ret;
 139
 140        men_z127_gpio = devm_kzalloc(dev, sizeof(struct men_z127_gpio),
 141                                     GFP_KERNEL);
 142        if (!men_z127_gpio)
 143                return -ENOMEM;
 144
 145        men_z127_gpio->mem = mcb_request_mem(mdev, dev_name(dev));
 146        if (IS_ERR(men_z127_gpio->mem)) {
 147                dev_err(dev, "failed to request device memory");
 148                return PTR_ERR(men_z127_gpio->mem);
 149        }
 150
 151        men_z127_gpio->reg_base = ioremap(men_z127_gpio->mem->start,
 152                                          resource_size(men_z127_gpio->mem));
 153        if (men_z127_gpio->reg_base == NULL) {
 154                ret = -ENXIO;
 155                goto err_release;
 156        }
 157
 158        mcb_set_drvdata(mdev, men_z127_gpio);
 159
 160        ret = bgpio_init(&men_z127_gpio->gc, &mdev->dev, 4,
 161                         men_z127_gpio->reg_base + MEN_Z127_PSR,
 162                         men_z127_gpio->reg_base + MEN_Z127_CTRL,
 163                         NULL,
 164                         men_z127_gpio->reg_base + MEN_Z127_GPIODR,
 165                         NULL, 0);
 166        if (ret)
 167                goto err_unmap;
 168
 169        men_z127_gpio->gc.set_config = men_z127_set_config;
 170
 171        ret = gpiochip_add_data(&men_z127_gpio->gc, men_z127_gpio);
 172        if (ret) {
 173                dev_err(dev, "failed to register MEN 16Z127 GPIO controller");
 174                goto err_unmap;
 175        }
 176
 177        dev_info(dev, "MEN 16Z127 GPIO driver registered");
 178
 179        return 0;
 180
 181err_unmap:
 182        iounmap(men_z127_gpio->reg_base);
 183err_release:
 184        mcb_release_mem(men_z127_gpio->mem);
 185        return ret;
 186}
 187
 188static void men_z127_remove(struct mcb_device *mdev)
 189{
 190        struct men_z127_gpio *men_z127_gpio = mcb_get_drvdata(mdev);
 191
 192        gpiochip_remove(&men_z127_gpio->gc);
 193        iounmap(men_z127_gpio->reg_base);
 194        mcb_release_mem(men_z127_gpio->mem);
 195}
 196
 197static const struct mcb_device_id men_z127_ids[] = {
 198        { .device = 0x7f },
 199        { }
 200};
 201MODULE_DEVICE_TABLE(mcb, men_z127_ids);
 202
 203static struct mcb_driver men_z127_driver = {
 204        .driver = {
 205                .name = "z127-gpio",
 206        },
 207        .probe = men_z127_probe,
 208        .remove = men_z127_remove,
 209        .id_table = men_z127_ids,
 210};
 211module_mcb_driver(men_z127_driver);
 212
 213MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
 214MODULE_DESCRIPTION("MEN 16z127 GPIO Controller");
 215MODULE_LICENSE("GPL v2");
 216MODULE_ALIAS("mcb:16z127");
 217