aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-sch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-sch.c')
-rw-r--r--drivers/gpio/gpio-sch.c293
1 files changed, 112 insertions, 181 deletions
diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 41e91d70301e..99720c8bc8ed 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -29,290 +29,221 @@
29 29
30#include <linux/gpio.h> 30#include <linux/gpio.h>
31 31
32static DEFINE_SPINLOCK(gpio_lock); 32#define GEN 0x00
33 33#define GIO 0x04
34#define CGEN (0x00) 34#define GLV 0x08
35#define CGIO (0x04) 35
36#define CGLV (0x08) 36struct sch_gpio {
37 37 struct gpio_chip chip;
38#define RGEN (0x20) 38 spinlock_t lock;
39#define RGIO (0x24) 39 unsigned short iobase;
40#define RGLV (0x28) 40 unsigned short core_base;
41 41 unsigned short resume_base;
42static unsigned short gpio_ba; 42};
43
44static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned gpio_num)
45{
46 u8 curr_dirs;
47 unsigned short offset, bit;
48
49 spin_lock(&gpio_lock);
50
51 offset = CGIO + gpio_num / 8;
52 bit = gpio_num % 8;
53
54 curr_dirs = inb(gpio_ba + offset);
55
56 if (!(curr_dirs & (1 << bit)))
57 outb(curr_dirs | (1 << bit), gpio_ba + offset);
58 43
59 spin_unlock(&gpio_lock); 44#define to_sch_gpio(c) container_of(c, struct sch_gpio, chip)
60 return 0;
61}
62 45
63static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num) 46static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
47 unsigned reg)
64{ 48{
65 int res; 49 unsigned base = 0;
66 unsigned short offset, bit;
67 50
68 offset = CGLV + gpio_num / 8; 51 if (gpio >= sch->resume_base) {
69 bit = gpio_num % 8; 52 gpio -= sch->resume_base;
53 base += 0x20;
54 }
70 55
71 res = !!(inb(gpio_ba + offset) & (1 << bit)); 56 return base + reg + gpio / 8;
72 return res;
73} 57}
74 58
75static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val) 59static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
76{ 60{
77 u8 curr_vals; 61 if (gpio >= sch->resume_base)
78 unsigned short offset, bit; 62 gpio -= sch->resume_base;
79 63 return gpio % 8;
80 spin_lock(&gpio_lock);
81
82 offset = CGLV + gpio_num / 8;
83 bit = gpio_num % 8;
84
85 curr_vals = inb(gpio_ba + offset);
86
87 if (val)
88 outb(curr_vals | (1 << bit), gpio_ba + offset);
89 else
90 outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
91 spin_unlock(&gpio_lock);
92} 64}
93 65
94static int sch_gpio_core_direction_out(struct gpio_chip *gc, 66static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
95 unsigned gpio_num, int val)
96{ 67{
97 u8 curr_dirs;
98 unsigned short offset, bit; 68 unsigned short offset, bit;
69 u8 enable;
99 70
100 spin_lock(&gpio_lock); 71 spin_lock(&sch->lock);
101 72
102 offset = CGIO + gpio_num / 8; 73 offset = sch_gpio_offset(sch, gpio, GEN);
103 bit = gpio_num % 8; 74 bit = sch_gpio_bit(sch, gpio);
104
105 curr_dirs = inb(gpio_ba + offset);
106 if (curr_dirs & (1 << bit))
107 outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
108 75
109 spin_unlock(&gpio_lock); 76 enable = inb(sch->iobase + offset);
77 if (!(enable & (1 << bit)))
78 outb(enable | (1 << bit), sch->iobase + offset);
110 79
111 /* 80 spin_unlock(&sch->lock);
112 * according to the datasheet, writing to the level register has no
113 * effect when GPIO is programmed as input.
114 * Actually the the level register is read-only when configured as input.
115 * Thus presetting the output level before switching to output is _NOT_ possible.
116 * Hence we set the level after configuring the GPIO as output.
117 * But we cannot prevent a short low pulse if direction is set to high
118 * and an external pull-up is connected.
119 */
120 sch_gpio_core_set(gc, gpio_num, val);
121 return 0;
122} 81}
123 82
124static struct gpio_chip sch_gpio_core = { 83static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num)
125 .label = "sch_gpio_core",
126 .owner = THIS_MODULE,
127 .direction_input = sch_gpio_core_direction_in,
128 .get = sch_gpio_core_get,
129 .direction_output = sch_gpio_core_direction_out,
130 .set = sch_gpio_core_set,
131};
132
133static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
134 unsigned gpio_num)
135{ 84{
85 struct sch_gpio *sch = to_sch_gpio(gc);
136 u8 curr_dirs; 86 u8 curr_dirs;
137 unsigned short offset, bit; 87 unsigned short offset, bit;
138 88
139 spin_lock(&gpio_lock); 89 spin_lock(&sch->lock);
140 90
141 offset = RGIO + gpio_num / 8; 91 offset = sch_gpio_offset(sch, gpio_num, GIO);
142 bit = gpio_num % 8; 92 bit = sch_gpio_bit(sch, gpio_num);
143 93
144 curr_dirs = inb(gpio_ba + offset); 94 curr_dirs = inb(sch->iobase + offset);
145 95
146 if (!(curr_dirs & (1 << bit))) 96 if (!(curr_dirs & (1 << bit)))
147 outb(curr_dirs | (1 << bit), gpio_ba + offset); 97 outb(curr_dirs | (1 << bit), sch->iobase + offset);
148 98
149 spin_unlock(&gpio_lock); 99 spin_unlock(&sch->lock);
150 return 0; 100 return 0;
151} 101}
152 102
153static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num) 103static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
154{ 104{
105 struct sch_gpio *sch = to_sch_gpio(gc);
106 int res;
155 unsigned short offset, bit; 107 unsigned short offset, bit;
156 108
157 offset = RGLV + gpio_num / 8; 109 offset = sch_gpio_offset(sch, gpio_num, GLV);
158 bit = gpio_num % 8; 110 bit = sch_gpio_bit(sch, gpio_num);
111
112 res = !!(inb(sch->iobase + offset) & (1 << bit));
159 113
160 return !!(inb(gpio_ba + offset) & (1 << bit)); 114 return res;
161} 115}
162 116
163static void sch_gpio_resume_set(struct gpio_chip *gc, 117static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
164 unsigned gpio_num, int val)
165{ 118{
119 struct sch_gpio *sch = to_sch_gpio(gc);
166 u8 curr_vals; 120 u8 curr_vals;
167 unsigned short offset, bit; 121 unsigned short offset, bit;
168 122
169 spin_lock(&gpio_lock); 123 spin_lock(&sch->lock);
170 124
171 offset = RGLV + gpio_num / 8; 125 offset = sch_gpio_offset(sch, gpio_num, GLV);
172 bit = gpio_num % 8; 126 bit = sch_gpio_bit(sch, gpio_num);
173 127
174 curr_vals = inb(gpio_ba + offset); 128 curr_vals = inb(sch->iobase + offset);
175 129
176 if (val) 130 if (val)
177 outb(curr_vals | (1 << bit), gpio_ba + offset); 131 outb(curr_vals | (1 << bit), sch->iobase + offset);
178 else 132 else
179 outb((curr_vals & ~(1 << bit)), gpio_ba + offset); 133 outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
180 134
181 spin_unlock(&gpio_lock); 135 spin_unlock(&sch->lock);
182} 136}
183 137
184static int sch_gpio_resume_direction_out(struct gpio_chip *gc, 138static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
185 unsigned gpio_num, int val) 139 int val)
186{ 140{
141 struct sch_gpio *sch = to_sch_gpio(gc);
187 u8 curr_dirs; 142 u8 curr_dirs;
188 unsigned short offset, bit; 143 unsigned short offset, bit;
189 144
190 offset = RGIO + gpio_num / 8; 145 spin_lock(&sch->lock);
191 bit = gpio_num % 8;
192 146
193 spin_lock(&gpio_lock); 147 offset = sch_gpio_offset(sch, gpio_num, GIO);
148 bit = sch_gpio_bit(sch, gpio_num);
194 149
195 curr_dirs = inb(gpio_ba + offset); 150 curr_dirs = inb(sch->iobase + offset);
196 if (curr_dirs & (1 << bit)) 151 if (curr_dirs & (1 << bit))
197 outb(curr_dirs & ~(1 << bit), gpio_ba + offset); 152 outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
198 153
199 spin_unlock(&gpio_lock); 154 spin_unlock(&sch->lock);
200 155
201 /* 156 /*
202 * according to the datasheet, writing to the level register has no 157 * according to the datasheet, writing to the level register has no
203 * effect when GPIO is programmed as input. 158 * effect when GPIO is programmed as input.
204 * Actually the the level register is read-only when configured as input. 159 * Actually the the level register is read-only when configured as input.
205 * Thus presetting the output level before switching to output is _NOT_ possible. 160 * Thus presetting the output level before switching to output is _NOT_ possible.
206 * Hence we set the level after configuring the GPIO as output. 161 * Hence we set the level after configuring the GPIO as output.
207 * But we cannot prevent a short low pulse if direction is set to high 162 * But we cannot prevent a short low pulse if direction is set to high
208 * and an external pull-up is connected. 163 * and an external pull-up is connected.
209 */ 164 */
210 sch_gpio_resume_set(gc, gpio_num, val); 165 sch_gpio_set(gc, gpio_num, val);
211 return 0; 166 return 0;
212} 167}
213 168
214static struct gpio_chip sch_gpio_resume = { 169static struct gpio_chip sch_gpio_chip = {
215 .label = "sch_gpio_resume", 170 .label = "sch_gpio",
216 .owner = THIS_MODULE, 171 .owner = THIS_MODULE,
217 .direction_input = sch_gpio_resume_direction_in, 172 .direction_input = sch_gpio_direction_in,
218 .get = sch_gpio_resume_get, 173 .get = sch_gpio_get,
219 .direction_output = sch_gpio_resume_direction_out, 174 .direction_output = sch_gpio_direction_out,
220 .set = sch_gpio_resume_set, 175 .set = sch_gpio_set,
221}; 176};
222 177
223static int sch_gpio_probe(struct platform_device *pdev) 178static int sch_gpio_probe(struct platform_device *pdev)
224{ 179{
180 struct sch_gpio *sch;
225 struct resource *res; 181 struct resource *res;
226 int err, id;
227 182
228 id = pdev->id; 183 sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
229 if (!id) 184 if (!sch)
230 return -ENODEV; 185 return -ENOMEM;
231 186
232 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 187 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
233 if (!res) 188 if (!res)
234 return -EBUSY; 189 return -EBUSY;
235 190
236 if (!request_region(res->start, resource_size(res), pdev->name)) 191 if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
192 pdev->name))
237 return -EBUSY; 193 return -EBUSY;
238 194
239 gpio_ba = res->start; 195 spin_lock_init(&sch->lock);
196 sch->iobase = res->start;
197 sch->chip = sch_gpio_chip;
198 sch->chip.label = dev_name(&pdev->dev);
199 sch->chip.dev = &pdev->dev;
240 200
241 switch (id) { 201 switch (pdev->id) {
242 case PCI_DEVICE_ID_INTEL_SCH_LPC: 202 case PCI_DEVICE_ID_INTEL_SCH_LPC:
243 sch_gpio_core.base = 0; 203 sch->core_base = 0;
244 sch_gpio_core.ngpio = 10; 204 sch->resume_base = 10;
245 sch_gpio_resume.base = 10; 205 sch->chip.ngpio = 14;
246 sch_gpio_resume.ngpio = 4; 206
247 /* 207 /*
248 * GPIO[6:0] enabled by default 208 * GPIO[6:0] enabled by default
249 * GPIO7 is configured by the CMC as SLPIOVR 209 * GPIO7 is configured by the CMC as SLPIOVR
250 * Enable GPIO[9:8] core powered gpios explicitly 210 * Enable GPIO[9:8] core powered gpios explicitly
251 */ 211 */
252 outb(0x3, gpio_ba + CGEN + 1); 212 sch_gpio_enable(sch, 8);
213 sch_gpio_enable(sch, 9);
253 /* 214 /*
254 * SUS_GPIO[2:0] enabled by default 215 * SUS_GPIO[2:0] enabled by default
255 * Enable SUS_GPIO3 resume powered gpio explicitly 216 * Enable SUS_GPIO3 resume powered gpio explicitly
256 */ 217 */
257 outb(0x8, gpio_ba + RGEN); 218 sch_gpio_enable(sch, 13);
258 break; 219 break;
259 220
260 case PCI_DEVICE_ID_INTEL_ITC_LPC: 221 case PCI_DEVICE_ID_INTEL_ITC_LPC:
261 sch_gpio_core.base = 0; 222 sch->core_base = 0;
262 sch_gpio_core.ngpio = 5; 223 sch->resume_base = 5;
263 sch_gpio_resume.base = 5; 224 sch->chip.ngpio = 14;
264 sch_gpio_resume.ngpio = 9;
265 break; 225 break;
266 226
267 case PCI_DEVICE_ID_INTEL_CENTERTON_ILB: 227 case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
268 sch_gpio_core.base = 0; 228 sch->core_base = 0;
269 sch_gpio_core.ngpio = 21; 229 sch->resume_base = 21;
270 sch_gpio_resume.base = 21; 230 sch->chip.ngpio = 30;
271 sch_gpio_resume.ngpio = 9;
272 break; 231 break;
273 232
274 default: 233 default:
275 err = -ENODEV; 234 return -ENODEV;
276 goto err_sch_gpio_core;
277 } 235 }
278 236
279 sch_gpio_core.dev = &pdev->dev; 237 platform_set_drvdata(pdev, sch);
280 sch_gpio_resume.dev = &pdev->dev;
281
282 err = gpiochip_add(&sch_gpio_core);
283 if (err < 0)
284 goto err_sch_gpio_core;
285 238
286 err = gpiochip_add(&sch_gpio_resume); 239 return gpiochip_add(&sch->chip);
287 if (err < 0)
288 goto err_sch_gpio_resume;
289
290 return 0;
291
292err_sch_gpio_resume:
293 gpiochip_remove(&sch_gpio_core);
294
295err_sch_gpio_core:
296 release_region(res->start, resource_size(res));
297 gpio_ba = 0;
298
299 return err;
300} 240}
301 241
302static int sch_gpio_remove(struct platform_device *pdev) 242static int sch_gpio_remove(struct platform_device *pdev)
303{ 243{
304 struct resource *res; 244 struct sch_gpio *sch = platform_get_drvdata(pdev);
305 if (gpio_ba) {
306
307 gpiochip_remove(&sch_gpio_core);
308 gpiochip_remove(&sch_gpio_resume);
309
310 res = platform_get_resource(pdev, IORESOURCE_IO, 0);
311
312 release_region(res->start, resource_size(res));
313 gpio_ba = 0;
314 }
315 245
246 gpiochip_remove(&sch->chip);
316 return 0; 247 return 0;
317} 248}
318 249