Received: by 2002:a25:f815:0:0:0:0:0 with SMTP id u21csp1196217ybd; Wed, 26 Jun 2019 13:02:07 -0700 (PDT) X-Google-Smtp-Source: APXvYqz6KFkVv8qgABcoXrH9PgHaTZZ7izNRRhn3J8Y6hac022NrVzX1A+V8wNrzeO4BDm6rXOYx X-Received: by 2002:a17:90a:ad41:: with SMTP id w1mr1060786pjv.52.1561579327026; Wed, 26 Jun 2019 13:02:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561579327; cv=none; d=google.com; s=arc-20160816; b=SUvg1ahDa7xYDcnk4GZPwOVfYteZ3knCG7oG/ZhVLqjUecI9mg5I3TdepKzryEaNVL 61VJbBAqVwC96KRVDHov5TwmD+5TUmDZP77gQV9hyJloayHaqTU67sqRdMQOsatJvHtz fkh2u2+Bz37MMb5/efw6dZBkV+HzBwd0wMD58SwWGbH4pork78KYIeCzCiS/cA6XPGKH UC8CzvaC0ztRlTBUezeH/KN/HQXTc3G74F2h9tbKYZGc9yeVyyY0Nd9xs8JuNcP/Ke5J yg9wgvQMC9yXLz6C4e+ZiOxmF1YxrIvKsMC9n98BoPpxnaXwCvgIfbQjSOUD+Wu0i1eg 79Fg== 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=QYpKpd4iXEz7DFTApv+3xckUkSVCXRM9T0EJ8hDXQNY=; b=tlAYhwASvQ0b4JxJxFpga/627fxQQw8JDWrEqEjm6U81XanAdqmbdeYGWuHQ342JVl TfXWCXrYBoMN9DtMRNSHto/mB0wmeMU7qTRdyQLpqJzPYiw/09slvEHsxDqx1Vwbs7zH OL5EPwdDANpo0taqsRZJ9GC9Eo5ipit/ve/tqUhEABIvHpVe3njnvmQE0JlZvlGsCT8x BdyQNBwS4YoG0ehoo0N+xfMoiV60UhLr3cZxvPn1dOOXjhTlNsAw7lifjoj5BxCzSA10 fjw/mBbb8OeYdPDYmm4EemxAYuuzLdXZcDQRlpBaAl9w66ikpsDsMU2bNBP8CLXvNnQY xx5w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=xcTa4fUI; 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 t135si81207pfc.251.2019.06.26.13.01.50; Wed, 26 Jun 2019 13:02:07 -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=xcTa4fUI; 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 S1726586AbfFZUAt (ORCPT + 99 others); Wed, 26 Jun 2019 16:00:49 -0400 Received: from mail.kernel.org ([198.145.29.99]:37044 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726104AbfFZUAs (ORCPT ); Wed, 26 Jun 2019 16:00:48 -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 F14BD208E3; Wed, 26 Jun 2019 20:00:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1561579247; bh=noTqyNIwJyLDx8XJ2EstO7aBoUGnOC8TvIrd50fKSls=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=xcTa4fUI1752dJ1ZEfNu+4cOMWwsYWr24+5OYtJ4Prr5hg92/EhydxJf/zmMVHQWp ZrfR/+00DMolQiujaTnttLbiOsYaQwQlm6fAVFdGDPuwis+1+IdUEWhYVb9OHqZpZy qPCzYfl7c4I7LWPTcGrZMSJY9uIPY1h65ieNfKOw= Date: Wed, 26 Jun 2019 21:00:42 +0100 From: Jonathan Cameron To: Artur Rojek Cc: Rob Herring , Mark Rutland , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Maarten ter Huurne , Paul Cercueil Subject: Re: [PATCH 3/4] IIO: Ingenic JZ47xx: Set clock divider on probe Message-ID: <20190626210042.386ae6e2@archlinux> In-Reply-To: <20190623184732.5492-3-contact@artur-rojek.eu> References: <20190623184732.5492-1-contact@artur-rojek.eu> <20190623184732.5492-3-contact@artur-rojek.eu> X-Mailer: Claws Mail 3.17.3 (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 Sun, 23 Jun 2019 20:47:31 +0200 Artur Rojek wrote: > From: Maarten ter Huurne > > The SADC component can run at up to 8 MHz on JZ4725B, but is fed > a 12 MHz input clock (EXT). Divide it by two to get 6 MHz, then > set up another divider to match, to produce a 10us clock. > > If the clock dividers are left on their power-on defaults (a divider > of 1), the SADC mostly works, but will occasionally produce erroneous > readings. This led to button presses being detected out of nowhere on > the RS90 every few minutes. With this change, no ghost button presses > were logged in almost a day worth of testing. > > The ADCLK register for configuring clock dividers doesn't exist on > JZ4740, so avoid writing it there. > > A function has been introduced rather than a flag because there is a lot > of variation between the ADCLK registers on JZ47xx SoCs, both in > the internal layout of the register and in the frequency range > supported by the SADC. So this solution should make it easier > to add support for other JZ47xx SoCs later. > > Signed-off-by: Maarten ter Huurne > Signed-off-by: Artur Rojek This sounds like it perhaps should be marked as a fix and have appropriate fixes tag? Otherwise, looks fine to me. Jonathan > --- > drivers/iio/adc/ingenic-adc.c | 54 +++++++++++++++++++++++++++++++++++ > 1 file changed, 54 insertions(+) > > diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c > index 92b1d5037ac9..e234970b7150 100644 > --- a/drivers/iio/adc/ingenic-adc.c > +++ b/drivers/iio/adc/ingenic-adc.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -22,8 +23,11 @@ > #define JZ_ADC_REG_ADTCH 0x18 > #define JZ_ADC_REG_ADBDAT 0x1c > #define JZ_ADC_REG_ADSDAT 0x20 > +#define JZ_ADC_REG_ADCLK 0x28 > > #define JZ_ADC_REG_CFG_BAT_MD BIT(4) > +#define JZ_ADC_REG_ADCLK_CLKDIV_LSB 0 > +#define JZ_ADC_REG_ADCLK_CLKDIV10US_LSB 16 > > #define JZ_ADC_AUX_VREF 3300 > #define JZ_ADC_AUX_VREF_BITS 12 > @@ -34,6 +38,8 @@ > #define JZ4740_ADC_BATTERY_HIGH_VREF (7500 * 0.986) > #define JZ4740_ADC_BATTERY_HIGH_VREF_BITS 12 > > +struct ingenic_adc; > + > struct ingenic_adc_soc_data { > unsigned int battery_high_vref; > unsigned int battery_high_vref_bits; > @@ -41,6 +47,7 @@ struct ingenic_adc_soc_data { > size_t battery_raw_avail_size; > const int *battery_scale_avail; > size_t battery_scale_avail_size; > + int (*init_clk_div)(struct device *dev, struct ingenic_adc *adc); > }; > > struct ingenic_adc { > @@ -151,6 +158,42 @@ static const int jz4740_adc_battery_scale_avail[] = { > JZ_ADC_BATTERY_LOW_VREF, JZ_ADC_BATTERY_LOW_VREF_BITS, > }; > > +static int jz4725b_adc_init_clk_div(struct device *dev, struct ingenic_adc *adc) > +{ > + struct clk *parent_clk; > + unsigned long parent_rate, rate; > + unsigned int div_main, div_10us; > + > + parent_clk = clk_get_parent(adc->clk); > + if (!parent_clk) { > + dev_err(dev, "ADC clock has no parent\n"); > + return -ENODEV; > + } > + parent_rate = clk_get_rate(parent_clk); > + > + /* > + * The JZ4725B ADC works at 500 kHz to 8 MHz. > + * We pick the highest rate possible. > + * In practice we typically get 6 MHz, half of the 12 MHz EXT clock. > + */ > + div_main = DIV_ROUND_UP(parent_rate, 8000000); > + div_main = clamp(div_main, 1u, 64u); > + rate = parent_rate / div_main; > + if (rate < 500000 || rate > 8000000) { > + dev_err(dev, "No valid divider for ADC main clock\n"); > + return -EINVAL; > + } > + > + /* We also need a divider that produces a 10us clock. */ > + div_10us = DIV_ROUND_UP(rate, 100000); > + > + writel(((div_10us - 1) << JZ_ADC_REG_ADCLK_CLKDIV10US_LSB) | > + (div_main - 1) << JZ_ADC_REG_ADCLK_CLKDIV_LSB, > + adc->base + JZ_ADC_REG_ADCLK); > + > + return 0; > +} > + > static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = { > .battery_high_vref = JZ4725B_ADC_BATTERY_HIGH_VREF, > .battery_high_vref_bits = JZ4725B_ADC_BATTERY_HIGH_VREF_BITS, > @@ -158,6 +201,7 @@ static const struct ingenic_adc_soc_data jz4725b_adc_soc_data = { > .battery_raw_avail_size = ARRAY_SIZE(jz4725b_adc_battery_raw_avail), > .battery_scale_avail = jz4725b_adc_battery_scale_avail, > .battery_scale_avail_size = ARRAY_SIZE(jz4725b_adc_battery_scale_avail), > + .init_clk_div = jz4725b_adc_init_clk_div, > }; > > static const struct ingenic_adc_soc_data jz4740_adc_soc_data = { > @@ -167,6 +211,7 @@ static const struct ingenic_adc_soc_data jz4740_adc_soc_data = { > .battery_raw_avail_size = ARRAY_SIZE(jz4740_adc_battery_raw_avail), > .battery_scale_avail = jz4740_adc_battery_scale_avail, > .battery_scale_avail_size = ARRAY_SIZE(jz4740_adc_battery_scale_avail), > + .init_clk_div = NULL, /* no ADCLK register on JZ4740 */ > }; > > static int ingenic_adc_read_avail(struct iio_dev *iio_dev, > @@ -317,6 +362,15 @@ static int ingenic_adc_probe(struct platform_device *pdev) > return ret; > } > > + /* Set clock dividers. */ > + if (soc_data->init_clk_div) { > + ret = soc_data->init_clk_div(dev, adc); > + if (ret) { > + clk_disable_unprepare(adc->clk); > + return ret; > + } > + } > + > /* Put hardware in a known passive state. */ > writeb(0x00, adc->base + JZ_ADC_REG_ENABLE); > writeb(0xff, adc->base + JZ_ADC_REG_CTRL);