• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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