diff options
Diffstat (limited to 'drivers/pinctrl/pinctrl-baytrail.c')
| -rw-r--r-- | drivers/pinctrl/pinctrl-baytrail.c | 543 |
1 files changed, 0 insertions, 543 deletions
diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c deleted file mode 100644 index e9d735dcebfb..000000000000 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Pinctrl GPIO driver for Intel Baytrail - * Copyright (c) 2012-2013, Intel Corporation. - * - * Author: Mathias Nyman <mathias.nyman@linux.intel.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/types.h> -#include <linux/bitops.h> -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <linux/gpio.h> -#include <linux/irqdomain.h> -#include <linux/acpi.h> -#include <linux/acpi_gpio.h> -#include <linux/platform_device.h> -#include <linux/seq_file.h> -#include <linux/io.h> -#include <linux/pm_runtime.h> -#include <linux/pinctrl/pinctrl.h> - -/* memory mapped register offsets */ -#define BYT_CONF0_REG 0x000 -#define BYT_CONF1_REG 0x004 -#define BYT_VAL_REG 0x008 -#define BYT_DFT_REG 0x00c -#define BYT_INT_STAT_REG 0x800 - -/* BYT_CONF0_REG register bits */ -#define BYT_TRIG_NEG BIT(26) -#define BYT_TRIG_POS BIT(25) -#define BYT_TRIG_LVL BIT(24) -#define BYT_PIN_MUX 0x07 - -/* BYT_VAL_REG register bits */ -#define BYT_INPUT_EN BIT(2) /* 0: input enabled (active low)*/ -#define BYT_OUTPUT_EN BIT(1) /* 0: output enabled (active low)*/ -#define BYT_LEVEL BIT(0) - -#define BYT_DIR_MASK (BIT(1) | BIT(2)) -#define BYT_TRIG_MASK (BIT(26) | BIT(25) | BIT(24)) - -#define BYT_NGPIO_SCORE 102 -#define BYT_NGPIO_NCORE 28 -#define BYT_NGPIO_SUS 44 - -/* - * Baytrail gpio controller consist of three separate sub-controllers called - * SCORE, NCORE and SUS. The sub-controllers are identified by their acpi UID. - * - * GPIO numbering is _not_ ordered meaning that gpio # 0 in ACPI namespace does - * _not_ correspond to the first gpio register at controller's gpio base. - * There is no logic or pattern in mapping gpio numbers to registers (pads) so - * each sub-controller needs to have its own mapping table - */ - -/* score_pins[gpio_nr] = pad_nr */ - -static unsigned const score_pins[BYT_NGPIO_SCORE] = { - 85, 89, 93, 96, 99, 102, 98, 101, 34, 37, - 36, 38, 39, 35, 40, 84, 62, 61, 64, 59, - 54, 56, 60, 55, 63, 57, 51, 50, 53, 47, - 52, 49, 48, 43, 46, 41, 45, 42, 58, 44, - 95, 105, 70, 68, 67, 66, 69, 71, 65, 72, - 86, 90, 88, 92, 103, 77, 79, 83, 78, 81, - 80, 82, 13, 12, 15, 14, 17, 18, 19, 16, - 2, 1, 0, 4, 6, 7, 9, 8, 33, 32, - 31, 30, 29, 27, 25, 28, 26, 23, 21, 20, - 24, 22, 5, 3, 10, 11, 106, 87, 91, 104, - 97, 100, -}; - -static unsigned const ncore_pins[BYT_NGPIO_NCORE] = { - 19, 18, 17, 20, 21, 22, 24, 25, 23, 16, - 14, 15, 12, 26, 27, 1, 4, 8, 11, 0, - 3, 6, 10, 13, 2, 5, 9, 7, -}; - -static unsigned const sus_pins[BYT_NGPIO_SUS] = { - 29, 33, 30, 31, 32, 34, 36, 35, 38, 37, - 18, 7, 11, 20, 17, 1, 8, 10, 19, 12, - 0, 2, 23, 39, 28, 27, 22, 21, 24, 25, - 26, 51, 56, 54, 49, 55, 48, 57, 50, 58, - 52, 53, 59, 40, -}; - -static struct pinctrl_gpio_range byt_ranges[] = { - { - .name = "1", /* match with acpi _UID in probe */ - .npins = BYT_NGPIO_SCORE, - .pins = score_pins, - }, - { - .name = "2", - .npins = BYT_NGPIO_NCORE, - .pins = ncore_pins, - }, - { - .name = "3", - .npins = BYT_NGPIO_SUS, - .pins = sus_pins, - }, - { - }, -}; - -struct byt_gpio { - struct gpio_chip chip; - struct irq_domain *domain; - struct platform_device *pdev; - spinlock_t lock; - void __iomem *reg_base; - struct pinctrl_gpio_range *range; -}; - -static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, - int reg) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - u32 reg_offset; - void __iomem *ptr; - - if (reg == BYT_INT_STAT_REG) - reg_offset = (offset / 32) * 4; - else - reg_offset = vg->range->pins[offset] * 16; - - ptr = (void __iomem *) (vg->reg_base + reg_offset + reg); - return ptr; -} - -static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - - pm_runtime_get(&vg->pdev->dev); - - return 0; -} - -static void byt_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); - u32 value; - - /* clear interrupt triggering */ - value = readl(reg); - value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); - writel(value, reg); - - pm_runtime_put(&vg->pdev->dev); -} - -static int byt_irq_type(struct irq_data *d, unsigned type) -{ - struct byt_gpio *vg = irq_data_get_irq_chip_data(d); - u32 offset = irqd_to_hwirq(d); - u32 value; - unsigned long flags; - void __iomem *reg = byt_gpio_reg(&vg->chip, offset, BYT_CONF0_REG); - - if (offset >= vg->chip.ngpio) - return -EINVAL; - - spin_lock_irqsave(&vg->lock, flags); - value = readl(reg); - - /* For level trigges the BYT_TRIG_POS and BYT_TRIG_NEG bits - * are used to indicate high and low level triggering - */ - value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL); - - switch (type) { - case IRQ_TYPE_LEVEL_HIGH: - value |= BYT_TRIG_LVL; - case IRQ_TYPE_EDGE_RISING: - value |= BYT_TRIG_POS; - break; - case IRQ_TYPE_LEVEL_LOW: - value |= BYT_TRIG_LVL; - case IRQ_TYPE_EDGE_FALLING: - value |= BYT_TRIG_NEG; - break; - case IRQ_TYPE_EDGE_BOTH: - value |= (BYT_TRIG_NEG | BYT_TRIG_POS); - break; - } - writel(value, reg); - - spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - -static int byt_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); - return readl(reg) & BYT_LEVEL; -} - -static void byt_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); - unsigned long flags; - u32 old_val; - - spin_lock_irqsave(&vg->lock, flags); - - old_val = readl(reg); - - if (value) - writel(old_val | BYT_LEVEL, reg); - else - writel(old_val & ~BYT_LEVEL, reg); - - spin_unlock_irqrestore(&vg->lock, flags); -} - -static int byt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_VAL_REG); - unsigned long flags; - u32 value; - - spin_lock_irqsave(&vg->lock, flags); - - value = readl(reg) | BYT_DIR_MASK; - value = value & (~BYT_INPUT_EN); /* active low */ - writel(value, reg); - - spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - -static int byt_gpio_direction_output(struct gpio_chip *chip, - unsigned gpio, int value) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG); - unsigned long flags; - u32 reg_val; - - spin_lock_irqsave(&vg->lock, flags); - - reg_val = readl(reg) | (BYT_DIR_MASK | !!value); - reg_val &= ~(BYT_OUTPUT_EN | !value); - writel(reg_val, reg); - - spin_unlock_irqrestore(&vg->lock, flags); - - return 0; -} - -static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - int i; - unsigned long flags; - u32 conf0, val, offs; - - spin_lock_irqsave(&vg->lock, flags); - - for (i = 0; i < vg->chip.ngpio; i++) { - offs = vg->range->pins[i] * 16; - conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); - val = readl(vg->reg_base + offs + BYT_VAL_REG); - - seq_printf(s, - " gpio-%-3d %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s\n", - i, - val & BYT_INPUT_EN ? " " : "in", - val & BYT_OUTPUT_EN ? " " : "out", - val & BYT_LEVEL ? "hi" : "lo", - vg->range->pins[i], offs, - conf0 & 0x7, - conf0 & BYT_TRIG_NEG ? "fall " : "", - conf0 & BYT_TRIG_POS ? "rise " : "", - conf0 & BYT_TRIG_LVL ? "lvl " : ""); - } - spin_unlock_irqrestore(&vg->lock, flags); -} - -static int byt_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = container_of(chip, struct byt_gpio, chip); - return irq_create_mapping(vg->domain, offset); -} - -static void byt_gpio_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct irq_data *data = irq_desc_get_irq_data(desc); - struct byt_gpio *vg = irq_data_get_irq_handler_data(data); - struct irq_chip *chip = irq_data_get_irq_chip(data); - u32 base, pin, mask; - void __iomem *reg; - u32 pending; - unsigned virq; - int looplimit = 0; - - /* check from GPIO controller which pin triggered the interrupt */ - for (base = 0; base < vg->chip.ngpio; base += 32) { - - reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); - - while ((pending = readl(reg))) { - pin = __ffs(pending); - mask = BIT(pin); - /* Clear before handling so we can't lose an edge */ - writel(mask, reg); - - virq = irq_find_mapping(vg->domain, base + pin); - generic_handle_irq(virq); - - /* In case bios or user sets triggering incorretly a pin - * might remain in "interrupt triggered" state. - */ - if (looplimit++ > 32) { - dev_err(&vg->pdev->dev, - "Gpio %d interrupt flood, disabling\n", - base + pin); - - reg = byt_gpio_reg(&vg->chip, base + pin, - BYT_CONF0_REG); - mask = readl(reg); - mask &= ~(BYT_TRIG_NEG | BYT_TRIG_POS | - BYT_TRIG_LVL); - writel(mask, reg); - mask = readl(reg); /* flush */ - break; - } - } - } - chip->irq_eoi(data); -} - -static void byt_irq_unmask(struct irq_data *d) -{ -} - -static void byt_irq_mask(struct irq_data *d) -{ -} - -static struct irq_chip byt_irqchip = { - .name = "BYT-GPIO", - .irq_mask = byt_irq_mask, - .irq_unmask = byt_irq_unmask, - .irq_set_type = byt_irq_type, -}; - -static void byt_gpio_irq_init_hw(struct byt_gpio *vg) -{ - void __iomem *reg; - u32 base, value; - - /* clear interrupt status trigger registers */ - for (base = 0; base < vg->chip.ngpio; base += 32) { - reg = byt_gpio_reg(&vg->chip, base, BYT_INT_STAT_REG); - writel(0xffffffff, reg); - /* make sure trigger bits are cleared, if not then a pin - might be misconfigured in bios */ - value = readl(reg); - if (value) - dev_err(&vg->pdev->dev, - "GPIO interrupt error, pins misconfigured\n"); - } -} - -static int byt_gpio_irq_map(struct irq_domain *d, unsigned int virq, - irq_hw_number_t hw) -{ - struct byt_gpio *vg = d->host_data; - - irq_set_chip_and_handler_name(virq, &byt_irqchip, handle_simple_irq, - "demux"); - irq_set_chip_data(virq, vg); - irq_set_irq_type(virq, IRQ_TYPE_NONE); - - return 0; -} - -static const struct irq_domain_ops byt_gpio_irq_ops = { - .map = byt_gpio_irq_map, -}; - -static int byt_gpio_probe(struct platform_device *pdev) -{ - struct byt_gpio *vg; - struct gpio_chip *gc; - struct resource *mem_rc, *irq_rc; - struct device *dev = &pdev->dev; - struct acpi_device *acpi_dev; - struct pinctrl_gpio_range *range; - acpi_handle handle = ACPI_HANDLE(dev); - unsigned hwirq; - int ret; - - if (acpi_bus_get_device(handle, &acpi_dev)) - return -ENODEV; - - vg = devm_kzalloc(dev, sizeof(struct byt_gpio), GFP_KERNEL); - if (!vg) { - dev_err(&pdev->dev, "can't allocate byt_gpio chip data\n"); - return -ENOMEM; - } - - for (range = byt_ranges; range->name; range++) { - if (!strcmp(acpi_dev->pnp.unique_id, range->name)) { - vg->chip.ngpio = range->npins; - vg->range = range; - break; - } - } - - if (!vg->chip.ngpio || !vg->range) - return -ENODEV; - - vg->pdev = pdev; - platform_set_drvdata(pdev, vg); - - mem_rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); - vg->reg_base = devm_ioremap_resource(dev, mem_rc); - if (IS_ERR(vg->reg_base)) - return PTR_ERR(vg->reg_base); - - spin_lock_init(&vg->lock); - - gc = &vg->chip; - gc->label = dev_name(&pdev->dev); - gc->owner = THIS_MODULE; - gc->request = byt_gpio_request; - gc->free = byt_gpio_free; - gc->direction_input = byt_gpio_direction_input; - gc->direction_output = byt_gpio_direction_output; - gc->get = byt_gpio_get; - gc->set = byt_gpio_set; - gc->dbg_show = byt_gpio_dbg_show; - gc->base = -1; - gc->can_sleep = 0; - gc->dev = dev; - - ret = gpiochip_add(gc); - if (ret) { - dev_err(&pdev->dev, "failed adding byt-gpio chip\n"); - return ret; - } - - /* set up interrupts */ - irq_rc = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (irq_rc && irq_rc->start) { - hwirq = irq_rc->start; - gc->to_irq = byt_gpio_to_irq; - - vg->domain = irq_domain_add_linear(NULL, gc->ngpio, - &byt_gpio_irq_ops, vg); - if (!vg->domain) - return -ENXIO; - - byt_gpio_irq_init_hw(vg); - - irq_set_handler_data(hwirq, vg); - irq_set_chained_handler(hwirq, byt_gpio_irq_handler); - - /* Register interrupt handlers for gpio signaled acpi events */ - acpi_gpiochip_request_interrupts(gc); - } - - pm_runtime_enable(dev); - - return 0; -} - -static int byt_gpio_runtime_suspend(struct device *dev) -{ - return 0; -} - -static int byt_gpio_runtime_resume(struct device *dev) -{ - return 0; -} - -static const struct dev_pm_ops byt_gpio_pm_ops = { - .runtime_suspend = byt_gpio_runtime_suspend, - .runtime_resume = byt_gpio_runtime_resume, -}; - -static const struct acpi_device_id byt_gpio_acpi_match[] = { - { "INT33B2", 0 }, - { } -}; -MODULE_DEVICE_TABLE(acpi, byt_gpio_acpi_match); - -static int byt_gpio_remove(struct platform_device *pdev) -{ - struct byt_gpio *vg = platform_get_drvdata(pdev); - int err; - pm_runtime_disable(&pdev->dev); - err = gpiochip_remove(&vg->chip); - if (err) - dev_warn(&pdev->dev, "failed to remove gpio_chip.\n"); - - return 0; -} - -static struct platform_driver byt_gpio_driver = { - .probe = byt_gpio_probe, - .remove = byt_gpio_remove, - .driver = { - .name = "byt_gpio", - .owner = THIS_MODULE, - .pm = &byt_gpio_pm_ops, - .acpi_match_table = ACPI_PTR(byt_gpio_acpi_match), - }, -}; - -static int __init byt_gpio_init(void) -{ - return platform_driver_register(&byt_gpio_driver); -} - -subsys_initcall(byt_gpio_init); |
