linux/drivers/gpio/gpio-adnp.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2011-2012 Avionic Design GmbH
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License version 2 as
   6 * published by the Free Software Foundation.
   7 */
   8
   9#include <linux/gpio/driver.h>
  10#include <linux/i2c.h>
  11#include <linux/interrupt.h>
  12#include <linux/module.h>
  13#include <linux/of_irq.h>
  14#include <linux/seq_file.h>
  15#include <linux/slab.h>
  16
  17#define GPIO_DDR(gpio) (0x00 << (gpio)->reg_shift)
  18#define GPIO_PLR(gpio) (0x01 << (gpio)->reg_shift)
  19#define GPIO_IER(gpio) (0x02 << (gpio)->reg_shift)
  20#define GPIO_ISR(gpio) (0x03 << (gpio)->reg_shift)
  21#define GPIO_PTR(gpio) (0x04 << (gpio)->reg_shift)
  22
  23struct adnp {
  24        struct i2c_client *client;
  25        struct gpio_chip gpio;
  26        unsigned int reg_shift;
  27
  28        struct mutex i2c_lock;
  29        struct mutex irq_lock;
  30
  31        u8 *irq_enable;
  32        u8 *irq_level;
  33        u8 *irq_rise;
  34        u8 *irq_fall;
  35        u8 *irq_high;
  36        u8 *irq_low;
  37};
  38
  39static int adnp_read(struct adnp *adnp, unsigned offset, uint8_t *value)
  40{
  41        int err;
  42
  43        err = i2c_smbus_read_byte_data(adnp->client, offset);
  44        if (err < 0) {
  45                dev_err(adnp->gpio.parent, "%s failed: %d\n",
  46                        "i2c_smbus_read_byte_data()", err);
  47                return err;
  48        }
  49
  50        *value = err;
  51        return 0;
  52}
  53
  54static int adnp_write(struct adnp *adnp, unsigned offset, uint8_t value)
  55{
  56        int err;
  57
  58        err = i2c_smbus_write_byte_data(adnp->client, offset, value);
  59        if (err < 0) {
  60                dev_err(adnp->gpio.parent, "%s failed: %d\n",
  61                        "i2c_smbus_write_byte_data()", err);
  62                return err;
  63        }
  64
  65        return 0;
  66}
  67
  68static int adnp_gpio_get(struct gpio_chip *chip, unsigned offset)
  69{
  70        struct adnp *adnp = gpiochip_get_data(chip);
  71        unsigned int reg = offset >> adnp->reg_shift;
  72        unsigned int pos = offset & 7;
  73        u8 value;
  74        int err;
  75
  76        err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &value);
  77        if (err < 0)
  78                return err;
  79
  80        return (value & BIT(pos)) ? 1 : 0;
  81}
  82
  83static void __adnp_gpio_set(struct adnp *adnp, unsigned offset, int value)
  84{
  85        unsigned int reg = offset >> adnp->reg_shift;
  86        unsigned int pos = offset & 7;
  87        int err;
  88        u8 val;
  89
  90        err = adnp_read(adnp, GPIO_PLR(adnp) + reg, &val);
  91        if (err < 0)
  92                return;
  93
  94        if (value)
  95                val |= BIT(pos);
  96        else
  97                val &= ~BIT(pos);
  98
  99        adnp_write(adnp, GPIO_PLR(adnp) + reg, val);
 100}
 101
 102static void adnp_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 103{
 104        struct adnp *adnp = gpiochip_get_data(chip);
 105
 106        mutex_lock(&adnp->i2c_lock);
 107        __adnp_gpio_set(adnp, offset, value);
 108        mutex_unlock(&adnp->i2c_lock);
 109}
 110
 111static int adnp_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 112{
 113        struct adnp *adnp = gpiochip_get_data(chip);
 114        unsigned int reg = offset >> adnp->reg_shift;
 115        unsigned int pos = offset & 7;
 116        u8 value;
 117        int err;
 118
 119        mutex_lock(&adnp->i2c_lock);
 120
 121        err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
 122        if (err < 0)
 123                goto out;
 124
 125        value &= ~BIT(pos);
 126
 127        err = adnp_write(adnp, GPIO_DDR(adnp) + reg, value);
 128        if (err < 0)
 129                goto out;
 130
 131        err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &value);
 132        if (err < 0)
 133                goto out;
 134
 135        if (err & BIT(pos))
 136                err = -EACCES;
 137
 138        err = 0;
 139
 140out:
 141        mutex_unlock(&adnp->i2c_lock);
 142        return err;
 143}
 144
 145static int adnp_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
 146                                      int value)
 147{
 148        struct adnp *adnp = gpiochip_get_data(chip);
 149        unsigned int reg = offset >> adnp->reg_shift;
 150        unsigned int pos = offset & 7;
 151        int err;
 152        u8 val;
 153
 154        mutex_lock(&adnp->i2c_lock);
 155
 156        err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
 157        if (err < 0)
 158                goto out;
 159
 160        val |= BIT(pos);
 161
 162        err = adnp_write(adnp, GPIO_DDR(adnp) + reg, val);
 163        if (err < 0)
 164                goto out;
 165
 166        err = adnp_read(adnp, GPIO_DDR(adnp) + reg, &val);
 167        if (err < 0)
 168                goto out;
 169
 170        if (!(val & BIT(pos))) {
 171                err = -EPERM;
 172                goto out;
 173        }
 174
 175        __adnp_gpio_set(adnp, offset, value);
 176        err = 0;
 177
 178out:
 179        mutex_unlock(&adnp->i2c_lock);
 180        return err;
 181}
 182
 183static void adnp_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 184{
 185        struct adnp *adnp = gpiochip_get_data(chip);
 186        unsigned int num_regs = 1 << adnp->reg_shift, i, j;
 187        int err;
 188
 189        for (i = 0; i < num_regs; i++) {
 190                u8 ddr, plr, ier, isr;
 191
 192                mutex_lock(&adnp->i2c_lock);
 193
 194                err = adnp_read(adnp, GPIO_DDR(adnp) + i, &ddr);
 195                if (err < 0)
 196                        goto unlock;
 197
 198                err = adnp_read(adnp, GPIO_PLR(adnp) + i, &plr);
 199                if (err < 0)
 200                        goto unlock;
 201
 202                err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
 203                if (err < 0)
 204                        goto unlock;
 205
 206                err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
 207                if (err < 0)
 208                        goto unlock;
 209
 210                mutex_unlock(&adnp->i2c_lock);
 211
 212                for (j = 0; j < 8; j++) {
 213                        unsigned int bit = (i << adnp->reg_shift) + j;
 214                        const char *direction = "input ";
 215                        const char *level = "low ";
 216                        const char *interrupt = "disabled";
 217                        const char *pending = "";
 218
 219                        if (ddr & BIT(j))
 220                                direction = "output";
 221
 222                        if (plr & BIT(j))
 223                                level = "high";
 224
 225                        if (ier & BIT(j))
 226                                interrupt = "enabled ";
 227
 228                        if (isr & BIT(j))
 229                                pending = "pending";
 230
 231                        seq_printf(s, "%2u: %s %s IRQ %s %s\n", bit,
 232                                   direction, level, interrupt, pending);
 233                }
 234        }
 235
 236        return;
 237
 238unlock:
 239        mutex_unlock(&adnp->i2c_lock);
 240}
 241
 242static int adnp_gpio_setup(struct adnp *adnp, unsigned int num_gpios)
 243{
 244        struct gpio_chip *chip = &adnp->gpio;
 245        int err;
 246
 247        adnp->reg_shift = get_count_order(num_gpios) - 3;
 248
 249        chip->direction_input = adnp_gpio_direction_input;
 250        chip->direction_output = adnp_gpio_direction_output;
 251        chip->get = adnp_gpio_get;
 252        chip->set = adnp_gpio_set;
 253        chip->can_sleep = true;
 254
 255        if (IS_ENABLED(CONFIG_DEBUG_FS))
 256                chip->dbg_show = adnp_gpio_dbg_show;
 257
 258        chip->base = -1;
 259        chip->ngpio = num_gpios;
 260        chip->label = adnp->client->name;
 261        chip->parent = &adnp->client->dev;
 262        chip->of_node = chip->parent->of_node;
 263        chip->owner = THIS_MODULE;
 264
 265        err = devm_gpiochip_add_data(&adnp->client->dev, chip, adnp);
 266        if (err)
 267                return err;
 268
 269        return 0;
 270}
 271
 272static irqreturn_t adnp_irq(int irq, void *data)
 273{
 274        struct adnp *adnp = data;
 275        unsigned int num_regs, i;
 276
 277        num_regs = 1 << adnp->reg_shift;
 278
 279        for (i = 0; i < num_regs; i++) {
 280                unsigned int base = i << adnp->reg_shift, bit;
 281                u8 changed, level, isr, ier;
 282                unsigned long pending;
 283                int err;
 284
 285                mutex_lock(&adnp->i2c_lock);
 286
 287                err = adnp_read(adnp, GPIO_PLR(adnp) + i, &level);
 288                if (err < 0) {
 289                        mutex_unlock(&adnp->i2c_lock);
 290                        continue;
 291                }
 292
 293                err = adnp_read(adnp, GPIO_ISR(adnp) + i, &isr);
 294                if (err < 0) {
 295                        mutex_unlock(&adnp->i2c_lock);
 296                        continue;
 297                }
 298
 299                err = adnp_read(adnp, GPIO_IER(adnp) + i, &ier);
 300                if (err < 0) {
 301                        mutex_unlock(&adnp->i2c_lock);
 302                        continue;
 303                }
 304
 305                mutex_unlock(&adnp->i2c_lock);
 306
 307                /* determine pins that changed levels */
 308                changed = level ^ adnp->irq_level[i];
 309
 310                /* compute edge-triggered interrupts */
 311                pending = changed & ((adnp->irq_fall[i] & ~level) |
 312                                     (adnp->irq_rise[i] & level));
 313
 314                /* add in level-triggered interrupts */
 315                pending |= (adnp->irq_high[i] & level) |
 316                           (adnp->irq_low[i] & ~level);
 317
 318                /* mask out non-pending and disabled interrupts */
 319                pending &= isr & ier;
 320
 321                for_each_set_bit(bit, &pending, 8) {
 322                        unsigned int child_irq;
 323                        child_irq = irq_find_mapping(adnp->gpio.irq.domain,
 324                                                     base + bit);
 325                        handle_nested_irq(child_irq);
 326                }
 327        }
 328
 329        return IRQ_HANDLED;
 330}
 331
 332static void adnp_irq_mask(struct irq_data *d)
 333{
 334        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 335        struct adnp *adnp = gpiochip_get_data(gc);
 336        unsigned int reg = d->hwirq >> adnp->reg_shift;
 337        unsigned int pos = d->hwirq & 7;
 338
 339        adnp->irq_enable[reg] &= ~BIT(pos);
 340}
 341
 342static void adnp_irq_unmask(struct irq_data *d)
 343{
 344        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 345        struct adnp *adnp = gpiochip_get_data(gc);
 346        unsigned int reg = d->hwirq >> adnp->reg_shift;
 347        unsigned int pos = d->hwirq & 7;
 348
 349        adnp->irq_enable[reg] |= BIT(pos);
 350}
 351
 352static int adnp_irq_set_type(struct irq_data *d, unsigned int type)
 353{
 354        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 355        struct adnp *adnp = gpiochip_get_data(gc);
 356        unsigned int reg = d->hwirq >> adnp->reg_shift;
 357        unsigned int pos = d->hwirq & 7;
 358
 359        if (type & IRQ_TYPE_EDGE_RISING)
 360                adnp->irq_rise[reg] |= BIT(pos);
 361        else
 362                adnp->irq_rise[reg] &= ~BIT(pos);
 363
 364        if (type & IRQ_TYPE_EDGE_FALLING)
 365                adnp->irq_fall[reg] |= BIT(pos);
 366        else
 367                adnp->irq_fall[reg] &= ~BIT(pos);
 368
 369        if (type & IRQ_TYPE_LEVEL_HIGH)
 370                adnp->irq_high[reg] |= BIT(pos);
 371        else
 372                adnp->irq_high[reg] &= ~BIT(pos);
 373
 374        if (type & IRQ_TYPE_LEVEL_LOW)
 375                adnp->irq_low[reg] |= BIT(pos);
 376        else
 377                adnp->irq_low[reg] &= ~BIT(pos);
 378
 379        return 0;
 380}
 381
 382static void adnp_irq_bus_lock(struct irq_data *d)
 383{
 384        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 385        struct adnp *adnp = gpiochip_get_data(gc);
 386
 387        mutex_lock(&adnp->irq_lock);
 388}
 389
 390static void adnp_irq_bus_unlock(struct irq_data *d)
 391{
 392        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 393        struct adnp *adnp = gpiochip_get_data(gc);
 394        unsigned int num_regs = 1 << adnp->reg_shift, i;
 395
 396        mutex_lock(&adnp->i2c_lock);
 397
 398        for (i = 0; i < num_regs; i++)
 399                adnp_write(adnp, GPIO_IER(adnp) + i, adnp->irq_enable[i]);
 400
 401        mutex_unlock(&adnp->i2c_lock);
 402        mutex_unlock(&adnp->irq_lock);
 403}
 404
 405static struct irq_chip adnp_irq_chip = {
 406        .name = "gpio-adnp",
 407        .irq_mask = adnp_irq_mask,
 408        .irq_unmask = adnp_irq_unmask,
 409        .irq_set_type = adnp_irq_set_type,
 410        .irq_bus_lock = adnp_irq_bus_lock,
 411        .irq_bus_sync_unlock = adnp_irq_bus_unlock,
 412};
 413
 414static int adnp_irq_setup(struct adnp *adnp)
 415{
 416        unsigned int num_regs = 1 << adnp->reg_shift, i;
 417        struct gpio_chip *chip = &adnp->gpio;
 418        int err;
 419
 420        mutex_init(&adnp->irq_lock);
 421
 422        /*
 423         * Allocate memory to keep track of the current level and trigger
 424         * modes of the interrupts. To avoid multiple allocations, a single
 425         * large buffer is allocated and pointers are setup to point at the
 426         * corresponding offsets. For consistency, the layout of the buffer
 427         * is chosen to match the register layout of the hardware in that
 428         * each segment contains the corresponding bits for all interrupts.
 429         */
 430        adnp->irq_enable = devm_kzalloc(chip->parent, num_regs * 6,
 431                                        GFP_KERNEL);
 432        if (!adnp->irq_enable)
 433                return -ENOMEM;
 434
 435        adnp->irq_level = adnp->irq_enable + (num_regs * 1);
 436        adnp->irq_rise = adnp->irq_enable + (num_regs * 2);
 437        adnp->irq_fall = adnp->irq_enable + (num_regs * 3);
 438        adnp->irq_high = adnp->irq_enable + (num_regs * 4);
 439        adnp->irq_low = adnp->irq_enable + (num_regs * 5);
 440
 441        for (i = 0; i < num_regs; i++) {
 442                /*
 443                 * Read the initial level of all pins to allow the emulation
 444                 * of edge triggered interrupts.
 445                 */
 446                err = adnp_read(adnp, GPIO_PLR(adnp) + i, &adnp->irq_level[i]);
 447                if (err < 0)
 448                        return err;
 449
 450                /* disable all interrupts */
 451                err = adnp_write(adnp, GPIO_IER(adnp) + i, 0);
 452                if (err < 0)
 453                        return err;
 454
 455                adnp->irq_enable[i] = 0x00;
 456        }
 457
 458        err = devm_request_threaded_irq(chip->parent, adnp->client->irq,
 459                                        NULL, adnp_irq,
 460                                        IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 461                                        dev_name(chip->parent), adnp);
 462        if (err != 0) {
 463                dev_err(chip->parent, "can't request IRQ#%d: %d\n",
 464                        adnp->client->irq, err);
 465                return err;
 466        }
 467
 468        err = gpiochip_irqchip_add_nested(chip,
 469                                          &adnp_irq_chip,
 470                                          0,
 471                                          handle_simple_irq,
 472                                          IRQ_TYPE_NONE);
 473        if (err) {
 474                dev_err(chip->parent,
 475                        "could not connect irqchip to gpiochip\n");
 476                return err;
 477        }
 478
 479        gpiochip_set_nested_irqchip(chip, &adnp_irq_chip, adnp->client->irq);
 480
 481        return 0;
 482}
 483
 484static int adnp_i2c_probe(struct i2c_client *client,
 485                                    const struct i2c_device_id *id)
 486{
 487        struct device_node *np = client->dev.of_node;
 488        struct adnp *adnp;
 489        u32 num_gpios;
 490        int err;
 491
 492        err = of_property_read_u32(np, "nr-gpios", &num_gpios);
 493        if (err < 0)
 494                return err;
 495
 496        client->irq = irq_of_parse_and_map(np, 0);
 497        if (!client->irq)
 498                return -EPROBE_DEFER;
 499
 500        adnp = devm_kzalloc(&client->dev, sizeof(*adnp), GFP_KERNEL);
 501        if (!adnp)
 502                return -ENOMEM;
 503
 504        mutex_init(&adnp->i2c_lock);
 505        adnp->client = client;
 506
 507        err = adnp_gpio_setup(adnp, num_gpios);
 508        if (err)
 509                return err;
 510
 511        if (of_find_property(np, "interrupt-controller", NULL)) {
 512                err = adnp_irq_setup(adnp);
 513                if (err)
 514                        return err;
 515        }
 516
 517        i2c_set_clientdata(client, adnp);
 518
 519        return 0;
 520}
 521
 522static const struct i2c_device_id adnp_i2c_id[] = {
 523        { "gpio-adnp" },
 524        { },
 525};
 526MODULE_DEVICE_TABLE(i2c, adnp_i2c_id);
 527
 528static const struct of_device_id adnp_of_match[] = {
 529        { .compatible = "ad,gpio-adnp", },
 530        { },
 531};
 532MODULE_DEVICE_TABLE(of, adnp_of_match);
 533
 534static struct i2c_driver adnp_i2c_driver = {
 535        .driver = {
 536                .name = "gpio-adnp",
 537                .of_match_table = adnp_of_match,
 538        },
 539        .probe = adnp_i2c_probe,
 540        .id_table = adnp_i2c_id,
 541};
 542module_i2c_driver(adnp_i2c_driver);
 543
 544MODULE_DESCRIPTION("Avionic Design N-bit GPIO expander");
 545MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
 546MODULE_LICENSE("GPL");
 547