Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH 3/8] clk: renesas: cpg-mssr: Rename cpg_mssr_priv.mstp_lock
From: Stephen Boyd @ 2017-01-21  0:32 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Philipp Zabel, Simon Horman, Magnus Damm, Michael Turquette,
	Rob Herring, Mark Rutland, linux-clk, devicetree,
	linux-renesas-soc, linux-kernel, linux-arm-kernel
In-Reply-To: <1484921306-9967-4-git-send-email-geert+renesas@glider.be>

On 01/20, Geert Uytterhoeven wrote:
> The spinlock is used to protect Read-Modify-Write register accesses,
> which won't be limited to SMSTPCR register accesses.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH 4/8] clk: renesas: cpg-mssr: Add support for reset control
From: Stephen Boyd @ 2017-01-21  0:33 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Mark Rutland, devicetree, Simon Horman, Michael Turquette,
	Magnus Damm, linux-kernel, linux-renesas-soc, Rob Herring,
	Philipp Zabel, linux-clk, linux-arm-kernel
In-Reply-To: <1484921306-9967-5-git-send-email-geert+renesas@glider.be>

On 01/20, Geert Uytterhoeven wrote:
> Add optional support for the Reset Control feature of the Renesas Clock
> Pulse Generator / Module Standby and Software Reset module on R-Car
> Gen2, R-Car Gen3, and RZ/G1 SoCs.
> 
> This allows to reset SoC devices using the Reset Controller API.
> 
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH v2 1/3] dt-bindings: mfd: stm32f4: Fix STM32F4_X_CLOCK() macro
From: Stephen Boyd @ 2017-01-21  0:34 UTC (permalink / raw)
  To: gabriel.fernandez
  Cc: Mark Rutland, devicetree, daniel.thompson, radoslaw.pietrzyk,
	Alexandre Torgue, Arnd Bergmann, Nicolas Pitre, andrea.merello,
	Michael Turquette, olivier.bideau, Russell King, linux-kernel,
	Rob Herring, ludovic.barre, Maxime Coquelin, amelie.delaunay,
	linux-clk, linux-arm-kernel
In-Reply-To: <1483952833-14704-2-git-send-email-gabriel.fernandez@st.com>

On 01/09, gabriel.fernandez@st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
> 
> Macro to select a clock was not correct.
> 
> Offset of enable register starts at 0x30, then calculation to select a bit is:
> (@enable_reg - 0x30) / 4 * 32 + bit_to_select
> 
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> Tested-by: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
> ---

Acked-by: Stephen Boyd <sboyd@codeaurora.org>

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH 1/4] clk: stm32f7: Add stm32f7 clock DT bindings for STM32F746 boards
From: Stephen Boyd @ 2017-01-21  0:37 UTC (permalink / raw)
  To: gabriel.fernandez
  Cc: Rob Herring, Mark Rutland, Russell King, Maxime Coquelin,
	Alexandre Torgue, Michael Turquette, Nicolas Pitre, Arnd Bergmann,
	daniel.thompson, andrea.merello, radoslaw.pietrzyk, devicetree,
	linux-arm-kernel, linux-kernel, linux-clk, kernel, ludovic.barre,
	olivier.bideau, amelie.delaunay
In-Reply-To: <1483711165-17149-2-git-send-email-gabriel.fernandez@st.com>

On 01/06, gabriel.fernandez@st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
> 
> This patch introduces the stm32f7 clock DT bindings.
> 
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> ---

Applied to clk-stm32f4 because why not

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH 2/4] clk: stm32f7: Introduce stm32f7 clocks for STM32F746 boards
From: Stephen Boyd @ 2017-01-21  0:39 UTC (permalink / raw)
  To: gabriel.fernandez
  Cc: Mark Rutland, devicetree, daniel.thompson, radoslaw.pietrzyk,
	Alexandre Torgue, Arnd Bergmann, Nicolas Pitre, andrea.merello,
	Michael Turquette, olivier.bideau, Russell King, linux-kernel,
	Rob Herring, ludovic.barre, Maxime Coquelin, amelie.delaunay,
	linux-clk, linux-arm-kernel, kernel
In-Reply-To: <1483711165-17149-3-git-send-email-gabriel.fernandez@st.com>

On 01/06, gabriel.fernandez@st.com wrote:
> From: Gabriel Fernandez <gabriel.fernandez@st.com>
> 
> This patch enables clocks for STM32F746 boards.
> 
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
> ---

Applied to clk-next

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCHv4 1/5] clk: mvebu: support for 98DX3236 SoC
From: Stephen Boyd @ 2017-01-21  0:48 UTC (permalink / raw)
  To: Chris Packham
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Michael Turquette, Rob Herring, Mark Rutland,
	linux-clk-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170113091222.7132-2-chris.packham-6g8wRflRTwXFdCa3tKVlE6U/zSkkHjvu@public.gmane.org>

On 01/13, Chris Packham wrote:
> @@ -158,6 +170,14 @@ static const struct coreclk_soc_desc axp_coreclks = {
>  	.num_ratios = ARRAY_SIZE(axp_coreclk_ratios),
>  };
>  
> +static const struct coreclk_soc_desc mv98dx3236_coreclks = {
> +	.get_tclk_freq = mv98dx3236_get_tclk_freq,
> +	.get_cpu_freq = mv98dx3236_get_cpu_freq,
> +	.get_clk_ratio = NULL,
> +	.ratios = NULL,
> +	.num_ratios = 0,

Are these intentionally initialized to 0 explicitly? Otherwise we
could leave them out and it's all the same.

> +};
> +
>  /*
>   * Clock Gating Control
>   */
[..]
> @@ -243,5 +245,30 @@ static void __init of_cpu_clk_setup(struct device_node *node)
>  	iounmap(clock_complex_base);
>  }
>  
> +/* Use this function to call the generic setup with the correct
> + * clock operation
> + */
> +static void __init of_cpu_clk_setup(struct device_node *node)
> +{
> +	_of_cpu_clk_setup(node, &cpu_ops);
> +}
> +
>  CLK_OF_DECLARE(armada_xp_cpu_clock, "marvell,armada-xp-cpu-clock",
>  					 of_cpu_clk_setup);
> +
> +/* Define the clock and operations for the mv98dx3236 - it cannot perform
> + * any operations.
> + */
> +static const struct clk_ops mv98dx3236_cpu_ops = {
> +	.recalc_rate = NULL,
> +	.round_rate = NULL,
> +	.set_rate = NULL,

But clk_set_rate() works silently? Why not just register a clk
provider that returns a NULL pointer? Then there isn't any
structure to maintain?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v5 1/2] dt-bindings: brcm: clocks: add binding for brcmstb-cpu-clk-div
From: Stephen Boyd @ 2017-01-21  0:52 UTC (permalink / raw)
  To: Markus Mayer
  Cc: Michael Turquette, Rob Herring, Mark Rutland, Viresh Kumar,
	Rafael J . Wysocki, Arnd Bergmann, Markus Mayer,
	Broadcom Kernel List, Linux Clock List, Power Management List,
	Device Tree List, ARM Kernel List, Linux Kernel Mailing List
In-Reply-To: <20170119002933.7529-2-code-7CzEARzsJhSsTnJN9+BGXg@public.gmane.org>

On 01/18, Markus Mayer wrote:
> diff --git a/Documentation/devicetree/bindings/clock/brcm,brcmstb-cpu-clk-div.txt b/Documentation/devicetree/bindings/clock/brcm,brcmstb-cpu-clk-div.txt
> new file mode 100644
> index 0000000..c4acb53
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/brcm,brcmstb-cpu-clk-div.txt
> @@ -0,0 +1,27 @@
> +The CPU divider node serves as the sole clock for the CPU complex. It supports
> +power-of-2 clock division, with a divider of "1" as the default highest-speed
> +setting.
> +
> +Required properties:
> +- compatible: shall be "brcm,brcmstb-cpu-clk-div"
> +- reg: address and width of the divider configuration register
> +- #clock-cells: shall be set to 0
> +- clocks: phandle of clock provider which provides the source clock
> +          (this would typically be a "fixed-clock" type PLL)
> +- div-table: list of (raw_value,divider) ordered pairs that correspond to the
> +             allowed clock divider settings
> +- div-shift-width: least-significant bit position and width of divider value

Are these properties used? Please don't put these types of
details in DT.

> +
> +Optional properties:
> +- clock-names: the clock may be named
> +
> +Example:
> +	cpuclkdiv: cpu-clk-div@f03e257c {
> +		compatible = "brcm,brcmstb-cpu-clk-div";
> +		reg = <0xf03e257c 0x4>;

This register really looks like some offset in something larger.
Is there some clock controller? What's the hw block at
0xf03e2000? Maybe I already asked this.

> +		div-table = <0x00 1>;
> +		div-shift-width = <0 5>;
> +		#clock-cells = <0>;
> +		clocks = <&cpupll>;
> +		clock-names = "cpupll";
> +	};
> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 04/12] driver: clk: imx: Add clock driver for imx6sll
From: Stephen Boyd @ 2017-01-21  1:00 UTC (permalink / raw)
  To: Jacky Bai
  Cc: shawnguo@kernel.org, mturquette@baylibre.com, robh+dt@kernel.org,
	mark.rutland@arm.com, linus.walleij@linaro.org,
	kernel@pengutronix.de, Fabio Estevam, daniel.lezcano@linaro.org,
	tglx@linutronix.de, p.zabel@pengutronix.de,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	linux-gpio@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	jacky.baip@gmail.com
In-Reply-To: <AM3PR04MB53027B627AE8CEC6D7D0D1B87780@AM3PR04MB530.eurprd04.prod.outlook.com>

On 01/13, Jacky Bai wrote:
> > >
> > > The reason why we enable these two clks here is in below commit commit
> > > a5120e89e7e187a91852896f586876c7a2030804
> > > Author: Peter Chen <peter.chen@freescale.com>
> > > Date:   Fri Jan 18 10:38:05 2013 +0800
> > >       ARM i.MX6: change mxs usbphy clock usage
> > >
> > 
> > So can we mark these clks with CLK_IS_CRITICAL flag then instead?
> > Or are they disabled out of the bootloader?
> > 
> 
> Sure, using 'CLK_IS_CRITICAL'  should be ok for clks_init_on clocks.  But for  USBPHY*_GATE, it is
> only enabled when CONIG_USB_MXC_PHY is true.  And another concern is if we need to add CLK_IS_CRITICAL
> flag to clks_init_on clocks, we may need to add new wrapper function to register these critical clock. It is not very good.

Ok so set the critical flag when CONFIG_USB_MXC_PHY is enabled?
That isn't too hard to do.

> 
>  > >
> > > > > +	}
> > > > > +
> > > > > +	/* Lower the AHB clock rate before changing the clock source. */
> > > > > +	clk_set_rate(clks[IMX6SLL_CLK_AHB], 99000000);
> > > > > +
> > > > > +	/* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
> > > > > +	clk_set_parent(clks[IMX6SLL_CLK_PERIPH_CLK2_SEL],
> > > > clks[IMX6SLL_CLK_PLL3_USB_OTG]);
> > > > > +	clk_set_parent(clks[IMX6SLL_CLK_PERIPH],
> > > > clks[IMX6SLL_CLK_PERIPH_CLK2]);
> > > > > +	clk_set_parent(clks[IMX6SLL_CLK_PERIPH_PRE],
> > > > clks[IMX6SLL_CLK_PLL2_BUS]);
> > > > > +	clk_set_parent(clks[IMX6SLL_CLK_PERIPH],
> > > > > +clks[IMX6SLL_CLK_PERIPH_PRE]);
> > > > > +
> > > > > +	clk_set_rate(clks[IMX6SLL_CLK_AHB], 132000000);
> > > >
> > > > assigned-clocks for rates now? Or perhaps we shouldn't be exposing
> > > > these as clks if they have some sort of complicated rate sequence
> > > > switch that we can't guarantee with the clk_ops we have today.
> > >
> > > These clks will be used by some peripherals, so we need to expose these
> > clocks.
> > > And the above parent and rate swith sequence is not very easy to be
> > > handled in assigned-clocks, So we leave it in this place.
> > >
> > 
> > How do we guarantee that the rate switch doesn't happen later on, requiring
> > this coordinated sequence of clk operations?
> > 
> 
> This clock sequence is used for increasing the AXI and AHB bus clock rate. In normal
> use, it is very rarely that we need to change them again. If we really need to change
> AXI and AHB bus clock later, a similar sequence must be used to do this.
> 

Ok. It feels unsafe, so please make sure no child clocks have the
CLK_SET_RATE_PARENT flag set so we can't randomly change the rate
of this clk outside of this init code.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* Re: [PATCH v2 00/11] add support for VBUS max current and min voltage limits AXP20X and AXP22X PMICs
From: Chen-Yu Tsai @ 2017-01-21  1:10 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Quentin Schulz, Sebastian Reichel, Rob Herring, Mark Rutland,
	Chen-Yu Tsai, Russell King, Lee Jones, open list:THERMAL,
	devicetree, linux-kernel, linux-arm-kernel, Thomas Petazzoni
In-Reply-To: <20170112092821.5xkgpsbbsxaz3s7h@lukather>

Hi,

On Thu, Jan 12, 2017 at 5:28 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> On Fri, Dec 09, 2016 at 12:04:08PM +0100, Quentin Schulz wrote:
>> The X-Powers AXP209 and AXP20X PMICs are able to set a limit for the
>> VBUS power supply for both max current and min voltage supplied. This
>> series of patch adds the possibility to set these limits from sysfs.
>>
>> Also, the AXP223 PMIC shares most of its behaviour with the AXP221 but
>> the former can set the VBUS power supply max current to 100mA, unlike
>> the latter. The AXP223 VBUS power supply driver used to probe on the
>> AXP221 compatible. This series of patch introduces a new compatible for
>> the AXP223 to be able to set the current max limit to 100mA.
>>
>> With that new compatible, boards having the AXP223 see their DT updated
>> to use the VBUS power supply driver with the correct compatible.
>>
>> This series of patch also migrates from of_device_is_compatible function
>> to the data field of of_device_id to identify the compatible used to
>> probe. This improves the code readability.
>>
>> Mostly cosmetic changes in v2 and adding volatile and writeable regs to
>> AXP20X and AXP22X MFD cells for the VBUS power supply driver.
>
> Applied all the DT patches. I also fixed all the prefixes. Please make
> sure to look at what prefixes are used by a given subsystem next time.

I'm not seeing the DT patches. FYI the old DT does not work with the
new kernel driver updates. Because of the new AXP223 specific compatible
for the usb-power-supply, the updated mfd driver cannot match the old
device node, and the probe will fail at

        if (!of_device_is_available(pdev->dev.of_node))
                return -ENODEV;

I don't see an easy way out of this though. The mfd_cell structure only
takes one compatible string.

Regards
ChenYu

> Thanks!
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 1/6] rtc: sun6i: Expose the 32kHz oscillator
From: Chen-Yu Tsai @ 2017-01-21  2:14 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Alexandre Belloni, Alessandro Zummo, Chen-Yu Tsai,
	linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, Rob Herring,
	devicetree
In-Reply-To: <f1b2a5053cf143dccf110ab0d40c082903a958a7.1484927680.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On Fri, Jan 20, 2017 at 11:56 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The RTC controls the input source of the main 32kHz oscillator in the
> system, feeding it to the clock unit too.
>
> By default, this is using an internal, very inaccurate (+/- 30%)
> oscillator with a divider to make it roughly around 32kHz. This is however
> quite impractical for the RTC, since our time will not be tracked properly.
>
> Since this oscillator is an input of the main clock unit, and since that
> clock unit will be probed using CLK_OF_DECLARE, we have to use it as well,
> leading to a two stage probe: one to enable the clock, the other one to
> enable the RTC.
>
> There is also a slight change in the binding that is required (and should
> have been from the beginning), since we'll need a phandle to the external
> oscillator used on that board. We support the old binding by not allowing
> to switch to the external oscillator and only using the internal one (which
> was the previous behaviour) in the case where we're missing that phandle.

I'm not sure about this. The original behavior was wrong to begin with.
We were claiming 32768 Hz in the device tree already, and any users
would already be seeing the correct rate if we force the mux to the
external oscillator.

Furthermore, I don't think it's possible to turn the external oscillator
off, unlike the 24 MHz main oscillator. I do agree that exposing the
internal oscillator is the right thing to do. On some later SoCs it
is actually directly a source for the CPUS mux.

The code changes below look good.

Regards
ChenYu

> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/rtc/sun6i-rtc.txt |   8 +-
>  drivers/rtc/rtc-sun6i.c                             | 140 ++++++++++++-
>  2 files changed, 139 insertions(+), 9 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
> index f007e428a1ab..44d788240162 100644
> --- a/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
> +++ b/Documentation/devicetree/bindings/rtc/sun6i-rtc.txt
> @@ -8,10 +8,18 @@ Required properties:
>                   memory mapped region.
>  - interrupts   : IRQ lines for the RTC alarm 0 and alarm 1, in that order.
>
> +Required properties for new device trees
> +- clocks       : phandle to the 32kHz external oscillator
> +- clock-output-names : name of the LOSC clock created
> +- #clock-cells  : must be equals to 0
> +
>  Example:
>
>  rtc: rtc@01f00000 {
>         compatible = "allwinner,sun6i-a31-rtc";
>         reg = <0x01f00000 0x54>;
>         interrupts = <0 40 4>, <0 41 4>;
> +       clock-output-names = "osc32k";
> +       clocks = <&ext_osc32k>;
> +       #clock-cells = <0>;
>  };
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index c169a2cd4727..408dd512a6ac 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -20,6 +20,8 @@
>   * more details.
>   */
>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
>  #include <linux/delay.h>
>  #include <linux/err.h>
>  #include <linux/fs.h>
> @@ -33,15 +35,20 @@
>  #include <linux/of_device.h>
>  #include <linux/platform_device.h>
>  #include <linux/rtc.h>
> +#include <linux/slab.h>
>  #include <linux/types.h>
>
>  /* Control register */
>  #define SUN6I_LOSC_CTRL                                0x0000
> +#define SUN6I_LOSC_CTRL_KEY                    (0x16aa << 16)
>  #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC           BIT(9)
>  #define SUN6I_LOSC_CTRL_RTC_HMS_ACC            BIT(8)
>  #define SUN6I_LOSC_CTRL_RTC_YMD_ACC            BIT(7)
> +#define SUN6I_LOSC_CTRL_EXT_OSC                        BIT(0)
>  #define SUN6I_LOSC_CTRL_ACC_MASK               GENMASK(9, 7)
>
> +#define SUN6I_LOSC_CLK_PRESCAL                 0x0008
> +
>  /* RTC */
>  #define SUN6I_RTC_YMD                          0x0010
>  #define SUN6I_RTC_HMS                          0x0014
> @@ -114,8 +121,128 @@ struct sun6i_rtc_dev {
>         void __iomem *base;
>         int irq;
>         unsigned long alarm;
> +
> +       struct clk_hw hw;
> +       struct clk_hw *int_osc;
> +       struct clk *losc;
>  };
>
> +static struct sun6i_rtc_dev *sun6i_rtc;
> +
> +static unsigned long sun6i_rtc_osc_recalc_rate(struct clk_hw *hw,
> +                                              unsigned long parent_rate)
> +{
> +       struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw);
> +       u32 val;
> +
> +       val = readl(rtc->base + SUN6I_LOSC_CTRL);
> +       if (val & SUN6I_LOSC_CTRL_EXT_OSC)
> +               return parent_rate;
> +
> +       val = readl(rtc->base + SUN6I_LOSC_CLK_PRESCAL);
> +       val &= GENMASK(4, 0);
> +
> +       return parent_rate / (val + 1);
> +}
> +
> +static u8 sun6i_rtc_osc_get_parent(struct clk_hw *hw)
> +{
> +       struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw);
> +
> +       return readl(rtc->base + SUN6I_LOSC_CTRL) & SUN6I_LOSC_CTRL_EXT_OSC;
> +}
> +
> +static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index)
> +{
> +       struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw);
> +       u32 val;
> +
> +       if (index > 1)
> +               return -EINVAL;
> +
> +       val = readl(rtc->base + SUN6I_LOSC_CTRL);
> +       val &= ~SUN6I_LOSC_CTRL_EXT_OSC;
> +       val |= SUN6I_LOSC_CTRL_KEY;
> +       val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0;
> +       writel(val, rtc->base + SUN6I_LOSC_CTRL);
> +
> +       return 0;
> +}
> +
> +static const struct clk_ops sun6i_rtc_osc_ops = {
> +       .recalc_rate    = sun6i_rtc_osc_recalc_rate,
> +
> +       .get_parent     = sun6i_rtc_osc_get_parent,
> +       .set_parent     = sun6i_rtc_osc_set_parent,
> +};
> +
> +static void __init sun6i_rtc_clk_init(struct device_node *node)
> +{
> +       struct sun6i_rtc_dev *rtc;
> +       struct clk_init_data init = {
> +               .ops            = &sun6i_rtc_osc_ops,
> +       };
> +       const char *parents[2];
> +
> +       rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
> +       if (!rtc)
> +               pr_crit("Can't allocate RTC structure\n");
> +
> +       rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node));
> +       if (!rtc->base) {
> +               pr_crit("Can't map RTC registers");
> +               return;
> +       }
> +
> +       rtc->int_osc = clk_hw_register_fixed_rate_with_accuracy(NULL,
> +                                                               "rtc-int-osc",
> +                                                               NULL, 0,
> +                                                               667000,
> +                                                               300000000);
> +       if (IS_ERR(rtc->int_osc)) {
> +               pr_crit("Couldn't register the internal oscillator\n");
> +               return;
> +       }
> +
> +       /*
> +        * Due to the missing clocks property we had to express the
> +        * parenthood with the external oscillator that cannot fix (or
> +        * at least expect to have) in the old DTs, we have to be a
> +        * bit smart here.
> +        *
> +        * We deal with that by simply registering the internal
> +        * oscillator as our parent in all cases, and try to get the
> +        * external oscillator from the DT.
> +        *
> +        * In the case where we don't have it, of_clk_get_parent_name
> +        * will return NULL, which is ok, and of_clk_get_parent_count
> +        * will return 0, which is fine too. We will just register a
> +        * single parent, everything works.
> +        */
> +       parents[0] = clk_hw_get_name(rtc->int_osc);
> +       parents[1] = of_clk_get_parent_name(node, 0);
> +
> +       rtc->hw.init = &init;
> +
> +       init.parent_names = parents;
> +       init.num_parents = of_clk_get_parent_count(node) + 1;
> +       init.name = "rtc-osc";
> +       of_property_read_string(node, "clock-output-names", &init.name);
> +
> +       rtc->losc = clk_register(NULL, &rtc->hw);
> +       if (IS_ERR(rtc->losc)) {
> +               pr_crit("Couldn't register the LOSC clock\n");
> +               return;
> +       }
> +
> +       of_clk_add_hw_provider(node, of_clk_hw_simple_get, &rtc->hw);
> +
> +       /* Yes, I know, this is ugly. */
> +       sun6i_rtc = rtc;
> +}
> +CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc",
> +                     sun6i_rtc_clk_init);
> +
>  static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
>  {
>         struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id;
> @@ -349,22 +476,15 @@ static const struct rtc_class_ops sun6i_rtc_ops = {
>
>  static int sun6i_rtc_probe(struct platform_device *pdev)
>  {
> -       struct sun6i_rtc_dev *chip;
> -       struct resource *res;
> +       struct sun6i_rtc_dev *chip = sun6i_rtc;
>         int ret;
>
> -       chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
>         if (!chip)
> -               return -ENOMEM;
> +               return -ENODEV;
>
>         platform_set_drvdata(pdev, chip);
>         chip->dev = &pdev->dev;
>
> -       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       chip->base = devm_ioremap_resource(&pdev->dev, res);
> -       if (IS_ERR(chip->base))
> -               return PTR_ERR(chip->base);
> -
>         chip->irq = platform_get_irq(pdev, 0);
>         if (chip->irq < 0) {
>                 dev_err(&pdev->dev, "No IRQ resource\n");
> @@ -404,6 +524,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
>         /* disable alarm wakeup */
>         writel(0, chip->base + SUN6I_ALARM_CONFIG);
>
> +       clk_prepare_enable(chip->losc);
> +
>         chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev,
>                                         &sun6i_rtc_ops, THIS_MODULE);
>         if (IS_ERR(chip->rtc)) {
> --
> git-series 0.8.11

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* Re: [PATCH 2/6] rtc: sun6i: Add some locking
From: Chen-Yu Tsai @ 2017-01-21  2:18 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Alexandre Belloni, Alessandro Zummo, Chen-Yu Tsai,
	linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, Rob Herring,
	devicetree
In-Reply-To: <9b5c8ed82f636fd2061a9b7933c0e6b65d868643.1484927680.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

On Fri, Jan 20, 2017 at 11:56 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Some registers have a read-modify-write access pattern that are not atomic.
>
> Add some locking to prevent from concurrent accesses.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Acked-by: Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>

Though I think it would be better to add locking first, then add
clock support, if the original code already had issues?

> ---
>  drivers/rtc/rtc-sun6i.c | 20 ++++++++++++++++++--
>  1 file changed, 18 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index 408dd512a6ac..872d18609183 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -125,6 +125,8 @@ struct sun6i_rtc_dev {
>         struct clk_hw hw;
>         struct clk_hw *int_osc;
>         struct clk *losc;
> +
> +       spinlock_t lock;
>  };
>
>  static struct sun6i_rtc_dev *sun6i_rtc;
> @@ -155,16 +157,19 @@ static u8 sun6i_rtc_osc_get_parent(struct clk_hw *hw)
>  static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index)
>  {
>         struct sun6i_rtc_dev *rtc = container_of(hw, struct sun6i_rtc_dev, hw);
> +       unsigned long flags;
>         u32 val;
>
>         if (index > 1)
>                 return -EINVAL;
>
> +       spin_lock_irqsave(&rtc->lock, flags);
>         val = readl(rtc->base + SUN6I_LOSC_CTRL);
>         val &= ~SUN6I_LOSC_CTRL_EXT_OSC;
>         val |= SUN6I_LOSC_CTRL_KEY;
>         val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0;
>         writel(val, rtc->base + SUN6I_LOSC_CTRL);
> +       spin_unlock_irqrestore(&rtc->lock, flags);
>
>         return 0;
>  }
> @@ -187,6 +192,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
>         rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
>         if (!rtc)
>                 pr_crit("Can't allocate RTC structure\n");
> +       spin_lock_init(&rtc->lock);
>
>         rtc->base = of_io_request_and_map(node, 0, of_node_full_name(node));
>         if (!rtc->base) {
> @@ -246,8 +252,10 @@ CLK_OF_DECLARE_DRIVER(sun6i_rtc_clk, "allwinner,sun6i-a31-rtc",
>  static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
>  {
>         struct sun6i_rtc_dev *chip = (struct sun6i_rtc_dev *) id;
> +       irqreturn_t ret = IRQ_NONE;
>         u32 val;
>
> +       spin_lock(&chip->lock);
>         val = readl(chip->base + SUN6I_ALRM_IRQ_STA);
>
>         if (val & SUN6I_ALRM_IRQ_STA_CNT_IRQ_PEND) {
> @@ -256,10 +264,11 @@ static irqreturn_t sun6i_rtc_alarmirq(int irq, void *id)
>
>                 rtc_update_irq(chip->rtc, 1, RTC_AF | RTC_IRQF);
>
> -               return IRQ_HANDLED;
> +               ret = IRQ_HANDLED;
>         }
> +       spin_unlock(&chip->lock);
>
> -       return IRQ_NONE;
> +       return ret;
>  }
>
>  static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
> @@ -267,6 +276,7 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
>         u32 alrm_val = 0;
>         u32 alrm_irq_val = 0;
>         u32 alrm_wake_val = 0;
> +       unsigned long flags;
>
>         if (to) {
>                 alrm_val = SUN6I_ALRM_EN_CNT_EN;
> @@ -277,9 +287,11 @@ static void sun6i_rtc_setaie(int to, struct sun6i_rtc_dev *chip)
>                        chip->base + SUN6I_ALRM_IRQ_STA);
>         }
>
> +       spin_lock_irqsave(&chip->lock, flags);
>         writel(alrm_val, chip->base + SUN6I_ALRM_EN);
>         writel(alrm_irq_val, chip->base + SUN6I_ALRM_IRQ_EN);
>         writel(alrm_wake_val, chip->base + SUN6I_ALARM_CONFIG);
> +       spin_unlock_irqrestore(&chip->lock, flags);
>  }
>
>  static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
> @@ -318,11 +330,15 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
>  static int sun6i_rtc_getalarm(struct device *dev, struct rtc_wkalrm *wkalrm)
>  {
>         struct sun6i_rtc_dev *chip = dev_get_drvdata(dev);
> +       unsigned long flags;
>         u32 alrm_st;
>         u32 alrm_en;
>
> +       spin_lock_irqsave(&chip->lock, flags);
>         alrm_en = readl(chip->base + SUN6I_ALRM_IRQ_EN);
>         alrm_st = readl(chip->base + SUN6I_ALRM_IRQ_STA);
> +       spin_unlock_irqrestore(&chip->lock, flags);
> +
>         wkalrm->enabled = !!(alrm_en & SUN6I_ALRM_EN_CNT_EN);
>         wkalrm->pending = !!(alrm_st & SUN6I_ALRM_EN_CNT_EN);
>         rtc_time_to_tm(chip->alarm, &wkalrm->time);
> --
> git-series 0.8.11
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 3/6] rtc: sun6i: Disable the build as a module
From: Chen-Yu Tsai @ 2017-01-21  2:32 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Alexandre Belloni, Alessandro Zummo, Chen-Yu Tsai,
	linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, Rob Herring,
	devicetree
In-Reply-To: <de1e4b4eda6307b664c40d6c4502058f6bb88c60.1484927680.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Hi,

On Fri, Jan 20, 2017 at 11:56 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Since we have to provide the clock very early on, the RTC driver cannot be
> built as a module. Make sure that won't happen.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  drivers/rtc/Kconfig     |  2 +-
>  drivers/rtc/rtc-sun6i.c | 17 +----------------
>  2 files changed, 2 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index c93c5a8fba32..53e35c138ff3 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -1434,7 +1434,7 @@ config RTC_DRV_SUN4V
>           based RTC on SUN4V systems.
>
>  config RTC_DRV_SUN6I
> -       tristate "Allwinner A31 RTC"
> +       bool "Allwinner A31 RTC"
>         default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
>         depends on ARCH_SUNXI
>         help
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index 872d18609183..edd5627da10f 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -554,15 +554,6 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
>         return 0;
>  }
>
> -static int sun6i_rtc_remove(struct platform_device *pdev)
> -{
> -       struct sun6i_rtc_dev *chip = platform_get_drvdata(pdev);
> -
> -       rtc_device_unregister(chip->rtc);
> -
> -       return 0;
> -}
> -
>  static const struct of_device_id sun6i_rtc_dt_ids[] = {
>         { .compatible = "allwinner,sun6i-a31-rtc" },
>         { /* sentinel */ },
> @@ -571,15 +562,9 @@ MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids);
>
>  static struct platform_driver sun6i_rtc_driver = {
>         .probe          = sun6i_rtc_probe,
> -       .remove         = sun6i_rtc_remove,

I might have gotten this wrong in the past. It seems that the
.remove callback can still be called, even if the driver is
builtin, by unbinding the driver from the device using the
sysfs interface. So we still need it regardless.

We can get rid of the .remove callback by switching to
devm_rtc_device_register, but that is a separate issue.

Also, a personal preference, is that this change should precede
the clk change you mentioned in the commit message, since you
are making this change in anticipation of possible breakage
by that one.

Regards
ChenYu

>         .driver         = {
>                 .name           = "sun6i-rtc",
>                 .of_match_table = sun6i_rtc_dt_ids,
>         },
>  };
> -
> -module_platform_driver(sun6i_rtc_driver);
> -
> -MODULE_DESCRIPTION("sun6i RTC driver");
> -MODULE_AUTHOR("Chen-Yu Tsai <wens-jdAy2FN1RRM@public.gmane.org>");
> -MODULE_LICENSE("GPL");
> +builtin_platform_driver(sun6i_rtc_driver);
> --
> git-series 0.8.11

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

^ permalink raw reply

* [PATCH v5 0/3] mmc: sh_mobile_sdhi: fix missing r7s72100 clocks
From: Chris Brandt @ 2017-01-21  3:06 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Chris Brandt

At first this started out as a simple typo fix, until I realized
that the SDHI in the RZ/A1 has 2 clocks per channel and both need
to be turned on/off.

This patch series adds the ability to specify 2 clocks instead of
just 1, and does so for the RZ/A1 r7s72100.

This patch has been tested on an RZ/A1 RSK board. Card detect works
fine as well as bind/unbind.

v5:
* Take implementation details out of DT documentation and put into
  the driver code.

v4:
* No code changes, only text udpates to explain why there are 2 clocks
  and why we need to treat them as 1 clock.

Chris Brandt (3):
  mmc: sh_mobile_sdhi: add support for 2 clocks
  mmc: sh_mobile_sdhi: explain clock bindings
  ARM: dts: r7s72100: update sdhi clock bindings

 Documentation/devicetree/bindings/mmc/tmio_mmc.txt | 24 ++++++++++++++++++++++
 arch/arm/boot/dts/r7s72100.dtsi                    | 17 ++++++++++-----
 drivers/mmc/host/sh_mobile_sdhi.c                  | 24 ++++++++++++++++++++++
 include/dt-bindings/clock/r7s72100-clock.h         |  6 ++++--
 4 files changed, 64 insertions(+), 7 deletions(-)

-- 
2.10.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v5 1/3] mmc: sh_mobile_sdhi: add support for 2 clocks
From: Chris Brandt @ 2017-01-21  3:06 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven
  Cc: devicetree, linux-mmc, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170121030604.7672-1-chris.brandt@renesas.com>

Some controllers have 2 clock sources instead of 1. The 2nd clock
is for the internal card detect logic and must be enabled/disabled
along with the main core clock for proper operation.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
---
v4:
* add technical explanation within probe routine
v3:
* add more clarification to the commit log
v2:
* changed clk2 to clk_cd
* disable clk if clk_cd enable fails
* changed clock name from "carddetect" to "cd"
---
 drivers/mmc/host/sh_mobile_sdhi.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
index 59db14b..360d922 100644
--- a/drivers/mmc/host/sh_mobile_sdhi.c
+++ b/drivers/mmc/host/sh_mobile_sdhi.c
@@ -143,6 +143,7 @@ MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
 
 struct sh_mobile_sdhi {
 	struct clk *clk;
+	struct clk *clk_cd;
 	struct tmio_mmc_data mmc_data;
 	struct tmio_mmc_dma dma_priv;
 	struct pinctrl *pinctrl;
@@ -190,6 +191,12 @@ static int sh_mobile_sdhi_clk_enable(struct tmio_mmc_host *host)
 	if (ret < 0)
 		return ret;
 
+	ret = clk_prepare_enable(priv->clk_cd);
+	if (ret < 0) {
+		clk_disable_unprepare(priv->clk);
+		return ret;
+	}
+
 	/*
 	 * The clock driver may not know what maximum frequency
 	 * actually works, so it should be set with the max-frequency
@@ -255,6 +262,8 @@ static void sh_mobile_sdhi_clk_disable(struct tmio_mmc_host *host)
 	struct sh_mobile_sdhi *priv = host_to_priv(host);
 
 	clk_disable_unprepare(priv->clk);
+	if (priv->clk_cd)
+		clk_disable_unprepare(priv->clk_cd);
 }
 
 static int sh_mobile_sdhi_card_busy(struct mmc_host *mmc)
@@ -572,6 +581,21 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
 		goto eprobe;
 	}
 
+	/*
+	 * Some controllers provide a 2nd clock just to run the internal card
+	 * detection logic. Unfortunately, the existing driver architecture does
+	 * not support a separation of clocks for runtime PM usage. When
+	 * native hotplug is used, the tmio driver assumes that the core
+	 * must continue to run for card detect to stay active, so we cannot
+	 * disable it.
+	 * Additionally, it is prohibited to supply a clock to the core but not
+	 * to the card detect circuit. That leaves us with if separate clocks
+	 * are presented, we must treat them both as virtually 1 clock.
+	 */
+	priv->clk_cd = devm_clk_get(&pdev->dev, "cd");
+	if (IS_ERR(priv->clk_cd))
+		priv->clk_cd = NULL;
+
 	priv->pinctrl = devm_pinctrl_get(&pdev->dev);
 	if (!IS_ERR(priv->pinctrl)) {
 		priv->pins_default = pinctrl_lookup_state(priv->pinctrl,
-- 
2.10.1

^ permalink raw reply related

* [PATCH v5 2/3] mmc: sh_mobile_sdhi: explain clock bindings
From: Chris Brandt @ 2017-01-21  3:06 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA, Chris Brandt
In-Reply-To: <20170121030604.7672-1-chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>

In the case of a single clock source, you don't need names. However,
if the controller has 2 clock sources, you need to name them correctly
so the driver can find the 2nd one. The 2nd clock is for the internal
card detect logic.

Signed-off-by: Chris Brandt <chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>
---
v4:
* just explain there might be 2 clocks, don't explain how
  we will use them in the driver
v3:
* add more clarification about why there are sometimes 2 clocks
  and what you should do with them.
* remove 'status = "disabled"' from example
v2:
* fix spelling and change wording
* changed clock name from "carddetect" to "cd"
---
 Documentation/devicetree/bindings/mmc/tmio_mmc.txt | 24 ++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
index a1650ed..1464c16 100644
--- a/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
+++ b/Documentation/devicetree/bindings/mmc/tmio_mmc.txt
@@ -25,8 +25,32 @@ Required properties:
 		"renesas,sdhi-r8a7795" - SDHI IP on R8A7795 SoC
 		"renesas,sdhi-r8a7796" - SDHI IP on R8A7796 SoC
 
+- clocks: Most controllers only have 1 clock source per channel. However, on
+	  some variations of this controller, the internal card detection
+	  logic that exists in this controller is sectioned off to be run by a
+	  separate second clock source to allow the main core clock to be turned
+	  off to save power.
+	  If 2 clocks are specified by the hardware, you must name them as
+	  "core" and "cd".
+	  If the controller only has 1 clock, naming is not required.
+
 Optional properties:
 - toshiba,mmc-wrprotect-disable: write-protect detection is unavailable
 - pinctrl-names: should be "default", "state_uhs"
 - pinctrl-0: should contain default/high speed pin ctrl
 - pinctrl-1: should contain uhs mode pin ctrl
+
+Example showing 2 clocks:
+	sdhi0: sd@e804e000 {
+		compatible = "renesas,sdhi-r7s72100";
+		reg = <0xe804e000 0x100>;
+		interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
+			      GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+
+		clocks = <&mstp12_clks R7S72100_CLK_SDHI00>,
+			 <&mstp12_clks R7S72100_CLK_SDHI01>;
+		clock-names = "core", "cd";
+		cap-sd-highspeed;
+		cap-sdio-irq;
+	};
-- 
2.10.1


--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* [PATCH v5 3/3] ARM: dts: r7s72100: update sdhi clock bindings
From: Chris Brandt @ 2017-01-21  3:06 UTC (permalink / raw)
  To: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven
  Cc: devicetree, linux-mmc, linux-renesas-soc, Chris Brandt
In-Reply-To: <20170121030604.7672-1-chris.brandt@renesas.com>

The SDHI controller in the RZ/A1 has 2 clock sources per channel and both
need to be enabled/disabled for proper operation. This fixes the fact that
the define for R7S72100_CLK_SDHI1 was not correct to begin with (typo), and
that all 4 clock sources need to be defined an used.

Signed-off-by: Chris Brandt <chris.brandt@renesas.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
v2:
* add missing clock sources instead of just fixing typo
* changed clock name from "carddetect" to "cd"
---
 arch/arm/boot/dts/r7s72100.dtsi            | 17 ++++++++++++-----
 include/dt-bindings/clock/r7s72100-clock.h |  6 ++++--
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index 3dd427d..9d0b8d0 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -153,9 +153,12 @@
 			#clock-cells = <1>;
 			compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
 			reg = <0xfcfe0444 4>;
-			clocks = <&p1_clk>, <&p1_clk>;
-			clock-indices = <R7S72100_CLK_SDHI1 R7S72100_CLK_SDHI0>;
-			clock-output-names = "sdhi1", "sdhi0";
+			clocks = <&p1_clk>, <&p1_clk>, <&p1_clk>, <&p1_clk>;
+			clock-indices = <
+				R7S72100_CLK_SDHI00 R7S72100_CLK_SDHI01
+				R7S72100_CLK_SDHI10 R7S72100_CLK_SDHI11
+			>;
+			clock-output-names = "sdhi00", "sdhi01", "sdhi10", "sdhi11";
 		};
 	};
 
@@ -478,7 +481,9 @@
 			      GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
 			      GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
 
-		clocks = <&mstp12_clks R7S72100_CLK_SDHI0>;
+		clocks = <&mstp12_clks R7S72100_CLK_SDHI00>,
+			 <&mstp12_clks R7S72100_CLK_SDHI01>;
+		clock-names = "core", "cd";
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
@@ -491,7 +496,9 @@
 			      GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH
 			      GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>;
 
-		clocks = <&mstp12_clks R7S72100_CLK_SDHI1>;
+		clocks = <&mstp12_clks R7S72100_CLK_SDHI10>,
+			 <&mstp12_clks R7S72100_CLK_SDHI11>;
+		clock-names = "core", "cd";
 		cap-sd-highspeed;
 		cap-sdio-irq;
 		status = "disabled";
diff --git a/include/dt-bindings/clock/r7s72100-clock.h b/include/dt-bindings/clock/r7s72100-clock.h
index 29e01ed..f2d8428 100644
--- a/include/dt-bindings/clock/r7s72100-clock.h
+++ b/include/dt-bindings/clock/r7s72100-clock.h
@@ -45,7 +45,9 @@
 #define R7S72100_CLK_SPI4	3
 
 /* MSTP12 */
-#define R7S72100_CLK_SDHI0	3
-#define R7S72100_CLK_SDHI1	2
+#define R7S72100_CLK_SDHI00	3
+#define R7S72100_CLK_SDHI01	2
+#define R7S72100_CLK_SDHI10	1
+#define R7S72100_CLK_SDHI11	0
 
 #endif /* __DT_BINDINGS_CLOCK_R7S72100_H__ */
-- 
2.10.1

^ permalink raw reply related

* Re: [PATCH 4/6] rtc: sun6i: Force the mux to the external oscillator
From: Chen-Yu Tsai @ 2017-01-21  3:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Alexandre Belloni, Alessandro Zummo, Chen-Yu Tsai,
	linux-arm-kernel, rtc-linux-/JYPxA39Uh5TLH3MbocFFw, Rob Herring,
	devicetree
In-Reply-To: <409c56f0ed1c4b0026ad60cb1218c99fe1686408.1484927680.git-series.maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Hi,

On Fri, Jan 20, 2017 at 11:56 PM, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The internal oscillator is way too inaccurate to do something useful with
> it. Switch to the external oscillator if it is available.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  drivers/rtc/rtc-sun6i.c | 12 ++++++++++++
>  1 file changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
> index edd5627da10f..1695fae24cd5 100644
> --- a/drivers/rtc/rtc-sun6i.c
> +++ b/drivers/rtc/rtc-sun6i.c
> @@ -493,6 +493,7 @@ static const struct rtc_class_ops sun6i_rtc_ops = {
>  static int sun6i_rtc_probe(struct platform_device *pdev)
>  {
>         struct sun6i_rtc_dev *chip = sun6i_rtc;
> +       struct clk *parent;
>         int ret;
>
>         if (!chip)
> @@ -540,6 +541,17 @@ static int sun6i_rtc_probe(struct platform_device *pdev)
>         /* disable alarm wakeup */
>         writel(0, chip->base + SUN6I_ALARM_CONFIG);
>
> +       parent = clk_get(&pdev->dev, NULL);
> +       if (!IS_ERR(parent)) {
> +               ret = clk_set_parent(chip->losc, parent);
> +               clk_put(parent);
> +
> +               if (ret) {
> +                       dev_err(&pdev->dev,
> +                               "Failed to reparent the RTC to the external oscillator\n");
> +                       return ret;
> +               }
> +       }

Following what I mentioned in patch 1, maybe it is easier to force
the mux before the clocks are registered by writing directly to
the registers? We could also backport the changes to stable?

ChenYu

>         clk_prepare_enable(chip->losc);
>
>         chip->rtc = rtc_device_register("rtc-sun6i", &pdev->dev,
> --
> git-series 0.8.11
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 2/4] clk: samsung: Remove Exynos4415 driver (SoC not supported anymore)
From: Chanwoo Choi @ 2017-01-21  5:08 UTC (permalink / raw)
  To: Sylwester Nawrocki
  Cc: Mark Rutland, devicetree, linux-samsung-soc, Kukjin Kim,
	Chanwoo Choi, Stephen Boyd, Michael Turquette, Seung-Woo Kim,
	Tomasz Figa, Krzysztof Kozlowski, linux-kernel,
	Javier Martinez Canillas, Kyungmin Park, Rob Herring, dri-devel,
	linux-gpio, linux-clk, linux-arm-kernel
In-Reply-To: <c9b51cb6-f798-d41e-afff-f779b963345c@samsung.com>

Hi Sylwester,

I add reveiwed-by tag from this patch. But, on you tree, this patch[1] doesn’t
include the my reviewed-by tag.

[1] https://git.linuxtv.org/snawrocki/samsung.git/commit/?h=for-v4.11/clk/next&id=cb4ac949ea14416a2d57b7a343bc4b571074e3bd

2017-01-16 19:32 GMT+09:00 Sylwester Nawrocki <s.nawrocki@samsung.com>:
> On 01/14/2017 01:36 PM, Krzysztof Kozlowski wrote:
>> Support for Exynos4415 is going away because there are no internal nor
>> external users.
>>
>> Since commit 46dcf0ff0de3 ("ARM: dts: exynos: Remove exynos4415.dtsi"),
>> the platform cannot be instantiated so remove also the drivers.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Applied, thanks.
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel



-- 
Best Regards,
Chanwoo Choi
Samsung Electronics
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH v3 1/2] devicetree: document new marvell-8xxx and pwrseq-sd8787 options
From: Matt Ranostay @ 2017-01-21  5:50 UTC (permalink / raw)
  To: linux-mmc, linux-kernel; +Cc: ulf.hansson, Matt Ranostay, devicetree
In-Reply-To: <20170121055039.10924-1-matt@ranostay.consulting>

Cc: devicetree@vger.kernel.org
Signed-off-by: Matt Ranostay <matt@ranostay.consulting>
---
 .../devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt          | 14 ++++++++++++++
 .../devicetree/bindings/net/wireless/marvell-8xxx.txt      |  7 ++++++-
 2 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt

diff --git a/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt
new file mode 100644
index 000000000000..4bb56766982e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/mmc-pwrseq-sd8787.txt
@@ -0,0 +1,14 @@
+* Marvell SD8787 power sequence provider
+
+Required properties:
+- compatible: must be "mmc-pwrseq-sd8787".
+- powerdown-gpio: contains a power down GPIO specifier with active state
+- reset-gpio: contains a reset GPIO specifier with active state
+
+Example:
+
+	wifi_pwrseq: wifi_pwrseq {
+		compatible = "mmc-pwrseq-sd8787";
+		powerdown-gpio = <&twl_gpio 0 GPIO_ACTIVE_LOW>;
+		reset-gpio = <&twl_gpio 1 GPIO_ACTIVE_LOW>;
+	}
diff --git a/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
index 980b16df74c3..0854451ff91d 100644
--- a/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
+++ b/Documentation/devicetree/bindings/net/wireless/marvell-8xxx.txt
@@ -1,4 +1,4 @@
-Marvell 8897/8997 (sd8897/sd8997/pcie8997) SDIO/PCIE devices
+Marvell 8787/8897/8997 (sd8787/sd8897/sd8997/pcie8997) SDIO/PCIE devices
 ------
 
 This node provides properties for controlling the Marvell SDIO/PCIE wireless device.
@@ -8,6 +8,7 @@ connects the device to the system.
 Required properties:
 
   - compatible : should be one of the following:
+	* "marvell,sd8787"
 	* "marvell,sd8897"
 	* "marvell,sd8997"
 	* "pci11ab,2b42"
@@ -34,6 +35,9 @@ Optional properties:
 		 so that the wifi chip can wakeup host platform under certain condition.
 		 during system resume, the irq will be disabled to make sure
 		 unnecessary interrupt is not received.
+  - vmmc-supply: a phandle of a regulator, supplying VCC to the card
+  - mmc-pwrseq:  phandle to the MMC power sequence node. See "mmc-pwrseq-*"
+		 for documentation of MMC power sequence bindings.
 
 Example:
 
@@ -46,6 +50,7 @@ so that firmware can wakeup host using this device side pin.
 &mmc3 {
 	status = "okay";
 	vmmc-supply = <&wlan_en_reg>;
+	mmc-pwrseq = <&wifi_pwrseq>;
 	bus-width = <4>;
 	cap-power-off-card;
 	keep-power-in-suspend;
-- 
2.10.2


^ permalink raw reply related

* Re: [PATCH v5 2/3] mmc: sh_mobile_sdhi: explain clock bindings
From: Wolfram Sang @ 2017-01-21  9:36 UTC (permalink / raw)
  To: Chris Brandt
  Cc: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170121030604.7672-3-chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 489 bytes --]

On Fri, Jan 20, 2017 at 10:06:03PM -0500, Chris Brandt wrote:
> In the case of a single clock source, you don't need names. However,
> if the controller has 2 clock sources, you need to name them correctly
> so the driver can find the 2nd one. The 2nd clock is for the internal
> card detect logic.
> 
> Signed-off-by: Chris Brandt <chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>

Reviewed-by: Wolfram Sang <wsa+renesas-jBu1N2QxHDJrcw3mvpCnnVaTQe2KTcn/@public.gmane.org>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v5 1/3] mmc: sh_mobile_sdhi: add support for 2 clocks
From: Wolfram Sang @ 2017-01-21  9:37 UTC (permalink / raw)
  To: Chris Brandt
  Cc: Ulf Hansson, Rob Herring, Mark Rutland, Simon Horman,
	Wolfram Sang, Geert Uytterhoeven, devicetree, linux-mmc,
	linux-renesas-soc
In-Reply-To: <20170121030604.7672-2-chris.brandt@renesas.com>

[-- Attachment #1: Type: text/plain, Size: 386 bytes --]

On Fri, Jan 20, 2017 at 10:06:02PM -0500, Chris Brandt wrote:
> Some controllers have 2 clock sources instead of 1. The 2nd clock
> is for the internal card detect logic and must be enabled/disabled
> along with the main core clock for proper operation.
> 
> Signed-off-by: Chris Brandt <chris.brandt@renesas.com>

Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>


[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply

* Re: [PATCH v3 0/4] Amlogic Meson SAR ADC support
From: Jonathan Cameron @ 2017-01-21 12:37 UTC (permalink / raw)
  To: Martin Blumenstingl, knaack.h-Mmb7MZpHnFY,
	lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-clk-u79uwXL29TY76Z2rM5mHXA
  Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170119145822.26239-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

Hi Martin,

Quick process point.  Personally I'd much prefer it if new versions
fo the patch are not posted as replies to earlier versions.  It gets
awfully deep and hard to follow very quickly!

Thanks,

Jonathan

On 19/01/17 14:58, Martin Blumenstingl wrote:
> This series add support for the SAR ADC on Amlogic Meson GXBB, GXL and
> GXM SoCs.
> The hardware on GXBB provides 10-bit ADC results, while GXL and GXM are
> providing 12-bit results. Support for older SoCs (Meson8b and Meson8)
> can be added with little effort, most of which is testing I guess (I
> don't have any pre-GXBB hardware so I can't say).
> 
> A new set of clocks had to be added to the GXBB clock controller (used
> by the GXBB/GXL/GXM SoCs) which are required to get the ADC working.
> 
> The ADC itself can sample multiple channels at the same time and allows
> capturing multiple samples (which can be used for filtering/averaging).
> The ADC results are stored inside a FIFO register. More details on what
> the driver supports (or doesn't) can be found in the description of
> patch #3.
> 
> The code is based on the public S805 (Meson8b) and S905 (GXBB)
> datasheets, as well as by reading (various versions of) the vendor
> driver and by inspecting the registers on the vendor kernels of my
> testing-hardware.
> 
> Typical use-cases for the ADC on the Meson GX SoCs are:
> - adc-keys ("ADC attached resistor ladder buttons")
> - SoC temperature measurement (not supported by this driver yet as
>   the system firmware does this already and provides the values via the
>   SCPI protocol)
> - "version-strapping" (different resistor values are used to indicate
>   the board-revision)
> - and of course typical ADC measurements
> 
> Thanks to Heiner Kallweit, Jonathan Cameron, Lars-Peter Clausen and
> Peter Meerwald-Stadler for reviewing this series and providing valuable
> input!
> 
> Changes since v2 (all changes are for patch #3, except where noted):
> - fixed another typo in the interrupt (patch #4, thanks again Heiner
>   Kallweit)
> - change namespace of all register #defines to MESON_SAR_ADC (I
>   intentionally decided to keep SAR_ADC in it because that's the way
>   registers are named in the datasheet, thus making it easy to match the
>   registers without having to look up the offset all the time)
> - added additional parenthesis around MACRO parameters  for extra safety
> - removed unused definition for SAR_ADC_REG3_ADC_CLK_DIV_MASK (as we
>   already have SAR_ADC_REG3_ADC_CLK_DIV_SHIFT and
>   SAR_ADC_REG3_ADC_CLK_DIV_WIDTH which are used instead)
> - change value of "indexed" from "true" to "1"
> - remove type parameter from MESON_SAR_ADC_CHAN macro as all channels are
>   currently IIO_VOLTAGE channels
> - fixed another multi-line comment style violation
> - added timeout to meson_saradc_lock() (unlikely to be triggered, but
>   better safe then sorry - which would mean that we'd be keeping one core
>   busy infinitely)
> - fixed meson_saradc_remove() call order (first unregister the iio_dev,
>   then disable the hardware instead of the other way around)
> - use "consistent prefixing", which means that all #defines now use
>   MESON_SAR_ADC_ as prefix, while all enums, static global variables,
>   structs and functions use meson_sar_adc_ as prefix
> - rebased .dts and clk patches to apply to khilman's latest v4.11/dt64
>   (a minor  conflict had to be resolved in the clk patch due to
>   "clk: meson-gxbb: Export HDMI clocks")
> - added Tested-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org> to all
>   patches (thanks for testing!)
> 
> Changes since v1 (all changes are for patch #3, except where noted):
> - fix IRQ number in meson-gx.dtsi (thanks to Heiner Kallweit for
>   providing the correct value), affects patch #4
> - move the most used members of meson_saradc_priv to the beginning
> - remove unused struct member "completion" from meson_saradc_priv
> - use devm_kasprintf() instead of snprintf() + devm_kstrdup()
> - initialize indio_dev->dev.parent earlier in meson_saradc_probe()
> - moved meson_saradc_clear_fifo() logic to a separate function
> - add comment why a do ... while loop is required in
>   meson_saradc_wait_busy_clear()
> - remove SAR_ADC_NUM_CHANNELS and SAR_ADC_VALUE_MASK macros (each of them
>   was only used once and it's an unneeded level of abstraction)
> - fixed multiline comment syntax violations
> - dropped unneeded log messages during initialization
> - set iio_dev name to "meson-gxbb-saradc" or "meson-gxl-saradc"
> - use "indio_dev->dev.parent" in all kernel log calls (dev_warn/err/etc)
>   to make it show the OF node name (instead of the iio device name)
> - introduce struct meson_saradc_data to hold platform-specific
>   information (such as resolution in bits and the iio_dev name)
> 
> 
> Martin Blumenstingl (4):
>   Documentation: dt-bindings: add the Amlogic Meson SAR ADC
>     documentation
>   clk: gxbb: add the SAR ADC clocks and expose them
>   iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
>   ARM64: dts: meson: meson-gx: add the SAR ADC
> 
>  .../bindings/iio/adc/amlogic,meson-saradc.txt      |  31 +
>  arch/arm64/boot/dts/amlogic/meson-gx.dtsi          |   8 +
>  arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi        |  10 +
>  arch/arm64/boot/dts/amlogic/meson-gxl.dtsi         |  10 +
>  drivers/clk/meson/gxbb.c                           |  48 ++
>  drivers/clk/meson/gxbb.h                           |   9 +-
>  drivers/iio/adc/Kconfig                            |  12 +
>  drivers/iio/adc/Makefile                           |   1 +
>  drivers/iio/adc/meson_saradc.c                     | 916 +++++++++++++++++++++
>  include/dt-bindings/clock/gxbb-clkc.h              |   4 +
>  10 files changed, 1046 insertions(+), 3 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
>  create mode 100644 drivers/iio/adc/meson_saradc.c
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 1/4] Documentation: dt-bindings: add the Amlogic Meson SAR ADC documentation
From: Jonathan Cameron @ 2017-01-21 12:39 UTC (permalink / raw)
  To: Martin Blumenstingl, knaack.h-Mmb7MZpHnFY,
	lars-Qo5EllUWu/uELgA04lAiVw, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	khilman-rdvid1DuHRBWk0Htik3J/w, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-clk-u79uwXL29TY76Z2rM5mHXA
  Cc: carlo-KA+7E9HrN00dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8, mturquette-rdvid1DuHRBWk0Htik3J/w,
	sboyd-sgV2jX0FEOL9JmXXK+q4OQ, narmstrong-rdvid1DuHRBWk0Htik3J/w,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170119145822.26239-2-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

On 19/01/17 14:58, Martin Blumenstingl wrote:
> This adds the devicetree binding documentation for the SAR ADC found in
> Amlogic Meson SoCs.
> Currently only the GXBB, GXL and GXM SoCs are supported.
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
> Tested-by: Neil Armstrong <narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
Looks straight forward to me, but there is just enough here that I'm looking
for an Ack from Rob or Mark.

Thanks,

Jonathan
> ---
>  .../bindings/iio/adc/amlogic,meson-saradc.txt      | 31 ++++++++++++++++++++++
>  1 file changed, 31 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> new file mode 100644
> index 000000000000..9a0bec7afc63
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.txt
> @@ -0,0 +1,31 @@
> +* Amlogic Meson SAR (Successive Approximation Register) A/D converter
> +
> +Required properties:
> +- compatible:	depending on the SoC this should be one of:
> +			- "amlogic,meson-gxbb-saradc" for GXBB
> +			- "amlogic,meson-gxl-saradc" for GXL and GXM
> +		along with the generic "amlogic,meson-saradc"
> +- reg:		the physical base address and length of the registers
> +- clocks:	phandle and clock identifier (see clock-names)
> +- clock-names:	mandatory clocks:
> +			- "clkin" for the reference clock (typically XTAL)
> +			- "core" for the SAR ADC core clock
> +		optional clocks:
> +			- "sana" for the analog clock
> +			- "adc_clk" for the ADC (sampling) clock
> +			- "adc_sel" for the ADC (sampling) clock mux
> +- vref-supply:	the regulator supply for the ADC reference voltage
> +- #io-channel-cells: must be 1, see ../iio-bindings.txt
> +
> +Example:
> +	saradc: adc@8680 {
> +		compatible = "amlogic,meson-gxl-saradc", "amlogic,meson-saradc";
> +		#io-channel-cells = <1>;
> +		reg = <0x0 0x8680 0x0 0x34>;
> +		clocks = <&xtal>,
> +			 <&clkc CLKID_SAR_ADC>,
> +			 <&clkc CLKID_SANA>,
> +			 <&clkc CLKID_SAR_ADC_CLK>,
> +			 <&clkc CLKID_SAR_ADC_SEL>;
> +		clock-names = "clkin", "core", "sana", "adc_clk", "adc_sel";
> +	};
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 3/4] iio: adc: add a driver for the SAR ADC found in Amlogic Meson SoCs
From: Jonathan Cameron @ 2017-01-21 12:52 UTC (permalink / raw)
  To: Martin Blumenstingl, knaack.h, lars, pmeerw, robh+dt,
	mark.rutland, khilman, linux-iio, devicetree, linux-amlogic,
	linux-clk
  Cc: narmstrong, catalin.marinas, mturquette, will.deacon, carlo,
	sboyd, linux-arm-kernel
In-Reply-To: <20170119145822.26239-4-martin.blumenstingl@googlemail.com>

On 19/01/17 14:58, Martin Blumenstingl wrote:
> This adds support for the SAR (Successive Approximation Register) ADC
> on the Amlogic Meson SoCs.
> 
> The code is based on the public S805 (Meson8b) and S905 (GXBB)
> datasheets (see [0] and [1]), as well as by reading (various versions
> of) the vendor driver and by inspecting the registers on the vendor
> kernels of my testing-hardware.
> 
> Currently the GXBB, GXL and GXM SoCs are supported. GXBB hardware has
> 10-bit ADC resolution, while GXL and GXM have 12-bit ADC resolution.
> The code was written to support older SoCs (Meson8 and Meson8b) as well,
> but due to lack of actual testing-hardware no of_device_id was added for
> these.
> 
> Two "features" from the vendor driver are currently missing:
> - the vendor driver uses channel #7 for calibration (this improves the
>   accuracy of the results - in my tests the results were less than 3%
>   off without calibration compared to the vendor driver). Adding support
>   for this should be easy, but is not required for most applications.
> - channel #6 is connected to the SoCs internal temperature sensor.
>   Adding support for this is probably not so easy since (based on the
>   u-boot sources) most SoC versions are using different registers and
>   algorithms for the conversion from "ADC value" to temperature.
> 
> Supported by the hardware but currently not supported by the driver:
> - reading multiple channels at the same time (the hardware has a FIFO
>   buffer which stores multiple results)
> - continuous sampling (this would require a way to enable this
>   individually because otherwise the ADC would be drawing power
>   constantly)
> - interrupt support (similar to the vendor driver this new driver is
>   polling the results. It is unclear if the IRQ-mode is supported on
>   older (Meson6 or Meson8) hardware as well or if there are any errata)
> 
> [0]
> http://dn.odroid.com/S805/Datasheet/S805_Datasheet%20V0.8%2020150126.pdf
> [1] http://dn.odroid.com/S905/DataSheet/S905_Public_Datasheet_V1.1.4.pdf
> 
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> Tested-by: Neil Armstrong <narmstrong@baylibre.com>
Very nice.  One really minor comment inline, that I'd only bother
dealing with should you be rolling a V4 for some other reason.

I'll take this if Rob / Mark are happy with the device tree bindings.
Give me a bump if we see nothing from them in the next week or so (or if
I miss it!)

thanks

Jonathan
> ---
>  drivers/iio/adc/Kconfig        |  12 +
>  drivers/iio/adc/Makefile       |   1 +
>  drivers/iio/adc/meson_saradc.c | 916 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 929 insertions(+)
>  create mode 100644 drivers/iio/adc/meson_saradc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 9c8b558ba19e..86059b9b91bf 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -371,6 +371,18 @@ config MEN_Z188_ADC
>  	  This driver can also be built as a module. If so, the module will be
>  	  called men_z188_adc.
>  
> +config MESON_SARADC
> +	tristate "Amlogic Meson SAR ADC driver"
> +	default ARCH_MESON
> +	depends on OF && COMMON_CLK && (ARCH_MESON || COMPILE_TEST)
> +	select REGMAP_MMIO
> +	help
> +	  Say yes here to build support for the SAR ADC found in Amlogic Meson
> +	  SoCs.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called meson_saradc.
> +
>  config MXS_LRADC
>          tristate "Freescale i.MX23/i.MX28 LRADC"
>          depends on (ARCH_MXS || COMPILE_TEST) && HAS_IOMEM
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index d36c4be8d1fc..de05b9e75f8f 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -36,6 +36,7 @@ obj-$(CONFIG_MCP320X) += mcp320x.o
>  obj-$(CONFIG_MCP3422) += mcp3422.o
>  obj-$(CONFIG_MEDIATEK_MT6577_AUXADC) += mt6577_auxadc.o
>  obj-$(CONFIG_MEN_Z188_ADC) += men_z188_adc.o
> +obj-$(CONFIG_MESON_SARADC) += meson_saradc.o
>  obj-$(CONFIG_MXS_LRADC) += mxs-lradc.o
>  obj-$(CONFIG_NAU7802) += nau7802.o
>  obj-$(CONFIG_PALMAS_GPADC) += palmas_gpadc.o
> diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
> new file mode 100644
> index 000000000000..11a9686d2a9c
> --- /dev/null
> +++ b/drivers/iio/adc/meson_saradc.c
> @@ -0,0 +1,916 @@
> +/*
> + * Amlogic Meson Successive Approximation Register (SAR) A/D Converter
> + *
> + * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/iio/iio.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define MESON_SAR_ADC_REG0					0x00
> +	#define MESON_SAR_ADC_REG0_PANEL_DETECT			BIT(31)
> +	#define MESON_SAR_ADC_REG0_BUSY_MASK			GENMASK(30, 28)
> +	#define MESON_SAR_ADC_REG0_DELTA_BUSY			BIT(30)
> +	#define MESON_SAR_ADC_REG0_AVG_BUSY			BIT(29)
> +	#define MESON_SAR_ADC_REG0_SAMPLE_BUSY			BIT(28)
> +	#define MESON_SAR_ADC_REG0_FIFO_FULL			BIT(27)
> +	#define MESON_SAR_ADC_REG0_FIFO_EMPTY			BIT(26)
> +	#define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK		GENMASK(25, 21)
> +	#define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK		GENMASK(20, 19)
> +	#define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK		GENMASK(18, 16)
> +	#define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL		BIT(15)
> +	#define MESON_SAR_ADC_REG0_SAMPLING_STOP		BIT(14)
> +	#define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK		GENMASK(13, 12)
> +	#define MESON_SAR_ADC_REG0_DETECT_IRQ_POL		BIT(10)
> +	#define MESON_SAR_ADC_REG0_DETECT_IRQ_EN		BIT(9)
> +	#define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK		GENMASK(8, 4)
> +	#define MESON_SAR_ADC_REG0_FIFO_IRQ_EN			BIT(3)
> +	#define MESON_SAR_ADC_REG0_SAMPLING_START		BIT(2)
> +	#define MESON_SAR_ADC_REG0_CONTINUOUS_EN		BIT(1)
> +	#define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE		BIT(0)
> +
> +#define MESON_SAR_ADC_CHAN_LIST					0x04
> +	#define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK		GENMASK(26, 24)
> +	#define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan)	\
> +					(GENMASK(2, 0) << ((_chan) * 3))
> +
> +#define MESON_SAR_ADC_AVG_CNTL					0x08
> +	#define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan)	\
> +					(16 + ((_chan) * 2))
> +	#define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan)	\
> +					(GENMASK(17, 16) << ((_chan) * 2))
> +	#define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan)	\
> +					(0 + ((_chan) * 2))
> +	#define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan)	\
> +					(GENMASK(1, 0) << ((_chan) * 2))
> +
> +#define MESON_SAR_ADC_REG3					0x0c
> +	#define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY		BIT(31)
> +	#define MESON_SAR_ADC_REG3_CLK_EN			BIT(30)
> +	#define MESON_SAR_ADC_REG3_BL30_INITIALIZED		BIT(28)
> +	#define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN	BIT(27)
> +	#define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE	BIT(26)
> +	#define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK	GENMASK(25, 23)
> +	#define MESON_SAR_ADC_REG3_DETECT_EN			BIT(22)
> +	#define MESON_SAR_ADC_REG3_ADC_EN			BIT(21)
> +	#define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK	GENMASK(20, 18)
> +	#define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK	GENMASK(17, 16)
> +	#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT		10
> +	#define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH		5
> +	#define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK		GENMASK(9, 8)
> +	#define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK		GENMASK(7, 0)
> +
> +#define MESON_SAR_ADC_DELAY					0x10
> +	#define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK		GENMASK(25, 24)
> +	#define MESON_SAR_ADC_DELAY_BL30_BUSY			BIT(15)
> +	#define MESON_SAR_ADC_DELAY_KERNEL_BUSY			BIT(14)
> +	#define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK		GENMASK(23, 16)
> +	#define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK		GENMASK(9, 8)
> +	#define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK		GENMASK(7, 0)
> +
> +#define MESON_SAR_ADC_LAST_RD					0x14
> +	#define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK	GENMASK(23, 16)
> +	#define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK	GENMASK(9, 0)
> +
> +#define MESON_SAR_ADC_FIFO_RD					0x18
> +	#define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK		GENMASK(14, 12)
> +	#define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK		GENMASK(11, 0)
> +
> +#define MESON_SAR_ADC_AUX_SW					0x1c
> +	#define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_MASK(_chan)	\
> +					(GENMASK(10, 8) << (((_chan) - 2) * 2))
> +	#define MESON_SAR_ADC_AUX_SW_VREF_P_MUX			BIT(6)
> +	#define MESON_SAR_ADC_AUX_SW_VREF_N_MUX			BIT(5)
> +	#define MESON_SAR_ADC_AUX_SW_MODE_SEL			BIT(4)
> +	#define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW		BIT(3)
> +	#define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW		BIT(2)
> +	#define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW		BIT(1)
> +	#define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW		BIT(0)
> +
> +#define MESON_SAR_ADC_CHAN_10_SW				0x20
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK	GENMASK(25, 23)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX	BIT(22)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX	BIT(21)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL		BIT(20)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW	BIT(19)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW	BIT(18)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW	BIT(17)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW	BIT(16)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK	GENMASK(9, 7)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX	BIT(6)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX	BIT(5)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL		BIT(4)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW	BIT(3)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW	BIT(2)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW	BIT(1)
> +	#define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW	BIT(0)
> +
> +#define MESON_SAR_ADC_DETECT_IDLE_SW				0x24
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN	BIT(26)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK	GENMASK(25, 23)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX	BIT(22)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX	BIT(21)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL	BIT(20)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW	BIT(19)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW	BIT(18)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW	BIT(17)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW	BIT(16)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK	GENMASK(9, 7)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX	BIT(6)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX	BIT(5)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL	BIT(4)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW	BIT(3)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW	BIT(2)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW	BIT(1)
> +	#define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW	BIT(0)
> +
> +#define MESON_SAR_ADC_DELTA_10					0x28
> +	#define MESON_SAR_ADC_DELTA_10_TEMP_SEL			BIT(27)
> +	#define MESON_SAR_ADC_DELTA_10_TS_REVE1			BIT(26)
> +	#define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK	GENMASK(25, 16)
> +	#define MESON_SAR_ADC_DELTA_10_TS_REVE0			BIT(15)
> +	#define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT		11
> +	#define MESON_SAR_ADC_DELTA_10_TS_C_MASK		GENMASK(14, 11)
> +	#define MESON_SAR_ADC_DELTA_10_TS_VBG_EN		BIT(10)
> +	#define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK	GENMASK(9, 0)
> +
> +/*
> + * NOTE: registers from here are undocumented (the vendor Linux kernel driver
> + * and u-boot source served as reference). These only seem to be relevant on
> + * GXBB and newer.
> + */
> +#define MESON_SAR_ADC_REG11					0x2c
> +	#define MESON_SAR_ADC_REG11_BANDGAP_EN			BIT(13)
> +
> +#define MESON_SAR_ADC_REG13					0x34
> +	#define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK	GENMASK(13, 8)
> +
> +#define MESON_SAR_ADC_MAX_FIFO_SIZE				32
> +
> +#define MESON_SAR_ADC_CHAN(_chan) {					\
> +	.type = IIO_VOLTAGE,						\
> +	.indexed = 1,							\
> +	.channel = _chan,						\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
> +				BIT(IIO_CHAN_INFO_AVERAGE_RAW),		\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),		\
> +	.datasheet_name = "SAR_ADC_CH"#_chan,				\
> +}
> +
> +/*
> + * TODO: the hardware supports IIO_TEMP for channel 6 as well which is
> + * currently not supported by this driver.
> + */
> +static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
> +	MESON_SAR_ADC_CHAN(0),
> +	MESON_SAR_ADC_CHAN(1),
> +	MESON_SAR_ADC_CHAN(2),
> +	MESON_SAR_ADC_CHAN(3),
> +	MESON_SAR_ADC_CHAN(4),
> +	MESON_SAR_ADC_CHAN(5),
> +	MESON_SAR_ADC_CHAN(6),
> +	MESON_SAR_ADC_CHAN(7),
> +	IIO_CHAN_SOFT_TIMESTAMP(8),
> +};
> +
> +enum meson_sar_adc_avg_mode {
> +	NO_AVERAGING = 0x0,
> +	MEAN_AVERAGING = 0x1,
> +	MEDIAN_AVERAGING = 0x2,
> +};
> +
> +enum meson_sar_adc_num_samples {
> +	ONE_SAMPLE = 0x0,
> +	TWO_SAMPLES = 0x1,
> +	FOUR_SAMPLES = 0x2,
> +	EIGHT_SAMPLES = 0x3,
> +};
> +
> +enum meson_sar_adc_chan7_mux_sel {
> +	CHAN7_MUX_VSS = 0x0,
> +	CHAN7_MUX_VDD_DIV4 = 0x1,
> +	CHAN7_MUX_VDD_DIV2 = 0x2,
> +	CHAN7_MUX_VDD_MUL3_DIV4 = 0x3,
> +	CHAN7_MUX_VDD = 0x4,
> +	CHAN7_MUX_CH7_INPUT = 0x7,
> +};
> +
> +struct meson_sar_adc_data {
> +	unsigned int				resolution;
> +	const char				*name;
> +};
> +
> +struct meson_sar_adc_priv {
> +	struct regmap				*regmap;
> +	struct regulator			*vref;
> +	const struct meson_sar_adc_data		*data;
> +	struct clk				*clkin;
> +	struct clk				*core_clk;
> +	struct clk				*sana_clk;
> +	struct clk				*adc_sel_clk;
> +	struct clk				*adc_clk;
> +	struct clk_gate				clk_gate;
> +	struct clk				*adc_div_clk;
> +	struct clk_divider			clk_div;
> +};
> +
> +static const struct regmap_config meson_sar_adc_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 32,
> +	.reg_stride = 4,
> +	.max_register = MESON_SAR_ADC_REG13,
> +};
> +
> +static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	u32 regval;
> +
> +	regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
> +
> +	return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
> +}
> +
> +static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int regval, timeout = 10000;
> +
> +	/*
> +	 * NOTE: we need a small delay before reading the status, otherwise
> +	 * the sample engine may not have started internally (which would
> +	 * seem to us that sampling is already finished).
> +	 */
> +	do {
> +		udelay(1);
> +		regmap_read(priv->regmap, MESON_SAR_ADC_REG0, &regval);
> +	} while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--);
> +
> +	if (timeout < 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
> +					 const struct iio_chan_spec *chan,
> +					 int *val)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int ret, regval, fifo_chan, fifo_val, sum = 0, count = 0;
> +
> +	ret = meson_sar_adc_wait_busy_clear(indio_dev);
> +	if (ret)
> +		return ret;
> +
> +	while (meson_sar_adc_get_fifo_count(indio_dev) > 0 &&
> +	       count < MESON_SAR_ADC_MAX_FIFO_SIZE) {
> +		regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &regval);
> +
> +		fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK,
> +				      regval);
> +		if (fifo_chan != chan->channel)
> +			continue;
> +
> +		fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK,
> +				     regval);
> +		fifo_val &= (BIT(priv->data->resolution) - 1);
> +
> +		sum += fifo_val;
> +		count++;
> +	}
> +
> +	if (!count)
> +		return -ENOENT;
> +
> +	*val = sum / count;
> +
> +	return 0;
> +}
> +
> +static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev,
> +					const struct iio_chan_spec *chan,
> +					enum meson_sar_adc_avg_mode mode,
> +					enum meson_sar_adc_num_samples samples)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int val, channel = chan->channel;
> +
> +	val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
> +			   MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel),
> +			   val);
> +
> +	val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
> +			   MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val);
> +}
> +
> +static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
> +					const struct iio_chan_spec *chan)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	u32 regval;
> +
> +	/*
> +	 * the SAR ADC engine allows sampling multiple channels at the same
> +	 * time. to keep it simple we're only working with one *internal*
> +	 * channel, which starts counting at index 0 (which means: count = 1).
> +	 */
> +	regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
> +			   MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval);
> +
> +	/* map channel index 0 to the channel which we want to read */
> +	regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0),
> +			    chan->channel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
> +			   MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval);
> +
> +	regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
> +			    chan->channel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
> +			   MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
> +			   regval);
> +
> +	regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
> +			    chan->channel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
> +			   MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
> +			   regval);
> +
> +	if (chan->channel == 6)
> +		regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
> +				   MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0);
> +}
> +
> +static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev,
> +					enum meson_sar_adc_chan7_mux_sel sel)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	u32 regval;
> +
> +	regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
> +
> +	usleep_range(10, 20);
> +}
> +
> +static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
> +			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_SAMPLING_START,
> +			   MESON_SAR_ADC_REG0_SAMPLING_START);
> +}
> +
> +static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_SAMPLING_STOP,
> +			   MESON_SAR_ADC_REG0_SAMPLING_STOP);
> +
> +	/* wait until all modules are stopped */
> +	meson_sar_adc_wait_busy_clear(indio_dev);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			   MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
> +}
> +
> +static int meson_sar_adc_lock(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int val, timeout = 10000;
> +
> +	mutex_lock(&indio_dev->mlock);
> +
> +	/* prevent BL30 from using the SAR ADC while we are using it */
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_KERNEL_BUSY,
> +			   MESON_SAR_ADC_DELAY_KERNEL_BUSY);
> +
> +	/* wait until BL30 releases it's lock (so we can use the SAR ADC) */
> +	do {
> +		udelay(1);
> +		regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val);
> +	} while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--);
> +
> +	if (timeout < 0)
> +		return -ETIMEDOUT;
> +
> +	return 0;
> +}
> +
> +static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +
> +	/* allow BL30 to use the SAR ADC again */
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
> +
> +	mutex_unlock(&indio_dev->mlock);
> +}
> +
> +static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int count;
> +
> +	for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
> +		if (!meson_sar_adc_get_fifo_count(indio_dev))
> +			break;
> +
> +		regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, 0);
> +	}
> +}
> +
> +static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
> +				    const struct iio_chan_spec *chan,
> +				    enum meson_sar_adc_avg_mode avg_mode,
> +				    enum meson_sar_adc_num_samples avg_samples,
> +				    int *val)
> +{
> +	int ret;
> +
> +	ret = meson_sar_adc_lock(indio_dev);
> +	if (ret)
> +		return ret;
> +
> +	/* clear the FIFO to make sure we're not reading old values */
> +	meson_sar_adc_clear_fifo(indio_dev);
> +
> +	meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples);
> +
> +	meson_sar_adc_enable_channel(indio_dev, chan);
> +
> +	meson_sar_adc_start_sample_engine(indio_dev);
> +	ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val);
> +	meson_sar_adc_stop_sample_engine(indio_dev);
> +
> +	meson_sar_adc_unlock(indio_dev);
> +
> +	if (ret) {
> +		dev_warn(indio_dev->dev.parent,
> +			 "failed to read sample for channel %d: %d\n",
> +			 chan->channel, ret);
> +		return ret;
> +	}
> +
> +	return IIO_VAL_INT;
> +}
> +
> +static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
> +					   const struct iio_chan_spec *chan,
> +					   int *val, int *val2, long mask)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING,
> +						ONE_SAMPLE, val);
> +		break;
> +
> +	case IIO_CHAN_INFO_AVERAGE_RAW:
> +		return meson_sar_adc_get_sample(indio_dev, chan,
> +						MEAN_AVERAGING, EIGHT_SAMPLES,
> +						val);
> +		break;
> +
> +	case IIO_CHAN_INFO_SCALE:
> +		ret = regulator_get_voltage(priv->vref);
> +		if (ret < 0) {
> +			dev_err(indio_dev->dev.parent,
> +				"failed to get vref voltage: %d\n", ret);
> +			return ret;
> +		}
> +
> +		*val = ret / 1000;
> +		*val2 = priv->data->resolution;
> +		return IIO_VAL_FRACTIONAL_LOG2;
> +
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
> +				  void __iomem *base)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	struct clk_init_data init;
> +	const char *clk_parents[1];
> +
> +	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div",
> +				   of_node_full_name(indio_dev->dev.of_node));
> +	init.flags = 0;
> +	init.ops = &clk_divider_ops;
> +	clk_parents[0] = __clk_get_name(priv->clkin);
> +	init.parent_names = clk_parents;
> +	init.num_parents = 1;
> +
> +	priv->clk_div.reg = base + MESON_SAR_ADC_REG3;
> +	priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT;
> +	priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH;
> +	priv->clk_div.hw.init = &init;
> +	priv->clk_div.flags = 0;
> +
> +	priv->adc_div_clk = devm_clk_register(&indio_dev->dev,
> +					      &priv->clk_div.hw);
> +	if (WARN_ON(IS_ERR(priv->adc_div_clk)))
> +		return PTR_ERR(priv->adc_div_clk);
> +
> +	init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en",
> +				   of_node_full_name(indio_dev->dev.of_node));
> +	init.flags = CLK_SET_RATE_PARENT;
> +	init.ops = &clk_gate_ops;
> +	clk_parents[0] = __clk_get_name(priv->adc_div_clk);
> +	init.parent_names = clk_parents;
> +	init.num_parents = 1;
> +
> +	priv->clk_gate.reg = base + MESON_SAR_ADC_REG3;
> +	priv->clk_gate.bit_idx = fls(MESON_SAR_ADC_REG3_CLK_EN);
> +	priv->clk_gate.hw.init = &init;
> +
> +	priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw);
> +	if (WARN_ON(IS_ERR(priv->adc_clk)))
> +		return PTR_ERR(priv->adc_clk);
> +
> +	return 0;
> +}
> +
> +static int meson_sar_adc_init(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int regval, ret;
> +
> +	/*
> +	 * make sure we start at CH7 input since the other muxes are only used
> +	 * for internal calibration.
> +	 */
> +	meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
> +
> +	/*
> +	 * leave sampling delay and the input clocks as configured by BL30 to
> +	 * make sure BL30 gets the values it expects when reading the
> +	 * temperature sensor.
> +	 */
> +	regmap_read(priv->regmap, MESON_SAR_ADC_REG3, &regval);
> +	if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED)
> +		return 0;
> +
> +	meson_sar_adc_stop_sample_engine(indio_dev);
> +
> +	/* update the channel 6 MUX to select the temperature sensor */
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
> +			MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL,
> +			MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL);
> +
> +	/* disable all channels by default */
> +	regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY,
> +			   MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY);
> +
> +	/* delay between two samples = (10+1) * 1uS */
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
> +			   FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK,
> +				      10));
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
> +			   FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
> +				      0));
> +
> +	/* delay between two samples = (10+1) * 1uS */
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
> +			   FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
> +				      10));
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
> +			   MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
> +			   FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
> +				      1));
> +
> +	ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
> +	if (ret) {
> +		dev_err(indio_dev->dev.parent,
> +			"failed to set adc parent to clkin\n");
> +		return ret;
> +	}
> +
> +	ret = clk_set_rate(priv->adc_clk, 1200000);
> +	if (ret) {
> +		dev_err(indio_dev->dev.parent,
> +			"failed to set adc clock rate\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int ret;
> +
> +	ret = meson_sar_adc_lock(indio_dev);
> +	if (ret)
> +		goto err_lock;
> +
> +	ret = regulator_enable(priv->vref);
> +	if (ret < 0) {
> +		dev_err(indio_dev->dev.parent,
> +			"failed to enable vref regulator\n");
> +		goto err_vref;
> +	}
> +
> +	ret = clk_prepare_enable(priv->core_clk);
> +	if (ret) {
> +		dev_err(indio_dev->dev.parent, "failed to enable core clk\n");
> +		goto err_core_clk;
> +	}
> +
> +	ret = clk_prepare_enable(priv->sana_clk);
> +	if (ret) {
> +		dev_err(indio_dev->dev.parent, "failed to enable sana clk\n");
> +		goto err_sana_clk;
> +	}
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
> +			   MESON_SAR_ADC_REG11_BANDGAP_EN,
> +			   MESON_SAR_ADC_REG11_BANDGAP_EN);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_ADC_EN,
> +			   MESON_SAR_ADC_REG3_ADC_EN);
> +
> +	udelay(5);
> +
> +	ret = clk_prepare_enable(priv->adc_clk);
> +	if (ret) {
> +		dev_err(indio_dev->dev.parent, "failed to enable adc clk\n");
> +		goto err_adc_clk;
> +	}
> +
> +	meson_sar_adc_unlock(indio_dev);
> +
> +	return 0;
> +
> +err_adc_clk:
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_ADC_EN, 0);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
> +			   MESON_SAR_ADC_REG11_BANDGAP_EN, 0);
> +	clk_disable_unprepare(priv->sana_clk);
> +err_sana_clk:
> +	clk_disable_unprepare(priv->core_clk);
> +err_core_clk:
> +	regulator_disable(priv->vref);
> +err_vref:
> +	meson_sar_adc_unlock(indio_dev);
> +err_lock:
> +	return ret;
> +}
> +
> +static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
> +{
> +	struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
> +	int ret;
> +
> +	ret = meson_sar_adc_lock(indio_dev);
> +	if (ret)
> +		return ret;
> +
> +	clk_disable_unprepare(priv->adc_clk);
> +
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
> +			   MESON_SAR_ADC_REG3_ADC_EN, 0);
> +	regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
> +			   MESON_SAR_ADC_REG11_BANDGAP_EN, 0);
> +
> +	clk_disable_unprepare(priv->sana_clk);
> +	clk_disable_unprepare(priv->core_clk);
> +
> +	regulator_disable(priv->vref);
> +
> +	meson_sar_adc_unlock(indio_dev);
> +
> +	return 0;
> +}
> +
> +static const struct iio_info meson_sar_adc_iio_info = {
> +	.read_raw = meson_sar_adc_iio_info_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
> +	.resolution = 10,
> +	.name = "meson-gxbb-saradc",
> +};
> +
> +struct meson_sar_adc_data meson_sar_adc_gxl_data = {
> +	.resolution = 12,
> +	.name = "meson-gxl-saradc",
> +};
> +
> +static const struct of_device_id meson_sar_adc_of_match[] = {
> +	{
> +		.compatible = "amlogic,meson-gxbb-saradc",
> +		.data = &meson_sar_adc_gxbb_data,
> +	}, {
> +		.compatible = "amlogic,meson-gxl-saradc",
> +		.data = &meson_sar_adc_gxl_data,
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match);
> +
> +static int meson_sar_adc_probe(struct platform_device *pdev)
> +{
> +	struct meson_sar_adc_priv *priv;
> +	struct iio_dev *indio_dev;
> +	struct resource *res;
> +	void __iomem *base;
> +	const struct of_device_id *match;
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
> +	if (!indio_dev) {
> +		dev_err(&pdev->dev, "failed allocating iio device\n");
> +		return -ENOMEM;
> +	}
> +
> +	priv = iio_priv(indio_dev);
> +
> +	match = of_match_device(meson_sar_adc_of_match, &pdev->dev);
> +	priv->data = match->data;
> +
> +	indio_dev->name = priv->data->name;
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->dev.of_node = pdev->dev.of_node;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->info = &meson_sar_adc_iio_info;
> +
> +	indio_dev->channels = meson_sar_adc_iio_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(meson_sar_adc_iio_channels);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	base = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(base))
> +		return PTR_ERR(base);
> +
> +	priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
> +					     &meson_sar_adc_regmap_config);
> +	if (IS_ERR(priv->regmap))
> +		return PTR_ERR(priv->regmap);
> +
> +	priv->clkin = devm_clk_get(&pdev->dev, "clkin");
> +	if (IS_ERR(priv->clkin)) {
> +		dev_err(&pdev->dev, "failed to get clkin\n");
> +		return PTR_ERR(priv->clkin);
> +	}
> +
> +	priv->core_clk = devm_clk_get(&pdev->dev, "core");
> +	if (IS_ERR(priv->core_clk)) {
> +		dev_err(&pdev->dev, "failed to get core clk\n");
> +		return PTR_ERR(priv->core_clk);
> +	}
> +
> +	priv->sana_clk = devm_clk_get(&pdev->dev, "sana");
> +	if (IS_ERR(priv->sana_clk)) {
> +		if (PTR_ERR(priv->sana_clk) == -ENOENT) {
> +			priv->sana_clk = NULL;
> +		} else {
> +			dev_err(&pdev->dev, "failed to get sana clk\n");
> +			return PTR_ERR(priv->sana_clk);
> +		}
> +	}
> +
> +	priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk");
> +	if (IS_ERR(priv->adc_clk)) {
> +		if (PTR_ERR(priv->adc_clk) == -ENOENT) {
> +			priv->adc_clk = NULL;
> +		} else {
> +			dev_err(&pdev->dev, "failed to get adc clk\n");
> +			return PTR_ERR(priv->adc_clk);
> +		}
> +	}
> +
> +	priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel");
> +	if (IS_ERR(priv->adc_sel_clk)) {
> +		if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) {
> +			priv->adc_sel_clk = NULL;
> +		} else {
> +			dev_err(&pdev->dev, "failed to get adc_sel clk\n");
> +			return PTR_ERR(priv->adc_sel_clk);
> +		}
> +	}
> +
> +	/* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
> +	if (!priv->adc_clk) {
> +		ret = meson_sar_adc_clk_init(indio_dev, base);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	priv->vref = devm_regulator_get(&pdev->dev, "vref");
> +	if (IS_ERR(priv->vref)) {
> +		dev_err(&pdev->dev, "failed to get vref regulator\n");
> +		return PTR_ERR(priv->vref);
> +	}
> +
> +	ret = meson_sar_adc_init(indio_dev);
> +	if (ret)
> +		goto err;
> +
> +	ret = meson_sar_adc_hw_enable(indio_dev);
> +	if (ret)
> +		goto err;
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret)
> +		goto err_hw;
> +
> +	return 0;
> +
> +err_hw:
> +	meson_sar_adc_hw_disable(indio_dev);
> +err:
> +	return ret;
> +}
> +
> +static int meson_sar_adc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	return meson_sar_adc_hw_disable(indio_dev);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
Slight perference for not bothing with the if def fun which
can go wrong, but instead use __maybe_unused.

Arnd is busy pushing this into lots of drivers and I think it
is neater.

I don't care about this enough to insist on a respin if it's all
that anyone comes up with.

> +static int meson_sar_adc_suspend(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +
> +	return meson_sar_adc_hw_disable(indio_dev);
> +}
> +
> +static int meson_sar_adc_resume(struct device *dev)
> +{
> +	struct iio_dev *indio_dev = dev_get_drvdata(dev);
> +
> +	return meson_sar_adc_hw_enable(indio_dev);
> +}
> +#endif /* CONFIG_PM_SLEEP */
> +
> +static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
> +			 meson_sar_adc_suspend, meson_sar_adc_resume);
> +
> +static struct platform_driver meson_sar_adc_driver = {
> +	.probe		= meson_sar_adc_probe,
> +	.remove		= meson_sar_adc_remove,
> +	.driver		= {
> +		.name	= "meson-saradc",
> +		.of_match_table = meson_sar_adc_of_match,
> +		.pm = &meson_sar_adc_pm_ops,
> +	},
> +};
> +
> +module_platform_driver(meson_sar_adc_driver);
> +
> +MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
> +MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply

* Re: [PATCH 2/7] iio: adc: stm32: Enable use of stm32 timer triggers
From: Jonathan Cameron @ 2017-01-21 12:55 UTC (permalink / raw)
  To: kbuild test robot, Fabrice Gasnier
  Cc: kbuild-all-JC7UmRfGjtg, linux-I+IVW8TIWO2tmTQ+vhA3Yw,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, mark.rutland-5wv7dgnIgG8,
	mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w,
	alexandre.torgue-qxv4g6HH51o, lars-Qo5EllUWu/uELgA04lAiVw,
	knaack.h-Mmb7MZpHnFY, pmeerw-jW+XmwGofnusTnJN9+BGXg,
	benjamin.gaignard-QSEj5FYQhm4dnm+yROfE0A,
	benjamin.gaignard-qxv4g6HH51o
In-Reply-To: <201701200712.zoWuIMA4%fengguang.wu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

On 19/01/17 23:31, kbuild test robot wrote:
> Hi Fabrice,
> 
> [auto build test ERROR on next-20170119]
> [also build test ERROR on v4.10-rc4]
> [cannot apply to iio/togreg robh/for-next v4.9-rc8 v4.9-rc7 v4.9-rc6]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Fabrice-Gasnier/Add-support-for-triggered-buffer-mode-to-STM32-ADC/20170120-062214
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
There is a precursor patch set mentioned in the cover letter. Not sure there is
a sensible automated way to deal with that!

Jonathan
> 
> All errors (new ones prefixed by >>):
> 
>>> drivers/iio/adc/stm32-adc.c:26:49: fatal error: linux/iio/timer/stm32-timer-trigger.h: No such file or directory
>     #include <linux/iio/timer/stm32-timer-trigger.h>
>                                                     ^
>    compilation terminated.
> 
> vim +26 drivers/iio/adc/stm32-adc.c
> 
>     20	 */
>     21	
>     22	#include <linux/clk.h>
>     23	#include <linux/delay.h>
>     24	#include <linux/iio/iio.h>
>     25	#include <linux/iio/buffer.h>
>   > 26	#include <linux/iio/timer/stm32-timer-trigger.h>
>     27	#include <linux/iio/trigger.h>
>     28	#include <linux/iio/trigger_consumer.h>
>     29	#include <linux/iio/triggered_buffer.h>
> 
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox