.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * Renesas IRQC Driver |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2013 Magnus Damm |
---|
5 | | - * |
---|
6 | | - * This program is free software; you can redistribute it and/or modify |
---|
7 | | - * it under the terms of the GNU General Public License as published by |
---|
8 | | - * the Free Software Foundation; either version 2 of the License |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License |
---|
16 | | - * along with this program; if not, write to the Free Software |
---|
17 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
18 | 6 | */ |
---|
19 | 7 | |
---|
20 | 8 | #include <linux/init.h> |
---|
21 | 9 | #include <linux/platform_device.h> |
---|
22 | | -#include <linux/spinlock.h> |
---|
23 | 10 | #include <linux/interrupt.h> |
---|
24 | 11 | #include <linux/ioport.h> |
---|
25 | 12 | #include <linux/io.h> |
---|
.. | .. |
---|
60 | 47 | void __iomem *cpu_int_base; |
---|
61 | 48 | struct irqc_irq irq[IRQC_IRQ_MAX]; |
---|
62 | 49 | unsigned int number_of_irqs; |
---|
63 | | - struct platform_device *pdev; |
---|
| 50 | + struct device *dev; |
---|
64 | 51 | struct irq_chip_generic *gc; |
---|
65 | 52 | struct irq_domain *irq_domain; |
---|
66 | 53 | atomic_t wakeup_path; |
---|
.. | .. |
---|
73 | 60 | |
---|
74 | 61 | static void irqc_dbg(struct irqc_irq *i, char *str) |
---|
75 | 62 | { |
---|
76 | | - dev_dbg(&i->p->pdev->dev, "%s (%d:%d)\n", |
---|
77 | | - str, i->requested_irq, i->hw_irq); |
---|
| 63 | + dev_dbg(i->p->dev, "%s (%d:%d)\n", str, i->requested_irq, i->hw_irq); |
---|
78 | 64 | } |
---|
79 | 65 | |
---|
80 | 66 | static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = { |
---|
.. | .. |
---|
137 | 123 | |
---|
138 | 124 | static int irqc_probe(struct platform_device *pdev) |
---|
139 | 125 | { |
---|
| 126 | + struct device *dev = &pdev->dev; |
---|
| 127 | + const char *name = dev_name(dev); |
---|
140 | 128 | struct irqc_priv *p; |
---|
141 | | - struct resource *io; |
---|
142 | 129 | struct resource *irq; |
---|
143 | | - const char *name = dev_name(&pdev->dev); |
---|
144 | 130 | int ret; |
---|
145 | 131 | int k; |
---|
146 | 132 | |
---|
147 | | - p = kzalloc(sizeof(*p), GFP_KERNEL); |
---|
148 | | - if (!p) { |
---|
149 | | - dev_err(&pdev->dev, "failed to allocate driver data\n"); |
---|
150 | | - ret = -ENOMEM; |
---|
151 | | - goto err0; |
---|
152 | | - } |
---|
| 133 | + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); |
---|
| 134 | + if (!p) |
---|
| 135 | + return -ENOMEM; |
---|
153 | 136 | |
---|
154 | | - p->pdev = pdev; |
---|
| 137 | + p->dev = dev; |
---|
155 | 138 | platform_set_drvdata(pdev, p); |
---|
156 | 139 | |
---|
157 | | - pm_runtime_enable(&pdev->dev); |
---|
158 | | - pm_runtime_get_sync(&pdev->dev); |
---|
159 | | - |
---|
160 | | - /* get hold of manadatory IOMEM */ |
---|
161 | | - io = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
162 | | - if (!io) { |
---|
163 | | - dev_err(&pdev->dev, "not enough IOMEM resources\n"); |
---|
164 | | - ret = -EINVAL; |
---|
165 | | - goto err1; |
---|
166 | | - } |
---|
| 140 | + pm_runtime_enable(dev); |
---|
| 141 | + pm_runtime_get_sync(dev); |
---|
167 | 142 | |
---|
168 | 143 | /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */ |
---|
169 | 144 | for (k = 0; k < IRQC_IRQ_MAX; k++) { |
---|
.. | .. |
---|
178 | 153 | |
---|
179 | 154 | p->number_of_irqs = k; |
---|
180 | 155 | if (p->number_of_irqs < 1) { |
---|
181 | | - dev_err(&pdev->dev, "not enough IRQ resources\n"); |
---|
| 156 | + dev_err(dev, "not enough IRQ resources\n"); |
---|
182 | 157 | ret = -EINVAL; |
---|
183 | | - goto err1; |
---|
| 158 | + goto err_runtime_pm_disable; |
---|
184 | 159 | } |
---|
185 | 160 | |
---|
186 | 161 | /* ioremap IOMEM and setup read/write callbacks */ |
---|
187 | | - p->iomem = ioremap_nocache(io->start, resource_size(io)); |
---|
188 | | - if (!p->iomem) { |
---|
189 | | - dev_err(&pdev->dev, "failed to remap IOMEM\n"); |
---|
190 | | - ret = -ENXIO; |
---|
191 | | - goto err2; |
---|
| 162 | + p->iomem = devm_platform_ioremap_resource(pdev, 0); |
---|
| 163 | + if (IS_ERR(p->iomem)) { |
---|
| 164 | + ret = PTR_ERR(p->iomem); |
---|
| 165 | + goto err_runtime_pm_disable; |
---|
192 | 166 | } |
---|
193 | 167 | |
---|
194 | 168 | p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ |
---|
195 | 169 | |
---|
196 | | - p->irq_domain = irq_domain_add_linear(pdev->dev.of_node, |
---|
197 | | - p->number_of_irqs, |
---|
| 170 | + p->irq_domain = irq_domain_add_linear(dev->of_node, p->number_of_irqs, |
---|
198 | 171 | &irq_generic_chip_ops, p); |
---|
199 | 172 | if (!p->irq_domain) { |
---|
200 | 173 | ret = -ENXIO; |
---|
201 | | - dev_err(&pdev->dev, "cannot initialize irq domain\n"); |
---|
202 | | - goto err2; |
---|
| 174 | + dev_err(dev, "cannot initialize irq domain\n"); |
---|
| 175 | + goto err_runtime_pm_disable; |
---|
203 | 176 | } |
---|
204 | 177 | |
---|
205 | 178 | ret = irq_alloc_domain_generic_chips(p->irq_domain, p->number_of_irqs, |
---|
206 | | - 1, name, handle_level_irq, |
---|
| 179 | + 1, "irqc", handle_level_irq, |
---|
207 | 180 | 0, 0, IRQ_GC_INIT_NESTED_LOCK); |
---|
208 | 181 | if (ret) { |
---|
209 | | - dev_err(&pdev->dev, "cannot allocate generic chip\n"); |
---|
210 | | - goto err3; |
---|
| 182 | + dev_err(dev, "cannot allocate generic chip\n"); |
---|
| 183 | + goto err_remove_domain; |
---|
211 | 184 | } |
---|
212 | 185 | |
---|
213 | 186 | p->gc = irq_get_domain_generic_chip(p->irq_domain, 0); |
---|
214 | 187 | p->gc->reg_base = p->cpu_int_base; |
---|
215 | 188 | p->gc->chip_types[0].regs.enable = IRQC_EN_SET; |
---|
216 | 189 | p->gc->chip_types[0].regs.disable = IRQC_EN_STS; |
---|
| 190 | + p->gc->chip_types[0].chip.parent_device = dev; |
---|
217 | 191 | p->gc->chip_types[0].chip.irq_mask = irq_gc_mask_disable_reg; |
---|
218 | 192 | p->gc->chip_types[0].chip.irq_unmask = irq_gc_unmask_enable_reg; |
---|
219 | 193 | p->gc->chip_types[0].chip.irq_set_type = irqc_irq_set_type; |
---|
.. | .. |
---|
222 | 196 | |
---|
223 | 197 | /* request interrupts one by one */ |
---|
224 | 198 | for (k = 0; k < p->number_of_irqs; k++) { |
---|
225 | | - if (request_irq(p->irq[k].requested_irq, irqc_irq_handler, |
---|
226 | | - 0, name, &p->irq[k])) { |
---|
227 | | - dev_err(&pdev->dev, "failed to request IRQ\n"); |
---|
| 199 | + if (devm_request_irq(dev, p->irq[k].requested_irq, |
---|
| 200 | + irqc_irq_handler, 0, name, &p->irq[k])) { |
---|
| 201 | + dev_err(dev, "failed to request IRQ\n"); |
---|
228 | 202 | ret = -ENOENT; |
---|
229 | | - goto err4; |
---|
| 203 | + goto err_remove_domain; |
---|
230 | 204 | } |
---|
231 | 205 | } |
---|
232 | 206 | |
---|
233 | | - dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); |
---|
| 207 | + dev_info(dev, "driving %d irqs\n", p->number_of_irqs); |
---|
234 | 208 | |
---|
235 | 209 | return 0; |
---|
236 | | -err4: |
---|
237 | | - while (--k >= 0) |
---|
238 | | - free_irq(p->irq[k].requested_irq, &p->irq[k]); |
---|
239 | 210 | |
---|
240 | | -err3: |
---|
| 211 | +err_remove_domain: |
---|
241 | 212 | irq_domain_remove(p->irq_domain); |
---|
242 | | -err2: |
---|
243 | | - iounmap(p->iomem); |
---|
244 | | -err1: |
---|
245 | | - pm_runtime_put(&pdev->dev); |
---|
246 | | - pm_runtime_disable(&pdev->dev); |
---|
247 | | - kfree(p); |
---|
248 | | -err0: |
---|
| 213 | +err_runtime_pm_disable: |
---|
| 214 | + pm_runtime_put(dev); |
---|
| 215 | + pm_runtime_disable(dev); |
---|
249 | 216 | return ret; |
---|
250 | 217 | } |
---|
251 | 218 | |
---|
252 | 219 | static int irqc_remove(struct platform_device *pdev) |
---|
253 | 220 | { |
---|
254 | 221 | struct irqc_priv *p = platform_get_drvdata(pdev); |
---|
255 | | - int k; |
---|
256 | | - |
---|
257 | | - for (k = 0; k < p->number_of_irqs; k++) |
---|
258 | | - free_irq(p->irq[k].requested_irq, &p->irq[k]); |
---|
259 | 222 | |
---|
260 | 223 | irq_domain_remove(p->irq_domain); |
---|
261 | | - iounmap(p->iomem); |
---|
262 | 224 | pm_runtime_put(&pdev->dev); |
---|
263 | 225 | pm_runtime_disable(&pdev->dev); |
---|
264 | | - kfree(p); |
---|
265 | 226 | return 0; |
---|
266 | 227 | } |
---|
267 | 228 | |
---|