Devicetree
 help / color / mirror / Atom feed
* [PATCH 2/3] arm64: tegra: Enable multi-queue for DWC EQOS
From: Bhadram Varka @ 2018-06-02  9:11 UTC (permalink / raw)
  To: robh+dt, mark.rutland, catalin.marinas, will.deacon, treding,
	mperttunen
  Cc: linux-tegra, devicetree, linux-arm-kernel
In-Reply-To: <1527930713-4479-1-git-send-email-vbhadram@nvidia.com>

DWC EQOS supports four MTL queues for Tx and Rx
separately.

Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 48 ++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 0f4bed8..f27730d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -37,6 +37,52 @@
 		gpio-controller;
 	};
 
+	mtl_rx_setup: rx-queues-config {
+		snps,rx-queues-to-use = <4>;
+		snps,rx-sched-sp;
+		queue0 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x0>;
+			snps,priority = <0x0>;
+		};
+		queue1 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x1>;
+			snps,priority = <0x1>;
+		};
+		queue2 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x2>;
+			snps,priority = <0x2>;
+		};
+		queue3 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x2>;
+			snps,priority = <0x3>;
+		};
+	};
+
+	mtl_tx_setup: tx-queues-config {
+		snps,tx-queues-to-use = <4>;
+		snps,tx-sched-sp;
+		queue0 {
+			snps,dcb-algorithm;
+			snps,priority = <0x0>;
+		};
+		queue1 {
+			snps,dcb-algorithm;
+			snps,priority = <0x1>;
+		};
+		queue2 {
+			snps,dcb-algorithm;
+			snps,priority = <0x2>;
+		};
+		queue3 {
+			snps,dcb-algorithm;
+			snps,priority = <0x3>;
+		};
+	};
+
 	ethernet@2490000 {
 		compatible = "nvidia,tegra186-eqos",
 			     "snps,dwc-qos-ethernet-4.10";
@@ -57,6 +103,8 @@
 		snps,burst-map = <0x7>;
 		snps,txpbl = <32>;
 		snps,rxpbl = <8>;
+		snps,mtl-rx-config = <&mtl_rx_setup>;
+		snps,mtl-tx-config = <&mtl_tx_setup>;
 	};
 
 	memory-controller@2c00000 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/3] arm64: tegra: Configure DWC EQOS TxPBL for multi-queue
From: Bhadram Varka @ 2018-06-02  9:11 UTC (permalink / raw)
  To: robh+dt, mark.rutland, catalin.marinas, will.deacon, treding,
	mperttunen
  Cc: linux-tegra, devicetree, linux-arm-kernel
In-Reply-To: <1527930713-4479-1-git-send-email-vbhadram@nvidia.com>

PBL should be limited to half of the Queue size.

For multi-queue: Total MTL queue size 4KB.
PBL = 16, PBLx8 = 1 -> This setting would lead
to an effective burst = 8*16 = 128, which would
mean 128*16B = 2KB (half of queue size)

Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index f27730d..630cb81 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -101,7 +101,7 @@
 		snps,write-requests = <1>;
 		snps,read-requests = <3>;
 		snps,burst-map = <0x7>;
-		snps,txpbl = <32>;
+		snps,txpbl = <16>;
 		snps,rxpbl = <8>;
 		snps,mtl-rx-config = <&mtl_rx_setup>;
 		snps,mtl-tx-config = <&mtl_tx_setup>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 1/3] arm64: tegra: Remove unused interrupt properties
From: Bhadram Varka @ 2018-06-02  9:20 UTC (permalink / raw)
  To: robh+dt, mark.rutland, catalin.marinas, will.deacon, treding,
	mperttunen
  Cc: linux-tegra, devicetree, linux-arm-kernel

DWC EQOS on Tegra handles all interrupts through
common interrupt line. So lets remove unused power
and per-channel interrupt properties.

Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 11 +----------
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index b762227..252133b 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -41,16 +41,7 @@
 		compatible = "nvidia,tegra186-eqos",
 			     "snps,dwc-qos-ethernet-4.10";
 		reg = <0x0 0x02490000 0x0 0x10000>;
-		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>, /* common */
-			     <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>, /* power */
-			     <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, /* rx0 */
-			     <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>, /* tx0 */
-			     <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>, /* rx1 */
-			     <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>, /* tx1 */
-			     <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, /* rx2 */
-			     <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* tx2 */
-			     <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>, /* rx3 */
-			     <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; /* tx3 */
+		interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>; /* common */
 		clocks = <&bpmp TEGRA186_CLK_AXI_CBB>,
 			 <&bpmp TEGRA186_CLK_EQOS_AXI>,
 			 <&bpmp TEGRA186_CLK_EQOS_RX>,
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 2/3] arm64: tegra: Enable multi-queue for DWC EQOS
From: Bhadram Varka @ 2018-06-02  9:20 UTC (permalink / raw)
  To: robh+dt, mark.rutland, catalin.marinas, will.deacon, treding,
	mperttunen
  Cc: linux-tegra, devicetree, linux-arm-kernel
In-Reply-To: <1527931251-4809-1-git-send-email-vbhadram@nvidia.com>

DWC EQOS supports four MTL queues for Tx and Rx
separately.

Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 48 ++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 252133b..48c6caf 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -37,6 +37,52 @@
 		gpio-controller;
 	};
 
+	mtl_rx_setup: rx-queues-config {
+		snps,rx-queues-to-use = <4>;
+		snps,rx-sched-sp;
+		queue0 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x0>;
+			snps,priority = <0x0>;
+		};
+		queue1 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x1>;
+			snps,priority = <0x1>;
+		};
+		queue2 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x2>;
+			snps,priority = <0x2>;
+		};
+		queue3 {
+			snps,dcb-algorithm;
+			snps,map-to-dma-channel = <0x2>;
+			snps,priority = <0x3>;
+		};
+	};
+
+	mtl_tx_setup: tx-queues-config {
+		snps,tx-queues-to-use = <4>;
+		snps,tx-sched-sp;
+		queue0 {
+			snps,dcb-algorithm;
+			snps,priority = <0x0>;
+		};
+		queue1 {
+			snps,dcb-algorithm;
+			snps,priority = <0x1>;
+		};
+		queue2 {
+			snps,dcb-algorithm;
+			snps,priority = <0x2>;
+		};
+		queue3 {
+			snps,dcb-algorithm;
+			snps,priority = <0x3>;
+		};
+	};
+
 	ethernet@2490000 {
 		compatible = "nvidia,tegra186-eqos",
 			     "snps,dwc-qos-ethernet-4.10";
@@ -57,6 +103,8 @@
 		snps,burst-map = <0x7>;
 		snps,txpbl = <32>;
 		snps,rxpbl = <8>;
+		snps,mtl-rx-config = <&mtl_rx_setup>;
+		snps,mtl-tx-config = <&mtl_tx_setup>;
 	};
 
 	memory-controller@2c00000 {
-- 
2.7.4

^ permalink raw reply related

* [PATCH V2 3/3] arm64: tegra: Configure DWC EQOS TxPBL for multi-queue
From: Bhadram Varka @ 2018-06-02  9:20 UTC (permalink / raw)
  To: robh+dt, mark.rutland, catalin.marinas, will.deacon, treding,
	mperttunen
  Cc: linux-tegra, devicetree, linux-arm-kernel
In-Reply-To: <1527931251-4809-1-git-send-email-vbhadram@nvidia.com>

PBL should be limited to half of the Queue size.

For multi-queue: Total MTL queue size 4KB.
PBL = 16, PBLx8 = 1 -> This setting would lead
to an effective burst = 8*16 = 128, which would
mean 128*16B = 2KB (half of queue size)

Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra186.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 48c6caf..c4d70c5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -101,7 +101,7 @@
 		snps,write-requests = <1>;
 		snps,read-requests = <3>;
 		snps,burst-map = <0x7>;
-		snps,txpbl = <32>;
+		snps,txpbl = <16>;
 		snps,rxpbl = <8>;
 		snps,mtl-rx-config = <&mtl_rx_setup>;
 		snps,mtl-tx-config = <&mtl_tx_setup>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH 0/2] thermal: tsens: SDM845 support
From: Amit Kucheria @ 2018-06-02 11:11 UTC (permalink / raw)
  To: linux-arm-msm
  Cc: rnayak, bjorn.andersson, edubezval,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list, open list:THERMAL

Add SDM845 support in the tsens driver. I've create a separate file
(tsens-sdm845.c) because I expect it to diverge from the other drivers.

Cleanup the tsens_device structure while we're at it.


Amit Kucheria (2):
  thermal: tsens: Add support for SDM845 platform
  tsens: Get rid of unused fields in structure

 .../devicetree/bindings/thermal/qcom-tsens.txt     |  1 +
 drivers/thermal/qcom/Makefile                      |  2 +-
 drivers/thermal/qcom/tsens-sdm845.c                | 98 ++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c                       |  3 +
 drivers/thermal/qcom/tsens.h                       |  3 +-
 5 files changed, 104 insertions(+), 3 deletions(-)
 create mode 100644 drivers/thermal/qcom/tsens-sdm845.c

-- 
2.7.4

^ permalink raw reply

* [PATCH 1/2] thermal: tsens: Add support for SDM845 platform
From: Amit Kucheria @ 2018-06-02 11:11 UTC (permalink / raw)
  To: linux-arm-msm
  Cc: rnayak, bjorn.andersson, edubezval, Zhang Rui, Rob Herring,
	Mark Rutland, open list:THERMAL,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list
In-Reply-To: <cover.1527937396.git.amit.kucheria@linaro.org>

There are two tsens blocks on the SDM845. These will be configured through
the devicetree.

Signed-off-by: Amit Kucheria <amit.kucheria@linaro.org>
---
 .../devicetree/bindings/thermal/qcom-tsens.txt     |  1 +
 drivers/thermal/qcom/Makefile                      |  2 +-
 drivers/thermal/qcom/tsens-sdm845.c                | 98 ++++++++++++++++++++++
 drivers/thermal/qcom/tsens.c                       |  3 +
 drivers/thermal/qcom/tsens.h                       |  1 +
 5 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 drivers/thermal/qcom/tsens-sdm845.c

diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
index 292ed89..8652499 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -5,6 +5,7 @@ Required properties:
  - "qcom,msm8916-tsens" : For 8916 Family of SoCs
  - "qcom,msm8974-tsens" : For 8974 Family of SoCs
  - "qcom,msm8996-tsens" : For 8996 Family of SoCs
+ - "qcom,sdm845-tsens"  : For SDM845 Family of SoCs
 
 - reg: Address range of the thermal registers
 - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 2cc2193..dc9f169 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_QCOM_TSENS)	+= qcom_tsens.o
-qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o
+qcom_tsens-y			+= tsens.o tsens-common.o tsens-8916.o tsens-8974.o tsens-8960.o tsens-8996.o tsens-sdm845.o
diff --git a/drivers/thermal/qcom/tsens-sdm845.c b/drivers/thermal/qcom/tsens-sdm845.c
new file mode 100644
index 0000000..5d78f0b
--- /dev/null
+++ b/drivers/thermal/qcom/tsens-sdm845.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
+
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include "tsens.h"
+
+#define CNTL_OFFSET	4
+/* CNTL_OFFSET bitmasks */
+#define EN		BIT(0)
+#define SW_RST		BIT(1)
+
+#define SENSOR0_SHIFT	3
+
+#define TRDY_OFFSET     0xe4
+#define TRDY_READY_BIT  BIT(1)
+
+#define STATUS_OFFSET	0xa0
+#define LAST_TEMP_MASK	0xfff
+#define STATUS_VALID_BIT	BIT(21)
+#define CODE_SIGN_BIT		BIT(11)
+
+static int get_temp_sdm845(struct tsens_device *tmdev, int id, int *temp)
+{
+	struct tsens_sensor *s = &tmdev->sensor[id];
+	u32 code;
+	unsigned int sensor_addr;
+	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, ret;
+
+	ret = regmap_read(tmdev->map, TRDY_OFFSET, &code);
+	if (ret)
+		return ret;
+	if (code & TRDY_READY_BIT)
+		return -ENODATA;
+
+	sensor_addr = STATUS_OFFSET + s->hw_id * 4;
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	last_temp = code & LAST_TEMP_MASK;
+	if (code & STATUS_VALID_BIT)
+		goto done;
+
+	/* Try a second time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else {
+		last_temp2 = code & LAST_TEMP_MASK;
+	}
+
+	/* Try a third/last time */
+	ret = regmap_read(tmdev->map, sensor_addr, &code);
+	if (ret)
+		return ret;
+	if (code & STATUS_VALID_BIT) {
+		last_temp = code & LAST_TEMP_MASK;
+		goto done;
+	} else {
+		last_temp3 = code & LAST_TEMP_MASK;
+	}
+
+	if (last_temp == last_temp2)
+		last_temp = last_temp2;
+	else if (last_temp2 == last_temp3)
+		last_temp = last_temp3;
+done:
+	/* Code sign bit is the sign extension for a negative value */
+	if (last_temp & CODE_SIGN_BIT)
+		last_temp |= ~CODE_SIGN_BIT;
+
+	/* Temperatures are in deciCelicius */
+	*temp = last_temp * 100;
+
+	return 0;
+}
+
+static const struct regmap_config tsens_config = {
+	.reg_bits	= 32,
+	.val_bits	= 32,
+	.reg_stride	= 4,
+};
+
+
+static const struct tsens_ops ops_sdm845 = {
+  	.init		= init_common,
+	.get_temp	= get_temp_sdm845,
+};
+
+const struct tsens_data data_sdm845 = {
+	.ops		= &ops_sdm845,
+};
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 3f9fe6a..314a20f 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -72,6 +72,9 @@ static const struct of_device_id tsens_table[] = {
 	}, {
 		.compatible = "qcom,msm8996-tsens",
 		.data = &data_8996,
+	}, {
+		.compatible = "qcom,sdm845-tsens",
+		.data = &data_sdm845,
 	},
 	{}
 };
diff --git a/drivers/thermal/qcom/tsens.h b/drivers/thermal/qcom/tsens.h
index 911c197..f15660d 100644
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -90,5 +90,6 @@ int init_common(struct tsens_device *);
 int get_temp_common(struct tsens_device *, int, int *);
 
 extern const struct tsens_data data_8916, data_8974, data_8960, data_8996;
+extern const struct tsens_data data_sdm845;
 
 #endif /* __QCOM_TSENS_H__ */
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v2 2/2] clk: Add driver for MAX9485
From: Daniel Mack @ 2018-06-02 11:14 UTC (permalink / raw)
  To: Stephen Boyd, mturquette; +Cc: linux-clk, robh, devicetree, Daniel Mack
In-Reply-To: <152792003850.225090.13213694533140196613@swboyd.mtv.corp.google.com>

Hi Stephen,

Thanks for the review!

On Saturday, June 02, 2018 08:13 AM, Stephen Boyd wrote:
> Quoting Daniel Mack (2018-05-25 11:20:58)

>> +enum {
>> +       MAX9485_FS_12KHZ        = 0 << 0,
>> +       MAX9485_FS_32KHZ        = 1 << 0,
>> +       MAX9485_FS_44_1KHZ      = 2 << 0,
>> +       MAX9485_FS_48KHZ        = 3 << 0,
>> +};
>> +
>> +enum {
>> +       MAX9485_SCALE_256       = 0 << 2,
>> +       MAX9485_SCALE_384       = 1 << 2,
>> +       MAX9485_SCALE_768       = 2 << 2,
>> +};
> 
> Any reason to be an enum? Maybe they can just be #defines.

No particular reason, but an enum shows these values are grouped 
together. But I can also turn them into defines, it's just a matter of 
taste I guess.

>> +struct max9485_driver_data {
>> +       struct clk *xclk;
>> +       struct i2c_client *client;
>> +       u8 reg_value;
>> +       unsigned long clkout_rate;
>> +       struct regulator *supply;
>> +       struct gpio_desc *reset_gpio;
>> +       struct max9485_clk_hw hw[MAX9485_NUM_CLKS];
>> +
>> +       struct {
>> +               struct clk_hw_onecell_data data;
>> +               struct clk_hw *hw[MAX9485_NUM_CLKS];
> 
> I don't quite understand this one. There's already an array of clk_hw
> pointers inside of clk_hw_onecell_data so just use that? But then
> there's also an array of max9485_clk_hw structures, so maybe roll your
> own clk_hw getter function?

Ah, yes. The latter makes most sense. I was somehow stuck with the idea 
that the onecell helper makes sense here. Thanks for the heads-up.

>> +static int max9485_update_bits(struct max9485_driver_data *drvdata,
>> +                              u8 mask, u8 value)
>> +{
>> +       int ret;
>> +
>> +       drvdata->reg_value &= ~mask;
>> +       drvdata->reg_value |= value;
>> +
>> +       dev_dbg(&drvdata->client->dev,
>> +               "updating mask %02x value %02x -> %02x\n",
>> +               mask, value, drvdata->reg_value);
>> +
>> +       ret = i2c_master_send(drvdata->client,
>> +                             &drvdata->reg_value,
>> +                             sizeof(drvdata->reg_value));
> 
> Maybe use a regmap instead? Then you could use regmap_update_bits() in
> the places you need it.

I wish, but nope, regmap doesn't work for devices that don't actually 
have registers, like this one. There's no extra byte for a register 
address or such, just one plain byte of payload.

[...]

>> +               return -ENOMEM;
>> +
>> +       drvdata->xclk = devm_clk_get(dev, "xclk");
>> +       if (IS_ERR(drvdata->xclk))
>> +               return PTR_ERR(drvdata->xclk);
>> +
>> +       freq = clk_get_rate(drvdata->xclk);
>> +       if (freq != MAX9485_INPUT_FREQ) {
>> +               dev_err(dev, "Illegal xclk frequency of %ld\n", freq);
>> +               return -EINVAL;
>> +       }
> 
> Is this necessary? Seems pretty useless to do everywhere to make sure
> that someone didn't design the hardware incorrectly. It would be better
> to return the rate of the parent "xclk" by not having a recalc_rate hook
> and relying on the parent's rate.

Hmm, but the hardware doesn't work if the clock is anything else than 
27.0MHz. But I'll remove the check no problem. After all, we don't check 
the regulator voltages either.

I've addressed all other comments. Will resend v3.


Thanks again!
Daniel

^ permalink raw reply

* [PATCH v3 0/2] clk: Add driver for MAX9485
From: Daniel Mack @ 2018-06-02 11:15 UTC (permalink / raw)
  To: mturquette, sboyd; +Cc: linux-clk, robh, devicetree, Daniel Mack

This is v3 of the driver for Maxim's MAX9485 programmable audio clock
generator.

v2 → v3:

* Addressed a lot of issues pointed out by Stephen Boyd:
  * Dropped local register caching
  * Implement own OF clk_hw getter in favor of the onecell helper
  * Implemented recalc_rate() properly by reading from the hardware
  * Dropped input clock frequency validation
  * Style issues

* Fixed a gpio line handling bug in resume
* Added Rob's Revied-by to 1/2

v1 → v2:

* Now served as two patches, one for the DT bits, and one for the actual
  implementation. The DT bits are put in the 1st patch because the
  implementation depends on the shared header file.

* Added support for suspend/resume

Daniel Mack (2):
  dts: clk: add devicetree bindings for MAX9485
  clk: Add driver for MAX9485

 .../devicetree/bindings/clock/maxim,max9485.txt    |  59 +++
 drivers/clk/Kconfig                                |   6 +
 drivers/clk/Makefile                               |   1 +
 drivers/clk/clk-max9485.c                          | 402 +++++++++++++++++++++
 include/dt-bindings/clock/maxim,max9485.h          |  18 +
 5 files changed, 486 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/maxim,max9485.txt
 create mode 100644 drivers/clk/clk-max9485.c
 create mode 100644 include/dt-bindings/clock/maxim,max9485.h

-- 
2.14.3

^ permalink raw reply

* [PATCH v3 1/2] dts: clk: add devicetree bindings for MAX9485
From: Daniel Mack @ 2018-06-02 11:15 UTC (permalink / raw)
  To: mturquette, sboyd; +Cc: linux-clk, robh, devicetree, Daniel Mack
In-Reply-To: <20180602111531.32143-1-daniel@zonque.org>

This patch adds the devicetree bindings for MAX9485, a programmable audio
clock generator.

Signed-off-by: Daniel Mack <daniel@zonque.org>
Reviewed-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/clock/maxim,max9485.txt    | 59 ++++++++++++++++++++++
 include/dt-bindings/clock/maxim,max9485.h          | 18 +++++++
 2 files changed, 77 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/maxim,max9485.txt
 create mode 100644 include/dt-bindings/clock/maxim,max9485.h

diff --git a/Documentation/devicetree/bindings/clock/maxim,max9485.txt b/Documentation/devicetree/bindings/clock/maxim,max9485.txt
new file mode 100644
index 000000000000..61bec1100a94
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/maxim,max9485.txt
@@ -0,0 +1,59 @@
+Devicetree bindings for Maxim MAX9485 Programmable Audio Clock Generator
+
+This device exposes 4 clocks in total:
+
+- MAX9485_MCLKOUT: 	A gated, buffered output of the input clock of 27 MHz
+- MAX9485_CLKOUT:	A PLL that can be configured to 16 different discrete
+			frequencies
+- MAX9485_CLKOUT[1,2]:	Two gated outputs for MAX9485_CLKOUT
+
+MAX9485_CLKOUT[1,2] are children of MAX9485_CLKOUT which upchain all rate set
+requests.
+
+Required properties:
+- compatible:	"maxim,max9485"
+- clocks:	Input clock, must provice 27.000 MHz
+- clock-names:	Must be set to "xclk"
+- #clock-cells: From common clock binding; shall be set to 1
+
+Optional properties:
+- reset-gpios:		GPIO descriptor connected to the #RESET input pin
+- vdd-supply:		A regulator node for Vdd
+- clock-output-names:	Name of output clocks, as defined in common clock
+			bindings
+
+If not explicitly set, the output names are "mclkout", "clkout", "clkout1"
+and "clkout2".
+
+Clocks are defined as preprocessor macros in the dt-binding header.
+
+Example:
+
+	#include <dt-bindings/clock/maxim,max9485.h>
+
+	xo-27mhz: xo-27mhz {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <27000000>;
+	};
+
+	&i2c0 {
+		max9485: audio-clock@63 {
+			reg = <0x63>;
+			compatible = "maxim,max9485";
+			clock-names = "xclk";
+			clocks = <&xo-27mhz>;
+			reset-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>;
+			vdd-supply = <&3v3-reg>;
+			#clock-cells = <1>;
+		};
+	};
+
+	// Clock consumer node
+
+	foo@0 {
+		compatible = "bar,foo";
+		/* ... */
+		clock-names = "foo-input-clk";
+		clocks = <&max9485 MAX9485_CLKOUT1>;
+	};
diff --git a/include/dt-bindings/clock/maxim,max9485.h b/include/dt-bindings/clock/maxim,max9485.h
new file mode 100644
index 000000000000..185b09ce1869
--- /dev/null
+++ b/include/dt-bindings/clock/maxim,max9485.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2018 Daniel Mack
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DT_BINDINGS_MAX9485_CLK_H
+#define __DT_BINDINGS_MAX9485_CLK_H
+
+#define MAX9485_MCLKOUT	0
+#define MAX9485_CLKOUT	1
+#define MAX9485_CLKOUT1	2
+#define MAX9485_CLKOUT2	3
+
+#endif /* __DT_BINDINGS_MAX9485_CLK_H */
-- 
2.14.3

^ permalink raw reply related

* [PATCH v3 2/2] clk: Add driver for MAX9485
From: Daniel Mack @ 2018-06-02 11:15 UTC (permalink / raw)
  To: mturquette, sboyd; +Cc: linux-clk, robh, devicetree, Daniel Mack
In-Reply-To: <20180602111531.32143-1-daniel@zonque.org>

This patch adds a driver for MAX9485, a programmable audio clock generator.

The device requires a 27.000 MHz clock input. It can provide a gated
buffered output of its input clock and two gated outputs of a PLL that can
generate one out of 16 discrete frequencies. There is only one PLL however,
so the two gated outputs will always have the same frequency but they can
be switched individually.

The driver for this device exposes 4 clocks in total:

- MAX9485_MCLKOUT:      A gated, buffered output of the input clock
- MAX9485_CLKOUT:       A PLL that can be configured to 16 different
			discrete frequencies
- MAX9485_CLKOUT[1,2]:  Two gated outputs for MAX9485_CLKOUT

Some PLL output frequencies can be achieved with different register
settings. The driver will select the one with lowest jitter in such cases.

Signed-off-by: Daniel Mack <daniel@zonque.org>
---
 drivers/clk/Kconfig       |   6 +
 drivers/clk/Makefile      |   1 +
 drivers/clk/clk-max9485.c | 402 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 409 insertions(+)
 create mode 100644 drivers/clk/clk-max9485.c

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 34968a381d0f..0f85eb7386ad 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -45,6 +45,12 @@ config COMMON_CLK_MAX77686
 	  This driver supports Maxim 77620/77686/77802 crystal oscillator
 	  clock.
 
+config COMMON_CLK_MAX9485
+	tristate "Clock driver for Maxim 9485 Programmable Clock Generator"
+	depends on I2C
+	---help---
+	  This driver supports Maxim 9485 Programmable Audio Clock Generator
+
 config COMMON_CLK_RK808
 	tristate "Clock driver for RK805/RK808/RK818"
 	depends on MFD_RK808
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index de6d06ac790b..27417ba3c1df 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -31,6 +31,7 @@ obj-$(CONFIG_COMMON_CLK_ASPEED)		+= clk-aspeed.o
 obj-$(CONFIG_ARCH_HIGHBANK)		+= clk-highbank.o
 obj-$(CONFIG_CLK_HSDK)			+= clk-hsdk-pll.o
 obj-$(CONFIG_COMMON_CLK_MAX77686)	+= clk-max77686.o
+obj-$(CONFIG_COMMON_CLK_MAX9485)	+= clk-max9485.o
 obj-$(CONFIG_ARCH_MOXART)		+= clk-moxart.o
 obj-$(CONFIG_ARCH_NOMADIK)		+= clk-nomadik.o
 obj-$(CONFIG_ARCH_NSPIRE)		+= clk-nspire.o
diff --git a/drivers/clk/clk-max9485.c b/drivers/clk/clk-max9485.c
new file mode 100644
index 000000000000..4bae7deeda10
--- /dev/null
+++ b/drivers/clk/clk-max9485.c
@@ -0,0 +1,402 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * clk-max9485.c: MAX9485 Programmable Audio Clock Generator
+ *
+ * (c) 2018 Daniel Mack <daniel@zonque.org>
+ *
+ * References:
+ *   MAX9485 Datasheet
+ *     http://www.maximintegrated.com/datasheet/index.mvp/id/4421
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/regulator/consumer.h>
+
+#include <dt-bindings/clock/maxim,max9485.h>
+
+#define MAX9485_NUM_CLKS 4
+
+/* This chip has only one register of 8 bit width. */
+
+#define MAX9485_FS_12KHZ	(0 << 0)
+#define MAX9485_FS_32KHZ	(1 << 0)
+#define MAX9485_FS_44_1KHZ	(2 << 0)
+#define MAX9485_FS_48KHZ	(3 << 0)
+
+#define MAX9485_SCALE_256	(0 << 2)
+#define MAX9485_SCALE_384	(1 << 2)
+#define MAX9485_SCALE_768	(2 << 2)
+
+#define MAX9485_DOUBLE		BIT(4)
+#define MAX9485_CLKOUT1_ENABLE	BIT(5)
+#define MAX9485_CLKOUT2_ENABLE	BIT(6)
+#define MAX9485_MCLK_ENABLE	BIT(7)
+#define MAX9485_FREQ_MASK	0x1f
+
+struct max9485_rate {
+	unsigned long out;
+	u8 reg_value;
+};
+
+/*
+ * Ordered by frequency. For frequency the hardware can generate with
+ * multiple settings, the one with lowest jitter is listed first.
+ */
+static const struct max9485_rate max9485_rates[] = {
+	{  3072000, MAX9485_FS_12KHZ   | MAX9485_SCALE_256 },
+	{  4608000, MAX9485_FS_12KHZ   | MAX9485_SCALE_384 },
+	{  8192000, MAX9485_FS_32KHZ   | MAX9485_SCALE_256 },
+	{  9126000, MAX9485_FS_12KHZ   | MAX9485_SCALE_768 },
+	{ 11289600, MAX9485_FS_44_1KHZ | MAX9485_SCALE_256 },
+	{ 12288000, MAX9485_FS_48KHZ   | MAX9485_SCALE_256 },
+	{ 12288000, MAX9485_FS_32KHZ   | MAX9485_SCALE_384 },
+	{ 16384000, MAX9485_FS_32KHZ   | MAX9485_SCALE_256 | MAX9485_DOUBLE },
+	{ 16934400, MAX9485_FS_44_1KHZ | MAX9485_SCALE_384 },
+	{ 18384000, MAX9485_FS_48KHZ   | MAX9485_SCALE_384 },
+	{ 22579200, MAX9485_FS_44_1KHZ | MAX9485_SCALE_256 | MAX9485_DOUBLE },
+	{ 24576000, MAX9485_FS_48KHZ   | MAX9485_SCALE_256 | MAX9485_DOUBLE },
+	{ 24576000, MAX9485_FS_32KHZ   | MAX9485_SCALE_384 | MAX9485_DOUBLE },
+	{ 24576000, MAX9485_FS_32KHZ   | MAX9485_SCALE_768 },
+	{ 33868800, MAX9485_FS_44_1KHZ | MAX9485_SCALE_384 | MAX9485_DOUBLE },
+	{ 33868800, MAX9485_FS_44_1KHZ | MAX9485_SCALE_768 },
+	{ 36864000, MAX9485_FS_48KHZ   | MAX9485_SCALE_384 | MAX9485_DOUBLE },
+	{ 36864000, MAX9485_FS_48KHZ   | MAX9485_SCALE_768 },
+	{ 49152000, MAX9485_FS_32KHZ   | MAX9485_SCALE_768 | MAX9485_DOUBLE },
+	{ 67737600, MAX9485_FS_44_1KHZ | MAX9485_SCALE_768 | MAX9485_DOUBLE },
+	{ 73728000, MAX9485_FS_48KHZ   | MAX9485_SCALE_768 | MAX9485_DOUBLE },
+	{ } /* sentinel */
+};
+
+struct max9485_driver_data;
+
+struct max9485_clk_hw {
+	struct clk_hw hw;
+	struct clk_init_data init;
+	u8 enable_bit;
+	struct max9485_driver_data *drvdata;
+};
+
+struct max9485_driver_data {
+	struct clk *xclk;
+	struct i2c_client *client;
+	u8 reg_value;
+	struct regulator *supply;
+	struct gpio_desc *reset_gpio;
+	struct max9485_clk_hw hw[MAX9485_NUM_CLKS];
+};
+
+static inline struct max9485_clk_hw *to_max9485_clk(struct clk_hw *hw)
+{
+	return container_of(hw, struct max9485_clk_hw, hw);
+}
+
+static int max9485_update_bits(struct max9485_driver_data *drvdata,
+			       u8 mask, u8 value)
+{
+	int ret;
+
+	drvdata->reg_value &= ~mask;
+	drvdata->reg_value |= value;
+
+	dev_dbg(&drvdata->client->dev,
+		"updating mask %02x value %02x -> %02x\n",
+		mask, value, drvdata->reg_value);
+
+	ret = i2c_master_send(drvdata->client,
+			      &drvdata->reg_value,
+			      sizeof(drvdata->reg_value));
+
+	return ret < 0 ? ret : 0;
+}
+
+static int max9485_clk_prepare(struct clk_hw *hw)
+{
+	struct max9485_clk_hw *clk_hw = to_max9485_clk(hw);
+
+	return max9485_update_bits(clk_hw->drvdata,
+				   clk_hw->enable_bit,
+				   clk_hw->enable_bit);
+}
+
+static void max9485_clk_unprepare(struct clk_hw *hw)
+{
+	struct max9485_clk_hw *clk_hw = to_max9485_clk(hw);
+
+	max9485_update_bits(clk_hw->drvdata, clk_hw->enable_bit, 0);
+}
+
+/*
+ * CLKOUT - configurable clock output
+ */
+static int max9485_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct max9485_clk_hw *clk_hw = to_max9485_clk(hw);
+	const struct max9485_rate *entry;
+
+	for (entry = max9485_rates; entry->out != 0; entry++)
+		if (entry->out == rate)
+			break;
+
+	if (entry->out == 0)
+		return -EINVAL;
+
+	return max9485_update_bits(clk_hw->drvdata,
+				   MAX9485_FREQ_MASK,
+				   entry->reg_value);
+}
+
+static unsigned long max9485_clkout_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct max9485_clk_hw *clk_hw = to_max9485_clk(hw);
+	struct max9485_driver_data *drvdata = clk_hw->drvdata;
+	const struct max9485_rate *entry;
+	int ret;
+
+	ret = i2c_master_recv(drvdata->client,
+			      &drvdata->reg_value,
+			      sizeof(drvdata->reg_value));
+	if (ret < 0) {
+		dev_warn(&drvdata->client->dev,
+			 "Unable to read register: %d\n", ret);
+		return 0;
+	}
+
+	for (entry = max9485_rates; entry->out != 0; entry++)
+		if ((drvdata->reg_value & MAX9485_FREQ_MASK) == entry->reg_value)
+			return entry->out;
+
+	return 0;
+}
+
+static long max9485_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
+				      unsigned long *parent_rate)
+{
+	const struct max9485_rate *curr, *prev = NULL;
+
+	for (curr = max9485_rates; curr->out != 0; curr++) {
+		/* Exact matches */
+		if (curr->out == rate)
+			return rate;
+
+		/*
+		 * Find the first entry that has a frequency higher than the
+		 * requested one.
+		 */
+		if (curr->out > rate) {
+			unsigned int mid;
+
+			/*
+			 * If this is the first entry, clamp the value to the
+			 * lowest possible frequency.
+			 */
+			if (!prev)
+				return curr->out;
+
+			/*
+			 * Otherwise, determine whether the previous entry or
+			 * current one is closer.
+			 */
+			mid = prev->out + ((curr->out - prev->out) / 2);
+
+			return (mid > rate) ? prev->out : curr->out;
+		}
+
+		prev = curr;
+	}
+
+	/* If the last entry was still too high, clamp the value */
+	return prev->out;
+}
+
+struct max9485_clk {
+	const char *name;
+	int parent_index;
+	const struct clk_ops ops;
+	u8 enable_bit;
+};
+
+static const struct max9485_clk max9485_clks[MAX9485_NUM_CLKS] = {
+	[MAX9485_MCLKOUT] = {
+		.name = "mclkout",
+		.parent_index = -1,
+		.enable_bit = MAX9485_MCLK_ENABLE,
+		.ops = {
+			.prepare	= max9485_clk_prepare,
+			.unprepare	= max9485_clk_unprepare,
+		},
+	},
+	[MAX9485_CLKOUT] = {
+		.name = "clkout",
+		.parent_index = -1,
+		.ops = {
+			.set_rate	= max9485_clkout_set_rate,
+			.round_rate	= max9485_clkout_round_rate,
+			.recalc_rate	= max9485_clkout_recalc_rate,
+		},
+	},
+	[MAX9485_CLKOUT1] = {
+		.name = "clkout1",
+		.parent_index = MAX9485_CLKOUT,
+		.enable_bit = MAX9485_CLKOUT1_ENABLE,
+		.ops = {
+			.prepare	= max9485_clk_prepare,
+			.unprepare	= max9485_clk_unprepare,
+		},
+	},
+	[MAX9485_CLKOUT2] = {
+		.name = "clkout2",
+		.parent_index = MAX9485_CLKOUT,
+		.enable_bit = MAX9485_CLKOUT2_ENABLE,
+		.ops = {
+			.prepare	= max9485_clk_prepare,
+			.unprepare	= max9485_clk_unprepare,
+		},
+	},
+};
+
+static struct clk_hw *max9485_of_clk_get(struct of_phandle_args *clkspec, void *data)
+{
+	struct max9485_driver_data *drvdata = data;
+	unsigned int idx = clkspec->args[0];
+
+	return &drvdata->hw[idx].hw;
+}
+
+static int max9485_i2c_probe(struct i2c_client *client,
+			     const struct i2c_device_id *id)
+{
+	struct max9485_driver_data *drvdata;
+	struct device *dev = &client->dev;
+	const char *xclk_name;
+	int i, ret;
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	drvdata->xclk = devm_clk_get(dev, "xclk");
+	if (IS_ERR(drvdata->xclk))
+		return PTR_ERR(drvdata->xclk);
+
+	xclk_name = __clk_get_name(drvdata->xclk);
+
+	drvdata->supply = devm_regulator_get(dev, "vdd");
+	if (IS_ERR(drvdata->supply))
+		return PTR_ERR(drvdata->supply);
+
+	ret = regulator_enable(drvdata->supply);
+	if (ret < 0)
+		return ret;
+
+	drvdata->reset_gpio =
+		devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+	if (IS_ERR(drvdata->reset_gpio))
+		return PTR_ERR(drvdata->reset_gpio);
+
+	i2c_set_clientdata(client, drvdata);
+	drvdata->client = client;
+
+	for (i = 0; i < MAX9485_NUM_CLKS; i++) {
+		int parent_index = max9485_clks[i].parent_index;
+		const char *name;
+
+		if (of_property_read_string_index(dev->of_node,
+						  "clock-output-names",
+						  i, &name) == 0) {
+			drvdata->hw[i].init.name = name;
+		} else {
+			drvdata->hw[i].init.name = max9485_clks[i].name;
+		}
+
+		drvdata->hw[i].init.ops = &max9485_clks[i].ops;
+		drvdata->hw[i].init.num_parents = 1;
+		drvdata->hw[i].init.flags = 0;
+
+		if (parent_index > 0) {
+			drvdata->hw[i].init.parent_names =
+				&drvdata->hw[parent_index].init.name;
+			drvdata->hw[i].init.flags |= CLK_SET_RATE_PARENT;
+		} else {
+			drvdata->hw[i].init.parent_names = &xclk_name;
+		}
+
+		drvdata->hw[i].enable_bit = max9485_clks[i].enable_bit;
+		drvdata->hw[i].hw.init = &drvdata->hw[i].init;
+		drvdata->hw[i].drvdata = drvdata;
+
+		ret = devm_clk_hw_register(dev, &drvdata->hw[i].hw);
+		if (ret < 0)
+			return ret;
+	}
+
+	return devm_of_clk_add_hw_provider(dev, max9485_of_clk_get, drvdata);
+}
+
+static int __maybe_unused max9485_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max9485_driver_data *drvdata = i2c_get_clientdata(client);
+
+	gpiod_set_value_cansleep(drvdata->reset_gpio, 0);
+
+	return 0;
+}
+
+static int __maybe_unused max9485_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max9485_driver_data *drvdata = i2c_get_clientdata(client);
+	int ret;
+
+	gpiod_set_value_cansleep(drvdata->reset_gpio, 1);
+
+	ret = i2c_master_send(client, &drvdata->reg_value,
+			      sizeof(drvdata->reg_value));
+
+	return ret < 0 ? ret : 0;
+}
+
+static const struct dev_pm_ops max9485_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(max9485_suspend, max9485_resume)
+};
+
+static const struct of_device_id max9485_dt_ids[] = {
+	{ .compatible = "maxim,max9485", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, max9485_dt_ids);
+
+static const struct i2c_device_id max9485_i2c_ids[] = {
+	{ .name = "max9485", },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max9485_i2c_ids);
+
+static struct i2c_driver max9485_driver = {
+	.driver = {
+		.name		= "max9485",
+		.pm		= &max9485_pm_ops,
+		.of_match_table	= max9485_dt_ids,
+	},
+	.probe = max9485_i2c_probe,
+	.id_table = max9485_i2c_ids,
+};
+module_i2c_driver(max9485_driver);
+
+MODULE_AUTHOR("Daniel Mack <daniel@zonque.org>");
+MODULE_DESCRIPTION("MAX9485 Programmable Audio Clock Generator");
+MODULE_LICENSE("GPL v2");
-- 
2.14.3

^ permalink raw reply related

* Re: [PATCH v2 5/5] arm64: dts: renesas: r8a7795: add ccree binding
From: Simon Horman @ 2018-06-02 13:12 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Gilad Ben-Yossef, Magnus Damm, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon, Geert Uytterhoeven,
	Michael Turquette, Stephen Boyd, Herbert Xu, David S. Miller,
	Ofir Drang, Linux-Renesas,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux ARM, Linux kernel mailing list, linux-clk
In-Reply-To: <CAMuHMdUX874g6pAz-Ze-yA3S+6aOhzUkfGN9wmQUhy-y0f7dMw@mail.gmail.com>

On Fri, Jun 01, 2018 at 10:12:24AM +0200, Geert Uytterhoeven wrote:
> Hi Gilad,
> 
> On Thu, May 31, 2018 at 1:55 PM, Gilad Ben-Yossef <gilad@benyossef.com> wrote:
> > On Tue, May 29, 2018 at 7:19 PM, Simon Horman <horms@verge.net.au> wrote:
> >> On Thu, May 24, 2018 at 03:19:10PM +0100, Gilad Ben-Yossef wrote:
> >>> Add bindings for CryptoCell instance in the SoC.
> >>>
> >>> Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
> >>
> >> In so far as I can review the details of this (which is not much) this
> >> looks fine to me. I am, however, a little unclear in when it should be
> >> accepted.
> >
> > Since Herbert Xu ACKed the driver changes, I would say the only gating
> > commit is Geert's CR clock patch.
> 
> These are queued for v4.19.
> 
> > If that one is in, than I would say this one should go in as well.
> 
> As the device node now has a power-domains property, the genpd code will
> try to attach it to the CPG/MSSR PM Domain, which is a clock domain.
> In the absence of the clock patch, the device's module clock cannot be
> found, and dev_pm_domain_attach() and thus platform_drv_probe() will fail,
> before calling the device driver's .probe() function.
> 
> So there is no longer a dependency on the clock patch, and the DT patch can
> go in in parallel (although I prefer its subject to be changed
> s/binding/device device/).

Thanks, I have applied the following (but may not push until next week).

From: Gilad Ben-Yossef <gilad@benyossef.com>
Subject: [PATCH] arm64: dts: renesas: r8a7795: add ccree to device tree

Add bindings for CryptoCell instance in the SoC.

Signed-off-by: Gilad Ben-Yossef <gilad@benyossef.com>
Reviewed-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
---
 arch/arm64/boot/dts/renesas/r8a7795.dtsi | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index d842940b2f43..3ac75dbf2d93 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -528,6 +528,15 @@
 			status = "disabled";
 		};
 
+		arm_cc630p: crypto@e6601000 {
+			compatible = "arm,cryptocell-630p-ree";
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			reg = <0x0 0xe6601000 0 0x1000>;
+			clocks = <&cpg CPG_MOD 229>;
+			resets = <&cpg 229>;
+			power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+		};
+
 		i2c3: i2c@e66d0000 {
 			#address-cells = <1>;
 			#size-cells = <0>;
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH 1/2] clk: imx6ul: add GPIO clock gates
From: Fabio Estevam @ 2018-06-02 13:48 UTC (permalink / raw)
  To: Stefan Wahren
  Cc: Michael Trimarchi, Rob Herring, Fabio Estevam, Mark Rutland,
	Anson Huang, Matteo Lisi, Shawn Guo, Sascha Hauer,
	Michael Turquette, Stephen Boyd, linux-clk, NXP Linux Team,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <1439344955.9677.1526991935718@email.1und1.de>

Hi Stefan,

On Tue, May 22, 2018 at 9:25 AM, Stefan Wahren <stefan.wahren@i2se.com> wrote:

>> --- a/include/dt-bindings/clock/imx6ul-clock.h
>> +++ b/include/dt-bindings/clock/imx6ul-clock.h
>> @@ -242,20 +242,25 @@
>>  #define IMX6UL_CLK_CKO2_PODF         229
>>  #define IMX6UL_CLK_CKO2                      230
>>  #define IMX6UL_CLK_CKO                       231
>> +#define IMX6UL_CLK_GPIO1             232
>> +#define IMX6UL_CLK_GPIO2             233
>> +#define IMX6UL_CLK_GPIO3             234
>> +#define IMX6UL_CLK_GPIO4             235
>> +#define IMX6UL_CLK_GPIO5             236
>
> this change looks like a breakage of devicetree ABI. You are changing the mean of the existing clock IDs on i.MX6ULL, which probably regress the combination of older DTBs with newer kernel.

Good point! I will send a fix for f5a4670de96678 ("clk: imx: Add new
clo01 and clo2 controlled
by CCOSR") which did the same reordering.

Thanks

^ permalink raw reply

* [PATCH] dt-bindings: clock: imx6ul: Do not change the clock definition order
From: Fabio Estevam @ 2018-06-02 13:53 UTC (permalink / raw)
  To: sboyd
  Cc: michael, stefan.wahren, robh+dt, devicetree, linux-clk,
	anson.huang, stefan, Fabio Estevam

From: Fabio Estevam <fabio.estevam@nxp.com>

Commit f5a4670de96678 ("clk: imx: Add new clo01 and clo2 controlled
by CCOSR") introduced the CLK_CLKO definitions, but didn't put them
at the end of the list, which may cause dtb breakage when running an old
dtb with a newer kernel.

In order to avoid that, simply add the new CLK_CKO clock definitions
at the end of the list.

Fixes: f5a4670de96678 ("clk: imx: Add new clo01 and clo2 controlled by CCOSR")
Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
 include/dt-bindings/clock/imx6ul-clock.h | 40 +++++++++++++++-----------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
index 9564597..0aa1d9c 100644
--- a/include/dt-bindings/clock/imx6ul-clock.h
+++ b/include/dt-bindings/clock/imx6ul-clock.h
@@ -235,27 +235,25 @@
 #define IMX6UL_CLK_CSI_PODF		222
 #define IMX6UL_CLK_PLL3_120M		223
 #define IMX6UL_CLK_KPP			224
-#define IMX6UL_CLK_CKO1_SEL		225
-#define IMX6UL_CLK_CKO1_PODF		226
-#define IMX6UL_CLK_CKO1			227
-#define IMX6UL_CLK_CKO2_SEL		228
-#define IMX6UL_CLK_CKO2_PODF		229
-#define IMX6UL_CLK_CKO2			230
-#define IMX6UL_CLK_CKO			231
-
-/* For i.MX6ULL */
-#define IMX6ULL_CLK_ESAI_PRED		232
-#define IMX6ULL_CLK_ESAI_PODF		233
-#define IMX6ULL_CLK_ESAI_EXTAL		234
-#define IMX6ULL_CLK_ESAI_MEM		235
-#define IMX6ULL_CLK_ESAI_IPG		236
-#define IMX6ULL_CLK_DCP_CLK		237
-#define IMX6ULL_CLK_EPDC_PRE_SEL	238
-#define IMX6ULL_CLK_EPDC_SEL		239
-#define IMX6ULL_CLK_EPDC_PODF		240
-#define IMX6ULL_CLK_EPDC_ACLK		241
-#define IMX6ULL_CLK_EPDC_PIX		242
-#define IMX6ULL_CLK_ESAI_SEL		243
+#define IMX6ULL_CLK_ESAI_PRED		225
+#define IMX6ULL_CLK_ESAI_PODF		226
+#define IMX6ULL_CLK_ESAI_EXTAL		227
+#define IMX6ULL_CLK_ESAI_MEM		228
+#define IMX6ULL_CLK_ESAI_IPG		229
+#define IMX6ULL_CLK_DCP_CLK		230
+#define IMX6ULL_CLK_EPDC_PRE_SEL	231
+#define IMX6ULL_CLK_EPDC_SEL		232
+#define IMX6ULL_CLK_EPDC_PODF		233
+#define IMX6ULL_CLK_EPDC_ACLK		234
+#define IMX6ULL_CLK_EPDC_PIX		235
+#define IMX6ULL_CLK_ESAI_SEL		236
+#define IMX6UL_CLK_CKO1_SEL		237
+#define IMX6UL_CLK_CKO1_PODF		238
+#define IMX6UL_CLK_CKO1			239
+#define IMX6UL_CLK_CKO2_SEL		240
+#define IMX6UL_CLK_CKO2_PODF		241
+#define IMX6UL_CLK_CKO2			242
+#define IMX6UL_CLK_CKO			243
 #define IMX6UL_CLK_END			244
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
-- 
2.7.4

^ permalink raw reply related

* [PATCH v2] dt-bindings: clock: imx6ul: Do not change the clock definition order
From: Fabio Estevam @ 2018-06-02 14:02 UTC (permalink / raw)
  To: sboyd
  Cc: michael, stefan.wahren, robh+dt, devicetree, linux-clk,
	anson.huang, stefan, Fabio Estevam

From: Fabio Estevam <fabio.estevam@nxp.com>

Commit f5a4670de966 ("clk: imx: Add new clo01 and clo2 controlled
by CCOSR") introduced the CLK_CLKO definitions, but didn't put them
at the end of the list, which may cause dtb breakage when running an old
dtb with a newer kernel.

In order to avoid that, simply add the new CLK_CKO clock definitions
at the end of the list.

Fixes: f5a4670de966 ("clk: imx: Add new clo01 and clo2 controlled by CCOSR")
Reported-by: Stefan Wahren <stefan.wahren@i2se.com>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
Changes since v1:
- Use 12 char for the commit id

 include/dt-bindings/clock/imx6ul-clock.h | 40 +++++++++++++++-----------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/include/dt-bindings/clock/imx6ul-clock.h b/include/dt-bindings/clock/imx6ul-clock.h
index 9564597..0aa1d9c 100644
--- a/include/dt-bindings/clock/imx6ul-clock.h
+++ b/include/dt-bindings/clock/imx6ul-clock.h
@@ -235,27 +235,25 @@
 #define IMX6UL_CLK_CSI_PODF		222
 #define IMX6UL_CLK_PLL3_120M		223
 #define IMX6UL_CLK_KPP			224
-#define IMX6UL_CLK_CKO1_SEL		225
-#define IMX6UL_CLK_CKO1_PODF		226
-#define IMX6UL_CLK_CKO1			227
-#define IMX6UL_CLK_CKO2_SEL		228
-#define IMX6UL_CLK_CKO2_PODF		229
-#define IMX6UL_CLK_CKO2			230
-#define IMX6UL_CLK_CKO			231
-
-/* For i.MX6ULL */
-#define IMX6ULL_CLK_ESAI_PRED		232
-#define IMX6ULL_CLK_ESAI_PODF		233
-#define IMX6ULL_CLK_ESAI_EXTAL		234
-#define IMX6ULL_CLK_ESAI_MEM		235
-#define IMX6ULL_CLK_ESAI_IPG		236
-#define IMX6ULL_CLK_DCP_CLK		237
-#define IMX6ULL_CLK_EPDC_PRE_SEL	238
-#define IMX6ULL_CLK_EPDC_SEL		239
-#define IMX6ULL_CLK_EPDC_PODF		240
-#define IMX6ULL_CLK_EPDC_ACLK		241
-#define IMX6ULL_CLK_EPDC_PIX		242
-#define IMX6ULL_CLK_ESAI_SEL		243
+#define IMX6ULL_CLK_ESAI_PRED		225
+#define IMX6ULL_CLK_ESAI_PODF		226
+#define IMX6ULL_CLK_ESAI_EXTAL		227
+#define IMX6ULL_CLK_ESAI_MEM		228
+#define IMX6ULL_CLK_ESAI_IPG		229
+#define IMX6ULL_CLK_DCP_CLK		230
+#define IMX6ULL_CLK_EPDC_PRE_SEL	231
+#define IMX6ULL_CLK_EPDC_SEL		232
+#define IMX6ULL_CLK_EPDC_PODF		233
+#define IMX6ULL_CLK_EPDC_ACLK		234
+#define IMX6ULL_CLK_EPDC_PIX		235
+#define IMX6ULL_CLK_ESAI_SEL		236
+#define IMX6UL_CLK_CKO1_SEL		237
+#define IMX6UL_CLK_CKO1_PODF		238
+#define IMX6UL_CLK_CKO1			239
+#define IMX6UL_CLK_CKO2_SEL		240
+#define IMX6UL_CLK_CKO2_PODF		241
+#define IMX6UL_CLK_CKO2			242
+#define IMX6UL_CLK_CKO			243
 #define IMX6UL_CLK_END			244
 
 #endif /* __DT_BINDINGS_CLOCK_IMX6UL_H */
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH 1/2] clk: imx6ul: add GPIO clock gates
From: Michael Nazzareno Trimarchi @ 2018-06-02 14:04 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Stefan Wahren, Rob Herring, Fabio Estevam, Mark Rutland,
	Anson Huang, Matteo Lisi, Shawn Guo, Sascha Hauer,
	Michael Turquette, Stephen Boyd, linux-clk, NXP Linux Team,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAOMZO5BVhjwGpJ22qBihKcjWyvBkzNPU0cNtNY9HToLLEkYByA@mail.gmail.com>

Hi

On Sat, Jun 2, 2018 at 3:48 PM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Stefan,
>
> On Tue, May 22, 2018 at 9:25 AM, Stefan Wahren <stefan.wahren@i2se.com> wrote:
>
>>> --- a/include/dt-bindings/clock/imx6ul-clock.h
>>> +++ b/include/dt-bindings/clock/imx6ul-clock.h
>>> @@ -242,20 +242,25 @@
>>>  #define IMX6UL_CLK_CKO2_PODF         229
>>>  #define IMX6UL_CLK_CKO2                      230
>>>  #define IMX6UL_CLK_CKO                       231
>>> +#define IMX6UL_CLK_GPIO1             232
>>> +#define IMX6UL_CLK_GPIO2             233
>>> +#define IMX6UL_CLK_GPIO3             234
>>> +#define IMX6UL_CLK_GPIO4             235
>>> +#define IMX6UL_CLK_GPIO5             236
>>
>> this change looks like a breakage of devicetree ABI. You are changing the mean of the existing clock IDs on i.MX6ULL, which probably regress the combination of older DTBs with newer kernel.
>
> Good point! I will send a fix for f5a4670de96678 ("clk: imx: Add new
> clo01 and clo2 controlled
> by CCOSR") which did the same reordering.
>

ull is a preatty new platform so one board was listed. Are you sure
that we need?

Michael

> Thanks



-- 
| Michael Nazzareno Trimarchi                     Amarula Solutions BV |
| COO  -  Founder                                      Cruquiuskade 47 |
| +31(0)851119172                                 Amsterdam 1018 AM NL |
|                  [`as] http://www.amarulasolutions.com               |

^ permalink raw reply

* Re: [PATCH 1/2] clk: imx6ul: add GPIO clock gates
From: Fabio Estevam @ 2018-06-02 14:07 UTC (permalink / raw)
  To: Michael Nazzareno Trimarchi
  Cc: Stefan Wahren, Rob Herring, Fabio Estevam, Mark Rutland,
	Anson Huang, Matteo Lisi, Shawn Guo, Sascha Hauer,
	Michael Turquette, Stephen Boyd, linux-clk, NXP Linux Team,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAOf5uwneWyjNpD-tGGL7CgL2_jJFvDtzbi+NBg7wqGMGR4qGCw@mail.gmail.com>

Hi Michael,

On Sat, Jun 2, 2018 at 11:04 AM, Michael Nazzareno Trimarchi
<michael@amarulasolutions.com> wrote:

> ull is a preatty new platform so one board was listed. Are you sure
> that we need?

There are several imx6ul based dts in mainline and it is better if we
can avoid dtb breakage when possible.

In this case we can avoid the dtb breakage by adding the new clock
definitions at the end of the file, just like we do for all the other
imx devices.

^ permalink raw reply

* Re: [PATCH 1/2] clk: imx6ul: add GPIO clock gates
From: Michael Nazzareno Trimarchi @ 2018-06-02 14:12 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: Stefan Wahren, Rob Herring, Fabio Estevam, Mark Rutland,
	Anson Huang, Matteo Lisi, Shawn Guo, Sascha Hauer,
	Michael Turquette, Stephen Boyd, linux-clk, NXP Linux Team,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-kernel,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <CAOMZO5DfpwEDrBrMaTCt1_2Kkkm_tuVLE2WMy5z2=iO_rRFVEg@mail.gmail.com>

Hi Fabio

On Sat, Jun 2, 2018 at 4:07 PM, Fabio Estevam <festevam@gmail.com> wrote:
> Hi Michael,
>
> On Sat, Jun 2, 2018 at 11:04 AM, Michael Nazzareno Trimarchi
> <michael@amarulasolutions.com> wrote:
>
>> ull is a preatty new platform so one board was listed. Are you sure
>> that we need?
>
> There are several imx6ul based dts in mainline and it is better if we
> can avoid dtb breakage when possible.
>
> In this case we can avoid the dtb breakage by adding the new clock
> definitions at the end of the file, just like we do for all the other
> imx devices.

Yes, when I add new ul clock I move down ull (that is new), but agree
that this is not possible in general.

Michael

^ permalink raw reply

* Re: [PATCH] ARM: dts: exynos: Add missing CPU clocks to secondary CPUs on Exynos542x
From: Alim Akhtar @ 2018-06-02 15:39 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Rob Herring, Mark Rutland, Kukjin Kim, Marek Szyprowski,
	Viresh Kumar, devicetree, linux-arm-kernel, linux-samsung-soc,
	linux-kernel
In-Reply-To: <20180530164922.31851-1-krzk@kernel.org>

Hi Krzysztof,

On Wed, May 30, 2018 at 10:19 PM, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> Secondary CPUs should have the same information in DeviceTree as booting
> CPU from both correctness point of view and for possible hotplug
> scenarios.
>
> Suggested-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
> ---
>  arch/arm/boot/dts/exynos5420-cpus.dtsi | 6 ++++++
>  arch/arm/boot/dts/exynos5422-cpus.dtsi | 8 +++++++-
>  2 files changed, 13 insertions(+), 1 deletion(-)

Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>

Tested on exynos5800 peach-pi, so feel free to add

Tested-by: Alim Akhtar <alim.akhtar@samsung.com>

>
> diff --git a/arch/arm/boot/dts/exynos5420-cpus.dtsi b/arch/arm/boot/dts/exynos5420-cpus.dtsi
> index a8e449471304..0ee6e92a3c29 100644
> --- a/arch/arm/boot/dts/exynos5420-cpus.dtsi
> +++ b/arch/arm/boot/dts/exynos5420-cpus.dtsi
> @@ -38,6 +38,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x1>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -49,6 +50,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x2>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -60,6 +62,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x3>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -83,6 +86,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x101>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> @@ -94,6 +98,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x102>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> @@ -105,6 +110,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x103>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> diff --git a/arch/arm/boot/dts/exynos5422-cpus.dtsi b/arch/arm/boot/dts/exynos5422-cpus.dtsi
> index 7c130a00d1a8..e4a5857c135f 100644
> --- a/arch/arm/boot/dts/exynos5422-cpus.dtsi
> +++ b/arch/arm/boot/dts/exynos5422-cpus.dtsi
> @@ -37,6 +37,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x101>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> @@ -48,6 +49,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x102>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> @@ -59,6 +61,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a7";
>                         reg = <0x103>;
> +                       clocks = <&clock CLK_KFC_CLK>;
>                         clock-frequency = <1000000000>;
>                         cci-control-port = <&cci_control0>;
>                         operating-points-v2 = <&cluster_a7_opp_table>;
> @@ -69,8 +72,8 @@
>                 cpu4: cpu@0 {
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
> -                       clocks = <&clock CLK_ARM_CLK>;
>                         reg = <0x0>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -82,6 +85,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x1>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -93,6 +97,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x2>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> @@ -104,6 +109,7 @@
>                         device_type = "cpu";
>                         compatible = "arm,cortex-a15";
>                         reg = <0x3>;
> +                       clocks = <&clock CLK_ARM_CLK>;
>                         clock-frequency = <1800000000>;
>                         cci-control-port = <&cci_control1>;
>                         operating-points-v2 = <&cluster_a15_opp_table>;
> --
> 2.14.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Regards,
Alim

^ permalink raw reply

* [PATCH v2] arm: sun4i: Add support for Pengpod 1000 tablet
From: Bob Ham @ 2018-06-02 16:03 UTC (permalink / raw)
  To: Maxime Ripard, Chen-Yu Tsai
  Cc: Rob Herring, Mark Rutland, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

This is initial support for the Pengpod 1000 tablet.  The display is
not currently working but the UART, SD card and USB all work fine.

Signed-off-by: Bob Ham <rah-2mWpNWY8JZLk1uMJSBkQmQ@public.gmane.org>
---
Changes since v1:

* Added SPDX license identifier

arch/arm/boot/dts/Makefile                   |   1 +
 arch/arm/boot/dts/sun4i-a10-pengpod-1000.dts | 234 +++++++++++++++++++++++++++
 2 files changed, 235 insertions(+)
 create mode 100644 arch/arm/boot/dts/sun4i-a10-pengpod-1000.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index ade7a38543dc..e6e93e7ffc8b 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -893,6 +893,7 @@ dtb-$(CONFIG_MACH_SUN4I) += \
 	sun4i-a10-olinuxino-lime.dtb \
 	sun4i-a10-pcduino.dtb \
 	sun4i-a10-pcduino2.dtb \
+	sun4i-a10-pengpod-1000.dtb \
 	sun4i-a10-pov-protab2-ips9.dtb
 dtb-$(CONFIG_MACH_SUN5I) += \
 	sun5i-a10s-auxtek-t003.dtb \
diff --git a/arch/arm/boot/dts/sun4i-a10-pengpod-1000.dts b/arch/arm/boot/dts/sun4i-a10-pengpod-1000.dts
new file mode 100644
index 000000000000..788163a80f3a
--- /dev/null
+++ b/arch/arm/boot/dts/sun4i-a10-pengpod-1000.dts
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2015 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ * Copyright 2017 Robert Ham <rah-2mWpNWY8JZLk1uMJSBkQmQ@public.gmane.org>
+ *
+ * SPDX-License-Identifier: (GPL-2.0-or-later or X11)
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file 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.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun4i-a10.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pwm/pwm.h>
+
+/ {
+	model = "PengPod 1000";
+	compatible = "pengpod,1000", "allwinner,sun4i-a10";
+
+	aliases {
+		serial0 = &uart0;
+	};
+
+	backlight: backlight {
+		compatible = "pwm-backlight";
+		pinctrl-names = "default";
+		pinctrl-0 = <&bl_en_pin_pengpod1000>;
+		pwms = <&pwm 0 50000 PWM_POLARITY_INVERTED>;
+		brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+		default-brightness-level = <8>;
+		enable-gpios = <&pio 7 7 GPIO_ACTIVE_HIGH>; /* PH7 */
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&codec {
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&reg_dcdc2>;
+};
+
+&ehci0 {
+	status = "okay";
+};
+
+&ehci1 {
+	status = "okay";
+};
+
+&i2c0 {
+	status = "okay";
+
+	axp209: pmic@34 {
+		compatible = "x-powers,axp209";
+		reg = <0x34>;
+		interrupts = <0>;
+	};
+};
+
+#include "axp209.dtsi"
+
+&i2c1 {
+	status = "okay";
+
+	mma7660: accelerometer@4c {
+		compatible = "fsl,mma7660";
+		reg = <0x4c>;
+	};
+};
+
+&i2c2 {
+	status = "okay";
+
+	ft5406ee8: touchscreen@38 {
+		compatible = "edt,edt-ft5406";
+		reg = <0x38>;
+		interrupt-parent = <&pio>;
+		interrupts = <7 21 IRQ_TYPE_EDGE_FALLING>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&touchscreen_pins>;
+		reset-gpios = <&pio 1 13 GPIO_ACTIVE_LOW>;
+		touchscreen-size-x = <1024>;
+		touchscreen-size-y = <600>;
+		touchscreen-swapped-x-y;
+	};
+};
+
+&mmc0 {
+	vmmc-supply = <&reg_vcc3v3>;
+	bus-width = <4>;
+	cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>; /* PH1 */
+	cd-inverted;
+	status = "okay";
+};
+
+&pio {
+	bl_en_pin_pengpod1000: bl_en_pin@0 {
+		pins = "PH7";
+		function = "gpio_out";
+	};
+
+	touchscreen_pins: touchscreen_pins@0 {
+		pins = "PB13";
+		function = "gpio_out";
+	};
+
+	usb0_id_detect_pin: usb0_id_detect_pin@0 {
+		pins = "PH4";
+		function = "gpio_in";
+		bias-pull-up;
+	};
+
+	usb0_vbus_detect_pin: usb0_vbus_detect_pin@0 {
+		pins = "PH5";
+		function = "gpio_in";
+		bias-pull-down;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm0_pin>;
+	status = "okay";
+};
+
+&reg_dcdc2 {
+	regulator-always-on;
+	regulator-min-microvolt = <1000000>;
+	regulator-max-microvolt = <1400000>;
+	regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+	regulator-always-on;
+	regulator-min-microvolt = <1250000>;
+	regulator-max-microvolt = <1250000>;
+	regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo1 {
+	regulator-name = "vdd-rtc";
+};
+
+&reg_ldo2 {
+	regulator-always-on;
+	regulator-min-microvolt = <3000000>;
+	regulator-max-microvolt = <3000000>;
+	regulator-name = "avcc";
+};
+
+&ohci0 {
+	status = "okay";
+};
+
+&otg_sram {
+	status = "okay";
+};
+
+&reg_usb0_vbus {
+	status = "okay";
+};
+
+&reg_usb1_vbus {
+	status = "okay";
+};
+
+&reg_usb2_vbus {
+	status = "okay";
+};
+
+&uart0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart0_pb_pins>;
+	status = "okay";
+};
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbphy {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+	usb0_id_det-gpio = <&pio 7 4 GPIO_ACTIVE_HIGH>; /* PH4 */
+	usb0_vbus_det-gpio = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
+	usb0_vbus-supply = <&reg_usb0_vbus>;
+	usb1_vbus-supply = <&reg_usb1_vbus>;
+	usb2_vbus-supply = <&reg_usb2_vbus>;
+	status = "okay";
+};
-- 
2.11.0

^ permalink raw reply related

* [PATCH 0/3] Add gpio interrupt support for Actions Semi S900 SoC
From: Manivannan Sadhasivam @ 2018-06-02 16:54 UTC (permalink / raw)
  To: linus.walleij, robh+dt, afaerber
  Cc: liuwei, mp-cs, 96boards, devicetree, andy.shevchenko,
	daniel.thompson, amit.kucheria, linux-arm-kernel, linux-gpio,
	linux-kernel, hzhang, bdong, manivannanece23, thomas.liau,
	jeff.chen, Manivannan Sadhasivam

This patchset adds interrupt support for Actions Semi S900 GPIO's. Each
port has individual register sets for configuring the below interrupt
types:

1. Rising Edge Interrupt
2. Falling Edge Interrupt
3. High Level Interrupt
4. Low Level Interrupt

Thanks,
Mani

Manivannan Sadhasivam (3):
  dt-bindings: pinctrl: Add gpio interrupt bindings for Actions S900 SoC
  arm64: dts: actions: Add interrupt properties to pinctrl node for S900
  pinctrl: actions: Add interrupt support for OWL S900 SoC

 .../bindings/pinctrl/actions,s900-pinctrl.txt |  10 +
 arch/arm64/boot/dts/actions/s900.dtsi         |   8 +
 drivers/pinctrl/actions/Kconfig               |   1 +
 drivers/pinctrl/actions/pinctrl-owl.c         | 231 +++++++++++++++++-
 drivers/pinctrl/actions/pinctrl-owl.h         |  22 +-
 drivers/pinctrl/actions/pinctrl-s900.c        |  31 ++-
 6 files changed, 285 insertions(+), 18 deletions(-)

-- 
2.17.0

^ permalink raw reply

* [PATCH 1/3] dt-bindings: pinctrl: Add gpio interrupt bindings for Actions S900 SoC
From: Manivannan Sadhasivam @ 2018-06-02 16:54 UTC (permalink / raw)
  To: linus.walleij, robh+dt, afaerber
  Cc: liuwei, mp-cs, 96boards, devicetree, andy.shevchenko,
	daniel.thompson, amit.kucheria, linux-arm-kernel, linux-gpio,
	linux-kernel, hzhang, bdong, manivannanece23, thomas.liau,
	jeff.chen, Manivannan Sadhasivam
In-Reply-To: <20180602165415.30956-1-manivannan.sadhasivam@linaro.org>

Add gpio interrupt bindings for Actions Semi S900 SoC.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 .../bindings/pinctrl/actions,s900-pinctrl.txt          | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt
index 8fb5a53775e8..81b58dddd3ed 100644
--- a/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/actions,s900-pinctrl.txt
@@ -19,6 +19,10 @@ Required Properties:
                     defines the interrupt number, the second encodes
                     the trigger flags described in
                     bindings/interrupt-controller/interrupts.txt
+- interrupts: The interrupt outputs from the controller. There is one GPIO
+              interrupt per GPIO bank. The number of interrupts listed depends
+              on the number of GPIO banks on the SoC. The interrupts must be
+              ordered by bank, starting with bank 0.
 
 Please refer to pinctrl-bindings.txt in this directory for details of the
 common pinctrl bindings used by client devices, including the meaning of the
@@ -180,6 +184,12 @@ Example:
                   #gpio-cells = <2>;
                   interrupt-controller;
                   #interrupt-cells = <2>;
+                  interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 
                   uart2-default: uart2-default {
                           pinmux {
-- 
2.17.0

^ permalink raw reply related

* [PATCH 2/3] arm64: dts: actions: Add interrupt properties to pinctrl node for S900
From: Manivannan Sadhasivam @ 2018-06-02 16:54 UTC (permalink / raw)
  To: linus.walleij, robh+dt, afaerber
  Cc: liuwei, mp-cs, 96boards, devicetree, andy.shevchenko,
	daniel.thompson, amit.kucheria, linux-arm-kernel, linux-gpio,
	linux-kernel, hzhang, bdong, manivannanece23, thomas.liau,
	jeff.chen, Manivannan Sadhasivam
In-Reply-To: <20180602165415.30956-1-manivannan.sadhasivam@linaro.org>

Add interrupt properties to pinctrl node for Actions Semi S900 SoC.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 arch/arm64/boot/dts/actions/s900.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/actions/s900.dtsi b/arch/arm64/boot/dts/actions/s900.dtsi
index aa3a49b0d646..7ae8b931f000 100644
--- a/arch/arm64/boot/dts/actions/s900.dtsi
+++ b/arch/arm64/boot/dts/actions/s900.dtsi
@@ -181,6 +181,14 @@
 			gpio-controller;
 			gpio-ranges = <&pinctrl 0 0 146>;
 			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
 		};
 
 		timer: timer@e0228000 {
-- 
2.17.0

^ permalink raw reply related

* [PATCH 3/3] pinctrl: actions: Add interrupt support for OWL S900 SoC
From: Manivannan Sadhasivam @ 2018-06-02 16:54 UTC (permalink / raw)
  To: linus.walleij, robh+dt, afaerber
  Cc: liuwei, mp-cs, 96boards, devicetree, andy.shevchenko,
	daniel.thompson, amit.kucheria, linux-arm-kernel, linux-gpio,
	linux-kernel, hzhang, bdong, manivannanece23, thomas.liau,
	jeff.chen, Manivannan Sadhasivam
In-Reply-To: <20180602165415.30956-1-manivannan.sadhasivam@linaro.org>

Add interrupt support for Actions Semi OWL S900 SoC.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
---
 drivers/pinctrl/actions/Kconfig        |   1 +
 drivers/pinctrl/actions/pinctrl-owl.c  | 231 ++++++++++++++++++++++++-
 drivers/pinctrl/actions/pinctrl-owl.h  |  22 ++-
 drivers/pinctrl/actions/pinctrl-s900.c |  31 ++--
 4 files changed, 267 insertions(+), 18 deletions(-)

diff --git a/drivers/pinctrl/actions/Kconfig b/drivers/pinctrl/actions/Kconfig
index 490927b4ea76..2397cb0f6011 100644
--- a/drivers/pinctrl/actions/Kconfig
+++ b/drivers/pinctrl/actions/Kconfig
@@ -5,6 +5,7 @@ config PINCTRL_OWL
 	select PINCONF
 	select GENERIC_PINCONF
 	select GPIOLIB
+	select GPIOLIB_IRQCHIP
 	help
 	  Say Y here to enable Actions Semi OWL pinctrl driver
 
diff --git a/drivers/pinctrl/actions/pinctrl-owl.c b/drivers/pinctrl/actions/pinctrl-owl.c
index 76243caa08c6..d40c61caeea3 100644
--- a/drivers/pinctrl/actions/pinctrl-owl.c
+++ b/drivers/pinctrl/actions/pinctrl-owl.c
@@ -45,6 +45,8 @@ struct owl_pinctrl {
 	struct clk *clk;
 	const struct owl_pinctrl_soc_data *soc;
 	void __iomem *base;
+	struct irq_domain *domain;
+	int *irq;
 };
 
 static void owl_update_bits(void __iomem *base, u32 mask, u32 val)
@@ -701,16 +703,193 @@ static int owl_gpio_direction_output(struct gpio_chip *chip,
 	return 0;
 }
 
+static int owl_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct owl_pinctrl *pctrl = gpiochip_get_data(chip);
+
+	return irq_find_mapping(pctrl->domain, offset);
+}
+
+static void owl_gpio_irq_mask(struct irq_data *data)
+{
+	struct owl_pinctrl *pctrl = irq_data_get_irq_chip_data(data);
+	const struct owl_gpio_port *port;
+	void __iomem *gpio_base;
+	unsigned long flags;
+	unsigned int gpio = data->hwirq;
+	u32 val;
+
+	port = owl_gpio_get_port(pctrl, &gpio);
+	if (WARN_ON(port == NULL))
+		return;
+
+	gpio_base = pctrl->base + port->offset;
+
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+
+	owl_gpio_update_reg(gpio_base + port->intc_msk, gpio, false);
+
+	/* disable port interrupt if no interrupt pending bit is active */
+	val = readl_relaxed(gpio_base + port->intc_msk);
+	if (val == 0)
+		owl_gpio_update_reg(gpio_base + port->intc_ctl,
+					OWL_GPIO_CTLR_ENABLE, false);
+
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void owl_gpio_irq_unmask(struct irq_data *data)
+{
+	struct owl_pinctrl *pctrl = irq_data_get_irq_chip_data(data);
+	const struct owl_gpio_port *port;
+	void __iomem *gpio_base;
+	unsigned long flags;
+	unsigned int gpio = data->hwirq;
+	u32 value;
+
+	port = owl_gpio_get_port(pctrl, &gpio);
+	if (WARN_ON(port == NULL))
+		return;
+
+	gpio_base = pctrl->base + port->offset;
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+
+	/* enable port interrupt */
+	value = readl_relaxed(gpio_base + port->intc_ctl);
+	value |= BIT(OWL_GPIO_CTLR_ENABLE) | BIT(OWL_GPIO_CTLR_SAMPLE_CLK_24M);
+	writel_relaxed(value, gpio_base + port->intc_ctl);
+
+	/* enable GPIO interrupt */
+	owl_gpio_update_reg(gpio_base + port->intc_msk, gpio, true);
+
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static void owl_gpio_irq_ack(struct irq_data *data)
+{
+	struct owl_pinctrl *pctrl = irq_data_get_irq_chip_data(data);
+	const struct owl_gpio_port *port;
+	void __iomem *gpio_base;
+	unsigned long flags;
+	unsigned int gpio = data->hwirq;
+
+	port = owl_gpio_get_port(pctrl, &gpio);
+	if (WARN_ON(port == NULL))
+		return;
+
+	gpio_base = pctrl->base + port->offset;
+
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+
+	owl_gpio_update_reg(gpio_base + port->intc_ctl,
+				OWL_GPIO_CTLR_PENDING, true);
+
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+
+static int owl_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+	struct owl_pinctrl *pctrl = irq_data_get_irq_chip_data(data);
+	const struct owl_gpio_port *port;
+	void __iomem *gpio_base;
+	unsigned long flags;
+	unsigned int gpio = data->hwirq;
+	unsigned int offset, value, irq_type = 0;
+
+	port = owl_gpio_get_port(pctrl, &gpio);
+	if (WARN_ON(port == NULL))
+		return -ENODEV;
+
+	gpio_base = pctrl->base + port->offset;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		irq_type = OWL_GPIO_INT_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		irq_type = OWL_GPIO_INT_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		irq_type = OWL_GPIO_INT_LEVEL_HIGH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		irq_type = OWL_GPIO_INT_LEVEL_LOW;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	raw_spin_lock_irqsave(&pctrl->lock, flags);
+
+	offset = gpio < 16 ? 4 : 0;
+	value = readl_relaxed(gpio_base + port->intc_type + offset);
+	value &= ~(OWL_GPIO_INT_MASK << ((gpio % 16) * 2));
+	value |= irq_type << ((gpio % 16) * 2);
+	writel_relaxed(value, gpio_base + port->intc_type + offset);
+
+	raw_spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	if (type & IRQ_TYPE_EDGE_BOTH)
+		irq_set_handler_locked(data, handle_edge_irq);
+	else
+		irq_set_handler_locked(data, handle_level_irq);
+
+	return 0;
+}
+
+static void owl_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct owl_pinctrl *pctrl = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	const struct owl_gpio_port *port;
+	void __iomem *base;
+	unsigned int pin, irq, offset = 0, i;
+	unsigned long pending_irq;
+
+	chained_irq_enter(chip, desc);
+
+	for (i = 0; i < pctrl->soc->nports; i++) {
+		port = &pctrl->soc->ports[i];
+		base = pctrl->base + port->offset;
+		pending_irq = readl_relaxed(base + port->intc_pd);
+
+		for_each_set_bit(pin, &pending_irq, port->pins) {
+			irq = irq_find_mapping(pctrl->domain, offset + pin);
+			generic_handle_irq(irq);
+
+			/* clear pending interrupt */
+			owl_gpio_update_reg(base + port->intc_pd, pin, true);
+		}
+
+		offset += port->pins;
+	}
+
+	chained_irq_exit(chip, desc);
+}
+
+static struct irq_chip owl_gpio_irq_chip = {
+	.name           = "owlgpio",
+	.irq_mask       = owl_gpio_irq_mask,
+	.irq_unmask     = owl_gpio_irq_unmask,
+	.irq_ack        = owl_gpio_irq_ack,
+	.irq_set_type   = owl_gpio_irq_set_type,
+};
+
 static int owl_gpio_init(struct owl_pinctrl *pctrl)
 {
 	struct gpio_chip *chip;
-	int ret;
+	int irqno, ret, i;
 
 	chip = &pctrl->chip;
 	chip->base = -1;
 	chip->ngpio = pctrl->soc->ngpios;
 	chip->label = dev_name(pctrl->dev);
 	chip->parent = pctrl->dev;
+	chip->to_irq = owl_gpio_to_irq;
 	chip->owner = THIS_MODULE;
 	chip->of_node = pctrl->dev->of_node;
 
@@ -720,6 +899,29 @@ static int owl_gpio_init(struct owl_pinctrl *pctrl)
 		return ret;
 	}
 
+	pctrl->domain = irq_domain_add_linear(chip->of_node,
+					     chip->ngpio,
+					     &irq_domain_simple_ops,
+					     NULL);
+	if (!pctrl->domain) {
+		dev_err(pctrl->dev, "Couldn't register IRQ domain\n");
+		gpiochip_remove(&pctrl->chip);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < chip->ngpio; i++) {
+		irqno = irq_create_mapping(pctrl->domain, i);
+		irq_set_chip_and_handler(irqno, &owl_gpio_irq_chip,
+					 handle_edge_irq);
+		irq_set_chip_data(irqno, pctrl);
+	}
+
+	for (i = 0; i < pctrl->soc->nports; i++) {
+		irq_set_chained_handler_and_data(pctrl->irq[i],
+						owl_gpio_irq_handler,
+						pctrl);
+	}
+
 	return 0;
 }
 
@@ -728,7 +930,7 @@ int owl_pinctrl_probe(struct platform_device *pdev,
 {
 	struct resource *res;
 	struct owl_pinctrl *pctrl;
-	int ret;
+	int ret, i;
 
 	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
 	if (!pctrl)
@@ -772,14 +974,35 @@ int owl_pinctrl_probe(struct platform_device *pdev,
 					&owl_pinctrl_desc, pctrl);
 	if (IS_ERR(pctrl->pctrldev)) {
 		dev_err(&pdev->dev, "could not register Actions OWL pinmux driver\n");
-		return PTR_ERR(pctrl->pctrldev);
+		ret = PTR_ERR(pctrl->pctrldev);
+		goto err_exit;
+	}
+
+	pctrl->irq = devm_kcalloc(&pdev->dev, pctrl->soc->nports,
+				  sizeof(*pctrl->irq), GFP_KERNEL);
+	if (!pctrl->irq) {
+		ret = -ENOMEM;
+		goto err_exit;
+	}
+
+	for (i = 0; i < pctrl->soc->nports ; i++) {
+		pctrl->irq[i] = platform_get_irq(pdev, i);
+		if (pctrl->irq[i] < 0) {
+			ret = pctrl->irq[i];
+			goto err_exit;
+		}
 	}
 
 	ret = owl_gpio_init(pctrl);
 	if (ret)
-		return ret;
+		goto err_exit;
 
 	platform_set_drvdata(pdev, pctrl);
 
 	return 0;
+
+err_exit:
+	clk_disable_unprepare(pctrl->clk);
+
+	return ret;
 }
diff --git a/drivers/pinctrl/actions/pinctrl-owl.h b/drivers/pinctrl/actions/pinctrl-owl.h
index 74342378937c..a724d1d406d4 100644
--- a/drivers/pinctrl/actions/pinctrl-owl.h
+++ b/drivers/pinctrl/actions/pinctrl-owl.h
@@ -29,6 +29,18 @@ enum owl_pinconf_drv {
 	OWL_PINCONF_DRV_12MA,
 };
 
+/* GPIO CTRL Bit Definition */
+#define OWL_GPIO_CTLR_PENDING		0
+#define OWL_GPIO_CTLR_ENABLE		1
+#define OWL_GPIO_CTLR_SAMPLE_CLK_24M	2
+
+/* GPIO TYPE Bit Definition */
+#define OWL_GPIO_INT_LEVEL_HIGH		0
+#define OWL_GPIO_INT_LEVEL_LOW		1
+#define OWL_GPIO_INT_EDGE_RISING	2
+#define OWL_GPIO_INT_EDGE_FALLING	3
+#define OWL_GPIO_INT_MASK		3
+
 /**
  * struct owl_pullctl - Actions pad pull control register
  * @reg: offset to the pull control register
@@ -121,6 +133,10 @@ struct owl_pinmux_func {
  * @outen: offset of the output enable register.
  * @inen: offset of the input enable register.
  * @dat: offset of the data register.
+ * @intc_ctl: offset of the interrupt control register.
+ * @intc_pd: offset of the interrupt pending register.
+ * @intc_msk: offset of the interrupt mask register.
+ * @intc_type: offset of the interrupt type register.
  */
 struct owl_gpio_port {
 	unsigned int offset;
@@ -128,6 +144,10 @@ struct owl_gpio_port {
 	unsigned int outen;
 	unsigned int inen;
 	unsigned int dat;
+	unsigned int intc_ctl;
+	unsigned int intc_pd;
+	unsigned int intc_msk;
+	unsigned int intc_type;
 };
 
 /**
@@ -140,7 +160,7 @@ struct owl_gpio_port {
  * @ngroups: number of entries in @groups.
  * @padinfo: array describing the pad info of this SoC.
  * @ngpios: number of pingroups the driver should expose as GPIOs.
- * @port: array describing all GPIO ports of this SoC.
+ * @ports: array describing all GPIO ports of this SoC.
  * @nports: number of GPIO ports in this SoC.
  */
 struct owl_pinctrl_soc_data {
diff --git a/drivers/pinctrl/actions/pinctrl-s900.c b/drivers/pinctrl/actions/pinctrl-s900.c
index 5503c7945764..ea67b14ef93b 100644
--- a/drivers/pinctrl/actions/pinctrl-s900.c
+++ b/drivers/pinctrl/actions/pinctrl-s900.c
@@ -1821,22 +1821,27 @@ static struct owl_padinfo s900_padinfo[NUM_PADS] = {
 	[SGPIO3] = PAD_INFO_PULLCTL_ST(SGPIO3)
 };
 
-#define OWL_GPIO_PORT(port, base, count, _outen, _inen, _dat)	\
-	[OWL_GPIO_PORT_##port] = {				\
-		.offset = base,					\
-		.pins = count,					\
-		.outen = _outen,				\
-		.inen = _inen,					\
-		.dat = _dat,					\
+#define OWL_GPIO_PORT(port, base, count, _outen, _inen, _dat,		\
+			_intc_ctl, _intc_pd, _intc_msk, _intc_type)	\
+	[OWL_GPIO_PORT_##port] = {					\
+		.offset = base,						\
+		.pins = count,						\
+		.outen = _outen,					\
+		.inen = _inen,						\
+		.dat = _dat,						\
+		.intc_ctl = _intc_ctl,					\
+		.intc_pd = _intc_pd,					\
+		.intc_msk = _intc_msk,					\
+		.intc_type = _intc_type,				\
 	}
 
 static const struct owl_gpio_port s900_gpio_ports[] = {
-	OWL_GPIO_PORT(A, 0x0000, 32, 0x0, 0x4, 0x8),
-	OWL_GPIO_PORT(B, 0x000C, 32, 0x0, 0x4, 0x8),
-	OWL_GPIO_PORT(C, 0x0018, 12, 0x0, 0x4, 0x8),
-	OWL_GPIO_PORT(D, 0x0024, 30, 0x0, 0x4, 0x8),
-	OWL_GPIO_PORT(E, 0x0030, 32, 0x0, 0x4, 0x8),
-	OWL_GPIO_PORT(F, 0x00F0, 8, 0x0, 0x4, 0x8)
+	OWL_GPIO_PORT(A, 0x0000, 32, 0x0, 0x4, 0x8, 0x204, 0x208, 0x20C, 0x240),
+	OWL_GPIO_PORT(B, 0x000C, 32, 0x0, 0x4, 0x8, 0x534, 0x204, 0x208, 0x23C),
+	OWL_GPIO_PORT(C, 0x0018, 12, 0x0, 0x4, 0x8, 0x52C, 0x200, 0x204, 0x238),
+	OWL_GPIO_PORT(D, 0x0024, 30, 0x0, 0x4, 0x8, 0x524, 0x1FC, 0x200, 0x234),
+	OWL_GPIO_PORT(E, 0x0030, 32, 0x0, 0x4, 0x8, 0x51C, 0x1F8, 0x1FC, 0x230),
+	OWL_GPIO_PORT(F, 0x00F0, 8, 0x0, 0x4, 0x8, 0x460, 0x140, 0x144, 0x178)
 };
 
 static struct owl_pinctrl_soc_data s900_pinctrl_data = {
-- 
2.17.0

^ permalink raw reply related

* [PATCH v2] thermal: qcom: tsens: Allow number of sensors to come from DT
From: Bjorn Andersson @ 2018-06-02 19:32 UTC (permalink / raw)
  To: Zhang Rui, Eduardo Valentin
  Cc: Rob Herring, Mark Rutland, Amit Kucheria, linux-pm, devicetree,
	linux-kernel, linux-arm-msm

For platforms that has multiple copies of the TSENS hardware block it's
convenient to specify the number of sensors per block in DeviceTree.

Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org>
Reviewed-by: Rob Herring <robh@kernel.org> [binding]
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---

Changes since v1:
- Added comment as suggested by Amit
- Picked up Amit and Rob's R-b

 .../devicetree/bindings/thermal/qcom-tsens.txt      |  1 +
 drivers/thermal/qcom/tsens.c                        | 13 ++++++++++---
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
index 292ed89d900b..06195e8f35e2 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -8,6 +8,7 @@ Required properties:
 
 - reg: Address range of the thermal registers
 - #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- #qcom,sensors: Number of sensors in tsens block
 - Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
 nvmem cells
 
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index 3f9fe6aa51cc..b212bebcfc36 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -116,6 +116,7 @@ static int tsens_probe(struct platform_device *pdev)
 	struct tsens_device *tmdev;
 	const struct tsens_data *data;
 	const struct of_device_id *id;
+	u32 num_sensors;
 
 	if (pdev->dev.of_node)
 		dev = &pdev->dev;
@@ -130,18 +131,24 @@ static int tsens_probe(struct platform_device *pdev)
 	else
 		data = &data_8960;
 
-	if (data->num_sensors <= 0) {
+	num_sensors = data->num_sensors;
+
+	/* Override driver provided num_sensors, if specified in DT */
+	if (np)
+		of_property_read_u32(np, "#qcom,sensors", &num_sensors);
+
+	if (num_sensors <= 0) {
 		dev_err(dev, "invalid number of sensors\n");
 		return -EINVAL;
 	}
 
 	tmdev = devm_kzalloc(dev, sizeof(*tmdev) +
-			     data->num_sensors * sizeof(*s), GFP_KERNEL);
+			     num_sensors * sizeof(*s), GFP_KERNEL);
 	if (!tmdev)
 		return -ENOMEM;
 
 	tmdev->dev = dev;
-	tmdev->num_sensors = data->num_sensors;
+	tmdev->num_sensors = num_sensors;
 	tmdev->ops = data->ops;
 	for (i = 0;  i < tmdev->num_sensors; i++) {
 		if (data->hw_ids)
-- 
2.17.0

^ permalink raw reply related


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