x86: gpio: Allow the pinctrl driver to set up the pin config
[oweals/u-boot.git] / drivers / gpio / intel_ich6_gpio.c
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 <syscon.h>
36 #include <asm/cpu.h>
37 #include <asm/gpio.h>
38 #include <asm/io.h>
39 #include <asm/pci.h>
40
41 DECLARE_GLOBAL_DATA_PTR;
42
43 #define GPIO_PER_BANK   32
44
45 struct ich6_bank_priv {
46         /* These are I/O addresses */
47         uint16_t use_sel;
48         uint16_t io_sel;
49         uint16_t lvl;
50 };
51
52 #define GPIO_USESEL_OFFSET(x)   (x)
53 #define GPIO_IOSEL_OFFSET(x)    (x + 4)
54 #define GPIO_LVL_OFFSET(x)      (x + 8)
55
56 /* TODO: Move this to device tree, or platform data */
57 void ich_gpio_set_gpio_map(const struct pch_gpio_map *map)
58 {
59         gd->arch.gpio_map = map;
60 }
61
62 static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value)
63 {
64         u32 val;
65
66         val = inl(base);
67         if (value)
68                 val |= (1UL << offset);
69         else
70                 val &= ~(1UL << offset);
71         outl(val, base);
72
73         return 0;
74 }
75
76 static int _ich6_gpio_set_direction(uint16_t base, unsigned offset, int dir)
77 {
78         u32 val;
79
80         if (!dir) {
81                 val = inl(base);
82                 val |= (1UL << offset);
83                 outl(val, base);
84         } else {
85                 val = inl(base);
86                 val &= ~(1UL << offset);
87                 outl(val, base);
88         }
89
90         return 0;
91 }
92
93 int gpio_ich6_pinctrl_init(void)
94 {
95         return 0;
96 }
97
98 static int gpio_ich6_ofdata_to_platdata(struct udevice *dev)
99 {
100         struct ich6_bank_platdata *plat = dev_get_platdata(dev);
101         u32 gpiobase;
102         int offset;
103         int ret;
104
105         ret = pch_get_gpio_base(dev->parent, &gpiobase);
106         if (ret)
107                 return ret;
108
109         offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1);
110         if (offset == -1) {
111                 debug("%s: Invalid register offset %d\n", __func__, offset);
112                 return -EINVAL;
113         }
114         plat->offset = offset;
115         plat->base_addr = gpiobase + offset;
116         plat->bank_name = fdt_getprop(gd->fdt_blob, dev->of_offset,
117                                       "bank-name", NULL);
118
119         return 0;
120 }
121
122 static int ich6_gpio_probe(struct udevice *dev)
123 {
124         struct ich6_bank_platdata *plat = dev_get_platdata(dev);
125         struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
126         struct ich6_bank_priv *bank = dev_get_priv(dev);
127         struct udevice *pinctrl;
128
129         /* Set up pin control if available */
130         syscon_get_by_driver_data(X86_SYSCON_PINCONF, &pinctrl);
131
132         uc_priv->gpio_count = GPIO_PER_BANK;
133         uc_priv->bank_name = plat->bank_name;
134         bank->use_sel = plat->base_addr;
135         bank->io_sel = plat->base_addr + 4;
136         bank->lvl = plat->base_addr + 8;
137
138         return 0;
139 }
140
141 static int ich6_gpio_request(struct udevice *dev, unsigned offset,
142                              const char *label)
143 {
144         struct ich6_bank_priv *bank = dev_get_priv(dev);
145         u32 tmplong;
146
147         /*
148          * Make sure that the GPIO pin we want isn't already in use for some
149          * built-in hardware function. We have to check this for every
150          * requested pin.
151          */
152         tmplong = inl(bank->use_sel);
153         if (!(tmplong & (1UL << offset))) {
154                 debug("%s: gpio %d is reserved for internal use\n", __func__,
155                       offset);
156                 return -EPERM;
157         }
158
159         return 0;
160 }
161
162 static int ich6_gpio_direction_input(struct udevice *dev, unsigned offset)
163 {
164         struct ich6_bank_priv *bank = dev_get_priv(dev);
165
166         return _ich6_gpio_set_direction(bank->io_sel, offset, 0);
167 }
168
169 static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset,
170                                        int value)
171 {
172         int ret;
173         struct ich6_bank_priv *bank = dev_get_priv(dev);
174
175         ret = _ich6_gpio_set_direction(bank->io_sel, offset, 1);
176         if (ret)
177                 return ret;
178
179         return _ich6_gpio_set_value(bank->lvl, offset, value);
180 }
181
182 static int ich6_gpio_get_value(struct udevice *dev, unsigned offset)
183 {
184         struct ich6_bank_priv *bank = dev_get_priv(dev);
185         u32 tmplong;
186         int r;
187
188         tmplong = inl(bank->lvl);
189         r = (tmplong & (1UL << offset)) ? 1 : 0;
190         return r;
191 }
192
193 static int ich6_gpio_set_value(struct udevice *dev, unsigned offset,
194                                int value)
195 {
196         struct ich6_bank_priv *bank = dev_get_priv(dev);
197         return _ich6_gpio_set_value(bank->lvl, offset, value);
198 }
199
200 static int ich6_gpio_get_function(struct udevice *dev, unsigned offset)
201 {
202         struct ich6_bank_priv *bank = dev_get_priv(dev);
203         u32 mask = 1UL << offset;
204
205         if (!(inl(bank->use_sel) & mask))
206                 return GPIOF_FUNC;
207         if (inl(bank->io_sel) & mask)
208                 return GPIOF_INPUT;
209         else
210                 return GPIOF_OUTPUT;
211 }
212
213 static const struct dm_gpio_ops gpio_ich6_ops = {
214         .request                = ich6_gpio_request,
215         .direction_input        = ich6_gpio_direction_input,
216         .direction_output       = ich6_gpio_direction_output,
217         .get_value              = ich6_gpio_get_value,
218         .set_value              = ich6_gpio_set_value,
219         .get_function           = ich6_gpio_get_function,
220 };
221
222 static const struct udevice_id intel_ich6_gpio_ids[] = {
223         { .compatible = "intel,ich6-gpio" },
224         { }
225 };
226
227 U_BOOT_DRIVER(gpio_ich6) = {
228         .name   = "gpio_ich6",
229         .id     = UCLASS_GPIO,
230         .of_match = intel_ich6_gpio_ids,
231         .ops    = &gpio_ich6_ops,
232         .ofdata_to_platdata     = gpio_ich6_ofdata_to_platdata,
233         .probe  = ich6_gpio_probe,
234         .priv_auto_alloc_size = sizeof(struct ich6_bank_priv),
235         .platdata_auto_alloc_size = sizeof(struct ich6_bank_platdata),
236 };