/* * AD7606 Parallel Interface ADC driver * * Copyright 2011 Analog Devices Inc. * * Licensed under the GPL-2. */ #include #include #include #include #include #include "../iio.h" #include "ad7606.h" static int ad7606_par16_read_block(struct device *dev, int count, void *buf) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct ad7606_state *st = iio_priv(indio_dev); insw((unsigned long) st->base_address, buf, count); return 0; } static const struct ad7606_bus_ops ad7606_par16_bops = { .read_block = ad7606_par16_read_block, }; static int ad7606_par8_read_block(struct device *dev, int count, void *buf) { struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct ad7606_state *st = iio_priv(indio_dev); insb((unsigned long) st->base_address, buf, count * 2); return 0; } static const struct ad7606_bus_ops ad7606_par8_bops = { .read_block = ad7606_par8_read_block, }; static int __devinit ad7606_par_probe(struct platform_device *pdev) { struct resource *res; struct iio_dev *indio_dev; void __iomem *addr; resource_size_t remap_size; int ret, irq; irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "no irq\n"); return -ENODEV; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) return -ENODEV; remap_size = resource_size(res); /* Request the regions */ if (!request_mem_region(res->start, remap_size, "iio-ad7606")) { ret = -EBUSY; goto out1; } addr = ioremap(res->start, remap_size); if (!addr) { ret = -ENOMEM; goto out1; } indio_dev = ad7606_probe(&pdev->dev, irq, addr, platform_get_device_id(pdev)->driver_data, remap_size > 1 ? &ad7606_par16_bops : &ad7606_par8_bops); if (IS_ERR(indio_dev)) { ret = PTR_ERR(indio_dev); goto out2; } platform_set_drvdata(pdev, indio_dev); return 0; out2: iounmap(addr); out1: release_mem_region(res->start, remap_size); return ret; } static int __devexit ad7606_par_remove(struct platform_device *pdev) { struct iio_dev *indio_dev = platform_get_drvdata(pdev); struct resource *res; struct ad7606_state *st = iio_priv(indio_dev); ad7606_remove(indio_dev); iounmap(st->base_address); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM static int ad7606_par_suspend(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); ad7606_suspend(indio_dev); return 0; } static int ad7606_par_resume(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); ad7606_resume(indio_dev); return 0; } static const struct dev_pm_ops ad7606_pm_ops = { .suspend = ad7606_par_suspend, .resume = ad7606_par_resume, }; #define AD7606_PAR_PM_OPS (&ad7606_pm_ops) #else #define AD7606_PAR_PM_OPS NULL #endif /* CONFIG_PM */ static struct platform_device_id ad7606_driver_ids[] = { { .name = "ad7606-8", .driver_data = ID_AD7606_8, }, { .name = "ad7606-6", .driver_data = ID_AD7606_6, }, { .name = "ad7606-4", .driver_data = ID_AD7606_4, }, { } }; MODULE_DEVICE_TABLE(platform, ad7606_driver_ids); static struct platform_driver ad7606_driver = { .probe = ad7606_par_probe, .remove = __devexit_p(ad7606_par_remove), .id_table = ad7606_driver_ids, .driver = { .name = "ad7606", .owner = THIS_MODULE, .pm = AD7606_PAR_PM_OPS, }, }; static int __init ad7606_init(void) { return platform_driver_register(&ad7606_driver); } static void __exit ad7606_cleanup(void) { platform_driver_unregister(&ad7606_driver); } module_init(ad7606_init); module_exit(ad7606_cleanup); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("Analog Devices AD7606 ADC"); MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:ad7606_par");