Commit 55ae10f8dbdf306e210240937ee4d558c8590447

Authored by Bill Richardson
Committed by Simon Glass
1 parent 468ebf190a

x86: gpio: Add GPIO driver for Intel ICH6 and later.

Implement <asm-generic/gpio.h> functions for Intel ICH6 and later.
Only GPIOs 0-31 are handled by this code.

Signed-off-by: Bill Richardson <wfrichar@chromium.org>

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 4 changed files with 393 additions and 0 deletions Side-by-side Diff

arch/x86/include/asm/gpio.h
  1 +/*
  2 + * Copyright (c) 2012, Google Inc. All rights reserved.
  3 + * See file CREDITS for list of people who contributed to this
  4 + * project.
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation; either version 2 of
  9 + * the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + */
  21 +
  22 +#ifndef _X86_GPIO_H_
  23 +#define _X86_GPIO_H_
  24 +
  25 +#include <asm-generic/gpio.h>
  26 +
  27 +#endif /* _X86_GPIO_H_ */
drivers/gpio/Makefile
... ... @@ -26,6 +26,7 @@
26 26 LIB := $(obj)libgpio.o
27 27  
28 28 COBJS-$(CONFIG_AT91_GPIO) += at91_gpio.o
  29 +COBJS-$(CONFIG_INTEL_ICH6_GPIO) += intel_ich6_gpio.o
29 30 COBJS-$(CONFIG_KIRKWOOD_GPIO) += kw_gpio.o
30 31 COBJS-$(CONFIG_MARVELL_GPIO) += mvgpio.o
31 32 COBJS-$(CONFIG_MARVELL_MFP) += mvmfp.o
drivers/gpio/intel_ich6_gpio.c
  1 +/*
  2 + * Copyright (c) 2012 The Chromium OS Authors.
  3 + * See file CREDITS for list of people who contributed to this
  4 + * project.
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License as
  8 + * published by the Free Software Foundation; either version 2 of
  9 + * the License, or (at your option) any later version.
  10 + *
  11 + * This program is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14 + * GNU General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU General Public License
  17 + * along with this program; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  19 + * MA 02111-1307 USA
  20 + */
  21 +
  22 +/*
  23 + * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed
  24 + * through the PCI bus. Each PCI device has 256 bytes of configuration space,
  25 + * consisting of a standard header and a device-specific set of registers. PCI
  26 + * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among
  27 + * other things). Within the PCI configuration space, the GPIOBASE register
  28 + * tells us where in the device's I/O region we can find more registers to
  29 + * actually access the GPIOs.
  30 + *
  31 + * PCI bus/device/function 0:1f:0 => PCI config registers
  32 + * PCI config register "GPIOBASE"
  33 + * PCI I/O space + [GPIOBASE] => start of GPIO registers
  34 + * GPIO registers => gpio pin function, direction, value
  35 + */
  36 +
  37 +#include <common.h>
  38 +#include <pci.h>
  39 +#include <asm/gpio.h>
  40 +#include <asm/io.h>
  41 +
  42 +/* Where in config space is the register that points to the GPIO registers? */
  43 +#define PCI_CFG_GPIOBASE 0x48
  44 +
  45 +/*
  46 + * There are often more than 32 GPIOs, depending on the ICH version.
  47 + * For now, we just support bank 0 because it's the same for all.
  48 + */
  49 +#define GPIO_MAX 31
  50 +
  51 +/* Within the I/O space, where are the registers to control the GPIOs? */
  52 +#define OFS_GPIO_USE_SEL 0x00
  53 +#define OFS_GPIO_IO_SEL 0x04
  54 +#define OFS_GP_LVL 0x0C
  55 +
  56 +static pci_dev_t dev; /* handle for 0:1f:0 */
  57 +static u32 gpiobase; /* offset into I/O space */
  58 +static int found_it_once; /* valid GPIO device? */
  59 +static int in_use[GPIO_MAX]; /* "lock" for access to pins */
  60 +
  61 +static int gpio_init(void)
  62 +{
  63 + u8 tmpbyte;
  64 + u16 tmpword;
  65 + u32 tmplong;
  66 +
  67 + /* Have we already done this? */
  68 + if (found_it_once)
  69 + return 0;
  70 +
  71 + /* Where should it be? */
  72 + dev = PCI_BDF(0, 0x1f, 0);
  73 +
  74 + /* Is the device present? */
  75 + pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
  76 + if (tmpword != PCI_VENDOR_ID_INTEL) {
  77 + debug("%s: wrong VendorID\n", __func__);
  78 + return -1;
  79 + }
  80 + /*
  81 + * We'd like to check the Device ID too, but pretty much any
  82 + * value is either a) correct with slight differences, or b)
  83 + * correct but undocumented. We'll have to check other things
  84 + * instead...
  85 + */
  86 +
  87 + /* I/O should already be enabled (it's a RO bit). */
  88 + pci_read_config_word(dev, PCI_COMMAND, &tmpword);
  89 + if (!(tmpword & PCI_COMMAND_IO)) {
  90 + debug("%s: device IO not enabled\n", __func__);
  91 + return -1;
  92 + }
  93 +
  94 + /* Header Type must be normal (bits 6-0 only; see spec.) */
  95 + pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
  96 + if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
  97 + debug("%s: invalid Header type\n", __func__);
  98 + return -1;
  99 + }
  100 +
  101 + /* Base Class must be a bridge device */
  102 + pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
  103 + if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
  104 + debug("%s: invalid class\n", __func__);
  105 + return -1;
  106 + }
  107 + /* Sub Class must be ISA */
  108 + pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
  109 + if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
  110 + debug("%s: invalid subclass\n", __func__);
  111 + return -1;
  112 + }
  113 +
  114 + /* Programming Interface must be 0x00 (no others exist) */
  115 + pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
  116 + if (tmpbyte != 0x00) {
  117 + debug("%s: invalid interface type\n", __func__);
  118 + return -1;
  119 + }
  120 +
  121 + /*
  122 + * GPIOBASE moved to its current offset with ICH6, but prior to
  123 + * that it was unused (or undocumented). Check that it looks
  124 + * okay: not all ones or zeros, and mapped to I/O space (bit 0).
  125 + */
  126 + pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
  127 + if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
  128 + !(tmplong & 0x00000001)) {
  129 + debug("%s: unexpected GPIOBASE value\n", __func__);
  130 + return -1;
  131 + }
  132 +
  133 + /*
  134 + * Okay, I guess we're looking at the right device. The actual
  135 + * GPIO registers are in the PCI device's I/O space, starting
  136 + * at the offset that we just read. Bit 0 indicates that it's
  137 + * an I/O address, not a memory address, so mask that off.
  138 + */
  139 + gpiobase = tmplong & 0xfffffffe;
  140 +
  141 + /* Finally. These are the droids we're looking for. */
  142 + found_it_once = 1;
  143 + return 0;
  144 +}
  145 +
  146 +int gpio_request(unsigned gpio, const char *label /* UNUSED */)
  147 +{
  148 + u32 tmplong;
  149 +
  150 + /* Are we doing it wrong? */
  151 + if (gpio > GPIO_MAX || in_use[gpio]) {
  152 + debug("%s: gpio unavailable\n", __func__);
  153 + return -1;
  154 + }
  155 +
  156 + /* Is the hardware ready? */
  157 + if (gpio_init()) {
  158 + debug("%s: gpio_init failed\n", __func__);
  159 + return -1;
  160 + }
  161 +
  162 + /*
  163 + * Make sure that the GPIO pin we want isn't already in use for some
  164 + * built-in hardware function. We have to check this for every
  165 + * requested pin.
  166 + */
  167 + tmplong = inl(gpiobase + OFS_GPIO_USE_SEL);
  168 + if (!(tmplong & (1UL << gpio))) {
  169 + debug("%s: reserved for internal use\n", __func__);
  170 + return -1;
  171 + }
  172 +
  173 + in_use[gpio] = 1;
  174 + return 0;
  175 +}
  176 +
  177 +int gpio_free(unsigned gpio)
  178 +{
  179 + if (gpio > GPIO_MAX || !in_use[gpio]) {
  180 + debug("%s: gpio unavailable\n", __func__);
  181 + return -1;
  182 + }
  183 + in_use[gpio] = 0;
  184 + return 0;
  185 +}
  186 +
  187 +int gpio_direction_input(unsigned gpio)
  188 +{
  189 + u32 tmplong;
  190 +
  191 + if (gpio > GPIO_MAX || !in_use[gpio]) {
  192 + debug("%s: gpio unavailable\n", __func__);
  193 + return -1;
  194 + }
  195 + tmplong = inl(gpiobase + OFS_GPIO_IO_SEL);
  196 + tmplong |= (1UL << gpio);
  197 + outl(gpiobase + OFS_GPIO_IO_SEL, tmplong);
  198 + return 0;
  199 +}
  200 +
  201 +int gpio_direction_output(unsigned gpio, int value)
  202 +{
  203 + u32 tmplong;
  204 +
  205 + if (gpio > GPIO_MAX || !in_use[gpio]) {
  206 + debug("%s: gpio unavailable\n", __func__);
  207 + return -1;
  208 + }
  209 + tmplong = inl(gpiobase + OFS_GPIO_IO_SEL);
  210 + tmplong &= ~(1UL << gpio);
  211 + outl(gpiobase + OFS_GPIO_IO_SEL, tmplong);
  212 + return 0;
  213 +}
  214 +
  215 +int gpio_get_value(unsigned gpio)
  216 +{
  217 + u32 tmplong;
  218 +
  219 + if (gpio > GPIO_MAX || !in_use[gpio]) {
  220 + debug("%s: gpio unavailable\n", __func__);
  221 + return -1;
  222 + }
  223 + tmplong = inl(gpiobase + OFS_GP_LVL);
  224 + return (tmplong & (1UL << gpio)) ? 1 : 0;
  225 +}
  226 +
  227 +int gpio_set_value(unsigned gpio, int value)
  228 +{
  229 + u32 tmplong;
  230 +
  231 + if (gpio > GPIO_MAX || !in_use[gpio]) {
  232 + debug("%s: gpio unavailable\n", __func__);
  233 + return -1;
  234 + }
  235 + tmplong = inl(gpiobase + OFS_GP_LVL);
  236 + if (value)
  237 + tmplong |= (1UL << gpio);
  238 + else
  239 + tmplong &= ~(1UL << gpio);
  240 + outl(gpiobase + OFS_GP_LVL, tmplong);
  241 + return 0;
  242 +}
... ... @@ -67,7 +67,130 @@
67 67 #define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
68 68 #define PCI_CLASS_DEVICE 0x0a /* Device class */
69 69 #define PCI_CLASS_CODE 0x0b /* Device class code */
  70 +#define PCI_CLASS_CODE_TOO_OLD 0x00
  71 +#define PCI_CLASS_CODE_STORAGE 0x01
  72 +#define PCI_CLASS_CODE_NETWORK 0x02
  73 +#define PCI_CLASS_CODE_DISPLAY 0x03
  74 +#define PCI_CLASS_CODE_MULTIMEDIA 0x04
  75 +#define PCI_CLASS_CODE_MEMORY 0x05
  76 +#define PCI_CLASS_CODE_BRIDGE 0x06
  77 +#define PCI_CLASS_CODE_COMM 0x07
  78 +#define PCI_CLASS_CODE_PERIPHERAL 0x08
  79 +#define PCI_CLASS_CODE_INPUT 0x09
  80 +#define PCI_CLASS_CODE_DOCKING 0x0A
  81 +#define PCI_CLASS_CODE_PROCESSOR 0x0B
  82 +#define PCI_CLASS_CODE_SERIAL 0x0C
  83 +#define PCI_CLASS_CODE_WIRELESS 0x0D
  84 +#define PCI_CLASS_CODE_I2O 0x0E
  85 +#define PCI_CLASS_CODE_SATELLITE 0x0F
  86 +#define PCI_CLASS_CODE_CRYPTO 0x10
  87 +#define PCI_CLASS_CODE_DATA 0x11
  88 +/* Base Class 0x12 - 0xFE is reserved */
  89 +#define PCI_CLASS_CODE_OTHER 0xFF
  90 +
70 91 #define PCI_CLASS_SUB_CODE 0x0a /* Device sub-class code */
  92 +#define PCI_CLASS_SUB_CODE_TOO_OLD_NOTVGA 0x00
  93 +#define PCI_CLASS_SUB_CODE_TOO_OLD_VGA 0x01
  94 +#define PCI_CLASS_SUB_CODE_STORAGE_SCSI 0x00
  95 +#define PCI_CLASS_SUB_CODE_STORAGE_IDE 0x01
  96 +#define PCI_CLASS_SUB_CODE_STORAGE_FLOPPY 0x02
  97 +#define PCI_CLASS_SUB_CODE_STORAGE_IPIBUS 0x03
  98 +#define PCI_CLASS_SUB_CODE_STORAGE_RAID 0x04
  99 +#define PCI_CLASS_SUB_CODE_STORAGE_ATA 0x05
  100 +#define PCI_CLASS_SUB_CODE_STORAGE_SATA 0x06
  101 +#define PCI_CLASS_SUB_CODE_STORAGE_SAS 0x07
  102 +#define PCI_CLASS_SUB_CODE_STORAGE_OTHER 0x80
  103 +#define PCI_CLASS_SUB_CODE_NETWORK_ETHERNET 0x00
  104 +#define PCI_CLASS_SUB_CODE_NETWORK_TOKENRING 0x01
  105 +#define PCI_CLASS_SUB_CODE_NETWORK_FDDI 0x02
  106 +#define PCI_CLASS_SUB_CODE_NETWORK_ATM 0x03
  107 +#define PCI_CLASS_SUB_CODE_NETWORK_ISDN 0x04
  108 +#define PCI_CLASS_SUB_CODE_NETWORK_WORLDFIP 0x05
  109 +#define PCI_CLASS_SUB_CODE_NETWORK_PICMG 0x06
  110 +#define PCI_CLASS_SUB_CODE_NETWORK_OTHER 0x80
  111 +#define PCI_CLASS_SUB_CODE_DISPLAY_VGA 0x00
  112 +#define PCI_CLASS_SUB_CODE_DISPLAY_XGA 0x01
  113 +#define PCI_CLASS_SUB_CODE_DISPLAY_3D 0x02
  114 +#define PCI_CLASS_SUB_CODE_DISPLAY_OTHER 0x80
  115 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_VIDEO 0x00
  116 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_AUDIO 0x01
  117 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_PHONE 0x02
  118 +#define PCI_CLASS_SUB_CODE_MULTIMEDIA_OTHER 0x80
  119 +#define PCI_CLASS_SUB_CODE_MEMORY_RAM 0x00
  120 +#define PCI_CLASS_SUB_CODE_MEMORY_FLASH 0x01
  121 +#define PCI_CLASS_SUB_CODE_MEMORY_OTHER 0x80
  122 +#define PCI_CLASS_SUB_CODE_BRIDGE_HOST 0x00
  123 +#define PCI_CLASS_SUB_CODE_BRIDGE_ISA 0x01
  124 +#define PCI_CLASS_SUB_CODE_BRIDGE_EISA 0x02
  125 +#define PCI_CLASS_SUB_CODE_BRIDGE_MCA 0x03
  126 +#define PCI_CLASS_SUB_CODE_BRIDGE_PCI 0x04
  127 +#define PCI_CLASS_SUB_CODE_BRIDGE_PCMCIA 0x05
  128 +#define PCI_CLASS_SUB_CODE_BRIDGE_NUBUS 0x06
  129 +#define PCI_CLASS_SUB_CODE_BRIDGE_CARDBUS 0x07
  130 +#define PCI_CLASS_SUB_CODE_BRIDGE_RACEWAY 0x08
  131 +#define PCI_CLASS_SUB_CODE_BRIDGE_SEMI_PCI 0x09
  132 +#define PCI_CLASS_SUB_CODE_BRIDGE_INFINIBAND 0x0A
  133 +#define PCI_CLASS_SUB_CODE_BRIDGE_OTHER 0x80
  134 +#define PCI_CLASS_SUB_CODE_COMM_SERIAL 0x00
  135 +#define PCI_CLASS_SUB_CODE_COMM_PARALLEL 0x01
  136 +#define PCI_CLASS_SUB_CODE_COMM_MULTIPORT 0x02
  137 +#define PCI_CLASS_SUB_CODE_COMM_MODEM 0x03
  138 +#define PCI_CLASS_SUB_CODE_COMM_GPIB 0x04
  139 +#define PCI_CLASS_SUB_CODE_COMM_SMARTCARD 0x05
  140 +#define PCI_CLASS_SUB_CODE_COMM_OTHER 0x80
  141 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_PIC 0x00
  142 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_DMA 0x01
  143 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_TIMER 0x02
  144 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_RTC 0x03
  145 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_HOTPLUG 0x04
  146 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_SD 0x05
  147 +#define PCI_CLASS_SUB_CODE_PERIPHERAL_OTHER 0x80
  148 +#define PCI_CLASS_SUB_CODE_INPUT_KEYBOARD 0x00
  149 +#define PCI_CLASS_SUB_CODE_INPUT_DIGITIZER 0x01
  150 +#define PCI_CLASS_SUB_CODE_INPUT_MOUSE 0x02
  151 +#define PCI_CLASS_SUB_CODE_INPUT_SCANNER 0x03
  152 +#define PCI_CLASS_SUB_CODE_INPUT_GAMEPORT 0x04
  153 +#define PCI_CLASS_SUB_CODE_INPUT_OTHER 0x80
  154 +#define PCI_CLASS_SUB_CODE_DOCKING_GENERIC 0x00
  155 +#define PCI_CLASS_SUB_CODE_DOCKING_OTHER 0x80
  156 +#define PCI_CLASS_SUB_CODE_PROCESSOR_386 0x00
  157 +#define PCI_CLASS_SUB_CODE_PROCESSOR_486 0x01
  158 +#define PCI_CLASS_SUB_CODE_PROCESSOR_PENTIUM 0x02
  159 +#define PCI_CLASS_SUB_CODE_PROCESSOR_ALPHA 0x10
  160 +#define PCI_CLASS_SUB_CODE_PROCESSOR_POWERPC 0x20
  161 +#define PCI_CLASS_SUB_CODE_PROCESSOR_MIPS 0x30
  162 +#define PCI_CLASS_SUB_CODE_PROCESSOR_COPROC 0x40
  163 +#define PCI_CLASS_SUB_CODE_SERIAL_1394 0x00
  164 +#define PCI_CLASS_SUB_CODE_SERIAL_ACCESSBUS 0x01
  165 +#define PCI_CLASS_SUB_CODE_SERIAL_SSA 0x02
  166 +#define PCI_CLASS_SUB_CODE_SERIAL_USB 0x03
  167 +#define PCI_CLASS_SUB_CODE_SERIAL_FIBRECHAN 0x04
  168 +#define PCI_CLASS_SUB_CODE_SERIAL_SMBUS 0x05
  169 +#define PCI_CLASS_SUB_CODE_SERIAL_INFINIBAND 0x06
  170 +#define PCI_CLASS_SUB_CODE_SERIAL_IPMI 0x07
  171 +#define PCI_CLASS_SUB_CODE_SERIAL_SERCOS 0x08
  172 +#define PCI_CLASS_SUB_CODE_SERIAL_CANBUS 0x09
  173 +#define PCI_CLASS_SUB_CODE_WIRELESS_IRDA 0x00
  174 +#define PCI_CLASS_SUB_CODE_WIRELESS_IR 0x01
  175 +#define PCI_CLASS_SUB_CODE_WIRELESS_RF 0x10
  176 +#define PCI_CLASS_SUB_CODE_WIRELESS_BLUETOOTH 0x11
  177 +#define PCI_CLASS_SUB_CODE_WIRELESS_BROADBAND 0x12
  178 +#define PCI_CLASS_SUB_CODE_WIRELESS_80211A 0x20
  179 +#define PCI_CLASS_SUB_CODE_WIRELESS_80211B 0x21
  180 +#define PCI_CLASS_SUB_CODE_WIRELESS_OTHER 0x80
  181 +#define PCI_CLASS_SUB_CODE_I2O_V1_0 0x00
  182 +#define PCI_CLASS_SUB_CODE_SATELLITE_TV 0x01
  183 +#define PCI_CLASS_SUB_CODE_SATELLITE_AUDIO 0x02
  184 +#define PCI_CLASS_SUB_CODE_SATELLITE_VOICE 0x03
  185 +#define PCI_CLASS_SUB_CODE_SATELLITE_DATA 0x04
  186 +#define PCI_CLASS_SUB_CODE_CRYPTO_NETWORK 0x00
  187 +#define PCI_CLASS_SUB_CODE_CRYPTO_ENTERTAINMENT 0x10
  188 +#define PCI_CLASS_SUB_CODE_CRYPTO_OTHER 0x80
  189 +#define PCI_CLASS_SUB_CODE_DATA_DPIO 0x00
  190 +#define PCI_CLASS_SUB_CODE_DATA_PERFCNTR 0x01
  191 +#define PCI_CLASS_SUB_CODE_DATA_COMMSYNC 0x10
  192 +#define PCI_CLASS_SUB_CODE_DATA_MGMT 0x20
  193 +#define PCI_CLASS_SUB_CODE_DATA_OTHER 0x80
71 194  
72 195 #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
73 196 #define PCI_LATENCY_TIMER 0x0d /* 8 bits */