gpio-sch.c (4b4193256c8d3bc3a5397b5cd9494c2ad386317d) gpio-sch.c (7a81638485c1a62a87b4c391ecc9c651a4a9dc19)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * GPIO interface for Intel Poulsbo SCH
4 *
5 * Copyright (c) 2010 CompuLab Ltd
6 * Author: Denis Turischev <denis@compulab.co.il>
7 */
8
9#include <linux/acpi.h>
10#include <linux/errno.h>
11#include <linux/gpio/driver.h>
12#include <linux/io.h>
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * GPIO interface for Intel Poulsbo SCH
4 *
5 * Copyright (c) 2010 CompuLab Ltd
6 * Author: Denis Turischev <denis@compulab.co.il>
7 */
8
9#include <linux/acpi.h>
10#include <linux/errno.h>
11#include <linux/gpio/driver.h>
12#include <linux/io.h>
13#include <linux/irq.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/pci_ids.h>
16#include <linux/platform_device.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/pci_ids.h>
17#include <linux/platform_device.h>
18#include <linux/types.h>
17
18#define GEN 0x00
19#define GIO 0x04
20#define GLV 0x08
19
20#define GEN 0x00
21#define GIO 0x04
22#define GLV 0x08
23#define GTPE 0x0c
24#define GTNE 0x10
25#define GGPE 0x14
26#define GSMI 0x18
27#define GTS 0x1c
21
28
29#define CORE_BANK_OFFSET 0x00
30#define RESUME_BANK_OFFSET 0x20
31
22struct sch_gpio {
23 struct gpio_chip chip;
32struct sch_gpio {
33 struct gpio_chip chip;
34 struct irq_chip irqchip;
24 spinlock_t lock;
25 unsigned short iobase;
26 unsigned short resume_base;
27};
28
29static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio,
30 unsigned int reg)
31{
35 spinlock_t lock;
36 unsigned short iobase;
37 unsigned short resume_base;
38};
39
40static unsigned int sch_gpio_offset(struct sch_gpio *sch, unsigned int gpio,
41 unsigned int reg)
42{
32 unsigned int base = 0;
43 unsigned int base = CORE_BANK_OFFSET;
33
34 if (gpio >= sch->resume_base) {
35 gpio -= sch->resume_base;
44
45 if (gpio >= sch->resume_base) {
46 gpio -= sch->resume_base;
36 base += 0x20;
47 base = RESUME_BANK_OFFSET;
37 }
38
39 return base + reg + gpio / 8;
40}
41
42static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio)
43{
44 if (gpio >= sch->resume_base)

--- 29 unchanged lines hidden (view full) ---

74 outb(reg_val | BIT(bit), sch->iobase + offset);
75 else
76 outb((reg_val & ~BIT(bit)), sch->iobase + offset);
77}
78
79static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
80{
81 struct sch_gpio *sch = gpiochip_get_data(gc);
48 }
49
50 return base + reg + gpio / 8;
51}
52
53static unsigned int sch_gpio_bit(struct sch_gpio *sch, unsigned int gpio)
54{
55 if (gpio >= sch->resume_base)

--- 29 unchanged lines hidden (view full) ---

85 outb(reg_val | BIT(bit), sch->iobase + offset);
86 else
87 outb((reg_val & ~BIT(bit)), sch->iobase + offset);
88}
89
90static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned int gpio_num)
91{
92 struct sch_gpio *sch = gpiochip_get_data(gc);
93 unsigned long flags;
82
94
83 spin_lock(&sch->lock);
95 spin_lock_irqsave(&sch->lock, flags);
84 sch_gpio_reg_set(sch, gpio_num, GIO, 1);
96 sch_gpio_reg_set(sch, gpio_num, GIO, 1);
85 spin_unlock(&sch->lock);
97 spin_unlock_irqrestore(&sch->lock, flags);
86 return 0;
87}
88
89static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num)
90{
91 struct sch_gpio *sch = gpiochip_get_data(gc);
92
93 return sch_gpio_reg_get(sch, gpio_num, GLV);
94}
95
96static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
97{
98 struct sch_gpio *sch = gpiochip_get_data(gc);
98 return 0;
99}
100
101static int sch_gpio_get(struct gpio_chip *gc, unsigned int gpio_num)
102{
103 struct sch_gpio *sch = gpiochip_get_data(gc);
104
105 return sch_gpio_reg_get(sch, gpio_num, GLV);
106}
107
108static void sch_gpio_set(struct gpio_chip *gc, unsigned int gpio_num, int val)
109{
110 struct sch_gpio *sch = gpiochip_get_data(gc);
111 unsigned long flags;
99
112
100 spin_lock(&sch->lock);
113 spin_lock_irqsave(&sch->lock, flags);
101 sch_gpio_reg_set(sch, gpio_num, GLV, val);
114 sch_gpio_reg_set(sch, gpio_num, GLV, val);
102 spin_unlock(&sch->lock);
115 spin_unlock_irqrestore(&sch->lock, flags);
103}
104
105static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
106 int val)
107{
108 struct sch_gpio *sch = gpiochip_get_data(gc);
116}
117
118static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned int gpio_num,
119 int val)
120{
121 struct sch_gpio *sch = gpiochip_get_data(gc);
122 unsigned long flags;
109
123
110 spin_lock(&sch->lock);
124 spin_lock_irqsave(&sch->lock, flags);
111 sch_gpio_reg_set(sch, gpio_num, GIO, 0);
125 sch_gpio_reg_set(sch, gpio_num, GIO, 0);
112 spin_unlock(&sch->lock);
126 spin_unlock_irqrestore(&sch->lock, flags);
113
114 /*
115 * according to the datasheet, writing to the level register has no
116 * effect when GPIO is programmed as input.
117 * Actually the the level register is read-only when configured as input.
118 * Thus presetting the output level before switching to output is _NOT_ possible.
119 * Hence we set the level after configuring the GPIO as output.
120 * But we cannot prevent a short low pulse if direction is set to high

--- 18 unchanged lines hidden (view full) ---

139 .owner = THIS_MODULE,
140 .direction_input = sch_gpio_direction_in,
141 .get = sch_gpio_get,
142 .direction_output = sch_gpio_direction_out,
143 .set = sch_gpio_set,
144 .get_direction = sch_gpio_get_direction,
145};
146
127
128 /*
129 * according to the datasheet, writing to the level register has no
130 * effect when GPIO is programmed as input.
131 * Actually the the level register is read-only when configured as input.
132 * Thus presetting the output level before switching to output is _NOT_ possible.
133 * Hence we set the level after configuring the GPIO as output.
134 * But we cannot prevent a short low pulse if direction is set to high

--- 18 unchanged lines hidden (view full) ---

153 .owner = THIS_MODULE,
154 .direction_input = sch_gpio_direction_in,
155 .get = sch_gpio_get,
156 .direction_output = sch_gpio_direction_out,
157 .set = sch_gpio_set,
158 .get_direction = sch_gpio_get_direction,
159};
160
161static int sch_irq_type(struct irq_data *d, unsigned int type)
162{
163 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
164 struct sch_gpio *sch = gpiochip_get_data(gc);
165 irq_hw_number_t gpio_num = irqd_to_hwirq(d);
166 unsigned long flags;
167 int rising, falling;
168
169 switch (type & IRQ_TYPE_SENSE_MASK) {
170 case IRQ_TYPE_EDGE_RISING:
171 rising = 1;
172 falling = 0;
173 break;
174 case IRQ_TYPE_EDGE_FALLING:
175 rising = 0;
176 falling = 1;
177 break;
178 case IRQ_TYPE_EDGE_BOTH:
179 rising = 1;
180 falling = 1;
181 break;
182 default:
183 return -EINVAL;
184 }
185
186 spin_lock_irqsave(&sch->lock, flags);
187
188 sch_gpio_reg_set(sch, gpio_num, GTPE, rising);
189 sch_gpio_reg_set(sch, gpio_num, GTNE, falling);
190
191 irq_set_handler_locked(d, handle_edge_irq);
192
193 spin_unlock_irqrestore(&sch->lock, flags);
194
195 return 0;
196}
197
198static void sch_irq_ack(struct irq_data *d)
199{
200 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
201 struct sch_gpio *sch = gpiochip_get_data(gc);
202 irq_hw_number_t gpio_num = irqd_to_hwirq(d);
203 unsigned long flags;
204
205 spin_lock_irqsave(&sch->lock, flags);
206 sch_gpio_reg_set(sch, gpio_num, GTS, 1);
207 spin_unlock_irqrestore(&sch->lock, flags);
208}
209
210static void sch_irq_mask_unmask(struct irq_data *d, int val)
211{
212 struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
213 struct sch_gpio *sch = gpiochip_get_data(gc);
214 irq_hw_number_t gpio_num = irqd_to_hwirq(d);
215 unsigned long flags;
216
217 spin_lock_irqsave(&sch->lock, flags);
218 sch_gpio_reg_set(sch, gpio_num, GGPE, val);
219 spin_unlock_irqrestore(&sch->lock, flags);
220}
221
222static void sch_irq_mask(struct irq_data *d)
223{
224 sch_irq_mask_unmask(d, 0);
225}
226
227static void sch_irq_unmask(struct irq_data *d)
228{
229 sch_irq_mask_unmask(d, 1);
230}
231
147static int sch_gpio_probe(struct platform_device *pdev)
148{
232static int sch_gpio_probe(struct platform_device *pdev)
233{
234 struct gpio_irq_chip *girq;
149 struct sch_gpio *sch;
150 struct resource *res;
151
152 sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
153 if (!sch)
154 return -ENOMEM;
155
156 res = platform_get_resource(pdev, IORESOURCE_IO, 0);

--- 45 unchanged lines hidden (view full) ---

202 break;
203
204 default:
205 return -ENODEV;
206 }
207
208 platform_set_drvdata(pdev, sch);
209
235 struct sch_gpio *sch;
236 struct resource *res;
237
238 sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
239 if (!sch)
240 return -ENOMEM;
241
242 res = platform_get_resource(pdev, IORESOURCE_IO, 0);

--- 45 unchanged lines hidden (view full) ---

288 break;
289
290 default:
291 return -ENODEV;
292 }
293
294 platform_set_drvdata(pdev, sch);
295
296 sch->irqchip.name = "sch_gpio";
297 sch->irqchip.irq_ack = sch_irq_ack;
298 sch->irqchip.irq_mask = sch_irq_mask;
299 sch->irqchip.irq_unmask = sch_irq_unmask;
300 sch->irqchip.irq_set_type = sch_irq_type;
301
302 girq = &sch->chip.irq;
303 girq->chip = &sch->irqchip;
304 girq->num_parents = 0;
305 girq->parents = NULL;
306 girq->parent_handler = NULL;
307 girq->default_type = IRQ_TYPE_NONE;
308 girq->handler = handle_bad_irq;
309
210 return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
211}
212
213static struct platform_driver sch_gpio_driver = {
214 .driver = {
215 .name = "sch_gpio",
216 },
217 .probe = sch_gpio_probe,
218};
219
220module_platform_driver(sch_gpio_driver);
221
222MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
223MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
224MODULE_LICENSE("GPL v2");
225MODULE_ALIAS("platform:sch_gpio");
310 return devm_gpiochip_add_data(&pdev->dev, &sch->chip, sch);
311}
312
313static struct platform_driver sch_gpio_driver = {
314 .driver = {
315 .name = "sch_gpio",
316 },
317 .probe = sch_gpio_probe,
318};
319
320module_platform_driver(sch_gpio_driver);
321
322MODULE_AUTHOR("Denis Turischev <denis@compulab.co.il>");
323MODULE_DESCRIPTION("GPIO interface for Intel Poulsbo SCH");
324MODULE_LICENSE("GPL v2");
325MODULE_ALIAS("platform:sch_gpio");