diff options
Diffstat (limited to 'drivers/gpio/gpio-mockup.c')
-rw-r--r-- | drivers/gpio/gpio-mockup.c | 77 |
1 files changed, 7 insertions, 70 deletions
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index a6565e128f9e..6db7163e6d98 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
23 | #include <linux/irq_work.h> | 23 | #include <linux/irq_sim.h> |
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/uaccess.h> | 25 | #include <linux/uaccess.h> |
26 | 26 | ||
@@ -47,18 +47,12 @@ enum { | |||
47 | struct gpio_mockup_line_status { | 47 | struct gpio_mockup_line_status { |
48 | int dir; | 48 | int dir; |
49 | bool value; | 49 | bool value; |
50 | bool irq_enabled; | ||
51 | }; | ||
52 | |||
53 | struct gpio_mockup_irq_context { | ||
54 | struct irq_work work; | ||
55 | int irq; | ||
56 | }; | 50 | }; |
57 | 51 | ||
58 | struct gpio_mockup_chip { | 52 | struct gpio_mockup_chip { |
59 | struct gpio_chip gc; | 53 | struct gpio_chip gc; |
60 | struct gpio_mockup_line_status *lines; | 54 | struct gpio_mockup_line_status *lines; |
61 | struct gpio_mockup_irq_context irq_ctx; | 55 | struct irq_sim irqsim; |
62 | struct dentry *dbg_dir; | 56 | struct dentry *dbg_dir; |
63 | }; | 57 | }; |
64 | 58 | ||
@@ -144,65 +138,11 @@ static int gpio_mockup_name_lines(struct device *dev, | |||
144 | return 0; | 138 | return 0; |
145 | } | 139 | } |
146 | 140 | ||
147 | static int gpio_mockup_to_irq(struct gpio_chip *chip, unsigned int offset) | 141 | static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) |
148 | { | ||
149 | return chip->irq_base + offset; | ||
150 | } | ||
151 | |||
152 | static void gpio_mockup_irqmask(struct irq_data *data) | ||
153 | { | 142 | { |
154 | struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | ||
155 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | 143 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); |
156 | 144 | ||
157 | chip->lines[data->irq - gc->irq_base].irq_enabled = false; | 145 | return irq_sim_irqnum(&chip->irqsim, offset); |
158 | } | ||
159 | |||
160 | static void gpio_mockup_irqunmask(struct irq_data *data) | ||
161 | { | ||
162 | struct gpio_chip *gc = irq_data_get_irq_chip_data(data); | ||
163 | struct gpio_mockup_chip *chip = gpiochip_get_data(gc); | ||
164 | |||
165 | chip->lines[data->irq - gc->irq_base].irq_enabled = true; | ||
166 | } | ||
167 | |||
168 | static struct irq_chip gpio_mockup_irqchip = { | ||
169 | .name = GPIO_MOCKUP_NAME, | ||
170 | .irq_mask = gpio_mockup_irqmask, | ||
171 | .irq_unmask = gpio_mockup_irqunmask, | ||
172 | }; | ||
173 | |||
174 | static void gpio_mockup_handle_irq(struct irq_work *work) | ||
175 | { | ||
176 | struct gpio_mockup_irq_context *irq_ctx; | ||
177 | |||
178 | irq_ctx = container_of(work, struct gpio_mockup_irq_context, work); | ||
179 | handle_simple_irq(irq_to_desc(irq_ctx->irq)); | ||
180 | } | ||
181 | |||
182 | static int gpio_mockup_irqchip_setup(struct device *dev, | ||
183 | struct gpio_mockup_chip *chip) | ||
184 | { | ||
185 | struct gpio_chip *gc = &chip->gc; | ||
186 | int irq_base, i; | ||
187 | |||
188 | irq_base = devm_irq_alloc_descs(dev, -1, 0, gc->ngpio, 0); | ||
189 | if (irq_base < 0) | ||
190 | return irq_base; | ||
191 | |||
192 | gc->irq_base = irq_base; | ||
193 | gc->irqchip = &gpio_mockup_irqchip; | ||
194 | |||
195 | for (i = 0; i < gc->ngpio; i++) { | ||
196 | irq_set_chip(irq_base + i, gc->irqchip); | ||
197 | irq_set_chip_data(irq_base + i, gc); | ||
198 | irq_set_handler(irq_base + i, &handle_simple_irq); | ||
199 | irq_modify_status(irq_base + i, | ||
200 | IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE); | ||
201 | } | ||
202 | |||
203 | init_irq_work(&chip->irq_ctx.work, gpio_mockup_handle_irq); | ||
204 | |||
205 | return 0; | ||
206 | } | 146 | } |
207 | 147 | ||
208 | static ssize_t gpio_mockup_event_write(struct file *file, | 148 | static ssize_t gpio_mockup_event_write(struct file *file, |
@@ -228,11 +168,8 @@ static ssize_t gpio_mockup_event_write(struct file *file, | |||
228 | chip = priv->chip; | 168 | chip = priv->chip; |
229 | gc = &chip->gc; | 169 | gc = &chip->gc; |
230 | 170 | ||
231 | if (chip->lines[priv->offset].irq_enabled) { | 171 | gpiod_set_value_cansleep(desc, val); |
232 | gpiod_set_value_cansleep(desc, val); | 172 | irq_sim_fire(&chip->irqsim, priv->offset); |
233 | priv->chip->irq_ctx.irq = gc->irq_base + priv->offset; | ||
234 | irq_work_queue(&priv->chip->irq_ctx.work); | ||
235 | } | ||
236 | 173 | ||
237 | return size; | 174 | return size; |
238 | } | 175 | } |
@@ -319,7 +256,7 @@ static int gpio_mockup_add(struct device *dev, | |||
319 | return ret; | 256 | return ret; |
320 | } | 257 | } |
321 | 258 | ||
322 | ret = gpio_mockup_irqchip_setup(dev, chip); | 259 | ret = devm_irq_sim_init(dev, &chip->irqsim, gc->ngpio); |
323 | if (ret) | 260 | if (ret) |
324 | return ret; | 261 | return ret; |
325 | 262 | ||