From 5fae8b86fdf083bc43bf759abad6661be9d0b9ac Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Fri, 24 Oct 2014 15:16:52 +0300 Subject: pinctrl: Move Intel Baytrail pinctrl driver under intel directory We are going to have more pinctrl drivers for Intel hardware so separate all our pin controller drivers to own directory. Signed-off-by: Mika Westerberg Signed-off-by: Linus Walleij --- drivers/pinctrl/Kconfig | 13 +- drivers/pinctrl/Makefile | 2 +- drivers/pinctrl/intel/Kconfig | 15 + drivers/pinctrl/intel/Makefile | 3 + drivers/pinctrl/intel/pinctrl-baytrail.c | 621 +++++++++++++++++++++++++++++++ drivers/pinctrl/pinctrl-baytrail.c | 621 ------------------------------- 6 files changed, 641 insertions(+), 634 deletions(-) create mode 100644 drivers/pinctrl/intel/Kconfig create mode 100644 drivers/pinctrl/intel/Makefile create mode 100644 drivers/pinctrl/intel/pinctrl-baytrail.c delete mode 100644 drivers/pinctrl/pinctrl-baytrail.c (limited to 'drivers/pinctrl') diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index c6a66de..d014f22 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -67,18 +67,6 @@ config PINCTRL_AT91 help Say Y here to enable the at91 pinctrl driver -config PINCTRL_BAYTRAIL - bool "Intel Baytrail GPIO pin control" - depends on GPIOLIB && ACPI && X86 - select GPIOLIB_IRQCHIP - help - driver for memory mapped GPIO functionality on Intel Baytrail - platforms. Supports 3 banks with 102, 28 and 44 gpios. - Most pins are usually muxed to some other functionality by firmware, - so only a small amount is available for gpio use. - - Requires ACPI device enumeration code to set up a platform device. - config PINCTRL_BCM2835 bool select PINMUX @@ -205,6 +193,7 @@ config PINCTRL_PALMAS source "drivers/pinctrl/berlin/Kconfig" source "drivers/pinctrl/freescale/Kconfig" +source "drivers/pinctrl/intel/Kconfig" source "drivers/pinctrl/mvebu/Kconfig" source "drivers/pinctrl/nomadik/Kconfig" source "drivers/pinctrl/qcom/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index 51f52d3..c030b3d 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -15,7 +15,6 @@ obj-$(CONFIG_PINCTRL_BF54x) += pinctrl-adi2-bf54x.o obj-$(CONFIG_PINCTRL_BF60x) += pinctrl-adi2-bf60x.o obj-$(CONFIG_PINCTRL_AT91) += pinctrl-at91.o obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o -obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o obj-$(CONFIG_PINCTRL_FALCON) += pinctrl-falcon.o obj-$(CONFIG_PINCTRL_PALMAS) += pinctrl-palmas.o @@ -39,6 +38,7 @@ obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-y += freescale/ +obj-$(CONFIG_X86) += intel/ obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-y += nomadik/ obj-$(CONFIG_ARCH_QCOM) += qcom/ diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig new file mode 100644 index 0000000..957c903 --- /dev/null +++ b/drivers/pinctrl/intel/Kconfig @@ -0,0 +1,15 @@ +# +# Intel pin control drivers +# + +config PINCTRL_BAYTRAIL + bool "Intel Baytrail GPIO pin control" + depends on GPIOLIB && ACPI + select GPIOLIB_IRQCHIP + help + driver for memory mapped GPIO functionality on Intel Baytrail + platforms. Supports 3 banks with 102, 28 and 44 gpios. + Most pins are usually muxed to some other functionality by firmware, + so only a small amount is available for gpio use. + + Requires ACPI device enumeration code to set up a platform device. diff --git a/drivers/pinctrl/intel/Makefile b/drivers/pinctrl/intel/Makefile new file mode 100644 index 0000000..d049b76 --- /dev/null +++ b/drivers/pinctrl/intel/Makefile @@ -0,0 +1,3 @@ +# Intel pin control drivers + +obj-$(CONFIG_PINCTRL_BAYTRAIL) += pinctrl-baytrail.o diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c new file mode 100644 index 0000000..3ece001 --- /dev/null +++ b/drivers/pinctrl/intel/pinctrl-baytrail.c @@ -0,0 +1,621 @@ +/* + * Pinctrl GPIO driver for Intel Baytrail + * Copyright (c) 2012-2013, Intel Corporation. + * + * Author: Mathias Nyman + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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_IODEN BIT(31) +#define BYT_DIRECT_IRQ_EN BIT(27) +#define BYT_TRIG_NEG BIT(26) +#define BYT_TRIG_POS BIT(25) +#define BYT_TRIG_LVL BIT(24) +#define BYT_PULL_STR_SHIFT 9 +#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT) +#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT) +#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) +#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) +#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) +#define BYT_PULL_ASSIGN_SHIFT 7 +#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT) +#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) +#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) +#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 + +#define BYT_SCORE_ACPI_UID "1" +#define BYT_NCORE_ACPI_UID "2" +#define BYT_SUS_ACPI_UID "3" + +/* + * 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 = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */ + .npins = BYT_NGPIO_SCORE, + .pins = score_pins, + }, + { + .name = BYT_NCORE_ACPI_UID, + .npins = BYT_NGPIO_NCORE, + .pins = ncore_pins, + }, + { + .name = BYT_SUS_ACPI_UID, + .npins = BYT_NGPIO_SUS, + .pins = sus_pins, + }, + { + }, +}; + +struct byt_gpio { + struct gpio_chip chip; + struct platform_device *pdev; + spinlock_t lock; + void __iomem *reg_base; + struct pinctrl_gpio_range *range; +}; + +#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip) + +static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, + int reg) +{ + struct byt_gpio *vg = to_byt_gpio(chip); + u32 reg_offset; + + if (reg == BYT_INT_STAT_REG) + reg_offset = (offset / 32) * 4; + else + reg_offset = vg->range->pins[offset] * 16; + + return vg->reg_base + reg_offset + reg; +} + +static bool is_special_pin(struct byt_gpio *vg, unsigned offset) +{ + /* SCORE pin 92-93 */ + if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && + offset >= 92 && offset <= 93) + return true; + + /* SUS pin 11-21 */ + if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && + offset >= 11 && offset <= 21) + return true; + + return false; +} + +static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) +{ + struct byt_gpio *vg = to_byt_gpio(chip); + void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); + u32 value; + bool special; + + /* + * In most cases, func pin mux 000 means GPIO function. + * But, some pins may have func pin mux 001 represents + * GPIO function. Only allow user to export pin with + * func pin mux preset as GPIO function by BIOS/FW. + */ + value = readl(reg) & BYT_PIN_MUX; + special = is_special_pin(vg, offset); + if ((special && value != 1) || (!special && value)) { + dev_err(&vg->pdev->dev, + "pin %u cannot be used as GPIO.\n", offset); + return -EINVAL; + } + + pm_runtime_get(&vg->pdev->dev); + + return 0; +} + +static void byt_gpio_free(struct gpio_chip *chip, unsigned offset) +{ + struct byt_gpio *vg = to_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 = to_byt_gpio(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 = to_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 = to_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 &= ~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 = to_byt_gpio(chip); + void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG); + void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG); + unsigned long flags; + u32 reg_val; + + spin_lock_irqsave(&vg->lock, flags); + + /* + * Before making any direction modifications, do a check if gpio + * is set for direct IRQ. On baytrail, setting GPIO to output does + * not make sense, so let's at least warn the caller before they shoot + * themselves in the foot. + */ + WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, + "Potential Error: Setting GPIO with direct_irq_en to output"); + + reg_val = readl(reg) | BYT_DIR_MASK; + reg_val &= ~BYT_OUTPUT_EN; + + if (value) + writel(reg_val | BYT_LEVEL, reg); + else + writel(reg_val & ~BYT_LEVEL, 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 = to_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++) { + const char *pull_str = NULL; + const char *pull = NULL; + const char *label; + offs = vg->range->pins[i] * 16; + conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); + val = readl(vg->reg_base + offs + BYT_VAL_REG); + + label = gpiochip_is_requested(chip, i); + if (!label) + label = "Unrequested"; + + switch (conf0 & BYT_PULL_ASSIGN_MASK) { + case BYT_PULL_ASSIGN_UP: + pull = "up"; + break; + case BYT_PULL_ASSIGN_DOWN: + pull = "down"; + break; + } + + switch (conf0 & BYT_PULL_STR_MASK) { + case BYT_PULL_STR_2K: + pull_str = "2k"; + break; + case BYT_PULL_STR_10K: + pull_str = "10k"; + break; + case BYT_PULL_STR_20K: + pull_str = "20k"; + break; + case BYT_PULL_STR_40K: + pull_str = "40k"; + break; + } + + seq_printf(s, + " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", + i, + label, + 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 ? " level" : " "); + + if (pull && pull_str) + seq_printf(s, " %-4s %-3s", pull, pull_str); + else + seq_puts(s, " "); + + if (conf0 & BYT_IODEN) + seq_puts(s, " open-drain"); + + seq_puts(s, "\n"); + } + spin_unlock_irqrestore(&vg->lock, flags); +} + +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 = to_byt_gpio(irq_desc_get_handler_data(desc)); + 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->chip.irqdomain, 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, + .flags = IRQCHIP_SKIP_SET_WAKE, +}; + +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_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); + 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 = false; + 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) { + byt_gpio_irq_init_hw(vg); + ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0, + handle_simple_irq, IRQ_TYPE_NONE); + if (ret) { + dev_err(dev, "failed to add irqchip\n"); + gpiochip_remove(gc); + return ret; + } + + gpiochip_set_chained_irqchip(gc, &byt_irqchip, + (unsigned)irq_rc->start, + byt_gpio_irq_handler); + } + + 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 }, + { "INT33FC", 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); + + pm_runtime_disable(&pdev->dev); + gpiochip_remove(&vg->chip); + + 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); + +static void __exit byt_gpio_exit(void) +{ + platform_driver_unregister(&byt_gpio_driver); +} +module_exit(byt_gpio_exit); diff --git a/drivers/pinctrl/pinctrl-baytrail.c b/drivers/pinctrl/pinctrl-baytrail.c deleted file mode 100644 index 3ece001..0000000 --- a/drivers/pinctrl/pinctrl-baytrail.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Pinctrl GPIO driver for Intel Baytrail - * Copyright (c) 2012-2013, Intel Corporation. - * - * Author: Mathias Nyman - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* 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_IODEN BIT(31) -#define BYT_DIRECT_IRQ_EN BIT(27) -#define BYT_TRIG_NEG BIT(26) -#define BYT_TRIG_POS BIT(25) -#define BYT_TRIG_LVL BIT(24) -#define BYT_PULL_STR_SHIFT 9 -#define BYT_PULL_STR_MASK (3 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_STR_2K (0 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_STR_10K (1 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_STR_20K (2 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_STR_40K (3 << BYT_PULL_STR_SHIFT) -#define BYT_PULL_ASSIGN_SHIFT 7 -#define BYT_PULL_ASSIGN_MASK (3 << BYT_PULL_ASSIGN_SHIFT) -#define BYT_PULL_ASSIGN_UP (1 << BYT_PULL_ASSIGN_SHIFT) -#define BYT_PULL_ASSIGN_DOWN (2 << BYT_PULL_ASSIGN_SHIFT) -#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 - -#define BYT_SCORE_ACPI_UID "1" -#define BYT_NCORE_ACPI_UID "2" -#define BYT_SUS_ACPI_UID "3" - -/* - * 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 = BYT_SCORE_ACPI_UID, /* match with acpi _UID in probe */ - .npins = BYT_NGPIO_SCORE, - .pins = score_pins, - }, - { - .name = BYT_NCORE_ACPI_UID, - .npins = BYT_NGPIO_NCORE, - .pins = ncore_pins, - }, - { - .name = BYT_SUS_ACPI_UID, - .npins = BYT_NGPIO_SUS, - .pins = sus_pins, - }, - { - }, -}; - -struct byt_gpio { - struct gpio_chip chip; - struct platform_device *pdev; - spinlock_t lock; - void __iomem *reg_base; - struct pinctrl_gpio_range *range; -}; - -#define to_byt_gpio(c) container_of(c, struct byt_gpio, chip) - -static void __iomem *byt_gpio_reg(struct gpio_chip *chip, unsigned offset, - int reg) -{ - struct byt_gpio *vg = to_byt_gpio(chip); - u32 reg_offset; - - if (reg == BYT_INT_STAT_REG) - reg_offset = (offset / 32) * 4; - else - reg_offset = vg->range->pins[offset] * 16; - - return vg->reg_base + reg_offset + reg; -} - -static bool is_special_pin(struct byt_gpio *vg, unsigned offset) -{ - /* SCORE pin 92-93 */ - if (!strcmp(vg->range->name, BYT_SCORE_ACPI_UID) && - offset >= 92 && offset <= 93) - return true; - - /* SUS pin 11-21 */ - if (!strcmp(vg->range->name, BYT_SUS_ACPI_UID) && - offset >= 11 && offset <= 21) - return true; - - return false; -} - -static int byt_gpio_request(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = to_byt_gpio(chip); - void __iomem *reg = byt_gpio_reg(chip, offset, BYT_CONF0_REG); - u32 value; - bool special; - - /* - * In most cases, func pin mux 000 means GPIO function. - * But, some pins may have func pin mux 001 represents - * GPIO function. Only allow user to export pin with - * func pin mux preset as GPIO function by BIOS/FW. - */ - value = readl(reg) & BYT_PIN_MUX; - special = is_special_pin(vg, offset); - if ((special && value != 1) || (!special && value)) { - dev_err(&vg->pdev->dev, - "pin %u cannot be used as GPIO.\n", offset); - return -EINVAL; - } - - pm_runtime_get(&vg->pdev->dev); - - return 0; -} - -static void byt_gpio_free(struct gpio_chip *chip, unsigned offset) -{ - struct byt_gpio *vg = to_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 = to_byt_gpio(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 = to_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 = to_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 &= ~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 = to_byt_gpio(chip); - void __iomem *conf_reg = byt_gpio_reg(chip, gpio, BYT_CONF0_REG); - void __iomem *reg = byt_gpio_reg(chip, gpio, BYT_VAL_REG); - unsigned long flags; - u32 reg_val; - - spin_lock_irqsave(&vg->lock, flags); - - /* - * Before making any direction modifications, do a check if gpio - * is set for direct IRQ. On baytrail, setting GPIO to output does - * not make sense, so let's at least warn the caller before they shoot - * themselves in the foot. - */ - WARN(readl(conf_reg) & BYT_DIRECT_IRQ_EN, - "Potential Error: Setting GPIO with direct_irq_en to output"); - - reg_val = readl(reg) | BYT_DIR_MASK; - reg_val &= ~BYT_OUTPUT_EN; - - if (value) - writel(reg_val | BYT_LEVEL, reg); - else - writel(reg_val & ~BYT_LEVEL, 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 = to_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++) { - const char *pull_str = NULL; - const char *pull = NULL; - const char *label; - offs = vg->range->pins[i] * 16; - conf0 = readl(vg->reg_base + offs + BYT_CONF0_REG); - val = readl(vg->reg_base + offs + BYT_VAL_REG); - - label = gpiochip_is_requested(chip, i); - if (!label) - label = "Unrequested"; - - switch (conf0 & BYT_PULL_ASSIGN_MASK) { - case BYT_PULL_ASSIGN_UP: - pull = "up"; - break; - case BYT_PULL_ASSIGN_DOWN: - pull = "down"; - break; - } - - switch (conf0 & BYT_PULL_STR_MASK) { - case BYT_PULL_STR_2K: - pull_str = "2k"; - break; - case BYT_PULL_STR_10K: - pull_str = "10k"; - break; - case BYT_PULL_STR_20K: - pull_str = "20k"; - break; - case BYT_PULL_STR_40K: - pull_str = "40k"; - break; - } - - seq_printf(s, - " gpio-%-3d (%-20.20s) %s %s %s pad-%-3d offset:0x%03x mux:%d %s%s%s", - i, - label, - 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 ? " level" : " "); - - if (pull && pull_str) - seq_printf(s, " %-4s %-3s", pull, pull_str); - else - seq_puts(s, " "); - - if (conf0 & BYT_IODEN) - seq_puts(s, " open-drain"); - - seq_puts(s, "\n"); - } - spin_unlock_irqrestore(&vg->lock, flags); -} - -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 = to_byt_gpio(irq_desc_get_handler_data(desc)); - 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->chip.irqdomain, 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, - .flags = IRQCHIP_SKIP_SET_WAKE, -}; - -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_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); - 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 = false; - 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) { - byt_gpio_irq_init_hw(vg); - ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0, - handle_simple_irq, IRQ_TYPE_NONE); - if (ret) { - dev_err(dev, "failed to add irqchip\n"); - gpiochip_remove(gc); - return ret; - } - - gpiochip_set_chained_irqchip(gc, &byt_irqchip, - (unsigned)irq_rc->start, - byt_gpio_irq_handler); - } - - 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 }, - { "INT33FC", 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); - - pm_runtime_disable(&pdev->dev); - gpiochip_remove(&vg->chip); - - 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); - -static void __exit byt_gpio_exit(void) -{ - platform_driver_unregister(&byt_gpio_driver); -} -module_exit(byt_gpio_exit); -- cgit v1.1