Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp1475986ybi; Sat, 27 Jul 2019 10:30:36 -0700 (PDT) X-Google-Smtp-Source: APXvYqzf8ZiycOU440nY7HFlKRA7VKwLVudzDA/4loJ8MSyBNqKbJSMsI8k9/HN9SLnCuJ1DhSSV X-Received: by 2002:a17:902:aa09:: with SMTP id be9mr17644452plb.52.1564248636125; Sat, 27 Jul 2019 10:30:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564248636; cv=none; d=google.com; s=arc-20160816; b=oPCcsD/jBUIXtjNVYp/wqSj33TMYJEuUu1YUgiUsy6mmdtmY/fzFvhT9VeBJTKc+tG kG6HWtXIEktDlXKCGxX/NOS897zFioLIVgTZf2lMYBRDEsypf3zbtqBLOP6VEPK7PLU4 VvmbMJ/Q2Fgo2l6httnX/0yHsnrsmBYQbkN09xMbRD3G+sJUEgEDH4lcRhS2lcl1mDZ6 4CD1IyWLx6PsTV7IiC7FQ5O4B0eJJuN1FYxDEO1CDZAeqlGYv5UqROyJ/KHIQi3Qa0U6 PohWhsDcsVockpRNB+4ZeudJX5p4qxfDohdyn1CwaUSHD8ziEICy8GZQDpSHKKzrXhk7 8ybA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:subject:cc:to:from:date :dkim-signature; bh=v0vCI7T8dKSalApkRoo5uTqlPYbplG9kFtVMdpVBHXw=; b=eMDt32wOg6ggR2Le3zHhaU+AesY4++9YGSapaLyBOCSRm0kBxksj+jlZuB0LR2xMkb v0E71NB15gbdj7POXz2ihsClNlHUOlp32Vad5PvAG9sWanUVFRcXd1XFvpsxmTaZcy8h ZDOv7Qn6CJJlCgW9cjAab06MALyrBXgsTF+PG1OBXCF+CmxMSh3E4jDRk7v5BxsQke7R hDEpv6D3tDvRM74NKf3Ih3+AzQV2JN3+tKOZJ3oEuIZLUuICSR8ZB5pgUEKpIAJOvNAY 5+yYd0x/OY34LdKjems/FCFfjsYgmOaG3MVxY7PHF5C9SEpknkqWQqIZDqEqzukdGOMF +ooA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=UpHUMlNR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id r8si24452642pgr.243.2019.07.27.10.30.20; Sat, 27 Jul 2019 10:30:36 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=UpHUMlNR; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387940AbfG0R1Q (ORCPT + 99 others); Sat, 27 Jul 2019 13:27:16 -0400 Received: from mail.kernel.org ([198.145.29.99]:37956 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387665AbfG0R1Q (ORCPT ); Sat, 27 Jul 2019 13:27:16 -0400 Received: from archlinux (cpc149474-cmbg20-2-0-cust94.5-4.cable.virginm.net [82.4.196.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 5A0092083B; Sat, 27 Jul 2019 17:27:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1564248435; bh=TgHbtdhceCuB6Z5ciNGix1YdP05JeK/vtR5Z63isVLo=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=UpHUMlNRce5rXGhikWfLBpsNdcA/Ub+11QzYDBBseNNpcTmA3puzd6QvA+2JQq0lB DxQOvy2FnEHdEVoD0uwnrx+r3NDmMwarVNntzw8MB1JyEvpe5mP/BWS/TDbQfNHXE2 GSaH9XTZOBNT38XOLttLVeWRBWNmDReikaG3xk1w= Date: Sat, 27 Jul 2019 18:27:09 +0100 From: Jonathan Cameron To: Baolin Wang Cc: knaack.h@gmx.de, lars@metafoo.de, pmeerw@pmeerw.net, freeman.liu@unisoc.com, vincent.guittot@linaro.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH] iio: adc: sc27xx: Change to polling mode to read data Message-ID: <20190727182709.037fc595@archlinux> In-Reply-To: <1870ea18729f93fb36694affaf7e9443733dd988.1564035575.git.baolin.wang@linaro.org> References: <1870ea18729f93fb36694affaf7e9443733dd988.1564035575.git.baolin.wang@linaro.org> X-Mailer: Claws Mail 3.17.4 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Thu, 25 Jul 2019 14:33:50 +0800 Baolin Wang wrote: > From: Freeman Liu > > On Spreadtrum platform, the headphone will read one ADC channel multiple > times to identify the headphone type, and the headphone identification is > sensitive of the ADC reading time. And we found it will take longer time > to reading ADC data by using interrupt mode comparing with the polling > mode, thus we should change to polling mode to improve the efficiency > of reading data, which can identify the headphone type successfully. > > Signed-off-by: Freeman Liu > Signed-off-by: Baolin Wang Hi, My concerns with this sort of approach is that we may be sacrificing power efficiency for some usecases to support one demanding one. The maximum sleep time is 1 second (I think) which is probably too long to poll a register for in general. Is there some way we can bound that time and perhaps switch between interrupt and polling modes depending on how long we expect to wait? Thanks, Jonathan > --- > drivers/iio/adc/sc27xx_adc.c | 81 ++++++++++++++---------------------------- > 1 file changed, 27 insertions(+), 54 deletions(-) > > diff --git a/drivers/iio/adc/sc27xx_adc.c b/drivers/iio/adc/sc27xx_adc.c > index f7f7a189..ea864290 100644 > --- a/drivers/iio/adc/sc27xx_adc.c > +++ b/drivers/iio/adc/sc27xx_adc.c > @@ -3,7 +3,6 @@ > > #include > #include > -#include > #include > #include > #include > @@ -46,14 +45,18 @@ > /* Bits definitions for SC27XX_ADC_INT_CLR registers */ > #define SC27XX_ADC_IRQ_CLR BIT(0) > > +/* Bits definitions for SC27XX_ADC_INT_RAW registers */ > +#define SC27XX_ADC_IRQ_RAW BIT(0) > + > /* Mask definition for SC27XX_ADC_DATA register */ > #define SC27XX_ADC_DATA_MASK GENMASK(11, 0) > > /* Timeout (ms) for the trylock of hardware spinlocks */ > #define SC27XX_ADC_HWLOCK_TIMEOUT 5000 > > -/* Timeout (ms) for ADC data conversion according to ADC datasheet */ > -#define SC27XX_ADC_RDY_TIMEOUT 100 > +/* Timeout (us) for ADC data conversion according to ADC datasheet */ > +#define SC27XX_ADC_RDY_TIMEOUT 1000000 This is 10 x the value I think... > +#define SC27XX_ADC_POLL_RAW_STATUS 500 > > /* Maximum ADC channel number */ > #define SC27XX_ADC_CHANNEL_MAX 32 > @@ -72,10 +75,8 @@ struct sc27xx_adc_data { > * subsystems which will access the unique ADC controller. > */ > struct hwspinlock *hwlock; > - struct completion completion; > int channel_scale[SC27XX_ADC_CHANNEL_MAX]; > u32 base; > - int value; > int irq; > }; > > @@ -188,9 +189,7 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, > int scale, int *val) > { > int ret; > - u32 tmp; > - > - reinit_completion(&data->completion); > + u32 tmp, value, status; > > ret = hwspin_lock_timeout_raw(data->hwlock, SC27XX_ADC_HWLOCK_TIMEOUT); > if (ret) { > @@ -203,6 +202,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, > if (ret) > goto unlock_adc; > > + ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, > + SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); > + if (ret) > + goto disable_adc; > + > /* Configure the channel id and scale */ > tmp = (scale << SC27XX_ADC_SCALE_SHIFT) & SC27XX_ADC_SCALE_MASK; > tmp |= channel & SC27XX_ADC_CHN_ID_MASK; > @@ -226,15 +230,22 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, > if (ret) > goto disable_adc; > > - ret = wait_for_completion_timeout(&data->completion, > - msecs_to_jiffies(SC27XX_ADC_RDY_TIMEOUT)); > - if (!ret) { > - dev_err(data->dev, "read ADC data timeout\n"); > - ret = -ETIMEDOUT; > - } else { > - ret = 0; > + ret = regmap_read_poll_timeout(data->regmap, > + data->base + SC27XX_ADC_INT_RAW, > + status, (status & SC27XX_ADC_IRQ_RAW), > + SC27XX_ADC_POLL_RAW_STATUS, > + SC27XX_ADC_RDY_TIMEOUT); > + if (ret) { > + dev_err(data->dev, "read adc timeout, status = 0x%x\n", status); > + goto disable_adc; > } > > + ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, &value); > + if (ret) > + goto disable_adc; > + > + value &= SC27XX_ADC_DATA_MASK; > + > disable_adc: > regmap_update_bits(data->regmap, data->base + SC27XX_ADC_CTL, > SC27XX_ADC_EN, 0); > @@ -242,32 +253,11 @@ static int sc27xx_adc_read(struct sc27xx_adc_data *data, int channel, > hwspin_unlock_raw(data->hwlock); > > if (!ret) > - *val = data->value; > + *val = value; > > return ret; > } > > -static irqreturn_t sc27xx_adc_isr(int irq, void *dev_id) > -{ > - struct sc27xx_adc_data *data = dev_id; > - int ret; > - > - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_CLR, > - SC27XX_ADC_IRQ_CLR, SC27XX_ADC_IRQ_CLR); > - if (ret) > - return IRQ_RETVAL(ret); > - > - ret = regmap_read(data->regmap, data->base + SC27XX_ADC_DATA, > - &data->value); > - if (ret) > - return IRQ_RETVAL(ret); > - > - data->value &= SC27XX_ADC_DATA_MASK; > - complete(&data->completion); > - > - return IRQ_HANDLED; > -} > - > static void sc27xx_adc_volt_ratio(struct sc27xx_adc_data *data, > int channel, int scale, > u32 *div_numerator, u32 *div_denominator) > @@ -454,11 +444,6 @@ static int sc27xx_adc_enable(struct sc27xx_adc_data *data) > if (ret) > goto disable_adc; > > - ret = regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, > - SC27XX_ADC_IRQ_EN, SC27XX_ADC_IRQ_EN); > - if (ret) > - goto disable_clk; > - > /* ADC channel scales' calibration from nvmem device */ > ret = sc27xx_adc_scale_calibration(data, true); > if (ret) > @@ -484,9 +469,6 @@ static void sc27xx_adc_disable(void *_data) > { > struct sc27xx_adc_data *data = _data; > > - regmap_update_bits(data->regmap, data->base + SC27XX_ADC_INT_EN, > - SC27XX_ADC_IRQ_EN, 0); > - > /* Disable ADC work clock and controller clock */ > regmap_update_bits(data->regmap, SC27XX_ARM_CLK_EN, > SC27XX_CLK_ADC_EN | SC27XX_CLK_ADC_CLK_EN, 0); > @@ -553,7 +535,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev) > return ret; > } > > - init_completion(&sc27xx_data->completion); > sc27xx_data->dev = &pdev->dev; > > ret = sc27xx_adc_enable(sc27xx_data); > @@ -569,14 +550,6 @@ static int sc27xx_adc_probe(struct platform_device *pdev) > return ret; > } > > - ret = devm_request_threaded_irq(&pdev->dev, sc27xx_data->irq, NULL, > - sc27xx_adc_isr, IRQF_ONESHOT, > - pdev->name, sc27xx_data); > - if (ret) { > - dev_err(&pdev->dev, "failed to request ADC irq\n"); > - return ret; > - } > - > indio_dev->dev.parent = &pdev->dev; > indio_dev->name = dev_name(&pdev->dev); > indio_dev->modes = INDIO_DIRECT_MODE;