aboutsummaryrefslogtreecommitdiffstats
path: root/meta-steppeeagle/recipes-kernel/amd-gpio
diff options
context:
space:
mode:
Diffstat (limited to 'meta-steppeeagle/recipes-kernel/amd-gpio')
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb28
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile14
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c886
-rw-r--r--meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h85
4 files changed, 1013 insertions, 0 deletions
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb b/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb
new file mode 100644
index 00000000..c003fe43
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/amd-gpio_1.0.bb
@@ -0,0 +1,28 @@
+DESCRIPTION = "This kernel module provides support for AMD GPIO driver"
+LICENSE = "BSD | GPLv2"
+LIC_FILES_CHKSUM = "file://gpio-amd.c;md5=a48cb57d6711b1801a62ea03a87e2e76 \
+ file://gpio-amd.h;md5=90e0a4a5923224a946619ee72f0f7522 \
+ file://Makefile;md5=1bede035509502b1669f098efbd904f3 \
+ "
+
+inherit module
+
+PR = "r0"
+PV = "1.0"
+
+SRC_URI = "file://Makefile \
+ file://gpio-amd.c \
+ file://gpio-amd.h \
+ "
+
+S = "${WORKDIR}"
+
+# Kernel module packages MUST begin with 'kernel-module-', otherwise
+# multilib image generation can fail.
+#
+# The following line is only necessary if the recipe name does not begin
+# with kernel-module-.
+#
+PKG_${PN} = "kernel-module-${PN}"
+
+FILES_${PN} += "${sysconfdir}"
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile b/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile
new file mode 100644
index 00000000..b9348759
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/Makefile
@@ -0,0 +1,14 @@
+obj-m := gpio-amd.o
+
+SRC := $(shell pwd)
+
+all:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC)
+
+clean:
+ rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
+ rm -f Module.markers Module.symvers modules.order
+ rm -rf .tmp_versions Modules.symvers
+
+modules_install:
+ $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install \ No newline at end of file
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c
new file mode 100644
index 00000000..6c790c11
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.c
@@ -0,0 +1,886 @@
+/*****************************************************************************
+*
+* Copyright (c) 2014, Advanced Micro Devices, Inc.
+* All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions are met:
+* * Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+* * Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in the
+* documentation and/or other materials provided with the distribution.
+* * Neither the name of Advanced Micro Devices, Inc. nor the names of
+* its contributors may be used to endorse or promote products derived
+* from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+* DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*
+***************************************************************************/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/gpio.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/io.h>
+
+#include <linux/cdev.h>
+#include <linux/fs.h> /* everything... */
+#include <asm/io.h>
+#include <linux/ioctl.h>
+#include <linux/device.h>
+
+#include "gpio-amd.h"
+
+static u32 gpiobase_phys;
+static u32 iomuxbase_phys;
+static struct pci_dev *amd_gpio_pci;
+static struct platform_device *amd_gpio_platform_device;
+
+
+static int dev_major;
+static int dev_minor = 0;
+
+static struct gpio_test_dev{
+ struct cdev cdev;
+ struct class *gpio_class;
+}gpio_test_dev;
+
+
+/* The following GPIO pins are reserved as per the specification. 184 max */
+static u8 mask[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
+ 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+};
+
+
+static int gpio_mask[AMD_GPIO_NUM_PINS];
+static unsigned int num_mask;
+module_param_array(gpio_mask, int, &num_mask, 0);
+MODULE_PARM_DESC(gpio_mask, "GPIO mask which marks them as reserved");
+
+static int gpio_mode[AMD_GPIO_NUM_PINS];
+static unsigned int num_modes;
+module_param_array(gpio_mode, int, &num_modes, 0);
+MODULE_PARM_DESC(gpio_mode, "Specifies whether the GPIO mentioned "
+ "in gpio_mask is 0-reserved, 1-available, 2-GPI only, "
+ "3-GPO only");
+
+static struct amd_gpio_chip {
+ struct gpio_chip gpio;
+
+ void __iomem *gpiobase;
+ void __iomem *iomuxbase;
+
+ struct platform_device *pdev;
+ spinlock_t lock;
+} amd_gpio_chip;
+
+static int amd_gpio_request(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u8 iomux_reg;
+ u32 gpio_reg = 0;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* check if this pin is available */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ spin_unlock_irqrestore(&chip->lock, flags);
+ pr_info("GPIO pin %u not available\n", offset);
+ return -EINVAL;
+ }
+
+ /* Program the GPIO Wake/Interrupt Switch offset is AMD_GPIO_MSWITCH */
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + AMD_GPIO_MSWITCH);
+ /* to disable all GPIO wake and interrupt*/
+ gpio_reg &= (~AMD_GPIO_WAKE_EN & ~AMD_GPIO_INTERRUPT_EN);
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + AMD_GPIO_MSWITCH));
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* clear wake status and interrupt status */
+ gpio_reg |= (AMD_GPIO_INTERPT_STATUS | AMD_GPIO_WAKE_STATUS);
+
+ /* Set disable both Pull Up and Pull Down and disable output */
+ gpio_reg &= (~AMD_GPIO_PULLUP_ENABLE & ~AMD_GPIO_PULLDN_ENABLE
+ & ~AMD_GPIO_DEB_CTRL & ~AMD_GPIO_SWCTRL_IN
+ & ~AMD_GPIO_WAKECTRL & ~AMD_GPIO_INTERPT_ENABLE);
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ /* Enable GPIO by writing to the corresponding IOMUX register */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + offset);
+ iomux_reg &= ~AMD_IOMUX_GPIO_MASK;
+
+ if(offset == 10 || offset == 72 || offset == 73 ||offset == 76)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC0;
+ else if(offset == 35 || offset == 64 || offset == 65 ||offset == 66 ||
+ offset == 71 || offset == 93 ||offset == 115 ||offset == 116)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC2;
+ else if(offset == 67 || offset == 70)
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC3;
+ else
+ iomux_reg |= AMD_IOMUX_ENABLE_FUNC1;
+
+ iowrite8(iomux_reg, ((u8 *)amd_gpio_chip.iomuxbase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+
+static int amd_gpio_get(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* Read the GPIO register */
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return (gpio_reg & AMD_GPIO_GET_INPUT) ? 1 : 0;
+}
+
+static void amd_gpio_set(struct gpio_chip *c, unsigned offset, int val)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+ /* Set GPIO Output depending on 'val' */
+ if (val)
+ gpio_reg |= AMD_GPIO_SET_OUTPUT;
+ else
+ gpio_reg &= ~AMD_GPIO_SET_OUTPUT;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int amd_gpio_direction_input(struct gpio_chip *c, unsigned offset)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in output mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int amd_gpio_direction_output(struct gpio_chip *c, unsigned offset,
+ int val)
+{
+ struct amd_gpio_chip *chip = container_of(c, struct amd_gpio_chip,
+ gpio);
+ unsigned long flags;
+ u32 gpio_reg;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPI, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_INPUT) {
+ pr_info("GPIO %u can only be set in input mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+
+
+ gpio_reg |= AMD_GPIO_DRV_STRENGTH(2);
+ /* Set disable both Pull Up and Pull Down */
+ gpio_reg &= (~AMD_GPIO_PULLUP_ENABLE & ~AMD_GPIO_PULLDN_ENABLE
+ & ~AMD_GPIO_DEB_CTRL & ~AMD_GPIO_SWCTRL_IN
+ & ~AMD_GPIO_WAKECTRL & ~AMD_GPIO_INTERPT_ENABLE);
+ /* Enable output */
+ gpio_reg |= AMD_GPIO_OUTPUT_ENABLE;
+
+ /* Set GPIO Output depending on 'val' */
+ if (val)
+ gpio_reg |= AMD_GPIO_SET_OUTPUT;
+ else
+ gpio_reg &= ~AMD_GPIO_SET_OUTPUT;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static struct amd_gpio_chip amd_gpio_chip = {
+ .gpio = {
+ .owner = THIS_MODULE,
+ .label = DRV_NAME,
+
+ .base = 0,
+ .ngpio = AMD_GPIO_NUM_PINS,
+ .names = NULL,
+ .request = amd_gpio_request,
+ .get = amd_gpio_get,
+ .set = amd_gpio_set,
+ .direction_input = amd_gpio_direction_input,
+ .direction_output = amd_gpio_direction_output,
+ },
+};
+
+/*
+* The PCI Device ID table below is used to identify the platform
+* the driver is supposed to work for. Since this is a platform
+* driver, we need a way for us to be able to find the correct
+* platform when the driver gets loaded, otherwise we should
+* bail out.
+*/
+static DEFINE_PCI_DEVICE_TABLE(amd_gpio_pci_tbl) = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, PCI_ANY_ID,
+ PCI_ANY_ID, },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, amd_gpio_pci_tbl);
+
+static void amd_update_gpio_mask(void)
+{
+ u8 iomux_reg;
+
+ /*
+ * Some of the GPIO pins have an alternate function assigned to
+ * them. That will be reflected in the corresponding IOMUX
+ * registers. If so, we mark these GPIO pins as reserved.
+ */
+
+ /* AGPIO10 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x0A);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[10] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO19 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x13);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[19] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO20 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x14);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[20] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO26 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1A);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[26] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO27 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1B);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[27] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO28 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1C);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[28] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO29 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[29] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO30 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1E);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[30] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO31 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x1F);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[31] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO35 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x23);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[35] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO64 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x40);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[64] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO65 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x41);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[65] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO66 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x42);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[66] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO67 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x43);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2))
+ mask[67] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO68 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x44);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[68] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO69 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x45);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[68] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO70 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x46);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2))
+ mask[70] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO71 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x47);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[71] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO72 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x48);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[72] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO73 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x49);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[73] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO76 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x4C);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[76] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO77 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x4D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[77] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO84 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x54);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[84] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO85 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x55);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[85] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO87 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x57);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[87] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO88 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x58);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[88] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO91 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x5B);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[91] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO93 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x5D);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[93] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO115 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x73);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[115] = AMD_GPIO_MODE_RESV;
+
+ /* EGPIO116 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x74);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC1) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[116] = AMD_GPIO_MODE_RESV;
+
+ /* AGPIO130 */
+ iomux_reg = ioread8((u8 *)amd_gpio_chip.iomuxbase + 0x82);
+ if (((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC0) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC2) ||
+ ((iomux_reg & AMD_IOMUX_GPIO_MASK) == AMD_IOMUX_ENABLE_FUNC3))
+ mask[86] = AMD_GPIO_MODE_RESV;
+}
+
+static int amd_gpio_init(struct platform_device *pdev)
+{
+ struct pci_dev *dev = NULL;
+ int i;
+ int err;
+
+ /* Match the PCI device */
+ for_each_pci_dev(dev) {
+ if (pci_match_id(amd_gpio_pci_tbl, dev) != NULL) {
+ amd_gpio_pci = dev;
+ break;
+ }
+ }
+
+ if (!amd_gpio_pci)
+ return -ENODEV;
+
+ /* GPIO registers range from AMD_GPIO_ACPIMMIO_BASE+1500h to
+ AMD_GPIO_ACPIMMIO_BASE+17FFh. */
+ if (!request_mem_region_exclusive(AMD_GPIO_ACPIMMIO_BASE
+ + AMD_GPIO_BANK_OFFSET, AMD_GPIO_MEM_MAP_SIZE, "AMD GPIO")) {
+ pr_err("mmio address 0x%04x already in use\n",
+ AMD_GPIO_ACPIMMIO_BASE + AMD_GPIO_BANK_OFFSET );
+ goto exit;
+ }
+ gpiobase_phys = AMD_GPIO_ACPIMMIO_BASE + AMD_GPIO_BANK_OFFSET;
+
+ amd_gpio_chip.gpiobase = ioremap(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+ if (!amd_gpio_chip.gpiobase) {
+ pr_err("failed to get gpiobase address\n");
+ goto unreg_gpio_region;
+ }
+
+ /* IOMUX Base Address starts from ACPI MMIO Base Address + 0xD00 */
+ if (!request_mem_region_exclusive(AMD_GPIO_ACPIMMIO_BASE
+ + AMD_IOMUX_MEM_MAP_OFFSET,
+ AMD_IOMUX_MEM_MAP_SIZE, "AMD IOMUX")) {
+ pr_err("mmio address 0x%04x already in use\n",
+ AMD_GPIO_ACPIMMIO_BASE + AMD_IOMUX_MEM_MAP_OFFSET);
+ goto unmap_gpio_region;
+ }
+ iomuxbase_phys = AMD_GPIO_ACPIMMIO_BASE + AMD_IOMUX_MEM_MAP_OFFSET;
+
+ amd_gpio_chip.iomuxbase = ioremap(iomuxbase_phys,
+ AMD_IOMUX_MEM_MAP_SIZE);
+ if (!amd_gpio_chip.iomuxbase) {
+ pr_err("failed to get iomuxbase address\n");
+ goto unreg_iomux_region;
+ }
+
+ /* Set up driver specific struct */
+ amd_gpio_chip.pdev = pdev;
+ spin_lock_init(&amd_gpio_chip.lock);
+
+ /* Register ourself with the GPIO core */
+ err = gpiochip_add(&amd_gpio_chip.gpio);
+ if (err)
+ goto unmap_iomux_region;
+
+ /*
+ * Lets take care of special GPIO pins, and mark them as reserved
+ * as appropriate.
+ */
+ amd_update_gpio_mask();
+
+ /*
+ * If the number of GPIO pins provided during module loading does
+ * not match the number of GPIO modes, we fall back to the default
+ * mask.
+ */
+ if (num_mask == num_modes) {
+ /*
+ * If the number of masks or the number of modes specified
+ * is more than the maximum number of GPIO pins supported
+ * by the driver, we set the limit to the one supported
+ * driver.
+ */
+ if (num_mask > AMD_GPIO_NUM_PINS)
+ num_mask = num_modes = AMD_GPIO_NUM_PINS;
+
+ /*
+ * The default mask is our de facto standard. The GPIO
+ * pins marked reserved in the default mask stay reserved
+ * no matter what the module load parameter says. Also, we
+ * set the mode of the GPIO pins depending on the value
+ * of gpio_mode provided.
+ */
+ for (i = 0; i < num_mask; i++) {
+ if (mask[gpio_mask[i]] != AMD_GPIO_MODE_RESV) {
+ mask[gpio_mask[i]] = gpio_mode[i];
+
+ /*
+ * gpio_request() can fail, in which case we
+ * won't set the GPIO modes.
+ */
+ if(!gpio_request(gpio_mask[i], DRV_NAME)) {
+ if (gpio_mode[i] ==
+ AMD_GPIO_MODE_INPUT)
+ gpio_direction_input(gpio_mask[i]);
+ else if (gpio_mode[i] ==
+ AMD_GPIO_MODE_OUTPUT)
+ gpio_direction_output(gpio_mask[i],
+ 0);
+
+ gpio_free(gpio_mask[i]);
+ }
+ }
+ }
+ }
+
+ return 0;
+
+unmap_iomux_region:
+ iounmap(amd_gpio_chip.iomuxbase);
+unreg_iomux_region:
+ release_mem_region(iomuxbase_phys, AMD_IOMUX_MEM_MAP_SIZE);
+unmap_gpio_region:
+ iounmap(amd_gpio_chip.gpiobase);
+unreg_gpio_region:
+ release_mem_region(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+exit:
+ return -ENODEV;
+}
+
+static int amd_gpio_remove(struct platform_device *pdev)
+{
+ int err;
+
+ err = gpiochip_remove(&amd_gpio_chip.gpio);
+ if (err) {
+ dev_err(&pdev->dev, "Unable to remove gpio chip\n");
+ return err;
+ }
+
+ iounmap(amd_gpio_chip.iomuxbase);
+ release_mem_region(iomuxbase_phys, AMD_IOMUX_MEM_MAP_SIZE);
+ iounmap(amd_gpio_chip.gpiobase);
+ release_mem_region(gpiobase_phys, AMD_GPIO_MEM_MAP_SIZE);
+
+ return 0;
+}
+
+static struct platform_driver amd_gpio_driver = {
+ .probe = amd_gpio_init,
+ .remove = amd_gpio_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = GPIO_MODULE_NAME,
+ },
+};
+
+/* interface to debug driver for gpio */
+
+static int amd_gpio_swctrlen(int offset, int value)
+{
+ struct amd_gpio_chip *chip = &amd_gpio_chip;
+ u32 gpio_reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ pr_info("GPIO %u is reserved\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in output mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ /* enable or disable sw input */
+ if(value)
+ gpio_reg |= AMD_GPIO_SWCTRL_EN;
+ else
+ gpio_reg &= ~AMD_GPIO_SWCTRL_EN;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int amd_gpio_swctrlin(int offset, int value)
+{
+ struct amd_gpio_chip *chip = &amd_gpio_chip;
+ u32 gpio_reg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ /* If the mask says the pin should be GPO, we return from here */
+ if (mask[offset] == AMD_GPIO_MODE_RESV) {
+ pr_info("GPIO %u is reserved\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ if (mask[offset] == AMD_GPIO_MODE_OUTPUT) {
+ pr_info("GPIO %u can only be set in input mode\n", offset);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ gpio_reg = ioread32((u32 *)amd_gpio_chip.gpiobase + offset);
+ /* Disable output by set the bit to 0 */
+ gpio_reg &= ~AMD_GPIO_OUTPUT_ENABLE;
+ /* enable or disable sw input */
+ if(value)
+ gpio_reg |= AMD_GPIO_SWCTRL_IN;
+ else
+ gpio_reg &= ~AMD_GPIO_SWCTRL_IN;
+
+ iowrite32(gpio_reg, ((u32 *)amd_gpio_chip.gpiobase + offset));
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+
+static int gpio_test_open(struct inode *inode, struct file *filp)
+{
+ struct gpio_test_dev *dev; /* device information */
+
+ dev = container_of(inode->i_cdev, struct gpio_test_dev, cdev);
+ filp->private_data = dev; /* for other methods */
+
+ return 0; /* success */
+}
+
+static int gpio_test_release(struct inode *inode, struct file *filp)
+{
+ return 0;
+}
+
+static long gpio_test_ioctl(struct file *filp,
+ unsigned cmd, unsigned long arg)
+{
+
+ debug_data tmp;
+ unsigned long retval = 0;
+
+ /* Check type and command number */
+ if (_IOC_TYPE(cmd) != GPIO_TEST_IOC_MAGIC)
+ return -ENOTTY;
+
+ retval = copy_from_user(&tmp, (void __user *)arg, sizeof(debug_data));
+ if(retval != 0)
+ return 0;
+
+ switch(cmd) {
+ case GPIO_IOC_SWCTRLIN:
+ retval = amd_gpio_swctrlin(tmp.offset,tmp.value);
+ break;
+ case GPIO_IOC_SWCTRLEN:
+ retval = amd_gpio_swctrlen(tmp.offset,tmp.value);
+ break;
+ default:
+ return -ENOTTY;
+ }
+
+ return retval;
+}
+
+struct file_operations gpio_test_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = gpio_test_ioctl,
+ .open = gpio_test_open,
+ .release = gpio_test_release,
+};
+
+
+static int __init amd_gpio_init_module(void)
+{
+ int err;
+ dev_t dev = 0;
+ struct device *gpio_device = 0;
+
+ pr_info("AMD GPIO Driver v%s\n", GPIO_VERSION);
+
+ err = platform_driver_register(&amd_gpio_driver);
+ if (err)
+ return err;
+
+ err = alloc_chrdev_region(&dev, dev_minor, 1,"gpio_test_driver");
+ if (err < 0) {
+ printk(KERN_WARNING " can't get major %d\n", dev_major);
+ goto unreg_platform_driver;
+ }
+
+ gpio_test_dev.gpio_class = class_create(THIS_MODULE, "gpio_test_driver");
+ if (IS_ERR(gpio_test_dev.gpio_class)) {
+ printk(" error in class create \n");
+ goto unregister_test_driver;
+ }
+
+ dev_major = MAJOR(dev);
+
+ gpio_device = device_create(gpio_test_dev.gpio_class, NULL, dev, NULL,
+ "gpio_test_driver");
+ if (IS_ERR(gpio_device)) {
+ printk(" error in device create \n");
+ goto destroy_class;
+ }
+
+ cdev_init(&gpio_test_dev.cdev, &gpio_test_fops);
+ err = cdev_add (&gpio_test_dev.cdev, dev, 1);
+ if(err)
+ goto destroy_device;
+
+ amd_gpio_platform_device = platform_device_register_simple(
+ GPIO_MODULE_NAME, -1, NULL, 0);
+ if (IS_ERR(amd_gpio_platform_device)) {
+ err = PTR_ERR(amd_gpio_platform_device);
+ goto cdev_delete;
+ }
+
+ return 0;
+
+cdev_delete:
+ cdev_del(&gpio_test_dev.cdev);
+destroy_device:
+ device_destroy(gpio_test_dev.gpio_class, dev);
+destroy_class:
+ class_destroy(gpio_test_dev.gpio_class);
+unregister_test_driver:
+ unregister_chrdev_region(dev, 1);
+unreg_platform_driver:
+ platform_driver_unregister(&amd_gpio_driver);
+ return err;
+}
+
+static void __exit amd_gpio_cleanup_module(void)
+{
+ dev_t dev = MKDEV(dev_major, dev_minor);
+
+ device_destroy(gpio_test_dev.gpio_class, dev);
+ class_destroy(gpio_test_dev.gpio_class);
+ cdev_del(&gpio_test_dev.cdev);
+ unregister_chrdev_region(dev, 1);
+ platform_device_unregister(amd_gpio_platform_device);
+ platform_driver_unregister(&amd_gpio_driver);
+ pr_info("AMD GPIO Module Unloaded\n");
+}
+
+module_init(amd_gpio_init_module);
+module_exit(amd_gpio_cleanup_module);
+
+
+
+MODULE_AUTHOR("Sudheesh Mavila <sudheesh.mavila@amd.com>");
+MODULE_DESCRIPTION("GPIO driver for AMD chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h
new file mode 100644
index 00000000..5574ef53
--- /dev/null
+++ b/meta-steppeeagle/recipes-kernel/amd-gpio/files/gpio-amd.h
@@ -0,0 +1,85 @@
+#ifndef _AMD_GPIO_H_
+#define _AMD_GPIO_H_
+
+#include <linux/types.h>
+
+/* Module and version information */
+#define GPIO_VERSION "0.1"
+#define GPIO_MODULE_NAME "AMD GPIO"
+#define GPIO_DRIVER_NAME GPIO_MODULE_NAME ", v" GPIO_VERSION
+
+#define DRV_NAME "amd-gpio"
+
+/* GPIO register definitions */
+#define AMD_GPIO_ACPIMMIO_BASE 0xFED80000
+#define AMD_GPIO_BANK_OFFSET 0x1500
+#define AMD_GPIO_MEM_MAP_SIZE 0x300
+#define AMD_GPIO_MSWITCH 63
+
+#define AMD_IOMUX_MEM_MAP_OFFSET 0x0D00
+#define AMD_IOMUX_MEM_MAP_SIZE 0x100
+
+#define AMD_PM_IOPORTS_SIZE 0x02
+
+/* IO port address for indirect access using the ACPI PM registers */
+#define AMD_IO_PM_INDEX_REG 0xCD6
+#define AMD_IO_PM_DATA_REG 0xCD7
+
+#define AMD_GPIO_NUM_PINS 184
+
+#define AMD_GPIO_DEB_TIMEOUT0 (0) /* debouncing logic disabled */
+#define AMD_GPIO_DEB_TIMEOUT1 (1)
+#define AMD_GPIO_DEB_TIMEOUT_MASK (7)
+#define AMD_GPIO_DEB_TIMEOUTUNIT (1 << 4)
+#define AMD_GPIO_DEB_CTRL (3 << 5)
+#define AMD_GPIO_LEVL_TRG (1 << 8) /* 0 - edge , 1 level */
+#define AMD_GPIO_ACTIVE_LEVEL (3 << 9)
+#define AMD_GPIO_INTERPT_ENABLE (3 << 11)
+#define AMD_GPIO_WAKECTRL (7 << 13)
+#define AMD_GPIO_GET_INPUT (1 << 16)
+#define AMD_GPIO_DRV_STRENGTH(x) (((x) & 3) << 17)
+#define AMD_GPIO_PULLUP_SEL (1 << 19)
+#define AMD_GPIO_PULLUP_ENABLE (1 << 20)
+#define AMD_GPIO_PULLDN_ENABLE (1 << 21)
+#define AMD_GPIO_SET_OUTPUT (1 << 22)
+#define AMD_GPIO_OUTPUT_ENABLE (1 << 23)
+#define AMD_GPIO_SWCTRL_IN (1 << 24)
+#define AMD_GPIO_SWCTRL_EN (1 << 25)
+#define AMD_GPIO_INTERPT_STATUS (1 << 28)
+#define AMD_GPIO_WAKE_STATUS (1 << 29)
+
+#define AMD_GPIO_WAKE_EN (1 << 31)
+#define AMD_GPIO_INTERRUPT_EN (1 << 30)
+
+#define AMD_IOMUX_ENABLE_FUNC0 0x0
+#define AMD_IOMUX_ENABLE_FUNC1 0x1
+#define AMD_IOMUX_ENABLE_FUNC2 0x2
+#define AMD_IOMUX_ENABLE_FUNC3 0x3
+#define AMD_IOMUX_GPIO_MASK 0x03
+
+#define AMD_PM_GPIO_BASE0 0x24
+#define AMD_PM_GPIO_BASE1 0x25
+#define AMD_PM_GPIO_BASE2 0x26
+#define AMD_PM_GPIO_BASE3 0x27
+
+
+
+
+/* GPIO pin mode definitions */
+#define AMD_GPIO_MODE_RESV 0 /* Reserved */
+#define AMD_GPIO_MODE_ANY 1 /* Either input or output */
+#define AMD_GPIO_MODE_INPUT 2 /* GPI */
+#define AMD_GPIO_MODE_OUTPUT 3 /* GPO */
+
+/* IOCTL numbers */
+
+typedef struct {
+ int offset;
+ int value;
+}debug_data;
+
+#define GPIO_TEST_IOC_MAGIC 'k'
+#define GPIO_IOC_SWCTRLIN _IOW(GPIO_TEST_IOC_MAGIC, 1, debug_data)
+#define GPIO_IOC_SWCTRLEN _IOW(GPIO_TEST_IOC_MAGIC, 2, debug_data)
+
+#endif /* _AMD_GPIO_H_ */