1 /* 2 * Copyright (c) 2012 The Chromium OS Authors. 3 * SPDX-License-Identifier: GPL-2.0+ 4 */ 5 6 /* 7 * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed 8 * through the PCI bus. Each PCI device has 256 bytes of configuration space, 9 * consisting of a standard header and a device-specific set of registers. PCI 10 * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among 11 * other things). Within the PCI configuration space, the GPIOBASE register 12 * tells us where in the device's I/O region we can find more registers to 13 * actually access the GPIOs. 14 * 15 * PCI bus/device/function 0:1f:0 => PCI config registers 16 * PCI config register "GPIOBASE" 17 * PCI I/O space + [GPIOBASE] => start of GPIO registers 18 * GPIO registers => gpio pin function, direction, value 19 * 20 * 21 * Danger Will Robinson! Bank 0 (GPIOs 0-31) seems to be fairly stable. Most 22 * ICH versions have more, but the decoding the matrix that describes them is 23 * absurdly complex and constantly changing. We'll provide Bank 1 and Bank 2, 24 * but they will ONLY work for certain unspecified chipsets because the offset 25 * from GPIOBASE changes randomly. Even then, many GPIOs are unimplemented or 26 * reserved or subject to arcane restrictions. 27 */ 28 29 #include <common.h> 30 #include <dm.h> 31 #include <errno.h> 32 #include <fdtdec.h> 33 #include <pch.h> 34 #include <pci.h> 35 #include <asm/cpu.h> 36 #include <asm/gpio.h> 37 #include <asm/io.h> 38 #include <asm/pci.h> 39 40 DECLARE_GLOBAL_DATA_PTR; 41 42 #define GPIO_PER_BANK 32 43 44 struct ich6_bank_priv { 45 /* These are I/O addresses */ 46 uint16_t use_sel; 47 uint16_t io_sel; 48 uint16_t lvl; 49 u32 lvl_write_cache; 50 bool use_lvl_write_cache; 51 }; 52 53 #define GPIO_USESEL_OFFSET(x) (x) 54 #define GPIO_IOSEL_OFFSET(x) (x + 4) 55 #define GPIO_LVL_OFFSET(x) (x + 8) 56 57 static int _ich6_gpio_set_value(struct ich6_bank_priv *bank, unsigned offset, 58 int value) 59 { 60 u32 val; 61 62 if (bank->use_lvl_write_cache) 63 val = bank->lvl_write_cache; 64 else 65 val = inl(bank->lvl); 66 67 if (value) 68 val |= (1UL << offset); 69 else 70 val &= ~(1UL << offset); 71 outl(val, bank->lvl); 72 if (bank->use_lvl_write_cache) 73 bank->lvl_write_cache = val; 74 75 return 0; 76 } 77 78 static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir) 79 { 80 u32 val; 81 82 if (!dir) { 83 val = inl(base); 84 val |= (1UL << offset); 85 outl(val, base); 86 } else { 87 val = inl(base); 88 val &= ~(1UL << offset); 89 outl(val, base); 90 } 91 92 return 0; 93 } 94 95 static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) 96 { 97 struct ich6_bank_platdata *plat = dev_get_platdata(dev); 98 u32 gpiobase; 99 int offset; 100 int ret; 101 102 ret = pch_get_gpio_base(dev->parent, &gpiobase); 103 if (ret) 104 return ret; 105 106 offset = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "reg", -1); 107 if (offset == -1) { 108 debug("%s: Invalid register offset %d\n", __func__, offset); 109 return -EINVAL; 110 } 111 plat->offset = offset; 112 plat->base_addr = gpiobase + offset; 113 plat->bank_name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), 114 "bank-name", NULL); 115 116 return 0; 117 } 118 119 static int ich6_gpio_probe(struct udevice *dev) 120 { 121 struct ich6_bank_platdata *plat = dev_get_platdata(dev); 122 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 123 struct ich6_bank_priv *bank = dev_get_priv(dev); 124 const void *prop; 125 126 uc_priv->gpio_count = GPIO_PER_BANK; 127 uc_priv->bank_name = plat->bank_name; 128 bank->use_sel = plat->base_addr; 129 bank->io_sel = plat->base_addr + 4; 130 bank->lvl = plat->base_addr + 8; 131 132 prop = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), 133 "use-lvl-write-cache", NULL); 134 if (prop) 135 bank->use_lvl_write_cache = true; 136 else 137 bank->use_lvl_write_cache = false; 138 bank->lvl_write_cache = 0; 139 140 return 0; 141 } 142 143 static int ich6_gpio_request(struct udevice *dev, unsigned offset, 144 const char *label) 145 { 146 struct ich6_bank_priv *bank = dev_get_priv(dev); 147 u32 tmplong; 148 149 /* 150 * Make sure that the GPIO pin we want isn't already in use for some 151 * built-in hardware function. We have to check this for every 152 * requested pin. 153 */ 154 tmplong = inl(bank->use_sel); 155 if (!(tmplong & (1UL << offset))) { 156 debug("%s: gpio %d is reserved for internal use\n", __func__, 157 offset); 158 return -EPERM; 159 } 160 161 return 0; 162 } 163 164 static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset) 165 { 166 struct ich6_bank_priv *bank = dev_get_priv(dev); 167 168 return _ich6_gpio_set_direction(bank->io_sel, offset, 0); 169 } 170 171 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset, 172 int value) 173 { 174 int ret; 175 struct ich6_bank_priv *bank = dev_get_priv(dev); 176 177 ret = _ich6_gpio_set_direction(bank->io_sel, offset, 1); 178 if (ret) 179 return ret; 180 181 return _ich6_gpio_set_value(bank, offset, value); 182 } 183 184 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset) 185 { 186 struct ich6_bank_priv *bank = dev_get_priv(dev); 187 u32 tmplong; 188 int r; 189 190 tmplong = inl(bank->lvl); 191 if (bank->use_lvl_write_cache) 192 tmplong |= bank->lvl_write_cache; 193 r = (tmplong & (1UL << offset)) ? 1 : 0; 194 return r; 195 } 196 197 static int ich6_gpio_set_value(struct udevice *dev, unsigned offset, 198 int value) 199 { 200 struct ich6_bank_priv *bank = dev_get_priv(dev); 201 return _ich6_gpio_set_value(bank, offset, value); 202 } 203 204 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset) 205 { 206 struct ich6_bank_priv *bank = dev_get_priv(dev); 207 u32 mask = 1UL << offset; 208 209 if (!(inl(bank->use_sel) & mask)) 210 return GPIOF_FUNC; 211 if (inl(bank->io_sel) & mask) 212 return GPIOF_INPUT; 213 else 214 return GPIOF_OUTPUT; 215 } 216 217 static const struct dm_gpio_ops gpio_ich6_ops = { 218 .request = ich6_gpio_request, 219 .direction_input = ich6_gpio_direction_input, 220 .direction_output = ich6_gpio_direction_output, 221 .get_value = ich6_gpio_get_value, 222 .set_value = ich6_gpio_set_value, 223 .get_function = ich6_gpio_get_function, 224 }; 225 226 static const struct udevice_id intel_ich6_gpio_ids[] = { 227 { .compatible = "intel,ich6-gpio" }, 228 { } 229 }; 230 231 U_BOOT_DRIVER(gpio_ich6) = { 232 .name = "gpio_ich6", 233 .id = UCLASS_GPIO, 234 .of_match = intel_ich6_gpio_ids, 235 .ops = &gpio_ich6_ops, 236 .ofdata_to_platdata = gpio_ich6_ofdata_to_platdata, 237 .probe = ich6_gpio_probe, 238 .priv_auto_alloc_size = sizeof(struct ich6_bank_priv), 239 .platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata), 240 }; 241