From patchwork Wed Dec 19 18:37:10 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Christophe PLAGNIOL-VILLARD X-Patchwork-Id: 1896721 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 7A624DF215 for ; Wed, 19 Dec 2012 18:42:30 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TlOXo-0006ro-N4; Wed, 19 Dec 2012 18:39:04 +0000 Received: from 17.mo5.mail-out.ovh.net ([46.105.56.132] helo=mo5.mail-out.ovh.net) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TlOXh-0006ov-1Q for linux-arm-kernel@lists.infradead.org; Wed, 19 Dec 2012 18:38:58 +0000 Received: from mail644.ha.ovh.net (b9.ovh.net [213.186.33.59]) by mo5.mail-out.ovh.net (Postfix) with SMTP id A0DC4108C011 for ; Wed, 19 Dec 2012 19:47:38 +0100 (CET) Received: from b0.ovh.net (HELO queueout) (213.186.33.50) by b0.ovh.net with SMTP; 19 Dec 2012 20:38:55 +0200 Received: from ns32433.ovh.net (HELO localhost) (plagnioj%jcrosoft.com@213.251.161.87) by ns0.ovh.net with SMTP; 19 Dec 2012 20:38:54 +0200 From: Jean-Christophe PLAGNIOL-VILLARD To: linux-arm-kernel@lists.infradead.org X-Ovh-Mailout: 178.32.228.5 (mo5.mail-out.ovh.net) Subject: [PATCH 1/3] ARM: AT91: IIO: add low and high res support for adc Date: Wed, 19 Dec 2012 19:37:10 +0100 Message-Id: <1355942232-26251-1-git-send-email-plagnioj@jcrosoft.com> X-Mailer: git-send-email 1.7.10 In-Reply-To: <20121219183236.GP23971@game.jcrosoft.org> References: <20121219183236.GP23971@game.jcrosoft.org> X-Ovh-Tracer-Id: 701998593197714429 X-Ovh-Remote: 213.251.161.87 (ns32433.ovh.net) X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-OVH-SPAMSTATE: OK X-OVH-SPAMSCORE: -100 X-OVH-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeehledrtdduucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfhrhhomheplfgvrghnqdevhhhrihhsthhophhhvgcurffntefipffkqffnqdggkffnnfettfffuceophhlrghgnhhiohhjsehjtghrohhsohhfthdrtghomheqnecujfgurhephffvufffkffojghfsedttdertdertddt X-Spam-Check: DONE|U 0.5/N X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeehledrtdduucetufdoteggodetrfcurfhrohhfihhlvgemucfqggfjnecuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenucfhrhhomheplfgvrghnqdevhhhrihhsthhophhhvgcurffntefipffkqffnqdggkffnnfettfffuceophhlrghgnhhiohhjsehjtghrohhsohhfthdrtghomheqnecujfgurhephffvufffkffojghfsedttdertdertddt X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121219_133857_399205_05A6E086 X-CRM114-Status: GOOD ( 21.50 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [46.105.56.132 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: linux-iio@vger.kernel.org, Nicolas Ferre , Ludovic Desroches , Jean-Christophe PLAGNIOL-VILLARD X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org From: Ludovic Desroches at91 adc offers the choice between two resolutions: low and high. The low and high resolution values depends on adc IP version, as many IP properties have been exposed through device tree, these settings have also been added to the dt bindings. Update at the same time the dtsi. Signed-off-by: Ludovic Desroches [plagnioj@jcrosoft.com: udpate current adc dt support] Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Cc: linux-iio@vger.kernel.org Cc: Nicolas Ferre --- .../devicetree/bindings/arm/atmel-adc.txt | 11 +++ arch/arm/boot/dts/at91sam9260.dtsi | 3 + arch/arm/boot/dts/at91sam9g45.dtsi | 3 + arch/arm/boot/dts/at91sam9x5.dtsi | 3 + drivers/iio/adc/at91_adc.c | 74 ++++++++++++++++++-- 5 files changed, 90 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt index c63097d..fd2d69e 100644 --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt @@ -14,9 +14,17 @@ Required properties: - atmel,adc-status-register: Offset of the Interrupt Status Register - atmel,adc-trigger-register: Offset of the Trigger Register - atmel,adc-vref: Reference voltage in millivolts for the conversions + - atmel,adc-res: List of resolution in bits supported by the ADC. List size + must be two at least. + - atmel,adc-res-names: Contains one identifier string for each resolution + in atmel,adc-res property. "lowres" and "highres" + identifiers are required. Optional properties: - atmel,adc-use-external: Boolean to enable of external triggers + - atmel,adc-use-res: String corresponding to an identifier from + atmel,adc-res-names property. If not specified, the highest + resolution will be used. Optional trigger Nodes: - Required properties: @@ -40,6 +48,9 @@ adc0: adc@fffb0000 { atmel,adc-trigger-register = <0x08>; atmel,adc-use-external; atmel,adc-vref = <3300>; + atmel,adc-res = <8 10>; + atmel,adc-res-names = "lowres", "highres"; + atmel,adc-use-res = "lowres"; trigger@0 { trigger-name = "external-rising"; diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi index cca34bc..7c605d2 100644 --- a/arch/arm/boot/dts/at91sam9260.dtsi +++ b/arch/arm/boot/dts/at91sam9260.dtsi @@ -506,6 +506,9 @@ atmel,adc-drdy-mask = <0x10000>; atmel,adc-status-register = <0x1c>; atmel,adc-trigger-register = <0x04>; + atmel,adc-res = <8 10>; + atmel,adc-res-names = "lowres", "highres"; + atmel,adc-use-res = "highres"; trigger@0 { trigger-name = "timer-counter-0"; diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi index 253afed..70c776e 100644 --- a/arch/arm/boot/dts/at91sam9g45.dtsi +++ b/arch/arm/boot/dts/at91sam9g45.dtsi @@ -488,6 +488,9 @@ atmel,adc-drdy-mask = <0x10000>; atmel,adc-status-register = <0x1c>; atmel,adc-trigger-register = <0x08>; + atmel,adc-res = <8 10>; + atmel,adc-res-names = "lowres", "highres"; + atmel,adc-use-res = "highres"; trigger@0 { trigger-name = "external-rising"; diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi index 70c1f5d..e52862d 100644 --- a/arch/arm/boot/dts/at91sam9x5.dtsi +++ b/arch/arm/boot/dts/at91sam9x5.dtsi @@ -469,6 +469,9 @@ atmel,adc-drdy-mask = <0x1000000>; atmel,adc-status-register = <0x30>; atmel,adc-trigger-register = <0xc0>; + atmel,adc-res = <8 10>; + atmel,adc-res-names = "lowres", "highres"; + atmel,adc-use-res = "highres"; trigger@0 { trigger-name = "external-rising"; diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 315bed1..f175a86 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -57,6 +57,8 @@ struct at91_adc_state { u32 trigger_number; bool use_external; u32 vref_mv; + u32 res; /* resolution used for convertions */ + bool low_res; /* the resolution corresponds to the lowest one */ wait_queue_head_t wq_data_avail; }; @@ -138,7 +140,7 @@ static int at91_adc_channel_init(struct iio_dev *idev) chan->channel = bit; chan->scan_index = idx; chan->scan_type.sign = 'u'; - chan->scan_type.realbits = 10; + chan->scan_type.realbits = st->res; chan->scan_type.storagebits = 16; chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT | IIO_CHAN_INFO_RAW_SEPARATE_BIT; @@ -372,6 +374,59 @@ static int at91_adc_read_raw(struct iio_dev *idev, return -EINVAL; } +static int at91_adc_of_get_resolution(struct at91_adc_state *st, + struct platform_device *pdev) +{ + struct iio_dev *idev = iio_priv_to_dev(st); + struct device_node *np = pdev->dev.of_node; + int count, i, ret = 0; + char *res_name, *s; + u32 *resolutions; + + count = of_property_count_strings(np, "atmel,adc-res-names"); + if (count < 2) { + dev_err(&idev->dev, "You must specified at least two resolution names for " + "adc-res-names property in the DT\n"); + return count; + } + + resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL); + if (!resolutions) + return -ENOMEM; + + if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) { + dev_err(&idev->dev, "Missing adc-res property in the DT.\n"); + ret = -ENODEV; + goto ret; + } + + if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name)) + res_name = "highres"; + + for (i = 0; i < count; i++) { + if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s)) + continue; + + if (strcmp(res_name, s)) + continue; + + st->res = resolutions[i]; + if (!strcmp(res_name, "lowres")) + st->low_res = true; + else + st->low_res = false; + + dev_info(&idev->dev, "Resolution used: %u bits\n", st->res); + goto ret; + } + + dev_err(&idev->dev, "There is no resolution for %s\n", res_name); + +ret: + kfree(resolutions); + return ret; +} + static int at91_adc_probe_dt(struct at91_adc_state *st, struct platform_device *pdev) { @@ -415,6 +470,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, } st->vref_mv = prop; + ret = at91_adc_of_get_resolution(st, pdev); + if (ret) + goto error_ret; + st->registers = devm_kzalloc(&idev->dev, sizeof(struct at91_adc_reg_desc), GFP_KERNEL); @@ -628,9 +687,16 @@ static int __devinit at91_adc_probe(struct platform_device *pdev) */ ticks = round_up((st->startup_time * adc_clk / 1000000) - 1, 8) / 8; - at91_adc_writel(st, AT91_ADC_MR, - (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | - (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); + + if (st->low_res) + at91_adc_writel(st, AT91_ADC_MR, + AT91_ADC_LOWRES | + (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | + (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); + else + at91_adc_writel(st, AT91_ADC_MR, + (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | + (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); /* Setup the ADC channels available on the board */ ret = at91_adc_channel_init(idev);