Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/6] media: rc: update sunxi-ir driver to get base clock frequency from devicetree
From: Sean Young @ 2018-01-05 15:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171219080747.4507-2-embed3d@gmail.com>

On Tue, Dec 19, 2017 at 09:07:42AM +0100, Philipp Rossak wrote:
> This patch updates the sunxi-ir driver to set the base clock frequency from
> devicetree.
> 
> This is necessary since there are different ir receivers on the
> market, that operate with different frequencies. So this value could be
> set if the attached ir receiver needs a different base clock frequency,
> than the default 8 MHz.
> 
> Signed-off-by: Philipp Rossak <embed3d@gmail.com>

Acked-by: Sean Young <sean@mess.org>


Sean

> ---
>  drivers/media/rc/sunxi-cir.c | 19 +++++++++++--------
>  1 file changed, 11 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
> index 97f367b446c4..f500cea228a9 100644
> --- a/drivers/media/rc/sunxi-cir.c
> +++ b/drivers/media/rc/sunxi-cir.c
> @@ -72,12 +72,8 @@
>  /* CIR_REG register idle threshold */
>  #define REG_CIR_ITHR(val)    (((val) << 8) & (GENMASK(15, 8)))
>  
> -/* Required frequency for IR0 or IR1 clock in CIR mode */
> +/* Required frequency for IR0 or IR1 clock in CIR mode (default) */
>  #define SUNXI_IR_BASE_CLK     8000000
> -/* Frequency after IR internal divider  */
> -#define SUNXI_IR_CLK          (SUNXI_IR_BASE_CLK / 64)
> -/* Sample period in ns */
> -#define SUNXI_IR_SAMPLE       (1000000000ul / SUNXI_IR_CLK)
>  /* Noise threshold in samples  */
>  #define SUNXI_IR_RXNOISE      1
>  /* Idle Threshold in samples */
> @@ -122,7 +118,8 @@ static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
>  			/* for each bit in fifo */
>  			dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
>  			rawir.pulse = (dt & 0x80) != 0;
> -			rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
> +			rawir.duration = ((dt & 0x7f) + 1) *
> +					 ir->rc->rx_resolution;
>  			ir_raw_event_store_with_filter(ir->rc, &rawir);
>  		}
>  	}
> @@ -148,6 +145,7 @@ static int sunxi_ir_probe(struct platform_device *pdev)
>  	struct device_node *dn = dev->of_node;
>  	struct resource *res;
>  	struct sunxi_ir *ir;
> +	u32 b_clk_freq = SUNXI_IR_BASE_CLK;
>  
>  	ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL);
>  	if (!ir)
> @@ -172,6 +170,9 @@ static int sunxi_ir_probe(struct platform_device *pdev)
>  		return PTR_ERR(ir->clk);
>  	}
>  
> +	/* Base clock frequency (optional) */
> +	of_property_read_u32(dn, "clock-frequency", &b_clk_freq);
> +
>  	/* Reset (optional) */
>  	ir->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
>  	if (IS_ERR(ir->rst))
> @@ -180,11 +181,12 @@ static int sunxi_ir_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>  
> -	ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
> +	ret = clk_set_rate(ir->clk, b_clk_freq);
>  	if (ret) {
>  		dev_err(dev, "set ir base clock failed!\n");
>  		goto exit_reset_assert;
>  	}
> +	dev_dbg(dev, "set base clock frequency to %d Hz.\n", b_clk_freq);
>  
>  	if (clk_prepare_enable(ir->apb_clk)) {
>  		dev_err(dev, "try to enable apb_ir_clk failed\n");
> @@ -225,7 +227,8 @@ static int sunxi_ir_probe(struct platform_device *pdev)
>  	ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
>  	ir->rc->dev.parent = dev;
>  	ir->rc->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
> -	ir->rc->rx_resolution = SUNXI_IR_SAMPLE;
> +	/* Frequency after IR internal divider with sample period in ns */
> +	ir->rc->rx_resolution = (1000000000ul / (b_clk_freq / 64));
>  	ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
>  	ir->rc->driver_name = SUNXI_IR_DEV;
>  
> -- 
> 2.11.0

^ permalink raw reply

* [GIT PULL] ARM: mvebu: fixes for v4.15 (#1)
From: Gregory CLEMENT @ 2018-01-05 15:42 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

Here is the first pull request for fixes for mvebu for v4.15.

Gregory

The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:

  Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)

are available in the Git repository at:

  git://git.infradead.org/linux-mvebu.git tags/mvebu-fixes-4.15-1

for you to fetch changes up to fefb476bc7fdda4cb1e768493128c15a896f2c4e:

  ARM64: dts: marvell: armada-cp110: Fix clock resources for various node (2018-01-05 16:04:53 +0100)

----------------------------------------------------------------
mvebu fixess for 4.15 (part 1)

2 device tree related fixes fixing 2 issues:
 - broken pinctrl support since 4.11 on OpenBlocks A7
 - implicit clock dependency making the kernel hang if the Xenon sdhci
   module was loaded before the mvpp2 Ethernet support (for this one
   the driver had to be fixed which was done in v4.14)

----------------------------------------------------------------
Gregory CLEMENT (1):
      ARM64: dts: marvell: armada-cp110: Fix clock resources for various node

Thomas Petazzoni (1):
      ARM: dts: kirkwood: fix pin-muxing of MPP7 on OpenBlocks A7

 arch/arm/boot/dts/kirkwood-openblocks_a7.dts         | 10 ++++++++--
 arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 13 ++++++++-----
 arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi  |  9 ++++++---
 3 files changed, 22 insertions(+), 10 deletions(-)

^ permalink raw reply

* [PATCH] ARM64: dts: marvell: armada-cp110: Fix clock resources for various node
From: Gregory CLEMENT @ 2018-01-05 15:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105153055.12232-1-gregory.clement@free-electrons.com>

Hi,
 
 On ven., janv. 05 2018, Gregory CLEMENT <gregory.clement@free-electrons.com> wrote:

> On the CP modules we found on Armada 7K/8K, many IP block actually also
> need a "logical" clock (from the bus). This patch add them which allows
> to fix some issues hanging the kernel:
>
> If Ethernet and sdhci driver are built as modules and sdhci was loaded
> first then the kernel hang.
>
> Fixes: bb16ea1742c8 ("mmc: sdhci-xenon: Fix clock resource by adding an
> optional bus clock")
> Cc: stable at vger.kernel.org
> Reported-by: Riku Voipio <riku.voipio@linaro.org>
> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>

Applied on mvebu/fixes

Gregory

> ---
>  arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 13 ++++++++-----
>  arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi  |  9 ++++++---
>  2 files changed, 14 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> index e3b64d03fbd8..9c7724e82aff 100644
> --- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
> @@ -63,8 +63,10 @@
>  			cpm_ethernet: ethernet at 0 {
>  				compatible = "marvell,armada-7k-pp22";
>  				reg = <0x0 0x100000>, <0x129000 0xb000>;
> -				clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>, <&cpm_clk 1 5>;
> -				clock-names = "pp_clk", "gop_clk", "mg_clk";
> +				clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>,
> +					 <&cpm_clk 1 5>, <&cpm_clk 1 18>;
> +				clock-names = "pp_clk", "gop_clk",
> +					      "mg_clk","axi_clk";
>  				marvell,system-controller = <&cpm_syscon0>;
>  				status = "disabled";
>  				dma-coherent;
> @@ -155,7 +157,8 @@
>  				#size-cells = <0>;
>  				compatible = "marvell,orion-mdio";
>  				reg = <0x12a200 0x10>;
> -				clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>;
> +				clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>,
> +					 <&cpm_clk 1 6>, <&cpm_clk 1 18>;
>  				status = "disabled";
>  			};
>  
> @@ -338,8 +341,8 @@
>  				compatible = "marvell,armada-cp110-sdhci";
>  				reg = <0x780000 0x300>;
>  				interrupts = <ICU_GRP_NSR 27 IRQ_TYPE_LEVEL_HIGH>;
> -				clock-names = "core";
> -				clocks = <&cpm_clk 1 4>;
> +				clock-names = "core","axi";
> +				clocks = <&cpm_clk 1 4>, <&cpm_clk 1 18>;
>  				dma-coherent;
>  				status = "disabled";
>  			};
> diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> index 0d51096c69f8..87ac68b2cf37 100644
> --- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> +++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
> @@ -63,8 +63,10 @@
>  			cps_ethernet: ethernet at 0 {
>  				compatible = "marvell,armada-7k-pp22";
>  				reg = <0x0 0x100000>, <0x129000 0xb000>;
> -				clocks = <&cps_clk 1 3>, <&cps_clk 1 9>, <&cps_clk 1 5>;
> -				clock-names = "pp_clk", "gop_clk", "mg_clk";
> +				clocks = <&cps_clk 1 3>, <&cps_clk 1 9>,
> +					 <&cps_clk 1 5>, <&cps_clk 1 18>;
> +				clock-names = "pp_clk", "gop_clk",
> +					      "mg_clk", "axi_clk";
>  				marvell,system-controller = <&cps_syscon0>;
>  				status = "disabled";
>  				dma-coherent;
> @@ -155,7 +157,8 @@
>  				#size-cells = <0>;
>  				compatible = "marvell,orion-mdio";
>  				reg = <0x12a200 0x10>;
> -				clocks = <&cps_clk 1 9>, <&cps_clk 1 5>;
> +				clocks = <&cps_clk 1 9>, <&cps_clk 1 5>,
> +					 <&cps_clk 1 6>, <&cps_clk 1 18>;
>  				status = "disabled";
>  			};
>  
> -- 
> 2.15.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [PATCH v3 2/2] dt-bindings: mailbox: Add Xilinx IPI Mailbox
From: Rob Herring @ 2018-01-05 15:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515109891-17133-3-git-send-email-jliang@xilinx.com>

On Thu, Jan 04, 2018 at 03:51:31PM -0800, Wendy Liang wrote:
> Xilinx ZynqMP IPI(Inter Processor Interrupt) is a hardware block
> in ZynqMP SoC used for the communication between various processor
> systems.
> 
> Signed-off-by: Wendy Liang <jliang@xilinx.com>
> ---
>  .../bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt   | 104 +++++++++++++++++++++
>  1 file changed, 104 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/xlnx,zynqmp-ipi-mailbox.txt

Please add acks and reviewed-by's when posting new versions.

^ permalink raw reply

* [PATCH] ARM64: dts: marvell: armada-cp110: Fix clock resources for various node
From: Gregory CLEMENT @ 2018-01-05 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

On the CP modules we found on Armada 7K/8K, many IP block actually also
need a "logical" clock (from the bus). This patch add them which allows
to fix some issues hanging the kernel:

If Ethernet and sdhci driver are built as modules and sdhci was loaded
first then the kernel hang.

Fixes: bb16ea1742c8 ("mmc: sdhci-xenon: Fix clock resource by adding an
optional bus clock")
Cc: stable at vger.kernel.org
Reported-by: Riku Voipio <riku.voipio@linaro.org>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
---
 arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi | 13 ++++++++-----
 arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi  |  9 ++++++---
 2 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
index e3b64d03fbd8..9c7724e82aff 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
@@ -63,8 +63,10 @@
 			cpm_ethernet: ethernet at 0 {
 				compatible = "marvell,armada-7k-pp22";
 				reg = <0x0 0x100000>, <0x129000 0xb000>;
-				clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>, <&cpm_clk 1 5>;
-				clock-names = "pp_clk", "gop_clk", "mg_clk";
+				clocks = <&cpm_clk 1 3>, <&cpm_clk 1 9>,
+					 <&cpm_clk 1 5>, <&cpm_clk 1 18>;
+				clock-names = "pp_clk", "gop_clk",
+					      "mg_clk","axi_clk";
 				marvell,system-controller = <&cpm_syscon0>;
 				status = "disabled";
 				dma-coherent;
@@ -155,7 +157,8 @@
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
 				reg = <0x12a200 0x10>;
-				clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>;
+				clocks = <&cpm_clk 1 9>, <&cpm_clk 1 5>,
+					 <&cpm_clk 1 6>, <&cpm_clk 1 18>;
 				status = "disabled";
 			};
 
@@ -338,8 +341,8 @@
 				compatible = "marvell,armada-cp110-sdhci";
 				reg = <0x780000 0x300>;
 				interrupts = <ICU_GRP_NSR 27 IRQ_TYPE_LEVEL_HIGH>;
-				clock-names = "core";
-				clocks = <&cpm_clk 1 4>;
+				clock-names = "core","axi";
+				clocks = <&cpm_clk 1 4>, <&cpm_clk 1 18>;
 				dma-coherent;
 				status = "disabled";
 			};
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
index 0d51096c69f8..87ac68b2cf37 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
@@ -63,8 +63,10 @@
 			cps_ethernet: ethernet at 0 {
 				compatible = "marvell,armada-7k-pp22";
 				reg = <0x0 0x100000>, <0x129000 0xb000>;
-				clocks = <&cps_clk 1 3>, <&cps_clk 1 9>, <&cps_clk 1 5>;
-				clock-names = "pp_clk", "gop_clk", "mg_clk";
+				clocks = <&cps_clk 1 3>, <&cps_clk 1 9>,
+					 <&cps_clk 1 5>, <&cps_clk 1 18>;
+				clock-names = "pp_clk", "gop_clk",
+					      "mg_clk", "axi_clk";
 				marvell,system-controller = <&cps_syscon0>;
 				status = "disabled";
 				dma-coherent;
@@ -155,7 +157,8 @@
 				#size-cells = <0>;
 				compatible = "marvell,orion-mdio";
 				reg = <0x12a200 0x10>;
-				clocks = <&cps_clk 1 9>, <&cps_clk 1 5>;
+				clocks = <&cps_clk 1 9>, <&cps_clk 1 5>,
+					 <&cps_clk 1 6>, <&cps_clk 1 18>;
 				status = "disabled";
 			};
 
-- 
2.15.1

^ permalink raw reply related

* [PATCH 1/7] arm64: dts: marvell: use SPDX-License-Identifier for Armada SoCs
From: Andrew Lunn @ 2018-01-05 15:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87r2r49wxw.fsf@free-electrons.com>

On Fri, Jan 05, 2018 at 03:55:55PM +0100, Gregory CLEMENT wrote:
> Hi Andrew,
>  
>  On ven., janv. 05 2018, Andrew Lunn <andrew@lunn.ch> wrote:
> 
> >> > The previous license was GPL-2.0+ or X11, not GPL-2.0+ or MIT. Any
> >> > reason to change from X11 to MIT ?
> >> 
> >> As explained in the commit log:
> >> " the X11 license text [1] is explicitly for the X Consortium and has a
> >> couple of extra clauses. The MIT license text [2] is actually what the
> >> current DT files claim."
> >> 
> >> Also as I wrote it was already discussed on the mainling lists (device
> >> tree one and LAKML) see:
> >> http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489922.html
> >
> > Hi Gregory
> >
> > If i remember correctly, there was a reason for X11 over MIT. I think
> > Russell King looked into this. Maybe you can find the discussion on
> > the mailing list?

Hi Gregory

I'm meaning an older discussion, when we first started using dual
license. There was some discussion back then as to MIT vs X11.
That discussion could be relevant here.

What we need to be careful of is ensuring the changes you are making
here don't actually change the licenses.  If the intent was to use
X11, and we actually state "X11 license" in the source code, we need
to be careful if we replace that with MIT.

   Andrew

^ permalink raw reply

* [PATCH v3 0/6] arm: sunxi: IR support for A83T
From: Maxime Ripard @ 2018-01-05 14:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105120253.zvwaz25scuk76bnt@gofer.mess.org>

Hi,

On Fri, Jan 05, 2018 at 12:02:53PM +0000, Sean Young wrote:
> On Tue, Dec 19, 2017 at 09:07:41AM +0100, Philipp Rossak wrote:
> > This patch series adds support for the sunxi A83T ir module and enhances 
> > the sunxi-ir driver. Right now the base clock frequency for the ir driver
> > is a hard coded define and is set to 8 MHz.
> > This works for the most common ir receivers. On the Sinovoip Bananapi M3 
> > the ir receiver needs, a 3 MHz base clock frequency to work without
> > problems with this driver.
> > 
> > This patch series adds support for an optinal property that makes it able
> > to override the default base clock frequency and enables the ir interface 
> > on the a83t and the Bananapi M3.
> > 
> > changes since v2:
> > * reorder cir pin (alphabetical)
> > * fix typo in documentation
> > 
> > changes since v1:
> > * fix typos, reword Documentation
> > * initialize 'b_clk_freq' to 'SUNXI_IR_BASE_CLK' & remove if statement
> > * change dev_info() to dev_dbg()
> > * change naming to cir* in dts/dtsi
> > * Added acked Ackedi-by to related patch
> > * use whole memory block instead of registers needed + fix for h3/h5
> > 
> > changes since rfc:
> > * The property is now optinal. If the property is not available in 
> >   the dtb the driver uses the default base clock frequency.
> > * the driver prints out the the selected base clock frequency.
> > * changed devicetree property from base-clk-frequency to clock-frequency
> > 
> > Regards,
> > Philipp
> > 
> > 
> > Philipp Rossak (6):
> >   media: rc: update sunxi-ir driver to get base clock frequency from
> >     devicetree
> >   media: dt: bindings: Update binding documentation for sunxi IR
> >     controller
> >   arm: dts: sun8i: a83t: Add the cir pin for the A83T
> >   arm: dts: sun8i: a83t: Add support for the cir interface
> >   arm: dts: sun8i: a83t: bananapi-m3: Enable IR controller
> >   arm: dts: sun8i: h3-h8: ir register size should be the whole memory
> >     block
> 
> I can take this series (through rc-core, i.e. linux-media), but I need an
> maintainer Acked-by: for the sun[x8]i dts changes (all four patches).

We'll merge them through our tree. We usually have a rather big number
of patches around, so we'd be better off avoiding conflicts :)

Philipp, can you resubmit the DTs as soon as -rc1 is out?

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180105/72beeaab/attachment.sig>

^ permalink raw reply

* [GIT PULL] TI DaVinci SoC support updates for v4.16
From: Sekhar Nori @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105070904.ckixnqva6qkbaukc@localhost>

Hi Olof,

On Friday 05 January 2018 12:39 PM, Olof Johansson wrote:
> On Sat, Dec 23, 2017 at 09:21:31PM +0530, Sekhar Nori wrote:
>> The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:
>>
>>   Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)
>>
>> are available in the git repository at:
>>
>>   git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-for-v4.16/soc
>>
>> for you to fetch changes up to ed3c0c2b4fdcbe05194ee3f5e634ece3018d3b76:
>>
>>   ARM: dts: da850-lcdk: Remove leading 0x and 0s from unit address (2017-12-23 15:46:25 +0530)
>>
>> ----------------------------------------------------------------
>> DaVinci SoC updates consisting of non-critical bug fixes including constifying
>> data structures, DT warning fixes for W=1 and code simplification.
>>
>> Also a defconfig update for DaVinci, enabling support for USB network adaptors.
> 
> Hi,
> 
> We usually don't mix DT and other updates (and sometimes we keep defconfig
> updates separate from SoC ones, but that's not needed here).
> 
> Can you respin with DT separate? Feel free to just send-email the patch to us,
> or send a pull request with it if you prefer.

I sent a v2 pull request. I had two more patches that were ready to be
queued for which I was planning on sending another pull request anyway.
I added those in the v2.

Thanks,
Sekhar

^ permalink raw reply

* [PATCH v2 11/11] arm64: Implement branch predictor hardening for affected Cortex-A CPUs
From: Marc Zyngier @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5A4F8FCD.3000903@arm.com>

On 05/01/18 14:46, James Morse wrote:
> Hi Marc, Will,
> 
> (SOB-chain suggests a missing From: tag on this and patch 7)
> 
> On 05/01/18 13:12, Will Deacon wrote:
>> Cortex-A57, A72, A73 and A75 are susceptible to branch predictor aliasing
>> and can theoretically be attacked by malicious code.
>>
>> This patch implements a PSCI-based mitigation for these CPUs when available.
>> The call into firmware will invalidate the branch predictor state, preventing
>> any malicious entries from affecting other victim contexts.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> Signed-off-by: Will Deacon <will.deacon@arm.com>
> 
>> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
>> index 06a931eb2673..2e9146534174 100644
>> --- a/arch/arm64/kernel/bpi.S
>> +++ b/arch/arm64/kernel/bpi.S
>> @@ -53,3 +53,27 @@ ENTRY(__bp_harden_hyp_vecs_start)
>>  	vectors __kvm_hyp_vector
>>  	.endr
>>  ENTRY(__bp_harden_hyp_vecs_end)
>> +ENTRY(__psci_hyp_bp_inval_start)
> 
>> +	sub	sp, sp, #(8 * 18)
> 
> Where does 18 come from? Isn't this storing 9 sets of 16 bytes?

Or 18 registers of 8 bytes each.

> 
>> +	stp	x16, x17, [sp, #(16 * 0)]
>> +	stp	x14, x15, [sp, #(16 * 1)]
>> +	stp	x12, x13, [sp, #(16 * 2)]
>> +	stp	x10, x11, [sp, #(16 * 3)]
>> +	stp	x8, x9, [sp, #(16 * 4)]
>> +	stp	x6, x7, [sp, #(16 * 5)]
>> +	stp	x4, x5, [sp, #(16 * 6)]
>> +	stp	x2, x3, [sp, #(16 * 7)]
> 
>> +	stp	x0, x1, [sp, #(18 * 8)]
> 
> 16->18 typo?

/me bashes head against keyboard, as this is likely to generate less
crap then me trying to write something half correct...

The fun part is that the Seattle box I booted yesterday with that crap
is still happily churning along. I guess I'm corrupting something that
really doesn't matter...

> 
> 
>> +	mov	x0, #0x84000000
>> +	smc	#0
>> +	ldp	x16, x17, [sp, #(16 * 0)]
>> +	ldp	x14, x15, [sp, #(16 * 1)]
>> +	ldp	x12, x13, [sp, #(16 * 2)]
>> +	ldp	x10, x11, [sp, #(16 * 3)]
>> +	ldp	x8, x9, [sp, #(16 * 4)]
>> +	ldp	x6, x7, [sp, #(16 * 5)]
>> +	ldp	x4, x5, [sp, #(16 * 6)]
>> +	ldp	x2, x3, [sp, #(16 * 7)]
> 
>> +	ldp	x0, x1, [sp, #(18 * 8)]
>> +	add	sp, sp, #(8 * 18)
> 
> (and here?)

Yup.

Thanks for pointing that out. I'll fetch a brown paper bag.

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [PATCH 00/13] replace print_symbol() with printk()-s
From: Sergey Senozhatsky @ 2018-01-05 14:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105144239.i3pc6npgmoi4ddln@pathway.suse.cz>

On (01/05/18 15:42), Petr Mladek wrote:
[..]
> > oh, one more thing. one extra patch, which gets rid of
> > print_symbol()/__print_symbol().
> 
> I am all for it. But I would postpone this removal to 4.17.
> The reason is rather ugly. 13th patch is already in arc tree.
> We would need to shuffle the patch or coordinate pull requests.
> I think that it is not worth it. There is no real hurry.
> I doubt that the would be any new user in the meantime.
> 
> Best Regards,
> Petr
> 
> PS: I have just pushed 12 patches into printk.git for-4.16 branch.
> I will merge this to linux-next branch on Monday. I will not
> be around the computer over the weekend...

OK. thanks!

	-ss

^ permalink raw reply

* [PATCH 1/7] arm64: dts: marvell: use SPDX-License-Identifier for Armada SoCs
From: Gregory CLEMENT @ 2018-01-05 14:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143820.GB4038@lunn.ch>

Hi Andrew,
 
 On ven., janv. 05 2018, Andrew Lunn <andrew@lunn.ch> wrote:

>> > The previous license was GPL-2.0+ or X11, not GPL-2.0+ or MIT. Any
>> > reason to change from X11 to MIT ?
>> 
>> As explained in the commit log:
>> " the X11 license text [1] is explicitly for the X Consortium and has a
>> couple of extra clauses. The MIT license text [2] is actually what the
>> current DT files claim."
>> 
>> Also as I wrote it was already discussed on the mainling lists (device
>> tree one and LAKML) see:
>> http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489922.html
>
> Hi Gregory
>
> If i remember correctly, there was a reason for X11 over MIT. I think
> Russell King looked into this. Maybe you can find the discussion on
> the mailing list?

The point from Russell King was that "MIT license" was ambiguous. But
the text of the license we used was exactly the one named as MIT in
SPDX. That's the reason why using the MIT key word for SPDX would be the
wright things to do.

Note also that Here [1], Russell already gave his opinion about it. In
the thread the complain was more about the spdx itself that the
name of the license. And his main concerned was about not having the
license text available. But it should be resolved because all the
license text will be part of the kernel sources [2].

Thanks,

Gregory

[1]:
http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/490649.html
[2]:
https://lkml.org/lkml/2017/12/4/935

>
>     Andrew
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

-- 
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

^ permalink raw reply

* [GIT PULL v2 2/2] TI DaVinci DT updates for v4.16
From: Sekhar Nori @ 2018-01-05 14:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105145248.1994-1-nsekhar@ti.com>

The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:

  Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-for-v4.16/dt

for you to fetch changes up to 7669b122085018c1f64720d11c24ae6d2549193d:

  ARM: dts: da850-lcdk: Remove leading 0x and 0s from unit address (2018-01-05 19:21:21 +0530)

----------------------------------------------------------------
A DT warning fix for W=1 warning message.

----------------------------------------------------------------
Mathieu Malaterre (1):
      ARM: dts: da850-lcdk: Remove leading 0x and 0s from unit address

 arch/arm/boot/dts/da850-lcdk.dts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

^ permalink raw reply

* [GIT PULL v2 1/2] TI DaVinci SoC support updates for v4.16
From: Sekhar Nori @ 2018-01-05 14:52 UTC (permalink / raw)
  To: linux-arm-kernel

The following changes since commit 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323:

  Linux 4.15-rc1 (2017-11-26 16:01:47 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci.git tags/davinci-for-v4.16/soc-v2

for you to fetch changes up to 23bbeaef90ab7607d03428bbb708efe44f43c761:

  ARM: davinci: constify gpio_led (2018-01-05 19:28:41 +0530)

----------------------------------------------------------------
DaVinci SoC updates consisting of non-critical bug fixes including constifying
data structures, removal of unnecessary newlines from gpio labels and code
simplification.

Also a defconfig update for DaVinci, enabling support for USB network adaptors.

----------------------------------------------------------------
Aparna Balasubramanian (1):
      ARM: davinci_all_defconfig: enable support for USB network adaptors

Arvind Yadav (1):
      ARM: davinci: constify gpio_led

Bhumika Goyal (2):
      ARM: davinci: make argument to davinci_common_init() as const
      ARM: davinci: make davinci_soc_info structures const

Julia Lawall (1):
      ARM: davinci: drop unneeded newline

Vasyl Gomonovych (1):
      ARM: davinci: Use PTR_ERR_OR_ZERO()

 arch/arm/configs/davinci_all_defconfig      | 1 +
 arch/arm/mach-davinci/board-da850-evm.c     | 4 ++--
 arch/arm/mach-davinci/board-neuros-osd2.c   | 2 +-
 arch/arm/mach-davinci/common.c              | 2 +-
 arch/arm/mach-davinci/da830.c               | 2 +-
 arch/arm/mach-davinci/da850.c               | 2 +-
 arch/arm/mach-davinci/devices-da8xx.c       | 4 ++--
 arch/arm/mach-davinci/dm355.c               | 2 +-
 arch/arm/mach-davinci/dm365.c               | 2 +-
 arch/arm/mach-davinci/dm644x.c              | 2 +-
 arch/arm/mach-davinci/dm646x.c              | 4 ++--
 arch/arm/mach-davinci/include/mach/common.h | 2 +-
 12 files changed, 15 insertions(+), 14 deletions(-)

^ permalink raw reply

* [PATCH v2 11/11] arm64: Implement branch predictor hardening for affected Cortex-A CPUs
From: James Morse @ 2018-01-05 14:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515157961-20963-12-git-send-email-will.deacon@arm.com>

Hi Marc, Will,

(SOB-chain suggests a missing From: tag on this and patch 7)

On 05/01/18 13:12, Will Deacon wrote:
> Cortex-A57, A72, A73 and A75 are susceptible to branch predictor aliasing
> and can theoretically be attacked by malicious code.
> 
> This patch implements a PSCI-based mitigation for these CPUs when available.
> The call into firmware will invalidate the branch predictor state, preventing
> any malicious entries from affecting other victim contexts.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Will Deacon <will.deacon@arm.com>

> diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S
> index 06a931eb2673..2e9146534174 100644
> --- a/arch/arm64/kernel/bpi.S
> +++ b/arch/arm64/kernel/bpi.S
> @@ -53,3 +53,27 @@ ENTRY(__bp_harden_hyp_vecs_start)
>  	vectors __kvm_hyp_vector
>  	.endr
>  ENTRY(__bp_harden_hyp_vecs_end)
> +ENTRY(__psci_hyp_bp_inval_start)

> +	sub	sp, sp, #(8 * 18)

Where does 18 come from? Isn't this storing 9 sets of 16 bytes?


> +	stp	x16, x17, [sp, #(16 * 0)]
> +	stp	x14, x15, [sp, #(16 * 1)]
> +	stp	x12, x13, [sp, #(16 * 2)]
> +	stp	x10, x11, [sp, #(16 * 3)]
> +	stp	x8, x9, [sp, #(16 * 4)]
> +	stp	x6, x7, [sp, #(16 * 5)]
> +	stp	x4, x5, [sp, #(16 * 6)]
> +	stp	x2, x3, [sp, #(16 * 7)]

> +	stp	x0, x1, [sp, #(18 * 8)]

16->18 typo?


> +	mov	x0, #0x84000000
> +	smc	#0
> +	ldp	x16, x17, [sp, #(16 * 0)]
> +	ldp	x14, x15, [sp, #(16 * 1)]
> +	ldp	x12, x13, [sp, #(16 * 2)]
> +	ldp	x10, x11, [sp, #(16 * 3)]
> +	ldp	x8, x9, [sp, #(16 * 4)]
> +	ldp	x6, x7, [sp, #(16 * 5)]
> +	ldp	x4, x5, [sp, #(16 * 6)]
> +	ldp	x2, x3, [sp, #(16 * 7)]

> +	ldp	x0, x1, [sp, #(18 * 8)]
> +	add	sp, sp, #(8 * 18)

(and here?)

> +ENTRY(__psci_hyp_bp_inval_end)


Thanks,

James

^ permalink raw reply

* [PATCH 00/13] replace print_symbol() with printk()-s
From: Petr Mladek @ 2018-01-05 14:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105102538.GC471@jagdpanzerIV>

On Fri 2018-01-05 19:25:38, Sergey Senozhatsky wrote:
> On (01/05/18 19:21), Sergey Senozhatsky wrote:
> > On (01/05/18 11:03), Petr Mladek wrote:
> > [..]
> > > Anyway, print_symbol() is an old weird API and it would be nice
> > > to eventually get rid of it. I could take this patches into
> > > printk.git.
> > 
> > no objections from my side if the patch set will go through the printk tree.
> > shall we wait for ACKs or can we move on? do you plan to land it in 4.16?
> > 
> > > Would you mind if I change the commit messages to something like?:
> > > 
> > >     print_symbol() is an old weird API. It has been
> > >     obsoleted by printk() and %pS format specifier.
> > 
> > I wouldn't. let's drop the "weird" part. other than that looks
> > good to me.
> 
> oh, one more thing. one extra patch, which gets rid of
> print_symbol()/__print_symbol().

I am all for it. But I would postpone this removal to 4.17.
The reason is rather ugly. 13th patch is already in arc tree.
We would need to shuffle the patch or coordinate pull requests.
I think that it is not worth it. There is no real hurry.
I doubt that the would be any new user in the meantime.

Best Regards,
Petr

PS: I have just pushed 12 patches into printk.git for-4.16 branch.
I will merge this to linux-next branch on Monday. I will not
be around the computer over the weekend...

^ permalink raw reply

* [PATCH 1/7] arm64: dts: marvell: use SPDX-License-Identifier for Armada SoCs
From: Andrew Lunn @ 2018-01-05 14:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87vagga2nd.fsf@free-electrons.com>

> > The previous license was GPL-2.0+ or X11, not GPL-2.0+ or MIT. Any
> > reason to change from X11 to MIT ?
> 
> As explained in the commit log:
> " the X11 license text [1] is explicitly for the X Consortium and has a
> couple of extra clauses. The MIT license text [2] is actually what the
> current DT files claim."
> 
> Also as I wrote it was already discussed on the mainling lists (device
> tree one and LAKML) see:
> http://lists.infradead.org/pipermail/linux-arm-kernel/2017-February/489922.html

Hi Gregory

If i remember correctly, there was a reason for X11 over MIT. I think
Russell King looked into this. Maybe you can find the discussion on
the mailing list?

    Andrew

^ permalink raw reply

* [PATCH v4 2/6] clk: renesas: rcar-gen3: Add Z2 clock divider support
From: Geert Uytterhoeven @ 2018-01-05 14:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105140401.7iitpzdrlyqtasvz@verge.net.au>

Hi Simon,

On Fri, Jan 5, 2018 at 3:04 PM, Simon Horman <horms@verge.net.au> wrote:
> On Wed, Jan 03, 2018 at 01:47:08PM +0100, Geert Uytterhoeven wrote:
>> On Wed, Jan 3, 2018 at 1:18 PM, Simon Horman <horms+renesas@verge.net.au> wrote:
>> > From: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>> >
>> > This patch adds Z2 clock divider support for R-Car Gen3 SoC.
>> >
>> > Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>> > Signed-off-by: Simon Horman <horms+renesas@verge.net.au>

>> As the CPG/MSSR driver now has suspend/resume support, do we need
>> a notifier to restore the Z or Z2 registers? Or is that handled automatically
>> by cpufreq during system resume, for both the primary and the secondary
>> CPU cores?
>
> I am a bit unsure.
>
> When using the A57 cores, which is the default case, the Z clk is queried
> by CPUFreq on resume. It appears that on my system its already set to the
> correct value but I assume if it was not then it would be reset. However,
> this does not cover Z2 clk. So perhaps to be safe we need to register
> notifiers and make sure they they play nicely with CPUFreq?

Of course the CPU is special: unlike many other devices, it must be running
when the kernel is reentered upon system resume.
It may be running using a different frequency setting, though.
However, following "opp-suspend", the system will always suspend with the
Z clock running at 1.5GHz, which is the default?
So Z is probably OK.

It's more interesting to check what happens when the little cores are
enabled as well (unfortunately that requires different firmware).
1. Does cpufreq handle them correctly when they are onlined again during
   system resume?
2. What happens if you offline all big cores, and enter system suspend
   running with little cores only?
   Perhaps that's prevented by the "opp-suspend" property as well?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [PATCH] iio: adc: stm32: fix scan of multiple channels with DMA
From: Fabrice Gasnier @ 2018-01-05 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

By default, watermark is set to '1'. Watermark is used to fine tune
cyclic dma buffer period. In case watermark is left untouched (e.g. 1)
and several channels are being scanned, buffer period is wrongly set
(e.g. to 1 sample). As a consequence, data is never pushed to upper layer.
Fix buffer period size, by taking scan channels number into account.

Fixes: 2763ea0585c9 ("iio: adc: stm32: add optional dma support")

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
---
 drivers/iio/adc/stm32-adc.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index c9d96f9..cecf1e5 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -1315,6 +1315,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
 {
 	struct stm32_adc *adc = iio_priv(indio_dev);
 	unsigned int watermark = STM32_DMA_BUFFER_SIZE / 2;
+	unsigned int rx_buf_sz = STM32_DMA_BUFFER_SIZE;
 
 	/*
 	 * dma cyclic transfers are used, buffer is split into two periods.
@@ -1323,7 +1324,7 @@ static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
 	 * - one buffer (period) driver can push with iio_trigger_poll().
 	 */
 	watermark = min(watermark, val * (unsigned)(sizeof(u16)));
-	adc->rx_buf_sz = watermark * 2;
+	adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv);
 
 	return 0;
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 6/6] ARM: configs: at91: at91_dt unselect ATMEL_PIT
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

The PIT is not required anymore to successfully boot and may actually harm
in case preempt-rt is used because the PIT interrupt is shared.
Disable it so the TCB clocksource is used.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/configs/at91_dt_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index 09f262e59fef..3ec7afe7a6c9 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -181,6 +181,7 @@ CONFIG_RTC_DRV_AT91RM9200=y
 CONFIG_RTC_DRV_AT91SAM9=y
 CONFIG_DMADEVICES=y
 CONFIG_AT_HDMAC=y
+# CONFIG_ATMEL_PIT is not set
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_AT91_ADC=y
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 5/6] ARM: configs: at91: sama5: unselect ATMEL_PIT
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

The PIT is not required anymore to successfully boot and may actually harm
in case preempt-rt is used because the PIT interrupt is shared.
Disable it so the TCB clocksource is used.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/configs/sama5_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 81594322f3a0..e6b984f18002 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -198,6 +198,7 @@ CONFIG_RTC_DRV_AT91RM9200=y
 CONFIG_DMADEVICES=y
 CONFIG_AT_HDMAC=y
 CONFIG_AT_XDMAC=y
+# CONFIG_ATMEL_PIT is not set
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_AT91_ADC=y
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 4/6] ARM: configs: at91: use new TCB timer driver
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

Unselecting ATMEL_TCLIB switches the TCB timer driver from tcb_clksrc to
timer-atmel-tcb.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/configs/at91_dt_defconfig | 1 -
 arch/arm/configs/sama5_defconfig   | 1 -
 2 files changed, 2 deletions(-)

diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index e4b1be66b3f5..09f262e59fef 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -64,7 +64,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=4
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 6529cb43e0fd..81594322f3a0 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -76,7 +76,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=4
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
 CONFIG_ATMEL_SSC=y
 CONFIG_EEPROM_AT24=y
 CONFIG_SCSI=y
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 3/6] clocksource/drivers: atmel-pit: allow unselecting ATMEL_PIT
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

With the new TCB clocksource driver, atmel platforms are now able to boot
without the PIT driver. Allow unselecting it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/clocksource/Kconfig | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 5609572e0236..55ccfa0ba63b 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -381,7 +381,14 @@ config ARMV7M_SYSTICK
 
 config ATMEL_PIT
 	select TIMER_OF if OF
-	def_bool SOC_AT91SAM9 || SOC_SAMA5
+	bool "Atmel Periodic Interval Timer (PIT)"
+	depends on SOC_AT91SAM9 || SOC_SAMA5
+	default SOC_AT91SAM9 || SOC_SAMA5
+	help
+	  Select this to get a clocksource based on the Atmel Periodic Interval
+	  Timer. It has a relatively low resolution and the TC Block clocksource
+	  should be preferred.
+	  It also provides a clock event device.
 
 config ATMEL_ST
 	bool "Atmel ST timer support" if COMPILE_TEST
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 2/6] clocksource/drivers: Add a new driver for the Atmel ARM TC blocks
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

Add a driver for the Atmel Timer Counter Blocks. This driver provides a
clocksource and two clockevent devices.

One of the clockevent device is linked to the clocksource counter and so it
will run at the same frequency. This will be used when there is only on TCB
channel available for timers.

The other clockevent device runs on a separate TCB channel when available.

This driver uses regmap and syscon to be able to probe early in the boot
and avoid having to switch on the TCB clocksource later. Using regmap also
means that unused TCB channels may be used by other drivers (PWM for
example). read/writel are still used to access channel specific registers
to avoid the performance impact of regmap (mainly locking).

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 drivers/clocksource/Kconfig           |  14 +
 drivers/clocksource/Makefile          |   3 +-
 drivers/clocksource/timer-atmel-tcb.c | 608 ++++++++++++++++++++++++++++++++++
 3 files changed, 624 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clocksource/timer-atmel-tcb.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index c729a88007d0..5609572e0236 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -390,6 +390,20 @@ config ATMEL_ST
 	help
 	  Support for the Atmel ST timer.
 
+config ATMEL_ARM_TCB_CLKSRC
+	bool "TC Block Clocksource"
+	select REGMAP_MMIO
+	depends on GENERIC_CLOCKEVENTS
+	depends on SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAMA5 || COMPILE_TEST
+	depends on !ATMEL_TCLIB
+	default SOC_AT91RM9200 || SOC_AT91SAM9 || SOC_SAMA5
+	help
+	  Select this to get a high precision clocksource based on a
+	  TC block with a 5+ MHz base clock rate.
+	  On platforms with 16-bit counters, two timer channels are combined
+	  to make a single 32-bit timer.
+	  It can also be used as a clock event device supporting oneshot mode.
+
 config CLKSRC_METAG_GENERIC
 	def_bool y if METAG
 	help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 72711f1491e3..d3aa71da783b 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -3,7 +3,8 @@ obj-$(CONFIG_TIMER_OF)		+= timer-of.o
 obj-$(CONFIG_TIMER_PROBE)	+= timer-probe.o
 obj-$(CONFIG_ATMEL_PIT)		+= timer-atmel-pit.o
 obj-$(CONFIG_ATMEL_ST)		+= timer-atmel-st.o
-obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o
+obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o
+obj-$(CONFIG_ATMEL_ARM_TCB_CLKSRC)	+= timer-atmel-tcb.o
 obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
 obj-$(CONFIG_SCx200HR_TIMER)	+= scx200_hrt.o
 obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
diff --git a/drivers/clocksource/timer-atmel-tcb.c b/drivers/clocksource/timer-atmel-tcb.c
new file mode 100644
index 000000000000..7fde9cfbf203
--- /dev/null
+++ b/drivers/clocksource/timer-atmel-tcb.c
@@ -0,0 +1,608 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/sched_clock.h>
+#include <soc/at91/atmel_tcb.h>
+
+static struct atmel_tcb_clksrc {
+	struct clocksource clksrc;
+	struct clock_event_device clkevt;
+	struct regmap *regmap;
+	void __iomem *base;
+	struct clk *clk[2];
+	char name[20];
+	int channels[2];
+	int bits;
+	int irq;
+	struct {
+		u32 cmr;
+		u32 imr;
+		u32 rc;
+		bool clken;
+	} cache[2];
+	u32 bmr_cache;
+	bool registered;
+} tc = {
+	.clksrc = {
+		.rating		= 200,
+		.mask		= CLOCKSOURCE_MASK(32),
+		.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+	},
+	.clkevt	= {
+		.features	= CLOCK_EVT_FEAT_ONESHOT,
+		/* Should be lower than at91rm9200's system timer */
+		.rating		= 125,
+	},
+};
+
+static struct tc_clkevt_device {
+	struct clock_event_device clkevt;
+	struct regmap *regmap;
+	void __iomem *base;
+	struct clk *slow_clk;
+	struct clk *clk;
+	char name[20];
+	int channel;
+	int irq;
+	struct {
+		u32 cmr;
+		u32 imr;
+		u32 rc;
+		bool clken;
+	} cache;
+	bool registered;
+} tce = {
+	.clkevt	= {
+		.features		= CLOCK_EVT_FEAT_PERIODIC |
+					  CLOCK_EVT_FEAT_ONESHOT,
+		/*
+		 * Should be lower than at91rm9200's system timer
+		 * but higher than tc.clkevt.rating
+		 */
+		.rating			= 140,
+	},
+};
+
+/*
+ * Clockevent device using its own channel
+ */
+static int tc_clkevt2_shutdown(struct clock_event_device *d)
+{
+	writel(0xff, tce.base + ATMEL_TC_IDR(tce.channel));
+	writel(ATMEL_TC_CCR_CLKDIS, tce.base + ATMEL_TC_CCR(tce.channel));
+	if (!clockevent_state_detached(d))
+		clk_disable(tce.clk);
+
+	return 0;
+}
+
+/* For now, we always use the 32K clock ... this optimizes for NO_HZ,
+ * because using one of the divided clocks would usually mean the
+ * tick rate can never be less than several dozen Hz (vs 0.5 Hz).
+ *
+ * A divided clock could be good for high resolution timers, since
+ * 30.5 usec resolution can seem "low".
+ */
+static int tc_clkevt2_set_oneshot(struct clock_event_device *d)
+{
+	if (clockevent_state_oneshot(d) || clockevent_state_periodic(d))
+		tc_clkevt2_shutdown(d);
+
+	clk_enable(tce.clk);
+
+	/* slow clock, count up to RC, then irq and stop */
+	writel(ATMEL_TC_CMR_TCLK(4) | ATMEL_TC_CMR_CPCSTOP |
+	       ATMEL_TC_CMR_WAVE | ATMEL_TC_CMR_WAVESEL_UPRC,
+	       tce.base + ATMEL_TC_CMR(tce.channel));
+	writel(ATMEL_TC_CPCS, tce.base + ATMEL_TC_IER(tce.channel));
+
+	return 0;
+}
+
+static int tc_clkevt2_set_periodic(struct clock_event_device *d)
+{
+	if (clockevent_state_oneshot(d) || clockevent_state_periodic(d))
+		tc_clkevt2_shutdown(d);
+
+	/* By not making the gentime core emulate periodic mode on top
+	 * of oneshot, we get lower overhead and improved accuracy.
+	 */
+	clk_enable(tce.clk);
+
+	/* slow clock, count up to RC, then irq and restart */
+	writel(ATMEL_TC_CMR_TCLK(4) | ATMEL_TC_CMR_WAVE |
+	       ATMEL_TC_CMR_WAVESEL_UPRC,
+	       tce.base + ATMEL_TC_CMR(tce.channel));
+	writel((32768 + HZ / 2) / HZ, tce.base + ATMEL_TC_RC(tce.channel));
+
+	/* Enable clock and interrupts on RC compare */
+	writel(ATMEL_TC_CPCS, tce.base + ATMEL_TC_IER(tce.channel));
+	writel(ATMEL_TC_CCR_CLKEN | ATMEL_TC_CCR_SWTRG,
+	       tce.base + ATMEL_TC_CCR(tce.channel));
+
+	return 0;
+}
+
+static int tc_clkevt2_next_event(unsigned long delta,
+				 struct clock_event_device *d)
+{
+	writel(delta, tce.base + ATMEL_TC_RC(tce.channel));
+	writel(ATMEL_TC_CCR_CLKEN | ATMEL_TC_CCR_SWTRG,
+	       tce.base + ATMEL_TC_CCR(tce.channel));
+
+	return 0;
+}
+
+static irqreturn_t tc_clkevt2_irq(int irq, void *handle)
+{
+	unsigned int sr;
+
+	sr = readl(tce.base + ATMEL_TC_SR(tce.channel));
+	if (sr & ATMEL_TC_CPCS) {
+		tce.clkevt.event_handler(&tce.clkevt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static void tc_clkevt2_suspend(struct clock_event_device *d)
+{
+	tce.cache.cmr = readl(tce.base + ATMEL_TC_CMR(tce.channel));
+	tce.cache.imr = readl(tce.base + ATMEL_TC_IMR(tce.channel));
+	tce.cache.rc = readl(tce.base + ATMEL_TC_RC(tce.channel));
+	tce.cache.clken = !!(readl(tce.base + ATMEL_TC_SR(tce.channel)) &
+				ATMEL_TC_CLKSTA);
+}
+
+static void tc_clkevt2_resume(struct clock_event_device *d)
+{
+	/* Restore registers for the channel, RA and RB are not used  */
+	writel(tce.cache.cmr, tc.base + ATMEL_TC_CMR(tce.channel));
+	writel(tce.cache.rc, tc.base + ATMEL_TC_RC(tce.channel));
+	writel(0, tc.base + ATMEL_TC_RA(tce.channel));
+	writel(0, tc.base + ATMEL_TC_RB(tce.channel));
+	/* Disable all the interrupts */
+	writel(0xff, tc.base + ATMEL_TC_IDR(tce.channel));
+	/* Reenable interrupts that were enabled before suspending */
+	writel(tce.cache.imr, tc.base + ATMEL_TC_IER(tce.channel));
+
+	/* Start the clock if it was used */
+	if (tce.cache.clken)
+		writel(ATMEL_TC_CCR_CLKEN | ATMEL_TC_CCR_SWTRG,
+		       tc.base + ATMEL_TC_CCR(tce.channel));
+}
+
+static int __init tc_clkevt_register(struct device_node *node,
+				     struct regmap *regmap, void __iomem *base,
+				     int channel, int irq, int bits)
+{
+	int ret;
+
+	tce.regmap = regmap;
+	tce.base = base;
+	tce.channel = channel;
+	tce.irq = irq;
+
+	tce.slow_clk = of_clk_get_by_name(node->parent, "slow_clk");
+	if (IS_ERR(tce.slow_clk))
+		return PTR_ERR(tce.slow_clk);
+
+	ret = clk_prepare_enable(tce.slow_clk);
+	if (ret)
+		return ret;
+
+	tce.clk = tcb_clk_get(node, tce.channel);
+	if (IS_ERR(tce.clk)) {
+		ret = PTR_ERR(tce.clk);
+		goto err_slow;
+	}
+
+	snprintf(tce.name, sizeof(tce.name), "%s:%d",
+		 kbasename(node->parent->full_name), channel);
+	tce.clkevt.cpumask = cpumask_of(0);
+	tce.clkevt.name = tce.name;
+	tce.clkevt.set_next_event = tc_clkevt2_next_event,
+	tce.clkevt.set_state_shutdown = tc_clkevt2_shutdown,
+	tce.clkevt.set_state_periodic = tc_clkevt2_set_periodic,
+	tce.clkevt.set_state_oneshot = tc_clkevt2_set_oneshot,
+	tce.clkevt.suspend = tc_clkevt2_suspend,
+	tce.clkevt.resume = tc_clkevt2_resume,
+
+	/* try to enable clk to avoid future errors in mode change */
+	ret = clk_prepare_enable(tce.clk);
+	if (ret)
+		goto err_slow;
+	clk_disable(tce.clk);
+
+	clockevents_config_and_register(&tce.clkevt, 32768, 1, bits - 1);
+
+	ret = request_irq(tce.irq, tc_clkevt2_irq, IRQF_TIMER | IRQF_SHARED,
+			  tce.clkevt.name, &tce);
+	if (ret)
+		goto err_clk;
+
+	tce.registered = true;
+
+	return 0;
+
+err_clk:
+	clk_unprepare(tce.clk);
+err_slow:
+	clk_disable_unprepare(tce.slow_clk);
+
+	return ret;
+}
+
+/*
+ * Clocksource and clockevent using the same channel(s)
+ */
+static u64 tc_get_cycles(struct clocksource *cs)
+{
+	u32 lower, upper;
+
+	do {
+		upper = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1]));
+		lower = readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[0]));
+	} while (upper != readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[1])));
+
+	return (upper << 16) | lower;
+}
+
+static u64 tc_get_cycles32(struct clocksource *cs)
+{
+	return readl_relaxed(tc.base + ATMEL_TC_CV(tc.channels[0]));
+}
+
+static u64 notrace tc_sched_clock_read(void)
+{
+	return tc_get_cycles(&tc.clksrc);
+}
+
+static u64 notrace tc_sched_clock_read32(void)
+{
+	return tc_get_cycles32(&tc.clksrc);
+}
+
+static int tcb_clkevt_next_event(unsigned long delta,
+				 struct clock_event_device *d)
+{
+	u32 old, next, cur;
+
+
+	old = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
+	next = old + delta;
+	writel(next, tc.base + ATMEL_TC_RC(tc.channels[0]));
+	cur = readl(tc.base + ATMEL_TC_CV(tc.channels[0]));
+
+	/* check whether the delta elapsed while setting the register */
+	if ((next < old && cur < old && cur > next) ||
+	    (next > old && (cur < old || cur > next))) {
+		/*
+		 * Clear the CPCS bit in the status register to avoid
+		 * generating a spurious interrupt next time a valid
+		 * timer event is configured.
+		 */
+		old = readl(tc.base + ATMEL_TC_SR(tc.channels[0]));
+		return -ETIME;
+	}
+
+	writel(ATMEL_TC_CPCS, tc.base + ATMEL_TC_IER(tc.channels[0]));
+
+	return 0;
+}
+
+static irqreturn_t tc_clkevt_irq(int irq, void *handle)
+{
+	unsigned int sr;
+
+	sr = readl(tc.base + ATMEL_TC_SR(tc.channels[0]));
+	if (sr & ATMEL_TC_CPCS) {
+		tc.clkevt.event_handler(&tc.clkevt);
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+static int tcb_clkevt_oneshot(struct clock_event_device *dev)
+{
+	if (clockevent_state_oneshot(dev))
+		return 0;
+
+	/*
+	 * Because both clockevent devices may share the same IRQ, we don't want
+	 * the less likely one to stay requested
+	 */
+	return request_irq(tc.irq, tc_clkevt_irq, IRQF_TIMER | IRQF_SHARED,
+			   tc.name, &tc);
+}
+
+static int tcb_clkevt_shutdown(struct clock_event_device *dev)
+{
+	writel(0xff, tc.base + ATMEL_TC_IDR(tc.channels[0]));
+	if (tc.bits == 16)
+		writel(0xff, tc.base + ATMEL_TC_IDR(tc.channels[1]));
+
+	if (!clockevent_state_detached(dev))
+		free_irq(tc.irq, &tc);
+
+	return 0;
+}
+
+static void __init tcb_setup_dual_chan(struct atmel_tcb_clksrc *tc,
+				       int mck_divisor_idx)
+{
+	/* first channel: waveform mode, input mclk/8, clock TIOA on overflow */
+	writel(mck_divisor_idx			/* likely divide-by-8 */
+	       | ATMEL_TC_CMR_WAVE
+	       | ATMEL_TC_CMR_WAVESEL_UP	/* free-run */
+	       | ATMEL_TC_CMR_ACPA(SET)		/* TIOA rises at 0 */
+	       | ATMEL_TC_CMR_ACPC(CLEAR),	/* (duty cycle 50%) */
+	       tc->base + ATMEL_TC_CMR(tc->channels[0]));
+	writel(0x0000, tc->base + ATMEL_TC_RA(tc->channels[0]));
+	writel(0x8000, tc->base + ATMEL_TC_RC(tc->channels[0]));
+	writel(0xff, tc->base + ATMEL_TC_IDR(tc->channels[0]));	/* no irqs */
+	writel(ATMEL_TC_CCR_CLKEN, tc->base + ATMEL_TC_CCR(tc->channels[0]));
+
+	/* second channel: waveform mode, input TIOA */
+	writel(ATMEL_TC_CMR_XC(tc->channels[1])		/* input: TIOA */
+	       | ATMEL_TC_CMR_WAVE
+	       | ATMEL_TC_CMR_WAVESEL_UP,		/* free-run */
+	       tc->base + ATMEL_TC_CMR(tc->channels[1]));
+	writel(0xff, tc->base + ATMEL_TC_IDR(tc->channels[1]));	/* no irqs */
+	writel(ATMEL_TC_CCR_CLKEN, tc->base + ATMEL_TC_CCR(tc->channels[1]));
+
+	/* chain both channel, we assume the previous channel */
+	regmap_write(tc->regmap, ATMEL_TC_BMR,
+		     ATMEL_TC_BMR_TCXC(1 + tc->channels[1], tc->channels[1]));
+	/* then reset all the timers */
+	regmap_write(tc->regmap, ATMEL_TC_BCR, ATMEL_TC_BCR_SYNC);
+}
+
+static void __init tcb_setup_single_chan(struct atmel_tcb_clksrc *tc,
+					 int mck_divisor_idx)
+{
+	/* channel 0:  waveform mode, input mclk/8 */
+	writel(mck_divisor_idx			/* likely divide-by-8 */
+	       | ATMEL_TC_CMR_WAVE
+	       | ATMEL_TC_CMR_WAVESEL_UP,	/* free-run */
+	       tc->base + ATMEL_TC_CMR(tc->channels[0]));
+	writel(0xff, tc->base + ATMEL_TC_IDR(tc->channels[0]));	/* no irqs */
+	writel(ATMEL_TC_CCR_CLKEN, tc->base + ATMEL_TC_CCR(tc->channels[0]));
+
+	/* then reset all the timers */
+	regmap_write(tc->regmap, ATMEL_TC_BCR, ATMEL_TC_BCR_SYNC);
+}
+
+static void tc_clksrc_suspend(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < 1 + (tc.bits == 16); i++) {
+		tc.cache[i].cmr = readl(tc.base + ATMEL_TC_CMR(tc.channels[i]));
+		tc.cache[i].imr = readl(tc.base + ATMEL_TC_IMR(tc.channels[i]));
+		tc.cache[i].rc = readl(tc.base + ATMEL_TC_RC(tc.channels[i]));
+		tc.cache[i].clken = !!(readl(tc.base +
+					     ATMEL_TC_SR(tc.channels[i])) &
+				       ATMEL_TC_CLKSTA);
+	}
+
+	if (tc.bits == 16)
+		regmap_read(tc.regmap, ATMEL_TC_BMR, &tc.bmr_cache);
+}
+
+static void tc_clksrc_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < 1 + (tc.bits == 16); i++) {
+		/* Restore registers for the channel, RA and RB are not used  */
+		writel(tc.cache[i].cmr, tc.base + ATMEL_TC_CMR(tc.channels[i]));
+		writel(tc.cache[i].rc, tc.base + ATMEL_TC_RC(tc.channels[i]));
+		writel(0, tc.base + ATMEL_TC_RA(tc.channels[i]));
+		writel(0, tc.base + ATMEL_TC_RB(tc.channels[i]));
+		/* Disable all the interrupts */
+		writel(0xff, tc.base + ATMEL_TC_IDR(tc.channels[i]));
+		/* Reenable interrupts that were enabled before suspending */
+		writel(tc.cache[i].imr, tc.base + ATMEL_TC_IER(tc.channels[i]));
+
+		/* Start the clock if it was used */
+		if (tc.cache[i].clken)
+			writel(ATMEL_TC_CCR_CLKEN, tc.base +
+			       ATMEL_TC_CCR(tc.channels[i]));
+	}
+
+	/* in case of dual channel, chain channels */
+	if (tc.bits == 16)
+		regmap_write(tc.regmap, ATMEL_TC_BMR, tc.bmr_cache);
+	/* Finally, trigger all the channels*/
+	regmap_write(tc.regmap, ATMEL_TC_BCR, ATMEL_TC_BCR_SYNC);
+}
+
+static int __init tcb_clksrc_register(struct device_node *node,
+				      struct regmap *regmap, void __iomem *base,
+				      int channel, int channel1, int irq,
+				      int bits)
+{
+	u32 rate, divided_rate = 0;
+	int best_divisor_idx = -1;
+	int i, err = -1;
+	u64 (*tc_sched_clock)(void);
+
+	tc.regmap = regmap;
+	tc.base = base;
+	tc.channels[0] = channel;
+	tc.channels[1] = channel1;
+	tc.irq = irq;
+	tc.bits = bits;
+
+	tc.clk[0] = tcb_clk_get(node, tc.channels[0]);
+	if (IS_ERR(tc.clk[0]))
+		return PTR_ERR(tc.clk[0]);
+	err = clk_prepare_enable(tc.clk[0]);
+	if (err) {
+		pr_debug("can't enable T0 clk\n");
+		goto err_clk;
+	}
+
+	/* How fast will we be counting?  Pick something over 5 MHz.  */
+	rate = (u32)clk_get_rate(tc.clk[0]);
+	for (i = 0; i < 5; i++) {
+		unsigned int divisor = atmel_tc_divisors[i];
+		unsigned int tmp;
+
+		if (!divisor)
+			continue;
+
+		tmp = rate / divisor;
+		pr_debug("TC: %u / %-3u [%d] --> %u\n", rate, divisor, i, tmp);
+		if (best_divisor_idx > 0) {
+			if (tmp < 5 * 1000 * 1000)
+				continue;
+		}
+		divided_rate = tmp;
+		best_divisor_idx = i;
+	}
+
+	if (tc.bits == 32) {
+		tc.clksrc.read = tc_get_cycles32;
+		tcb_setup_single_chan(&tc, best_divisor_idx);
+		tc_sched_clock = tc_sched_clock_read32;
+		snprintf(tc.name, sizeof(tc.name), "%s:%d",
+			 kbasename(node->parent->full_name), tc.channels[0]);
+	} else {
+		tc.clk[1] = tcb_clk_get(node, tc.channels[1]);
+		if (IS_ERR(tc.clk[1]))
+			goto err_disable_t0;
+
+		err = clk_prepare_enable(tc.clk[1]);
+		if (err) {
+			pr_debug("can't enable T1 clk\n");
+			goto err_clk1;
+		}
+		tc.clksrc.read = tc_get_cycles,
+		tcb_setup_dual_chan(&tc, best_divisor_idx);
+		tc_sched_clock = tc_sched_clock_read;
+		snprintf(tc.name, sizeof(tc.name), "%s:%d,%d",
+			 kbasename(node->parent->full_name), tc.channels[0],
+			 tc.channels[1]);
+	}
+
+	pr_debug("%s at %d.%03d MHz\n", tc.name,
+		 divided_rate / 1000000,
+		 ((divided_rate + 500000) % 1000000) / 1000);
+
+	tc.clksrc.name = tc.name;
+	tc.clksrc.suspend = tc_clksrc_suspend;
+	tc.clksrc.resume = tc_clksrc_resume;
+
+	err = clocksource_register_hz(&tc.clksrc, divided_rate);
+	if (err)
+		goto err_disable_t1;
+
+	sched_clock_register(tc_sched_clock, 32, divided_rate);
+
+	tc.registered = true;
+
+	/* Set up and register clockevents */
+	tc.clkevt.name = tc.name;
+	tc.clkevt.cpumask = cpumask_of(0);
+	tc.clkevt.set_next_event = tcb_clkevt_next_event;
+	tc.clkevt.set_state_oneshot = tcb_clkevt_oneshot;
+	tc.clkevt.set_state_shutdown = tcb_clkevt_shutdown;
+	clockevents_config_and_register(&tc.clkevt, divided_rate, 1,
+					BIT(tc.bits) - 1);
+
+	return 0;
+
+err_disable_t1:
+	if (tc.bits == 16)
+		clk_disable_unprepare(tc.clk[1]);
+
+err_clk1:
+	if (tc.bits == 16)
+		clk_put(tc.clk[1]);
+
+err_disable_t0:
+	clk_disable_unprepare(tc.clk[0]);
+
+err_clk:
+	clk_put(tc.clk[0]);
+
+	pr_err("%s: unable to register clocksource/clockevent\n",
+	       tc.clksrc.name);
+
+	return err;
+}
+
+static int __init tcb_clksrc_init(struct device_node *node)
+{
+	const struct of_device_id *match;
+	const struct atmel_tcb_info *tcb_info;
+	struct regmap *regmap;
+	void __iomem *tcb_base;
+	u32 channel;
+	int bits, irq, err, chan1 = -1;
+
+	if (tc.registered && tce.registered)
+		return -ENODEV;
+
+	/*
+	 * The regmap has to be used to access registers that are shared
+	 * between channels on the same TCB but we keep direct IO access for
+	 * the counters to avoid the impact on performance
+	 */
+	regmap = syscon_node_to_regmap(node->parent);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	tcb_base = of_iomap(node->parent, 0);
+	if (!tcb_base) {
+		pr_err("%s +%d %s\n", __FILE__, __LINE__, __func__);
+		return -ENXIO;
+	}
+
+	match = of_match_node(atmel_tcb_dt_ids, node->parent);
+	tcb_info = match->data;
+	bits = tcb_info->bits;
+
+	err = of_property_read_u32_index(node, "reg", 0, &channel);
+	if (err)
+		return err;
+
+	irq = tcb_irq_get(node, channel);
+	if (irq < 0)
+		return irq;
+
+	if (tc.registered)
+		return tc_clkevt_register(node, regmap, tcb_base, channel, irq,
+					  bits);
+
+	if (bits == 16) {
+		of_property_read_u32_index(node, "reg", 1, &chan1);
+		if (chan1 == -1) {
+			if (tce.registered) {
+				pr_err("%s: clocksource needs two channels\n",
+				       node->parent->full_name);
+				return -EINVAL;
+			} else {
+				return tc_clkevt_register(node, regmap,
+							  tcb_base, channel,
+							  irq, bits);
+			}
+		}
+	}
+
+	return tcb_clksrc_register(node, regmap, tcb_base, channel, chan1, irq,
+				   bits);
+}
+CLOCKSOURCE_OF_DECLARE(atmel_tcb_clksrc, "atmel,tcb-timer",
+		       tcb_clksrc_init);
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 1/6] ARM: at91: add TCB registers definitions
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180105143006.5369-1-alexandre.belloni@free-electrons.com>

Add registers and bits definitions for the timer counter blocks found on
Atmel ARM SoCs.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 include/soc/at91/atmel_tcb.h | 229 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 include/soc/at91/atmel_tcb.h

diff --git a/include/soc/at91/atmel_tcb.h b/include/soc/at91/atmel_tcb.h
new file mode 100644
index 000000000000..f48e60f8ab92
--- /dev/null
+++ b/include/soc/at91/atmel_tcb.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2016 Atmel
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SOC_ATMEL_TCB_H
+#define __SOC_ATMEL_TCB_H
+
+/* Channel registers */
+#define ATMEL_TC_COFFS(c)		((c) * 0x40)
+#define ATMEL_TC_CCR(c)			ATMEL_TC_COFFS(c)
+#define ATMEL_TC_CMR(c)			(ATMEL_TC_COFFS(c) + 0x4)
+#define ATMEL_TC_SMMR(c)		(ATMEL_TC_COFFS(c) + 0x8)
+#define ATMEL_TC_RAB(c)			(ATMEL_TC_COFFS(c) + 0xc)
+#define ATMEL_TC_CV(c)			(ATMEL_TC_COFFS(c) + 0x10)
+#define ATMEL_TC_RA(c)			(ATMEL_TC_COFFS(c) + 0x14)
+#define ATMEL_TC_RB(c)			(ATMEL_TC_COFFS(c) + 0x18)
+#define ATMEL_TC_RC(c)			(ATMEL_TC_COFFS(c) + 0x1c)
+#define ATMEL_TC_SR(c)			(ATMEL_TC_COFFS(c) + 0x20)
+#define ATMEL_TC_IER(c)			(ATMEL_TC_COFFS(c) + 0x24)
+#define ATMEL_TC_IDR(c)			(ATMEL_TC_COFFS(c) + 0x28)
+#define ATMEL_TC_IMR(c)			(ATMEL_TC_COFFS(c) + 0x2c)
+#define ATMEL_TC_EMR(c)			(ATMEL_TC_COFFS(c) + 0x30)
+
+/* Block registers */
+#define ATMEL_TC_BCR			0xc0
+#define ATMEL_TC_BMR			0xc4
+#define ATMEL_TC_QIER			0xc8
+#define ATMEL_TC_QIDR			0xcc
+#define ATMEL_TC_QIMR			0xd0
+#define ATMEL_TC_QISR			0xd4
+#define ATMEL_TC_FMR			0xd8
+#define ATMEL_TC_WPMR			0xe4
+
+/* CCR fields */
+#define ATMEL_TC_CCR_CLKEN		BIT(0)
+#define ATMEL_TC_CCR_CLKDIS		BIT(1)
+#define ATMEL_TC_CCR_SWTRG		BIT(2)
+
+/* Common CMR fields */
+#define ATMEL_TC_CMR_TCLKS_MSK		GENMASK(2, 0)
+#define ATMEL_TC_CMR_TCLK(x)		(x)
+#define ATMEL_TC_CMR_XC(x)		((x) + 5)
+#define ATMEL_TC_CMR_CLKI		BIT(3)
+#define ATMEL_TC_CMR_BURST_MSK		GENMASK(5, 4)
+#define ATMEL_TC_CMR_BURST_XC(x)	(((x) + 1) << 4)
+#define ATMEL_TC_CMR_WAVE		BIT(15)
+
+/* Capture mode CMR fields */
+#define ATMEL_TC_CMR_LDBSTOP		BIT(6)
+#define ATMEL_TC_CMR_LDBDIS		BIT(7)
+#define ATMEL_TC_CMR_ETRGEDG_MSK	GENMASK(9, 8)
+#define ATMEL_TC_CMR_ETRGEDG_NONE	(0 << 8)
+#define ATMEL_TC_CMR_ETRGEDG_RISING	(1 << 8)
+#define ATMEL_TC_CMR_ETRGEDG_FALLING	(2 << 8)
+#define ATMEL_TC_CMR_ETRGEDG_BOTH	(3 << 8)
+#define ATMEL_TC_CMR_ABETRG		BIT(10)
+#define ATMEL_TC_CMR_CPCTRG		BIT(14)
+#define ATMEL_TC_CMR_LDRA_MSK		GENMASK(17, 16)
+#define ATMEL_TC_CMR_LDRA_NONE		(0 << 16)
+#define ATMEL_TC_CMR_LDRA_RISING	(1 << 16)
+#define ATMEL_TC_CMR_LDRA_FALLING	(2 << 16)
+#define ATMEL_TC_CMR_LDRA_BOTH		(3 << 16)
+#define ATMEL_TC_CMR_LDRB_MSK		GENMASK(19, 18)
+#define ATMEL_TC_CMR_LDRB_NONE		(0 << 18)
+#define ATMEL_TC_CMR_LDRB_RISING	(1 << 18)
+#define ATMEL_TC_CMR_LDRB_FALLING	(2 << 18)
+#define ATMEL_TC_CMR_LDRB_BOTH		(3 << 18)
+#define ATMEL_TC_CMR_SBSMPLR_MSK	GENMASK(22, 20)
+#define ATMEL_TC_CMR_SBSMPLR(x)		((x) << 20)
+
+/* Waveform mode CMR fields */
+#define ATMEL_TC_CMR_CPCSTOP		BIT(6)
+#define ATMEL_TC_CMR_CPCDIS		BIT(7)
+#define ATMEL_TC_CMR_EEVTEDG_MSK	GENMASK(9, 8)
+#define ATMEL_TC_CMR_EEVTEDG_NONE	(0 << 8)
+#define ATMEL_TC_CMR_EEVTEDG_RISING	(1 << 8)
+#define ATMEL_TC_CMR_EEVTEDG_FALLING	(2 << 8)
+#define ATMEL_TC_CMR_EEVTEDG_BOTH	(3 << 8)
+#define ATMEL_TC_CMR_EEVT_MSK		GENMASK(11, 10)
+#define ATMEL_TC_CMR_EEVT_XC(x)		(((x) + 1) << 10)
+#define ATMEL_TC_CMR_ENETRG		BIT(12)
+#define ATMEL_TC_CMR_WAVESEL_MSK	GENMASK(14, 13)
+#define ATMEL_TC_CMR_WAVESEL_UP		(0 << 13)
+#define ATMEL_TC_CMR_WAVESEL_UPDOWN	(1 << 13)
+#define ATMEL_TC_CMR_WAVESEL_UPRC	(2 << 13)
+#define ATMEL_TC_CMR_WAVESEL_UPDOWNRC	(3 << 13)
+#define ATMEL_TC_CMR_ACPA_MSK		GENMASK(17, 16)
+#define ATMEL_TC_CMR_ACPA(a)		(ATMEL_TC_CMR_ACTION_##a << 16)
+#define ATMEL_TC_CMR_ACPC_MSK		GENMASK(19, 18)
+#define ATMEL_TC_CMR_ACPC(a)		(ATMEL_TC_CMR_ACTION_##a << 18)
+#define ATMEL_TC_CMR_AEEVT_MSK		GENMASK(21, 20)
+#define ATMEL_TC_CMR_AEEVT(a)		(ATMEL_TC_CMR_ACTION_##a << 20)
+#define ATMEL_TC_CMR_ASWTRG_MSK		GENMASK(23, 22)
+#define ATMEL_TC_CMR_ASWTRG(a)		(ATMEL_TC_CMR_ACTION_##a << 22)
+#define ATMEL_TC_CMR_BCPB_MSK		GENMASK(25, 24)
+#define ATMEL_TC_CMR_BCPB(a)		(ATMEL_TC_CMR_ACTION_##a << 24)
+#define ATMEL_TC_CMR_BCPC_MSK		GENMASK(27, 26)
+#define ATMEL_TC_CMR_BCPC(a)		(ATMEL_TC_CMR_ACTION_##a << 26)
+#define ATMEL_TC_CMR_BEEVT_MSK		GENMASK(29, 28)
+#define ATMEL_TC_CMR_BEEVT(a)		(ATMEL_TC_CMR_ACTION_##a << 28)
+#define ATMEL_TC_CMR_BSWTRG_MSK		GENMASK(31, 30)
+#define ATMEL_TC_CMR_BSWTRG(a)		(ATMEL_TC_CMR_ACTION_##a << 30)
+#define ATMEL_TC_CMR_ACTION_NONE	0
+#define ATMEL_TC_CMR_ACTION_SET		1
+#define ATMEL_TC_CMR_ACTION_CLEAR	2
+#define ATMEL_TC_CMR_ACTION_TOGGLE	3
+
+/* SMMR fields */
+#define ATMEL_TC_SMMR_GCEN		BIT(0)
+#define ATMEL_TC_SMMR_DOWN		BIT(1)
+
+/* SR/IER/IDR/IMR fields */
+#define ATMEL_TC_COVFS			BIT(0)
+#define ATMEL_TC_LOVRS			BIT(1)
+#define ATMEL_TC_CPAS			BIT(2)
+#define ATMEL_TC_CPBS			BIT(3)
+#define ATMEL_TC_CPCS			BIT(4)
+#define ATMEL_TC_LDRAS			BIT(5)
+#define ATMEL_TC_LDRBS			BIT(6)
+#define ATMEL_TC_ETRGS			BIT(7)
+#define ATMEL_TC_CLKSTA			BIT(16)
+#define ATMEL_TC_MTIOA			BIT(17)
+#define ATMEL_TC_MTIOB			BIT(18)
+
+/* EMR fields */
+#define ATMEL_TC_EMR_TRIGSRCA_MSK	GENMASK(1, 0)
+#define ATMEL_TC_EMR_TRIGSRCA_TIOA	0
+#define ATMEL_TC_EMR_TRIGSRCA_PWMX	1
+#define ATMEL_TC_EMR_TRIGSRCB_MSK	GENMASK(5, 4)
+#define ATMEL_TC_EMR_TRIGSRCB_TIOB	(0 << 4)
+#define ATMEL_TC_EMR_TRIGSRCB_PWM	(1 << 4)
+#define ATMEL_TC_EMR_NOCLKDIV		BIT(8)
+
+/* BCR fields */
+#define ATMEL_TC_BCR_SYNC		BIT(0)
+
+/* BMR fields */
+#define ATMEL_TC_BMR_TCXC_MSK(c)	GENMASK(((c) * 2) + 1, (c) * 2)
+#define ATMEL_TC_BMR_TCXC(x, c)		((x) << (2 * (c)))
+#define ATMEL_TC_BMR_QDEN		BIT(8)
+#define ATMEL_TC_BMR_POSEN		BIT(9)
+#define ATMEL_TC_BMR_SPEEDEN		BIT(10)
+#define ATMEL_TC_BMR_QDTRANS		BIT(11)
+#define ATMEL_TC_BMR_EDGPHA		BIT(12)
+#define ATMEL_TC_BMR_INVA		BIT(13)
+#define ATMEL_TC_BMR_INVB		BIT(14)
+#define ATMEL_TC_BMR_INVIDX		BIT(15)
+#define ATMEL_TC_BMR_SWAP		BIT(16)
+#define ATMEL_TC_BMR_IDXPHB		BIT(17)
+#define ATMEL_TC_BMR_AUTOC		BIT(18)
+#define ATMEL_TC_MAXFILT_MSK		GENMASK(25, 20)
+#define ATMEL_TC_MAXFILT(x)		(((x) - 1) << 20)
+#define ATMEL_TC_MAXCMP_MSK		GENMASK(29, 26)
+#define ATMEL_TC_MAXCMP(x)		((x) << 26)
+
+/* QEDC fields */
+#define ATMEL_TC_QEDC_IDX		BIT(0)
+#define ATMEL_TC_QEDC_DIRCHG		BIT(1)
+#define ATMEL_TC_QEDC_QERR		BIT(2)
+#define ATMEL_TC_QEDC_MPE		BIT(3)
+#define ATMEL_TC_QEDC_DIR		BIT(8)
+
+/* FMR fields */
+#define ATMEL_TC_FMR_ENCF(x)		BIT(x)
+
+/* WPMR fields */
+#define ATMEL_TC_WPMR_WPKEY		(0x54494d << 8)
+#define ATMEL_TC_WPMR_WPEN		BIT(0)
+
+static inline struct clk *tcb_clk_get(struct device_node *node, int channel)
+{
+	struct clk *clk;
+	char clk_name[] = "t0_clk";
+
+	clk_name[1] += channel;
+	clk = of_clk_get_by_name(node->parent, clk_name);
+	if (!IS_ERR(clk))
+		return clk;
+
+	return of_clk_get_by_name(node->parent, "t0_clk");
+}
+
+static inline int tcb_irq_get(struct device_node *node, int channel)
+{
+	int irq;
+
+	irq = of_irq_get(node->parent, channel);
+	if (irq > 0)
+		return irq;
+
+	return of_irq_get(node->parent, 0);
+}
+
+static const u8 atmel_tc_divisors[5] = { 2, 8, 32, 128, 0, };
+
+struct atmel_tcb_info {
+	int bits;
+};
+
+static const struct atmel_tcb_info atmel_tcb_infos[] = {
+	{ .bits = 16 },
+	{ .bits = 32 },
+};
+
+static const struct of_device_id atmel_tcb_dt_ids[] = {
+	{
+		.compatible = "atmel,at91rm9200-tcb",
+		.data = &atmel_tcb_infos[0],
+	}, {
+		.compatible = "atmel,at91sam9x5-tcb",
+		.data = &atmel_tcb_infos[1],
+	}, {
+		/* sentinel */
+	}
+};
+
+#endif /* __SOC_ATMEL_TCB_H */
-- 
2.15.1

^ permalink raw reply related

* [PATCH v2 0/6] clocksource: rework Atmel TCB timer driver
From: Alexandre Belloni @ 2018-01-05 14:30 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This series gets back on the TCB drivers rework. It introduces a new driver to
handle the clocksource and clockevent devices.

As a reminder, this is necessary because:
 - the current tcb_clksrc driver is probed too late to be able to be used at
   boot and we now have SoCs that don't have a PIT. They currently are not able
   to boot a mainline kernel.
 - using the PIT doesn't work well with preempt-rt because its interrupt is
   shared (in particular with the UART and their interrupt flags are
   incompatible)
 - the current solution is wasting some TCB channels

The plan is to get this driver upstream, then convert the TCB PWM driver to be
able to get rid of the tcb_clksrc driver along with atmel_tclib.

I decided to leave out the clocksource/clockevent selection for now as it seems
the discussion is going nowhere. We can get back to that later

Main changes in v2:
 - use direct IO instead of regmap when accessing channel specific registers to
   avoid the regmap locking
 - implement suspend/resume

Alexandre Belloni (6):
  ARM: at91: add TCB registers definitions
  clocksource/drivers: Add a new driver for the Atmel ARM TC blocks
  clocksource/drivers: atmel-pit: allow unselecting ATMEL_PIT
  ARM: configs: at91: use new TCB timer driver
  ARM: configs: at91: sama5: unselect ATMEL_PIT
  ARM: configs: at91: at91_dt unselect ATMEL_PIT

 arch/arm/configs/at91_dt_defconfig    |   2 +-
 arch/arm/configs/sama5_defconfig      |   2 +-
 drivers/clocksource/Kconfig           |  23 +-
 drivers/clocksource/Makefile          |   3 +-
 drivers/clocksource/timer-atmel-tcb.c | 608 ++++++++++++++++++++++++++++++++++
 include/soc/at91/atmel_tcb.h          | 229 +++++++++++++
 6 files changed, 863 insertions(+), 4 deletions(-)
 create mode 100644 drivers/clocksource/timer-atmel-tcb.c
 create mode 100644 include/soc/at91/atmel_tcb.h

-- 
2.15.1

^ 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