aboutsummaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch')
-rw-r--r--recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch272
1 files changed, 272 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch b/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
new file mode 100644
index 0000000..ec541dc
--- /dev/null
+++ b/recipes-kernel/linux/files/0015-Quark-GPIO-1-2-quark.patch
@@ -0,0 +1,272 @@
+From xxxx Mon Sep 17 00:00:00 2001
+From: Josef Ahmad <josef.ahmad@linux.intel.com>
+Date: Tue, 11 Feb 2014 16:28:26 +0000
+Subject: [PATCH 15/21] Quark GPIO 1/2
+
+---
+ drivers/gpio/Kconfig | 7 ++-
+ drivers/gpio/gpiolib.c | 130 ++++++++++++++++++++++++++++++++++++++++++++
+ include/asm-generic/gpio.h | 4 ++
+ include/linux/gpio.h | 10 ++++
+ 4 files changed, 149 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
+index 682de75..afab416 100644
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -243,13 +243,14 @@ config GPIO_VR41XX
+ Say yes here to support the NEC VR4100 series General-purpose I/O Uint
+
+ config GPIO_SCH
+- tristate "Intel SCH/TunnelCreek/Centerton GPIO"
++ tristate "Intel SCH/TunnelCreek/Centerton/Quark GPIO"
+ depends on PCI && X86
+ select MFD_CORE
+ select LPC_SCH
+ help
+ Say yes here to support GPIO interface on Intel Poulsbo SCH,
+- Intel Tunnel Creek processor or Intel Centerton processor.
++ Intel Tunnel Creek processor, Intel Centerton processor or Intel
++ Quark.
+ The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
+ powered by the core power rail and are turned off during sleep
+ modes (S3 and higher). The remaining four GPIOs are powered by
+@@ -261,6 +262,8 @@ config GPIO_SCH
+ The Intel Centerton processor has a total of 30 GPIO pins.
+ Twenty-one are powered by the core power rail and 9 from the
+ suspend power supply.
++ The Intel Quark has 2 GPIOs powered by the core power well and 6
++ form the suspend power well.
+
+ config GPIO_ICH
+ tristate "Intel ICH GPIO"
+diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
+index 5359ca7..5e897ff 100644
+--- a/drivers/gpio/gpiolib.c
++++ b/drivers/gpio/gpiolib.c
+@@ -60,11 +60,17 @@ struct gpio_desc {
+ #define FLAG_ACTIVE_LOW 7 /* sysfs value has active low */
+ #define FLAG_OPEN_DRAIN 8 /* Gpio is open drain type */
+ #define FLAG_OPEN_SOURCE 9 /* Gpio is open source type */
++#define FLAG_PULLUP 10 /* Gpio drive is resistive pullup */
++#define FLAG_PULLDOWN 11 /* Gpio drive is resistive pulldown */
++#define FLAG_STRONG 12 /* Gpio drive is strong (fast output) */
++#define FLAG_HIZ 13 /* Gpio drive is Hi-Z (input) */
+
+ #define ID_SHIFT 16 /* add new flags before this one */
+
+ #define GPIO_FLAGS_MASK ((1 << ID_SHIFT) - 1)
+ #define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE))
++#define GPIO_DRIVE_MASK (BIT(FLAG_PULLUP) | BIT(FLAG_PULLDOWN) \
++ | BIT(FLAG_STRONG) | BIT(FLAG_HIZ))
+
+ #ifdef CONFIG_DEBUG_FS
+ const char *label;
+@@ -243,6 +249,10 @@ static DEFINE_MUTEX(sysfs_lock);
+ * * is read/write as zero/nonzero
+ * * also affects existing and subsequent "falling" and "rising"
+ * /edge configuration
++ * /drive
++ * * sets signal drive mode
++ * * is read/write as "pullup", "pulldown", "strong" or "hiz"
++ *
+ */
+
+ static ssize_t gpio_direction_show(struct device *dev,
+@@ -573,9 +583,85 @@ static ssize_t gpio_active_low_store(struct device *dev,
+ static const DEVICE_ATTR(active_low, 0644,
+ gpio_active_low_show, gpio_active_low_store);
+
++static ssize_t gpio_drive_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ const struct gpio_desc *desc = dev_get_drvdata(dev);
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(FLAG_EXPORT, &desc->flags)) {
++ status = -EIO;
++ } else {
++ if (test_bit(FLAG_PULLUP, &desc->flags))
++ status = sprintf(buf, "pullup\n");
++ else if (test_bit(FLAG_PULLDOWN, &desc->flags))
++ status = sprintf(buf, "pulldown\n");
++ else if (test_bit(FLAG_STRONG, &desc->flags))
++ status = sprintf(buf, "strong\n");
++ else if (test_bit(FLAG_HIZ, &desc->flags))
++ status = sprintf(buf, "hiz\n");
++ else
++ status = -EINVAL;
++ }
++
++ mutex_unlock(&sysfs_lock);
++ return status;
++}
++
++static ssize_t gpio_drive_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct gpio_desc *desc = dev_get_drvdata(dev);
++ unsigned gpio = desc - gpio_desc;
++ ssize_t status;
++
++ mutex_lock(&sysfs_lock);
++
++ if (!test_bit(FLAG_EXPORT, &desc->flags))
++ status = -EIO;
++ else {
++ if (sysfs_streq(buf, "pullup")) {
++ status = gpio_set_drive(gpio, GPIOF_DRIVE_PULLUP);
++ if (!status) {
++ desc->flags &= ~GPIO_DRIVE_MASK;
++ set_bit(FLAG_PULLUP, &desc->flags);
++ }
++ } else if (sysfs_streq(buf, "pulldown")) {
++ status = gpio_set_drive(gpio, GPIOF_DRIVE_PULLDOWN);
++ if (!status) {
++ desc->flags &= ~GPIO_DRIVE_MASK;
++ set_bit(FLAG_PULLDOWN, &desc->flags);
++ }
++ } else if (sysfs_streq(buf, "strong")) {
++ status = gpio_set_drive(gpio, GPIOF_DRIVE_STRONG);
++ if (!status) {
++ desc->flags &= ~GPIO_DRIVE_MASK;
++ set_bit(FLAG_STRONG, &desc->flags);
++ }
++ } else if (sysfs_streq(buf, "hiz")) {
++ status = gpio_set_drive(gpio, GPIOF_DRIVE_HIZ);
++ if (!status) {
++ desc->flags &= ~GPIO_DRIVE_MASK;
++ set_bit(FLAG_HIZ, &desc->flags);
++ }
++ } else {
++ status = -EINVAL;
++ }
++ }
++
++ mutex_unlock(&sysfs_lock);
++ return status ? : size;
++}
++
++static const DEVICE_ATTR(drive, 0644,
++ gpio_drive_show, gpio_drive_store);
++
+ static const struct attribute *gpio_attrs[] = {
+ &dev_attr_value.attr,
+ &dev_attr_active_low.attr,
++ &dev_attr_drive.attr,
+ NULL,
+ };
+
+@@ -1677,6 +1763,50 @@ fail:
+ }
+ EXPORT_SYMBOL_GPL(gpio_set_debounce);
+
++/**
++ * gpio_set_drive - sets drive @mode for a @gpio
++ * @gpio: the gpio to set the drive mode
++ * @mode: the drive mode
++ */
++int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++ unsigned long flags;
++ struct gpio_chip *chip;
++ struct gpio_desc *desc = &gpio_desc[gpio];
++ int status = -EINVAL;
++
++ spin_lock_irqsave(&gpio_lock, flags);
++
++ if (!gpio_is_valid(gpio))
++ goto fail;
++ chip = desc->chip;
++ if (!chip || !chip->set || !chip->set_drive)
++ goto fail;
++ gpio -= chip->base;
++ if (gpio >= chip->ngpio)
++ goto fail;
++ status = gpio_ensure_requested(desc, gpio);
++ if (status < 0)
++ goto fail;
++
++ /* now we know the gpio is valid and chip won't vanish */
++
++ spin_unlock_irqrestore(&gpio_lock, flags);
++
++ might_sleep_if(chip->can_sleep);
++
++ return chip->set_drive(chip, gpio, mode);
++
++fail:
++ spin_unlock_irqrestore(&gpio_lock, flags);
++ if (status)
++ pr_debug("%s: gpio-%d status %d\n",
++ __func__, gpio, status);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(gpio_set_drive);
++
+ /* I/O calls are only valid after configuration completed; the relevant
+ * "is this a valid GPIO" error checks should already have been done.
+ *
+diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h
+index 20ca766..8265ccc 100644
+--- a/include/asm-generic/gpio.h
++++ b/include/asm-generic/gpio.h
+@@ -65,6 +65,7 @@ struct device_node;
+ * @direction_output: configures signal "offset" as output, or returns error
+ * @set_debounce: optional hook for setting debounce time for specified gpio in
+ * interrupt triggered gpio chips
++ * @set_drive: optional hook for setting the drive signal for "offset"
+ * @set: assigns output value for signal "offset"
+ * @to_irq: optional hook supporting non-static gpio_to_irq() mappings;
+ * implementation may not sleep
+@@ -113,6 +114,8 @@ struct gpio_chip {
+ unsigned offset, int value);
+ int (*set_debounce)(struct gpio_chip *chip,
+ unsigned offset, unsigned debounce);
++ int (*set_drive)(struct gpio_chip *chip,
++ unsigned offset, unsigned mode);
+
+ void (*set)(struct gpio_chip *chip,
+ unsigned offset, int value);
+@@ -172,6 +175,7 @@ extern int gpio_direction_input(unsigned gpio);
+ extern int gpio_direction_output(unsigned gpio, int value);
+
+ extern int gpio_set_debounce(unsigned gpio, unsigned debounce);
++extern int gpio_set_drive(unsigned gpio, unsigned mode);
+
+ extern int gpio_get_value_cansleep(unsigned gpio);
+ extern void gpio_set_value_cansleep(unsigned gpio, int value);
+diff --git a/include/linux/gpio.h b/include/linux/gpio.h
+index bfe6656..cadd9d2 100644
+--- a/include/linux/gpio.h
++++ b/include/linux/gpio.h
+@@ -27,6 +27,11 @@
+ #define GPIOF_EXPORT_DIR_FIXED (GPIOF_EXPORT)
+ #define GPIOF_EXPORT_DIR_CHANGEABLE (GPIOF_EXPORT | GPIOF_EXPORT_CHANGEABLE)
+
++#define GPIOF_DRIVE_PULLUP (1 << 6)
++#define GPIOF_DRIVE_PULLDOWN (1 << 7)
++#define GPIOF_DRIVE_STRONG (1 << 8)
++#define GPIOF_DRIVE_HIZ (1 << 9)
++
+ /**
+ * struct gpio - a structure describing a GPIO with configuration
+ * @gpio: the GPIO number
+@@ -156,6 +161,11 @@ static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
+ return -ENOSYS;
+ }
+
++static inline int gpio_set_drive(unsigned gpio, unsigned mode)
++{
++ return -ENOSYS;
++}
++
+ static inline int gpio_get_value(unsigned gpio)
+ {
+ /* GPIO can never have been requested or set as {in,out}put */
+--
+1.7.4.1
+