1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <arch/io.h>
4 #include <device/pci_ops.h>
5 #include <device/pci_type.h>
6 #include <stdint.h>
7
8 #include "gpio.h"
9
10 #define MAX_GPIO_NUMBER 75 /* zero based */
11
12 /* LPC GPIO Base Address Register */
13 #define GPIO_BASE 0x48
14
get_gpio_base(void)15 static u16 get_gpio_base(void)
16 {
17 #ifdef __SIMPLE_DEVICE__
18 /* Don't assume GPIO_BASE is still the same */
19 return pci_read_config16(PCI_DEV(0, 0x1f, 0), GPIO_BASE) & 0xfffe;
20 #else
21 static u16 gpiobase;
22
23 if (gpiobase)
24 return gpiobase;
25
26 gpiobase = pci_read_config16(pcidev_on_root(0x1f, 0), GPIO_BASE) & 0xfffe;
27
28 return gpiobase;
29 #endif
30 }
31
setup_pch_gpios(const struct pch_gpio_map * gpio)32 void setup_pch_gpios(const struct pch_gpio_map *gpio)
33 {
34 u16 gpiobase = get_gpio_base();
35
36 /* The order of these calls does matter on ICH9M and prior.
37 * The level has to be set on pins configured as gpio,
38 * but on newer platforms we want to change the level first
39 * to make sure there are no glitches on the lines !
40 * Write the gpio level twice to satisfy both requirements.
41 */
42
43 /* GPIO Set 1 */
44 if (gpio->set1.level)
45 outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL);
46 if (gpio->set1.mode)
47 outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL);
48 if (gpio->set1.direction)
49 outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL);
50 if (gpio->set1.level)
51 outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL);
52 if (gpio->set1.reset)
53 outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1);
54 if (gpio->set1.invert)
55 outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV);
56 if (gpio->set1.blink)
57 outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK);
58
59 /* GPIO Set 2 */
60 if (gpio->set2.level)
61 outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2);
62 if (gpio->set2.mode)
63 outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2);
64 if (gpio->set2.direction)
65 outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2);
66 if (gpio->set2.level)
67 outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2);
68 if (gpio->set2.reset)
69 outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2);
70
71 /* GPIO Set 3 */
72 if (gpio->set3.level)
73 outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3);
74 if (gpio->set3.mode)
75 outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3);
76 if (gpio->set3.direction)
77 outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3);
78 if (gpio->set3.level)
79 outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3);
80 if (gpio->set3.reset)
81 outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3);
82 }
83
84 /*
85 * return current gpio level.
86 */
get_gpio(int gpio_num)87 int get_gpio(int gpio_num)
88 {
89 static const int gpio_reg_offsets[] = {GP_LVL, GP_LVL2, GP_LVL3};
90 u16 gpio_base = get_gpio_base();
91 int index, bit;
92
93 if (gpio_num > MAX_GPIO_NUMBER)
94 return 0; /* Just ignore wrong gpio numbers. */
95
96 index = gpio_num / 32;
97 bit = gpio_num % 32;
98
99 return (inl(gpio_base + gpio_reg_offsets[index]) >> bit) & 1;
100 }
101
102 /*
103 * get a number comprised of multiple GPIO values. gpio_num_array points to
104 * the array of gpio pin numbers to scan, terminated by -1.
105 */
get_gpios(const int * gpio_num_array)106 unsigned int get_gpios(const int *gpio_num_array)
107 {
108 int gpio;
109 unsigned int bitmask = 1;
110 unsigned int vector = 0;
111
112 while (bitmask &&
113 ((gpio = *gpio_num_array++) != -1)) {
114 if (get_gpio(gpio))
115 vector |= bitmask;
116 bitmask <<= 1;
117 }
118 return vector;
119 }
120
121 /*
122 * set gpio output to level.
123 */
set_gpio(int gpio_num,int value)124 void set_gpio(int gpio_num, int value)
125 {
126 static const int gpio_reg_offsets[] = {
127 GP_LVL, GP_LVL2, GP_LVL3
128 };
129 u16 gpio_base = get_gpio_base();
130 int index, bit;
131 u32 config;
132
133 if (gpio_num > MAX_GPIO_NUMBER)
134 return; /* Just ignore wrong gpio numbers. */
135
136 index = gpio_num / 32;
137 bit = gpio_num % 32;
138
139 config = inl(gpio_base + gpio_reg_offsets[index]);
140 config &= ~(1 << bit);
141 if (value != 0)
142 config |= (1 << bit);
143 outl(config, gpio_base + gpio_reg_offsets[index]);
144 }
145
gpio_is_native(int gpio_num)146 int gpio_is_native(int gpio_num)
147 {
148 static const int gpio_reg_offsets[] = {
149 GPIO_USE_SEL, GPIO_USE_SEL2, GPIO_USE_SEL3
150 };
151 u16 gpio_base = get_gpio_base();
152 int index, bit;
153 u32 config;
154
155 if (gpio_num > MAX_GPIO_NUMBER)
156 return 0; /* Just ignore wrong gpio numbers. */
157
158 index = gpio_num / 32;
159 bit = gpio_num % 32;
160
161 config = inl(gpio_base + gpio_reg_offsets[index]);
162 return !(config & (1 << bit));
163 }
164