linux/drivers/gpio/gpio-sch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * GPIO interface for Intel Poulsbo SCH
   4 *
   5 *  Copyright (c) 2010 CompuLab Ltd
   6 *  Author: Denis Turischev <denis@compulab.co.il>
   7 */
   8
   9#include <linux/acpi.h>
  10#include <linux/bitops.h>
  11#include <linux/errno.h>
  12#include <linux/gpio/driver.h>
  13#include <linux/io.h>
  14#include <linux/irq.h>
  15#include <linux/kernel.h>
  16#include <linux/module.h>
  17#include <linux/pci_ids.h>
  18#include <linux/platform_device.h>
  19#include <linux/types.h>
  20
  21#define GEN     0x00
  22#define GIO     0x04
  23#define GLV     0x08
  24#define GTPE    0x0c
  25#define GTNE    0x10
  26#define GGPE    0x14
  27#define GSMI    0x18
  28#define GTS     0x1c
  29
  30#define CORE_BANK_OFFSET        0x00
  31#define RESUME_BANK_OFFSET      0x20
  32
  33/*
  34 * iLB datasheet describes GPE0BLK registers, in particular GPE0E.GPIO bit.
  35 * Document Number: 328195-001
  36 */
  37#define GPE0E_GPIO      14
  38
  39struct sch_gpio {
  40        struct gpio_chip chip;
  41        struct irq_chip irqchip;
  42        spinlock_t lock;
  43        unsigned short iobase;
  44        unsigned short resume_base;
  45
  46        /* GPE handling */
  47        u32 gpe;
  48        acpi_gpe_handler gpe_handler;
  49};
  50
  51static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio,
  52                                unsigned int reg)
  53{
  54        unsigned int base = CORE_BANK_OFFSET;
  55
  56        if (gpio >= sch->resume_base) {
  57                gpio -= sch->resume_base;
  58                base = RESUME_BANK_OFFSET;
  59        }
  60
  61        return base + reg + gpio / 8;
  62}
  63
  64static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio)
  65{
  66        if (gpio >= sch->resume_base)
  67                gpio -= sch->resume_base;
  68        return gpio % 8;
  69}
  70
  71static int sch_gpio_reg_get(struct sch_gpio *sch, unsigned int gpio, unsigned int reg)
  72{
  73        unsigned short offset, bit;
  74        u8 reg_val;
  75
  76        offset = sch_gpio_offset(sch, gpio, reg);
  77        bit = sch_gpio_bit(sch, gpio);
  78
  79        reg_val = !!(inb(sch->iobase + offset) & BIT(bit));
  80
  81        return reg_val;
  82}
  83
  84static void sch_gpio_reg_set(struct sch_gpio *sch, unsigned int gpio, unsigned int reg,
  85                             int val)
  86{
  87        unsigned short offset, bit;
  88        u8 reg_val;
  89
  90        offset = sch_gpio_offset(sch, gpio, reg);
  91        bit = sch_gpio_bit(sch, gpio);
  92
  93        reg_val = inb(sch->iobase + offset);
  94
  95        if (val)
  96                outb(reg_val | BIT(bit), sch->iobase + offset);
  97        else
  98                outb((reg_val & ~BIT(bit)), sch->iobase + offset);
  99}
 100
 101static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
 102{
 103        struct sch_gpio *sch = gpiochip_get_data(gc);
 104        unsigned long flags;
 105
 106        spin_lock_irqsave(&sch->lock, flags);
 107        sch_gpio_reg_set(sch, gpio_num, GIO, 1);
 108        spin_unlock_irqrestore(&sch->lock, flags);
 109        return 0;
 110}
 111
 112static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num)
 113{
 114        struct sch_gpio *sch = gpiochip_get_data(gc);
 115
 116        return sch_gpio_reg_get(sch, gpio_num, GLV);
 117}
 118
 119static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
 120{
 121        struct sch_gpio *sch = gpiochip_get_data(gc);
 122        unsigned long flags;
 123
 124        spin_lock_irqsave(&sch->lock, flags);
 125        sch_gpio_reg_set(sch, gpio_num, GLV, val);
 126        spin_unlock_irqrestore(&sch->lock, flags);
 127}
 128
 129static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
 130                                  int val)
 131{
 132        struct sch_gpio *sch = gpiochip_get_data(gc);
 133        unsigned long flags;
 134
 135        spin_lock_irqsave(&sch->lock, flags);
 136        sch_gpio_reg_set(sch, gpio_num, GIO, 0);
 137        spin_unlock_irqrestore(&sch->lock, flags);
 138
 139        /*
 140         * according to the datasheet, writing to the level register has no
 141         * effect when GPIO is programmed as input.
 142         * Actually the the level register is read-only when configured as input.
 143         * Thus presetting the output level before switching to output is _NOT_ possible.
 144         * Hence we set the level after configuring the GPIO as output.
 145         * But we cannot prevent a short low pulse if direction is set to high
 146         * and an external pull-up is connected.
 147         */
 148        sch_gpio_set(gc, gpio_num, val);
 149        return 0;
 150}
 151
 152static int sch_gpio_get_direction(struct gpio_chip *gc, unsigned int gpio_num)
 153{
 154        struct sch_gpio *sch = gpiochip_get_data(gc);
 155
 156        if (sch_gpio_reg_get(sch, gpio_num, GIO))
 157                return GPIO_LINE_DIRECTION_IN;
 158
 159        return GPIO_LINE_DIRECTION_OUT;
 160}
 161
 162static const struct gpio_chip sch_gpio_chip = {
 163        .label                  = "sch_gpio",
 164        .owner                  = THIS_MODULE,
 165        .direction_input        = sch_gpio_direction_in,
 166        .get                    = sch_gpio_get,
 167        .direction_output       = sch_gpio_direction_out,
 168        .set                    = sch_gpio_set,
 169        .get_direction          = sch_gpio_get_direction,
 170};
 171
 172static int sch_irq_type(struct irq_data *d, unsigned int type)
 173{
 174        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 175        struct sch_gpio *sch = gpiochip_get_data(gc);
 176        irq_hw_number_t gpio_num = irqd_to_hwirq(d);
 177        unsigned long flags;
 178        int rising, falling;
 179
 180        switch (type & IRQ_TYPE_SENSE_MASK) {
 181        case IRQ_TYPE_EDGE_RISING:
 182                rising = 1;
 183                falling = 0;
 184                break;
 185        case IRQ_TYPE_EDGE_FALLING:
 186                rising = 0;
 187                falling = 1;
 188                break;
 189        case IRQ_TYPE_EDGE_BOTH:
 190                rising = 1;
 191                falling = 1;
 192                break;
 193        default:
 194                return -EINVAL;
 195        }
 196
 197        spin_lock_irqsave(&sch->lock, flags);
 198
 199        sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
 200        sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
 201
 202        irq_set_handler_locked(d, handle_edge_irq);
 203
 204        spin_unlock_irqrestore(&sch->lock, flags);
 205
 206        return 0;
 207}
 208
 209static void sch_irq_ack(struct irq_data *d)
 210{
 211        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 212        struct sch_gpio *sch = gpiochip_get_data(gc);
 213        irq_hw_number_t gpio_num = irqd_to_hwirq(d);
 214        unsigned long flags;
 215
 216        spin_lock_irqsave(&sch->lock, flags);
 217        sch_gpio_reg_set(sch, gpio_num, GTS, 1);
 218        spin_unlock_irqrestore(&sch->lock, flags);
 219}
 220
 221static void sch_irq_mask_unmask(struct irq_data *d, int val)
 222{
 223        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 224        struct sch_gpio *sch = gpiochip_get_data(gc);
 225        irq_hw_number_t gpio_num = irqd_to_hwirq(d);
 226        unsigned long flags;
 227
 228        spin_lock_irqsave(&sch->lock, flags);
 229        sch_gpio_reg_set(sch, gpio_num, GGPE, val);
 230        spin_unlock_irqrestore(&sch->lock, flags);
 231}
 232
 233static void sch_irq_mask(struct irq_data *d)
 234{
 235        sch_irq_mask_unmask(d, 0);
 236}
 237
 238static void sch_irq_unmask(struct irq_data *d)
 239{
 240        sch_irq_mask_unmask(d, 1);
 241}
 242
 243static u32 sch_gpio_gpe_handler(acpi_handle gpe_device, u32 gpe, void *context)
 244{
 245        struct sch_gpio *sch = context;
 246        struct gpio_chip *gc = &sch->chip;
 247        unsigned long core_status, resume_status;
 248        unsigned long pending;
 249        unsigned long flags;
 250        int offset;
 251        u32 ret;
 252
 253        spin_lock_irqsave(&sch->lock, flags);
 254
 255        core_status = inl(sch->iobase + CORE_BANK_OFFSET + GTS);
 256        resume_status = inl(sch->iobase + RESUME_BANK_OFFSET + GTS);
 257
 258        spin_unlock_irqrestore(&sch->lock, flags);
 259
 260        pending = (resume_status << sch->resume_base) | core_status;
 261        for_each_set_bit(offset, &pending, sch->chip.ngpio)
 262                generic_handle_irq(irq_find_mapping(gc->irq.domain, offset));
 263
 264        /* Set returning value depending on whether we handled an interrupt */
 265        ret = pending ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED;
 266
 267        /* Acknowledge GPE to ACPICA */
 268        ret |= ACPI_REENABLE_GPE;
 269
 270        return ret;
 271}
 272
 273static void sch_gpio_remove_gpe_handler(void *data)
 274{
 275        struct sch_gpio *sch = data;
 276
 277        acpi_disable_gpe(NULL, sch->gpe);
 278        acpi_remove_gpe_handler(NULL, sch->gpe, sch->gpe_handler);
 279}
 280
 281static int sch_gpio_install_gpe_handler(struct sch_gpio *sch)
 282{
 283        struct device *dev = sch->chip.parent;
 284        acpi_status status;
 285
 286        status = acpi_install_gpe_handler(NULL, sch->gpe, ACPI_GPE_LEVEL_TRIGGERED,
 287                                          sch->gpe_handler, sch);
 288        if (ACPI_FAILURE(status)) {
 289                dev_err(dev, "Failed to install GPE handler for %u: %s\n",
 290                        sch->gpe, acpi_format_exception(status));
 291                return -ENODEV;
 292        }
 293
 294        status = acpi_enable_gpe(NULL, sch->gpe);
 295        if (ACPI_FAILURE(status)) {
 296                dev_err(dev, "Failed to enable GPE handler for %u: %s\n",
 297                        sch->gpe, acpi_format_exception(status));
 298                acpi_remove_gpe_handler(NULL, sch->gpe, sch->gpe_handler);
 299                return -ENODEV;
 300        }
 301
 302        return devm_add_action_or_reset(dev, sch_gpio_remove_gpe_handler, sch);
 303}
 304
 305static int sch_gpio_probe(struct platform_device *pdev)
 306{
 307        struct gpio_irq_chip *girq;
 308        struct sch_gpio *sch;
 309        struct resource *res;
 310        int ret;
 311
 312        sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
 313        if (!sch)
 314                return -ENOMEM;
 315
 316        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 317        if (!res)
 318                return -EBUSY;
 319
 320        if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
 321                                 pdev->name))
 322                return -EBUSY;
 323
 324        spin_lock_init(&sch->lock);
 325        sch->iobase = res->start;
 326        sch->chip = sch_gpio_chip;
 327        sch->chip.label = dev_name(&pdev->dev);
 328        sch->chip.parent = &pdev->dev;
 329
 330        switch (pdev->id) {
 331        case PCI_DEVICE_ID_INTEL_SCH_LPC:
 332                sch->resume_base = 10;
 333                sch->chip.ngpio = 14;
 334
 335                /*
 336                 * GPIO[6:0] enabled by default
 337                 * GPIO7 is configured by the CMC as SLPIOVR
 338                 * Enable GPIO[9:8] core powered gpios explicitly
 339                 */
 340                sch_gpio_reg_set(sch, 8, GEN, 1);
 341                sch_gpio_reg_set(sch, 9, GEN, 1);
 342                /*
 343                 * SUS_GPIO[2:0] enabled by default
 344                 * Enable SUS_GPIO3 resume powered gpio explicitly
 345                 */
 346                sch_gpio_reg_set(sch, 13, GEN, 1);
 347                break;
 348
 349        case PCI_DEVICE_ID_INTEL_ITC_LPC:
 350                sch->resume_base = 5;
 351                sch->chip.ngpio = 14;
 352                break;
 353
 354        case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
 355                sch->resume_base = 21;
 356                sch->chip.ngpio = 30;
 357                break;
 358
 359        case PCI_DEVICE_ID_INTEL_QUARK_X1000_ILB:
 360                sch->resume_base = 2;
 361                sch->chip.ngpio = 8;
 362                break;
 363
 364        default:
 365                return -ENODEV;
 366        }
 367
 368        platform_set_drvdata(pdev, sch);
 369
 370        sch->irqchip.name = "sch_gpio";
 371        sch->irqchip.irq_ack = sch_irq_ack;
 372        sch->irqchip.irq_mask = sch_irq_mask;
 373        sch->irqchip.irq_unmask = sch_irq_unmask;
 374        sch->irqchip.irq_set_type = sch_irq_type;
 375
 376        girq = &sch->chip.irq;
 377        girq->chip = &sch->irqchip;
 378        girq->num_parents = 0;
 379        girq->parents = NULL;
 380        girq->parent_handler = NULL;
 381        girq->default_type = IRQ_TYPE_NONE;
 382        girq->handler = handle_bad_irq;
 383
 384        /* GPE setup is optional */
 385        sch->gpe = GPE0E_GPIO;
 386        sch->gpe_handler = sch_gpio_gpe_handler;
 387
 388        ret = sch_gpio_install_gpe_handler(sch);
 389        if (ret)
 390                dev_warn(&pdev->dev, "Can't setup GPE, no IRQ support\n");
 391
 392        return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
 393}
 394
 395static struct platform_driver sch_gpio_driver = {
 396        .driver = {
 397                .name = "sch_gpio",
 398        },
 399        .probe          = sch_gpio_probe,
 400};
 401
 402module_platform_driver(sch_gpio_driver);
 403
 404MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
 405MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
 406MODULE_LICENSE("GPL v2");
 407MODULE_ALIAS("platform:sch_gpio");
 408
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.