From c0eda9aef1c0ef7bb2812b739ddf400405568bef Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Tue, 12 Feb 2013 15:04:09 +0000 Subject: [PATCH] mfd: ab8500-core: Add ADC support for ab8540 Signed-off-by: Lee Jones Acked-by: Samuel Ortiz --- drivers/mfd/ab8500-core.c | 74 ++++++++++++++++++++++++++++++-------- drivers/mfd/ab8500-gpadc.c | 67 +++++++++++++++++++--------------- 2 files changed, 98 insertions(+), 43 deletions(-) diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index baaf2ed8095b..cdf6c1e59bc3 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c @@ -658,6 +658,15 @@ static struct resource ab8500_gpadc_resources[] = { }, }; +static struct resource ab8540_gpadc_resources[] = { + { + .name = "SW_CONV_END", + .start = AB8500_INT_GP_SW_ADC_CONV_END, + .end = AB8500_INT_GP_SW_ADC_CONV_END, + .flags = IORESOURCE_IRQ, + }, +}; + static struct resource ab8500_rtc_resources[] = { { .name = "60S", @@ -1013,12 +1022,6 @@ static struct mfd_cell abx500_common_devs[] = { .name = "abx500-clk", .of_compatible = "stericsson,abx500-clk", }, - { - .name = "ab8500-gpadc", - .of_compatible = "stericsson,ab8500-gpadc", - .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), - .resources = ab8500_gpadc_resources, - }, { .name = "ab8500-rtc", .of_compatible = "stericsson,ab8500-rtc", @@ -1118,6 +1121,12 @@ static struct mfd_cell ab8500_devs[] = { .name = "ab8500-codec", .of_compatible = "stericsson,ab8500-codec", }, + { + .name = "ab8500-gpadc", + .of_compatible = "stericsson,ab8500-gpadc", + .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), + .resources = ab8500_gpadc_resources, + }, }; static struct mfd_cell ab9540_devs[] = { @@ -1133,10 +1142,44 @@ static struct mfd_cell ab9540_devs[] = { { .name = "ab9540-codec", }, + { + .name = "ab8500-gpadc", + .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), + .resources = ab8500_gpadc_resources, + }, + { + .name = "ab-iddet", + .num_resources = ARRAY_SIZE(ab8505_iddet_resources), + .resources = ab8505_iddet_resources, + }, }; -/* Device list common to ab9540 and ab8505 */ -static struct mfd_cell ab9540_ab8505_devs[] = { +/* Device list for ab8505 */ +static struct mfd_cell ab8505_devs[] = { + { + .name = "ab-iddet", + .num_resources = ARRAY_SIZE(ab8505_iddet_resources), + .resources = ab8505_iddet_resources, + }, +}; + +static struct mfd_cell ab8540_devs[] = { + { + .name = "ab8500-gpio", + }, + { + .name = "ab8540-usb", + .num_resources = ARRAY_SIZE(ab8500_usb_resources), + .resources = ab8500_usb_resources, + }, + { + .name = "ab8540-codec", + }, + { + .name = "ab8500-gpadc", + .num_resources = ARRAY_SIZE(ab8540_gpadc_resources), + .resources = ab8540_gpadc_resources, + }, { .name = "ab-iddet", .num_resources = ARRAY_SIZE(ab8505_iddet_resources), @@ -1495,6 +1538,14 @@ static int ab8500_probe(struct platform_device *pdev) ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs, ARRAY_SIZE(ab9540_devs), NULL, ab8500->irq_base, ab8500->domain); + else if (is_ab8540(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8540_devs, + ARRAY_SIZE(ab8540_devs), NULL, + ab8500->irq_base, ab8500->domain); + else if (is_ab8505(ab8500)) + ret = mfd_add_devices(ab8500->dev, 0, ab8505_devs, + ARRAY_SIZE(ab8505_devs), NULL, + ab8500->irq_base, ab8500->domain); else ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs, ARRAY_SIZE(ab8500_devs), NULL, @@ -1502,13 +1553,6 @@ static int ab8500_probe(struct platform_device *pdev) if (ret) return ret; - if (is_ab9540(ab8500) || is_ab8505(ab8500)) - ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs, - ARRAY_SIZE(ab9540_ab8505_devs), NULL, - ab8500->irq_base, ab8500->domain); - if (ret) - return ret; - if (!no_bm) { /* Add battery management devices */ ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs, diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index 8673bf66f7d7..fc8da4496e84 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c @@ -311,6 +311,12 @@ int ab8500_gpadc_read_raw(struct ab8500_gpadc *gpadc, u8 channel, if (!gpadc) return -ENODEV; + /* check if convertion is supported */ + if ((gpadc->irq_sw < 0) && (conv_type == ADC_SW)) + return -ENOTSUPP; + if ((gpadc->irq_hw < 0) && (conv_type == ADC_HW)) + return -ENOTSUPP; + mutex_lock(&gpadc->ab8500_gpadc_lock); /* Enable VTVout LDO this is required for GPADC */ pm_runtime_get_sync(gpadc->dev); @@ -761,20 +767,12 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) } gpadc->irq_sw = platform_get_irq_byname(pdev, "SW_CONV_END"); - if (gpadc->irq_sw < 0) { - dev_err(gpadc->dev, "failed to get platform irq-%d\n", - gpadc->irq_sw); - ret = gpadc->irq_sw; - goto fail; - } + if (gpadc->irq_sw < 0) + dev_err(gpadc->dev, "failed to get platform sw_conv_end irq\n"); gpadc->irq_hw = platform_get_irq_byname(pdev, "HW_CONV_END"); - if (gpadc->irq_hw < 0) { - dev_err(gpadc->dev, "failed to get platform irq-%d\n", - gpadc->irq_hw); - ret = gpadc->irq_hw; - goto fail; - } + if (gpadc->irq_hw < 0) + dev_err(gpadc->dev, "failed to get platform hw_conv_end irq\n"); gpadc->dev = &pdev->dev; gpadc->parent = dev_get_drvdata(pdev->dev.parent); @@ -784,21 +782,30 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) init_completion(&gpadc->ab8500_gpadc_complete); /* Register interrupts */ - ret = request_threaded_irq(gpadc->irq_sw, NULL, - ab8500_bm_gpadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-sw", gpadc); - if (ret < 0) { - dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", - gpadc->irq_sw); - goto fail; + if (gpadc->irq_sw >= 0) { + ret = request_threaded_irq(gpadc->irq_sw, NULL, + ab8500_bm_gpadcconvend_handler, + IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-sw", + gpadc); + if (ret < 0) { + dev_err(gpadc->dev, + "Failed to register interrupt irq: %d\n", + gpadc->irq_sw); + goto fail; + } } - ret = request_threaded_irq(gpadc->irq_hw, NULL, - ab8500_bm_gpadcconvend_handler, - IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-hw", gpadc); - if (ret < 0) { - dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n", - gpadc->irq_hw); - goto fail; + + if (gpadc->irq_hw >= 0) { + ret = request_threaded_irq(gpadc->irq_hw, NULL, + ab8500_bm_gpadcconvend_handler, + IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc-hw", + gpadc); + if (ret < 0) { + dev_err(gpadc->dev, + "Failed to register interrupt irq: %d\n", + gpadc->irq_hw); + goto fail_irq; + } } /* VTVout LDO used to power up ab8500-GPADC */ @@ -821,7 +828,9 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) ab8500_gpadc_read_calibration_data(gpadc); list_add_tail(&gpadc->node, &ab8500_gpadc_list); dev_dbg(gpadc->dev, "probe success\n"); + return 0; + fail_irq: free_irq(gpadc->irq_sw, gpadc); free_irq(gpadc->irq_hw, gpadc); @@ -838,8 +847,10 @@ static int ab8500_gpadc_remove(struct platform_device *pdev) /* remove this gpadc entry from the list */ list_del(&gpadc->node); /* remove interrupt - completion of Sw ADC conversion */ - free_irq(gpadc->irq_sw, gpadc); - free_irq(gpadc->irq_hw, gpadc); + if (gpadc->irq_sw >= 0) + free_irq(gpadc->irq_sw, gpadc); + if (gpadc->irq_hw >= 0) + free_irq(gpadc->irq_hw, gpadc); pm_runtime_get_sync(gpadc->dev); pm_runtime_disable(gpadc->dev); -- 2.34.1