.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Emma Mobile GPIO Support - GIO |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (C) 2012 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> |
---|
.. | .. |
---|
271 | 259 | .xlate = irq_domain_xlate_twocell, |
---|
272 | 260 | }; |
---|
273 | 261 | |
---|
| 262 | +static void em_gio_irq_domain_remove(void *data) |
---|
| 263 | +{ |
---|
| 264 | + struct irq_domain *domain = data; |
---|
| 265 | + |
---|
| 266 | + irq_domain_remove(domain); |
---|
| 267 | +} |
---|
| 268 | + |
---|
274 | 269 | static int em_gio_probe(struct platform_device *pdev) |
---|
275 | 270 | { |
---|
276 | 271 | struct em_gio_priv *p; |
---|
277 | | - struct resource *io[2], *irq[2]; |
---|
278 | 272 | struct gpio_chip *gpio_chip; |
---|
279 | 273 | struct irq_chip *irq_chip; |
---|
280 | | - const char *name = dev_name(&pdev->dev); |
---|
| 274 | + struct device *dev = &pdev->dev; |
---|
| 275 | + const char *name = dev_name(dev); |
---|
281 | 276 | unsigned int ngpios; |
---|
282 | | - int ret; |
---|
| 277 | + int irq[2], ret; |
---|
283 | 278 | |
---|
284 | | - p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); |
---|
285 | | - if (!p) { |
---|
286 | | - ret = -ENOMEM; |
---|
287 | | - goto err0; |
---|
288 | | - } |
---|
| 279 | + p = devm_kzalloc(dev, sizeof(*p), GFP_KERNEL); |
---|
| 280 | + if (!p) |
---|
| 281 | + return -ENOMEM; |
---|
289 | 282 | |
---|
290 | 283 | p->pdev = pdev; |
---|
291 | 284 | platform_set_drvdata(pdev, p); |
---|
292 | 285 | spin_lock_init(&p->sense_lock); |
---|
293 | 286 | |
---|
294 | | - io[0] = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
295 | | - io[1] = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
---|
296 | | - irq[0] = platform_get_resource(pdev, IORESOURCE_IRQ, 0); |
---|
297 | | - irq[1] = platform_get_resource(pdev, IORESOURCE_IRQ, 1); |
---|
| 287 | + irq[0] = platform_get_irq(pdev, 0); |
---|
| 288 | + if (irq[0] < 0) |
---|
| 289 | + return irq[0]; |
---|
298 | 290 | |
---|
299 | | - if (!io[0] || !io[1] || !irq[0] || !irq[1]) { |
---|
300 | | - dev_err(&pdev->dev, "missing IRQ or IOMEM\n"); |
---|
301 | | - ret = -EINVAL; |
---|
302 | | - goto err0; |
---|
303 | | - } |
---|
| 291 | + irq[1] = platform_get_irq(pdev, 1); |
---|
| 292 | + if (irq[1] < 0) |
---|
| 293 | + return irq[1]; |
---|
304 | 294 | |
---|
305 | | - p->base0 = devm_ioremap_nocache(&pdev->dev, io[0]->start, |
---|
306 | | - resource_size(io[0])); |
---|
307 | | - if (!p->base0) { |
---|
308 | | - dev_err(&pdev->dev, "failed to remap low I/O memory\n"); |
---|
309 | | - ret = -ENXIO; |
---|
310 | | - goto err0; |
---|
311 | | - } |
---|
| 295 | + p->base0 = devm_platform_ioremap_resource(pdev, 0); |
---|
| 296 | + if (IS_ERR(p->base0)) |
---|
| 297 | + return PTR_ERR(p->base0); |
---|
312 | 298 | |
---|
313 | | - p->base1 = devm_ioremap_nocache(&pdev->dev, io[1]->start, |
---|
314 | | - resource_size(io[1])); |
---|
315 | | - if (!p->base1) { |
---|
316 | | - dev_err(&pdev->dev, "failed to remap high I/O memory\n"); |
---|
317 | | - ret = -ENXIO; |
---|
318 | | - goto err0; |
---|
319 | | - } |
---|
| 299 | + p->base1 = devm_platform_ioremap_resource(pdev, 1); |
---|
| 300 | + if (IS_ERR(p->base1)) |
---|
| 301 | + return PTR_ERR(p->base1); |
---|
320 | 302 | |
---|
321 | | - if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { |
---|
322 | | - dev_err(&pdev->dev, "Missing ngpios OF property\n"); |
---|
323 | | - ret = -EINVAL; |
---|
324 | | - goto err0; |
---|
| 303 | + if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) { |
---|
| 304 | + dev_err(dev, "Missing ngpios OF property\n"); |
---|
| 305 | + return -EINVAL; |
---|
325 | 306 | } |
---|
326 | 307 | |
---|
327 | 308 | gpio_chip = &p->gpio_chip; |
---|
328 | | - gpio_chip->of_node = pdev->dev.of_node; |
---|
| 309 | + gpio_chip->of_node = dev->of_node; |
---|
329 | 310 | gpio_chip->direction_input = em_gio_direction_input; |
---|
330 | 311 | gpio_chip->get = em_gio_get; |
---|
331 | 312 | gpio_chip->direction_output = em_gio_direction_output; |
---|
.. | .. |
---|
334 | 315 | gpio_chip->request = em_gio_request; |
---|
335 | 316 | gpio_chip->free = em_gio_free; |
---|
336 | 317 | gpio_chip->label = name; |
---|
337 | | - gpio_chip->parent = &pdev->dev; |
---|
| 318 | + gpio_chip->parent = dev; |
---|
338 | 319 | gpio_chip->owner = THIS_MODULE; |
---|
339 | 320 | gpio_chip->base = -1; |
---|
340 | 321 | gpio_chip->ngpio = ngpios; |
---|
341 | 322 | |
---|
342 | 323 | irq_chip = &p->irq_chip; |
---|
343 | | - irq_chip->name = name; |
---|
| 324 | + irq_chip->name = "gpio-em"; |
---|
344 | 325 | irq_chip->irq_mask = em_gio_irq_disable; |
---|
345 | 326 | irq_chip->irq_unmask = em_gio_irq_enable; |
---|
346 | 327 | irq_chip->irq_set_type = em_gio_irq_set_type; |
---|
.. | .. |
---|
348 | 329 | irq_chip->irq_release_resources = em_gio_irq_relres; |
---|
349 | 330 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND; |
---|
350 | 331 | |
---|
351 | | - p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, ngpios, 0, |
---|
| 332 | + p->irq_domain = irq_domain_add_simple(dev->of_node, ngpios, 0, |
---|
352 | 333 | &em_gio_irq_domain_ops, p); |
---|
353 | 334 | if (!p->irq_domain) { |
---|
354 | | - ret = -ENXIO; |
---|
355 | | - dev_err(&pdev->dev, "cannot initialize irq domain\n"); |
---|
356 | | - goto err0; |
---|
| 335 | + dev_err(dev, "cannot initialize irq domain\n"); |
---|
| 336 | + return -ENXIO; |
---|
357 | 337 | } |
---|
358 | 338 | |
---|
359 | | - if (devm_request_irq(&pdev->dev, irq[0]->start, |
---|
360 | | - em_gio_irq_handler, 0, name, p)) { |
---|
361 | | - dev_err(&pdev->dev, "failed to request low IRQ\n"); |
---|
362 | | - ret = -ENOENT; |
---|
363 | | - goto err1; |
---|
| 339 | + ret = devm_add_action_or_reset(dev, em_gio_irq_domain_remove, |
---|
| 340 | + p->irq_domain); |
---|
| 341 | + if (ret) |
---|
| 342 | + return ret; |
---|
| 343 | + |
---|
| 344 | + if (devm_request_irq(dev, irq[0], em_gio_irq_handler, 0, name, p)) { |
---|
| 345 | + dev_err(dev, "failed to request low IRQ\n"); |
---|
| 346 | + return -ENOENT; |
---|
364 | 347 | } |
---|
365 | 348 | |
---|
366 | | - if (devm_request_irq(&pdev->dev, irq[1]->start, |
---|
367 | | - em_gio_irq_handler, 0, name, p)) { |
---|
368 | | - dev_err(&pdev->dev, "failed to request high IRQ\n"); |
---|
369 | | - ret = -ENOENT; |
---|
370 | | - goto err1; |
---|
| 349 | + if (devm_request_irq(dev, irq[1], em_gio_irq_handler, 0, name, p)) { |
---|
| 350 | + dev_err(dev, "failed to request high IRQ\n"); |
---|
| 351 | + return -ENOENT; |
---|
371 | 352 | } |
---|
372 | 353 | |
---|
373 | | - ret = gpiochip_add_data(gpio_chip, p); |
---|
| 354 | + ret = devm_gpiochip_add_data(dev, gpio_chip, p); |
---|
374 | 355 | if (ret) { |
---|
375 | | - dev_err(&pdev->dev, "failed to add GPIO controller\n"); |
---|
376 | | - goto err1; |
---|
| 356 | + dev_err(dev, "failed to add GPIO controller\n"); |
---|
| 357 | + return ret; |
---|
377 | 358 | } |
---|
378 | 359 | |
---|
379 | | - return 0; |
---|
380 | | - |
---|
381 | | -err1: |
---|
382 | | - irq_domain_remove(p->irq_domain); |
---|
383 | | -err0: |
---|
384 | | - return ret; |
---|
385 | | -} |
---|
386 | | - |
---|
387 | | -static int em_gio_remove(struct platform_device *pdev) |
---|
388 | | -{ |
---|
389 | | - struct em_gio_priv *p = platform_get_drvdata(pdev); |
---|
390 | | - |
---|
391 | | - gpiochip_remove(&p->gpio_chip); |
---|
392 | | - |
---|
393 | | - irq_domain_remove(p->irq_domain); |
---|
394 | 360 | return 0; |
---|
395 | 361 | } |
---|
396 | 362 | |
---|
.. | .. |
---|
402 | 368 | |
---|
403 | 369 | static struct platform_driver em_gio_device_driver = { |
---|
404 | 370 | .probe = em_gio_probe, |
---|
405 | | - .remove = em_gio_remove, |
---|
406 | 371 | .driver = { |
---|
407 | 372 | .name = "em_gio", |
---|
408 | 373 | .of_match_table = em_gio_dt_ids, |
---|