Devicetree
 help / color / mirror / Atom feed
* Re: [RFC v1 2/3] drivers: nvmem: Add driver for QTI qfprom-efuse support
From: Srinivas Kandagatla @ 2020-05-13 13:20 UTC (permalink / raw)
  To: Ravi Kumar Bokka, Rob Herring
  Cc: linux-kernel, devicetree, rnayak, saiprakash.ranjan, dhavalp,
	mturney, sparate, c_rbokka, mkurumel
In-Reply-To: <1589307480-27508-3-git-send-email-rbokka@codeaurora.org>



On 12/05/2020 19:17, Ravi Kumar Bokka wrote:
> This patch adds new driver for QTI qfprom-efuse controller. This driver can
> access the raw qfprom regions for fuse blowing.

QTI?

> 
> The current existed qfprom driver is only supports for cpufreq, thermal sensors
> drivers by read out calibration data, speed bins..etc which is stored
> by qfprom efuses.

Can you explain bit more about this QFPROM instance, Is this QFPROM part 
of secure controller address space?
Is this closely tied to SoC or Secure controller version?

Any reason why this can not be integrated into qfprom driver with 
specific compatible.

> 
> Signed-off-by: Ravi Kumar Bokka <rbokka@codeaurora.org>
> ---
>   drivers/nvmem/Kconfig        |  10 +
>   drivers/nvmem/Makefile       |   2 +
>   drivers/nvmem/qfprom-efuse.c | 476 +++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 488 insertions(+)
>   create mode 100644 drivers/nvmem/qfprom-efuse.c
> 
...

> diff --git a/drivers/nvmem/qfprom-efuse.c b/drivers/nvmem/qfprom-efuse.c
> new file mode 100644
> index 0000000..2e3c275
> --- /dev/null
> +++ b/drivers/nvmem/qfprom-efuse.c
> @@ -0,0 +1,476 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (c) 2020, The Linux Foundation. All rights reserved.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/device.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/mod_devicetable.h>
> +#include <linux/nvmem-provider.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/regulator/consumer.h>
> +
> +#define QFPROM_BLOW_STATUS_BUSY 0x1
> +#define QFPROM_BLOW_STATUS_READY 0x0
> +
> +/* Blow timer clock frequency in Mhz for 10nm LPe technology */
> +#define QFPROM_BLOW_TIMER_OFFSET 0x03c
> +#define QFPROM_BLOW_TIMER_RESET_VALUE 0x0
> +
> +/* Amount of time required to hold charge to blow fuse in micro-seconds */
> +#define QFPROM_FUSE_BLOW_POLL_PERIOD 100
> +#define QFPROM_BLOW_STATUS_OFFSET 0x048
> +
> +#define QFPROM_ACCEL_OFFSET 0x044
> +
> +/**
> + * struct qfprom_efuse_platform_data - structure holding qfprom-efuse
> + * platform data
> + *
> + * @name: qfprom-efuse compatible name

??
> + * @fuse_blow_time_in_us: Should contain the wait time when doing the fuse blow
> + * @accel_value: Should contain qfprom accel value
> + * @accel_reset_value: The reset value of qfprom accel value
> + * @qfprom_blow_timer_value: The timer value of qfprom when doing efuse blow
> + * @qfprom_blow_reset_freq: The frequency required to set when fuse blowing
> + * is done
> + * @qfprom_blow_set_freq: The frequency required to set when we start the
> + * fuse blowing
> + * @qfprom_max_vol: max voltage required to set fuse blow
> + * @qfprom_min_vol: min voltage required to set fuse blow

How specific are these values per SoC?


> + */
> +struct qfprom_efuse_platform_data {
> +	const char *name;
> +	u8 fuse_blow_time_in_us;
> +	u32 accel_value;
> +	u32 accel_reset_value;
> +	u32 qfprom_blow_timer_value;
> +	u32 qfprom_blow_reset_freq;
> +	u32 qfprom_blow_set_freq;
> +	u32 qfprom_max_vol;
> +	u32 qfprom_min_vol;
> +};
> +
> +/**
> + * struct qfprom_efuse_priv - structure holding qfprom-efuse attributes
> + *
> + * @qfpbase: iomapped memory space for qfprom base
> + * @qfpraw: iomapped memory space for qfprom raw fuse region
> + * @qfpmap: iomapped memory space for qfprom fuse blow timer
> +
> + * @dev: qfprom device structure
> + * @secclk: clock supply
> + * @vcc: regulator supply
> +
> + * @qfpraw_start: qfprom raw fuse start region
> + * @qfpraw_end: qfprom raw fuse end region
> + * @qfprom_efuse_platform_data: qfprom platform data
> + */
> +struct qfprom_efuse_priv {
> +	void __iomem *qfpbase;
> +	void __iomem *qfpraw;
> +	void __iomem *qfpmap;

Why are these memory regions split? Can't you just have complete qfprom 
area and add fixed offset for qfpraw within the driver?

> +	struct device *dev;
> +	struct clk *secclk;
> +	struct regulator *vcc;
> +	resource_size_t qfpraw_start;
> +	resource_size_t qfpraw_end;
Why do we need to check this range? as long as we set the nvmem_config 
with correct range then you should not need this check.


> +	struct qfprom_efuse_platform_data efuse;
A pointer here should be good enough?
> +};
> +

...

> +/*
> + * sets the value of the blow timer, accel register and the clock
> + * and voltage settings
> + */
> +static int qfprom_enable_fuse_blowing(const struct qfprom_efuse_priv *priv)
> +{
> +	int ret;
> +
> +	ret = qfprom_disable_fuse_blowing(priv);
> +	if (ret) {
> +		dev_err(priv->dev, "qfprom_disable_fuse_blowing()\n");
> +		return ret;
> +	}

Why do we need to qfprom_disable_fuse_blowing() for every call to enable it?

Or are we missing some error handling in the caller?

> +
> +	writel(priv->efuse.qfprom_blow_timer_value, priv->qfpmap +
> +	       QFPROM_BLOW_TIMER_OFFSET);
> +	writel(priv->efuse.accel_value, priv->qfpmap + QFPROM_ACCEL_OFFSET);
> +
> +	ret = qfprom_set_clock_settings(priv);
> +	if (ret) {
> +		dev_err(priv->dev, "qpfrom_set_clock_settings()\n");
> +		return ret;
> +	}
> +
> +	ret = qfprom_set_voltage_settings(priv, priv->efuse.qfprom_min_vol,
> +					  priv->efuse.qfprom_max_vol);
> +	if (ret) {
> +		dev_err(priv->dev, "qfprom_set_voltage_settings()\n");
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +

<<
> +/*
> + * verifying to make sure address being written or read is from qfprom
> + * raw address range
> + */
> +bool addr_in_qfprom_range(const struct qfprom_efuse_priv *priv, u32 reg,
> +			  size_t bytes)
> +{
> +	if (((reg + bytes) > reg) && (reg >= priv->qfpraw_start) &&
> +	    ((reg + bytes) <= priv->qfpraw_end)) {
> +		return 1;
> +	}
> +
> +	return 0;
> +}
 >>
Above function is totally redundant, nvmem core already has checks for this.



> +
> +/*
> + * API for reading from raw qfprom region
> + */
> +static int qfprom_efuse_reg_read(void *context, unsigned int reg, void *_val,
> +				 size_t bytes)
> +{
> +	struct qfprom_efuse_priv *priv = context;
> +	u32 *value = _val;
> +	u32 align_check;
> +	int i = 0, words = bytes / 4;
> +
> +	dev_info(priv->dev,
> +		 "reading raw qfprom region offset: 0x%08x of size: %zd\n",
> +		 reg, bytes);

In general there is lot of debug info across the code, do you really 
need all this? Consider removing these!

> +
> +	if (bytes % 4 != 0x00) {
> +		dev_err(priv->dev,
> +			"Bytes: %zd to read should be word align\n",
> +			bytes);
> +		return -EINVAL;
> +	}

This word align check is also redundant once you set nvmem_config with 
correct word_size.


> +
> +	if (!addr_in_qfprom_range(priv, reg, bytes)) {
> +		dev_err(priv->dev,
> +			"Invalid qfprom raw region offset 0x%08x & bytes %zd\n",
> +			reg, bytes);
> +		return -EINVAL;
> +	}
> +
> +	align_check = (reg & 0xF);
> +
> +	if (((align_check & ~3) == align_check) && value != NULL)
> +		while (words--)
> +			*value++ = readl(priv->qfpbase + reg + (i++ * 4));
> +
> +	else
> +		dev_err(priv->dev,
> +			"Invalid input parameter 0x%08x fuse blow address\n",
> +			reg);
> +
> +	return 0;
> +}
...

> +
> +static int qfprom_efuse_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct resource *qfpbase, *qfpraw, *qfpmap;
> +	struct nvmem_device *nvmem;
> +	struct nvmem_config *econfig;
> +	struct qfprom_efuse_priv *priv;
> +	const struct qfprom_efuse_platform_data *drvdata;
> +	int ret;
> +
> +	dev_info(&pdev->dev, "[%s]: Invoked\n", __func__);
> +

too much debug!

> +	drvdata = of_device_get_match_data(&pdev->dev);
> +	if (!drvdata)
> +		return -EINVAL;
Unnecessary check as this driver will not be probed unless there is a 
compatible match.


> +
> +	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv)
> +		return -ENOMEM;
> +
> +	priv->efuse.fuse_blow_time_in_us = drvdata->fuse_blow_time_in_us;
> +	priv->efuse.accel_value = drvdata->accel_value;
> +	priv->efuse.accel_reset_value = drvdata->accel_reset_value;
> +	priv->efuse.qfprom_blow_timer_value = drvdata->qfprom_blow_timer_value;
> +	priv->efuse.qfprom_blow_reset_freq = drvdata->qfprom_blow_reset_freq;
> +	priv->efuse.qfprom_blow_set_freq = drvdata->qfprom_blow_set_freq;
> +	priv->efuse.qfprom_max_vol = drvdata->qfprom_max_vol;
> +	priv->efuse.qfprom_min_vol = drvdata->qfprom_min_vol;
> +	priv->dev = dev;
> +
> +	qfpbase = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	priv->qfpbase = devm_ioremap_resource(dev, qfpbase);
> +	if (IS_ERR(priv->qfpbase)) {
> +		ret = PTR_ERR(priv->qfpbase);
> +		goto err;
> +	}
> +
> +	qfpraw = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +
> +	priv->qfpraw = devm_ioremap_resource(dev, qfpraw);
> +	if (IS_ERR(priv->qfpraw)) {
> +		ret = PTR_ERR(priv->qfpraw);
> +		goto err;
> +	}
> +
> +	priv->qfpraw_start = qfpraw->start - qfpbase->start;
> +	priv->qfpraw_end = qfpraw->end - qfpbase->start;
> +
> +	qfpmap = platform_get_resource(pdev, IORESOURCE_MEM, 2);
> +
> +	priv->qfpmap = devm_ioremap_resource(dev, qfpmap);
> +	if (IS_ERR(priv->qfpmap)) {
> +		ret = PTR_ERR(priv->qfpmap);
> +		goto err;
> +	}
> +
> +	priv->vcc = devm_regulator_get(&pdev->dev, "vcc");

I see no reference to this regulator in dt bindings.
> +	if (IS_ERR(priv->vcc)) {
> +		ret = PTR_ERR(priv->vcc);
> +		if (ret == -ENODEV)
> +			ret = -EPROBE_DEFER;
Can you explain what is going on here?

> +
> +		goto err;
> +	}
> +
> +	priv->secclk = devm_clk_get(dev, "secclk");
> +	if (IS_ERR(priv->secclk)) {
> +		ret = PTR_ERR(priv->secclk);
> +		if (ret != -EPROBE_DEFER)
> +			dev_err(dev, "secclk error getting : %d\n", ret);
> +		goto err;
> +	}
> +
> +	ret = clk_prepare_enable(priv->secclk);
> +	if (ret) {
> +		dev_err(dev, "clk_prepare_enable() failed\n");
> +		goto err;
> +	}
> +
> +	econfig = devm_kzalloc(dev, sizeof(*econfig), GFP_KERNEL);
> +	if (!econfig)
Why not disabling the clk here?
> +		return -ENOMEM;

> +
> +	econfig->dev = dev;
> +	econfig->name = "qfprom-efuse";
> +	econfig->stride = 1;
> +	econfig->word_size = 1;
> +	econfig->reg_read = qfprom_efuse_reg_read;
> +	econfig->reg_write = qfprom_efuse_reg_write;
> +	econfig->size = resource_size(qfpraw);
> +	econfig->priv = priv;
> +
> +	nvmem = devm_nvmem_register(dev, econfig);
> +
> +	return PTR_ERR_OR_ZERO(nvmem);
probably you should check the nvmem here before returning to disable the 
clk properly.

> +
> +err:
> +	clk_disable_unprepare(priv->secclk);
> +	return ret;
> +}
> +
> +static const struct qfprom_efuse_platform_data sc7180_qfp_efuse_data = {
> +	.name = "sc7180-qfprom-efuse",
Redundant.

> +	.fuse_blow_time_in_us = 10,
> +	.accel_value = 0xD10,
> +	.accel_reset_value = 0x800,
> +	.qfprom_blow_timer_value = 25,
> +	.qfprom_blow_reset_freq = 19200000,
> +	.qfprom_blow_set_freq = 4800000,
> +	.qfprom_max_vol = 1904000,
> +	.qfprom_min_vol = 1800000,
> +};
> +
> +static const struct of_device_id qfprom_efuse_of_match[] = {
> +	{
> +		.compatible = "qcom,sc7180-qfprom-efuse",
> +		.data = &sc7180_qfp_efuse_data
> +	},
> +	{/* sentinel */},
> +};
> +
> +MODULE_DEVICE_TABLE(of, qfprom_efuse_of_match);
> +
> +static struct platform_driver qfprom_efuse_driver = {
> +	.probe = qfprom_efuse_probe,
> +	.driver = {
> +		.name = "sc7180-qfprom-efuse",
> +		.of_match_table = qfprom_efuse_of_match,
> +	},
> +};
> +
> +module_platform_driver(qfprom_efuse_driver);
> +MODULE_DESCRIPTION("QTI QFPROM Efuse driver");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply

* [PATCH] MIPS: dts: mscc: Updated changed name for miim pinctrl function
From: Lars Povlsen @ 2020-05-13 13:23 UTC (permalink / raw)
  To: Thomas Bogendoerfer
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-mips,
	devicetree, linux-kernel, Alexandre Belloni

This is an add-on patch to the main SoC Sparx5 series
(Message-ID: <20200513125532.24585-1-lars.povlsen@microchip.com>).

This changes the miim pinctrl function name from "miim1" to "miim" due
to refactoring in the driver, obsoleting the instance number.

The change in the driver was to better fit new platforms, as the
instance number is redundant information. Specifically, support for
the Microchip Sparx5 SoC is being submitted, where this change became
necessary.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 arch/mips/boot/dts/mscc/ocelot.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index 797d336db54d3..f94e8a02ed06b 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -214,7 +214,7 @@ uart2_pins: uart2-pins {

 			miim1: miim1 {
 				pins = "GPIO_14", "GPIO_15";
-				function = "miim1";
+				function = "miim";
 			};

 		};
--
2.26.2

^ permalink raw reply related

* Re: [PATCH] MIPS: dts: mscc: Updated changed name for miim pinctrl function
From: Alexandre Belloni @ 2020-05-13 13:27 UTC (permalink / raw)
  To: Lars Povlsen
  Cc: Thomas Bogendoerfer, Microchip Linux Driver Support, linux-mips,
	devicetree, linux-kernel
In-Reply-To: <20200513132347.24975-1-lars.povlsen@microchip.com>

On 13/05/2020 15:23:47+0200, Lars Povlsen wrote:
> This is an add-on patch to the main SoC Sparx5 series
> (Message-ID: <20200513125532.24585-1-lars.povlsen@microchip.com>).
> 
> This changes the miim pinctrl function name from "miim1" to "miim" due
> to refactoring in the driver, obsoleting the instance number.
> 
> The change in the driver was to better fit new platforms, as the
> instance number is redundant information. Specifically, support for
> the Microchip Sparx5 SoC is being submitted, where this change became
> necessary.
> 
> Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
> Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>

> ---
>  arch/mips/boot/dts/mscc/ocelot.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
> index 797d336db54d3..f94e8a02ed06b 100644
> --- a/arch/mips/boot/dts/mscc/ocelot.dtsi
> +++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
> @@ -214,7 +214,7 @@ uart2_pins: uart2-pins {
> 
>  			miim1: miim1 {
>  				pins = "GPIO_14", "GPIO_15";
> -				function = "miim1";
> +				function = "miim";
>  			};
> 
>  		};
> --
> 2.26.2

-- 
Alexandre Belloni, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

^ permalink raw reply

* [PATCH 0/3] mmc: Adding support for Microchip Sparx5 SoC
From: Lars Povlsen @ 2020-05-13 13:31 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter, SoC Team
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-mmc,
	devicetree, linux-arm-kernel, linux-kernel

This is an add-on series to the main SoC Sparx5 series
(Message-ID: <20200513125532.24585-1-lars.povlsen@microchip.com>).

It adds eMMC support for Sparx5, by adding a driver for the SoC SDHCI
controller, DT configuration and DT binding documentation.

Lars Povlsen (3):
  dt-bindings: mmc: Add Sparx5 SDHCI controller bindings
  sdhci: sparx5: Add Sparx5 SoC eMMC driver
  arm64: dts: sparx5: Add Sparx5 eMMC support

 .../mmc/microchip,dw-sparx5-sdhci.yaml        |  57 +++
 arch/arm64/boot/dts/microchip/sparx5.dtsi     |  24 ++
 .../boot/dts/microchip/sparx5_pcb125.dts      |  23 ++
 .../boot/dts/microchip/sparx5_pcb134_emmc.dts |  23 ++
 .../boot/dts/microchip/sparx5_pcb135_emmc.dts |  23 ++
 drivers/mmc/host/Kconfig                      |  13 +
 drivers/mmc/host/Makefile                     |   1 +
 drivers/mmc/host/sdhci-of-sparx5.c            | 348 ++++++++++++++++++
 8 files changed, 512 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml
 create mode 100644 drivers/mmc/host/sdhci-of-sparx5.c

--
2.26.2

^ permalink raw reply

* [PATCH 1/3] dt-bindings: mmc: Add Sparx5 SDHCI controller bindings
From: Lars Povlsen @ 2020-05-13 13:31 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter, SoC Team, Rob Herring
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-mmc,
	devicetree, linux-arm-kernel, linux-kernel, Alexandre Belloni
In-Reply-To: <20200513133122.25121-1-lars.povlsen@microchip.com>

The Sparx5 SDHCI controller is based on the Designware controller IP.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 .../mmc/microchip,dw-sparx5-sdhci.yaml        | 57 +++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml

diff --git a/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml b/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml
new file mode 100644
index 0000000000000..a9901c4bc25d3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/microchip,dw-sparx5-sdhci.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/microchip,dw-sparx5-sdhci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip Sparx5 Mobile Storage Host Controller Binding
+
+allOf:
+  - $ref: "mmc-controller.yaml"
+
+maintainers:
+  - Lars Povlsen <lars.povlsen@microchip.com>
+
+# Everything else is described in the common file
+properties:
+  compatible:
+    const: microchip,dw-sparx5-sdhci
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+    description:
+      Handle to "core" clock for the sdhci controller.
+
+  clock-names:
+    items:
+      - const: core
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - clocks
+  - clock-names
+
+examples:
+  - |
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/clock/microchip,sparx5.h>
+    sdhci0: mmc@600800000 {
+        compatible = "microchip,dw-sparx5-sdhci";
+        reg = <0x00800000 0x1000>;
+        pinctrl-0 = <&emmc_pins>;
+        pinctrl-names = "default";
+        clocks = <&clks CLK_ID_AUX1>;
+        clock-names = "core";
+        assigned-clocks = <&clks CLK_ID_AUX1>;
+        assigned-clock-rates = <800000000>;
+        interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+        bus-width = <8>;
+    };
--
2.26.2

^ permalink raw reply related

* [PATCH 3/3] arm64: dts: sparx5: Add Sparx5 eMMC support
From: Lars Povlsen @ 2020-05-13 13:31 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter, SoC Team
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-mmc,
	devicetree, linux-arm-kernel, linux-kernel, Alexandre Belloni
In-Reply-To: <20200513133122.25121-1-lars.povlsen@microchip.com>

This adds eMMC support to the applicable Sparx5 board configuration
files.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 arch/arm64/boot/dts/microchip/sparx5.dtsi     | 24 +++++++++++++++++++
 .../boot/dts/microchip/sparx5_pcb125.dts      | 23 ++++++++++++++++++
 .../boot/dts/microchip/sparx5_pcb134_emmc.dts | 23 ++++++++++++++++++
 .../boot/dts/microchip/sparx5_pcb135_emmc.dts | 23 ++++++++++++++++++
 4 files changed, 93 insertions(+)

diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
index 3e94ac9e7dd51..f09a49c41ce19 100644
--- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -5,6 +5,7 @@

 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/microchip,sparx5.h>

 / {
 	compatible = "microchip,sparx5";
@@ -151,6 +152,20 @@ timer1: timer@600105000 {
 			interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
 		};

+		sdhci0: sdhci@600800000 {
+			compatible = "microchip,dw-sparx5-sdhci";
+			status = "disabled";
+			reg = <0x6 0x00800000 0x1000>;
+			pinctrl-0 = <&emmc_pins>;
+			pinctrl-names = "default";
+			clocks = <&clks CLK_ID_AUX1>;
+			clock-names = "core";
+			assigned-clocks = <&clks CLK_ID_AUX1>;
+			assigned-clock-rates = <800000000>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			bus-width = <8>;
+		};
+
 		gpio: pinctrl@6110101e0 {
 			compatible = "microchip,sparx5-pinctrl";
 			reg = <0x6 0x110101e0 0x90>, <0x6 0x10508010 0x100>;
@@ -180,6 +195,15 @@ i2c2_pins: i2c2-pins {
 				pins = "GPIO_28", "GPIO_29";
 				function = "twi2";
 			};
+
+			emmc_pins: emmc-pins {
+				pins = "GPIO_34", "GPIO_35", "GPIO_36",
+					"GPIO_37", "GPIO_38", "GPIO_39",
+					"GPIO_40", "GPIO_41", "GPIO_42",
+					"GPIO_43", "GPIO_44", "GPIO_45",
+					"GPIO_46", "GPIO_47";
+				function = "emmc";
+			};
 		};

 		i2c0: i2c@600101000 {
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
index 91ee5b6cfc37a..573309fe45823 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb125.dts
@@ -16,6 +16,29 @@ memory@0 {
 	};
 };

+&gpio {
+	emmc_pins: emmc-pins {
+		/* NB: No "GPIO_35", "GPIO_36", "GPIO_37"
+		 * (N/A: CARD_nDETECT, CARD_WP, CARD_LED)
+		 */
+		pins = "GPIO_34", "GPIO_38", "GPIO_39",
+			"GPIO_40", "GPIO_41", "GPIO_42",
+			"GPIO_43", "GPIO_44", "GPIO_45",
+			"GPIO_46", "GPIO_47";
+		drive-strength = <3>;
+		function = "emmc";
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+	bus-width = <8>;
+	non-removable;
+	pinctrl-0 = <&emmc_pins>;
+	max-frequency = <8000000>;
+	microchip,clock-delay = <10>;
+};
+
 &i2c1 {
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
index 10081a66961bb..bbb9852c1f151 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb134_emmc.dts
@@ -15,3 +15,26 @@ memory@0 {
 		reg = <0x00000000 0x00000000 0x10000000>;
 	};
 };
+
+&gpio {
+	emmc_pins: emmc-pins {
+		/* NB: No "GPIO_35", "GPIO_36", "GPIO_37"
+		 * (N/A: CARD_nDETECT, CARD_WP, CARD_LED)
+		 */
+		pins = "GPIO_34", "GPIO_38", "GPIO_39",
+			"GPIO_40", "GPIO_41", "GPIO_42",
+			"GPIO_43", "GPIO_44", "GPIO_45",
+			"GPIO_46", "GPIO_47";
+		drive-strength = <3>;
+		function = "emmc";
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	non-removable;
+	max-frequency = <52000000>;
+	bus-width = <8>;
+	microchip,clock-delay = <10>;
+};
diff --git a/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts b/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
index 741f0e12260e5..f82266fe2ad49 100644
--- a/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
+++ b/arch/arm64/boot/dts/microchip/sparx5_pcb135_emmc.dts
@@ -15,3 +15,26 @@ memory@0 {
 		reg = <0x00000000 0x00000000 0x10000000>;
 	};
 };
+
+&gpio {
+	emmc_pins: emmc-pins {
+		/* NB: No "GPIO_35", "GPIO_36", "GPIO_37"
+		 * (N/A: CARD_nDETECT, CARD_WP, CARD_LED)
+		 */
+		pins = "GPIO_34", "GPIO_38", "GPIO_39",
+			"GPIO_40", "GPIO_41", "GPIO_42",
+			"GPIO_43", "GPIO_44", "GPIO_45",
+			"GPIO_46", "GPIO_47";
+		drive-strength = <3>;
+		function = "emmc";
+	};
+};
+
+&sdhci0 {
+	status = "okay";
+	pinctrl-0 = <&emmc_pins>;
+	non-removable;
+	max-frequency = <52000000>;
+	bus-width = <8>;
+	microchip,clock-delay = <10>;
+};
--
2.26.2

^ permalink raw reply related

* [PATCH 2/3] sdhci: sparx5: Add Sparx5 SoC eMMC driver
From: Lars Povlsen @ 2020-05-13 13:31 UTC (permalink / raw)
  To: Ulf Hansson, Adrian Hunter, SoC Team
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-mmc,
	devicetree, linux-arm-kernel, linux-kernel, Alexandre Belloni
In-Reply-To: <20200513133122.25121-1-lars.povlsen@microchip.com>

This adds the eMMC driver for the Sparx5 SoC. It is based upon the
designware IP, but requires some extra initialization and quirks.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 drivers/mmc/host/Kconfig           |  13 ++
 drivers/mmc/host/Makefile          |   1 +
 drivers/mmc/host/sdhci-of-sparx5.c | 348 +++++++++++++++++++++++++++++
 3 files changed, 362 insertions(+)
 create mode 100644 drivers/mmc/host/sdhci-of-sparx5.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 462b5352fea75..1e8396d09df75 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -213,6 +213,19 @@ config MMC_SDHCI_OF_DWCMSHC
 	  If you have a controller with this interface, say Y or M here.
 	  If unsure, say N.

+config MMC_SDHCI_OF_SPARX5
+	tristate "SDHCI OF support for the MCHP Sparx5 SoC"
+	depends on MMC_SDHCI_PLTFM
+	depends on ARCH_SPARX5
+	select MMC_SDHCI_IO_ACCESSORS
+	help
+	  This selects the Secure Digital Host Controller Interface (SDHCI)
+	  found in the MCHP Sparx5 SoC.
+
+	  If you have a Sparx5 SoC with this interface, say Y or M here.
+
+	  If unsure, say N.
+
 config MMC_SDHCI_CADENCE
 	tristate "SDHCI support for the Cadence SD/SDIO/eMMC controller"
 	depends on MMC_SDHCI_PLTFM
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index b929ef9412083..9f09b7ffaaa16 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -89,6 +89,7 @@ obj-$(CONFIG_MMC_SDHCI_OF_ARASAN)	+= sdhci-of-arasan.o
 obj-$(CONFIG_MMC_SDHCI_OF_ASPEED)	+= sdhci-of-aspeed.o
 obj-$(CONFIG_MMC_SDHCI_OF_AT91)		+= sdhci-of-at91.o
 obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
+obj-$(CONFIG_MMC_SDHCI_OF_SPARX5)	+= sdhci-of-sparx5.o
 obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
 obj-$(CONFIG_MMC_SDHCI_OF_DWCMSHC)	+= sdhci-of-dwcmshc.o
 obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
diff --git a/drivers/mmc/host/sdhci-of-sparx5.c b/drivers/mmc/host/sdhci-of-sparx5.c
new file mode 100644
index 0000000000000..8253bf80e175a
--- /dev/null
+++ b/drivers/mmc/host/sdhci-of-sparx5.c
@@ -0,0 +1,348 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * drivers/mmc/host/sdhci-of-sparx5.c
+ *
+ * MCHP Sparx5 SoC Secure Digital Host Controller Interface.
+ *
+ * Copyright (c) 2019 Microchip Inc.
+ *
+ * Author: Lars Povlsen <lars.povlsen@microchip.com>
+ */
+
+//#define DEBUG
+//#define TRACE_REGISTER
+
+#include <linux/sizes.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/dma-mapping.h>
+
+#include "sdhci-pltfm.h"
+
+#define CPU_REGS_GENERAL_CTRL	(0x22 * 4)
+#define  MSHC_DLY_CC_MASK	GENMASK(16, 13)
+#define  MSHC_DLY_CC_SHIFT	13
+#define  MSHC_DLY_CC_MAX	15
+
+#define CPU_REGS_PROC_CTRL	(0x2C * 4)
+#define  ACP_CACHE_FORCE_ENA	BIT(4)
+#define  ACP_AWCACHE		BIT(3)
+#define  ACP_ARCACHE		BIT(2)
+#define  ACP_CACHE_MASK		(ACP_CACHE_FORCE_ENA|ACP_AWCACHE|ACP_ARCACHE)
+
+#define MSHC2_VERSION			0x500	/* Off 0x140, reg 0x0 */
+#define MSHC2_TYPE			0x504	/* Off 0x140, reg 0x1 */
+#define MSHC2_EMMC_CTRL			0x52c	/* Off 0x140, reg 0xB */
+#define  MSHC2_EMMC_CTRL_EMMC_RST_N	BIT(2)
+#define  MSHC2_EMMC_CTRL_IS_EMMC	BIT(0)
+
+struct sdhci_sparx5_data {
+	struct sdhci_host *host;
+	struct regmap *cpu_ctrl;
+	int delay_clock;
+	struct device_attribute dev_delay_clock;
+};
+
+#define BOUNDARY_OK(addr, len) \
+	((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
+
+#if defined(TRACE_REGISTER)
+static void sdhci_sparx5_writel(struct sdhci_host *host, u32 val, int reg)
+{
+	pr_debug("$$$ writel(0x%08x, 0x%02x)\n", val, reg);
+	writel(val, host->ioaddr + reg);
+}
+
+static void sdhci_sparx5_writew(struct sdhci_host *host, u16 val, int reg)
+{
+	pr_debug("$$$ writew(0x%04x, 0x%02x)\n", val, reg);
+	writew(val, host->ioaddr + reg);
+}
+
+static void sdhci_sparx5_writeb(struct sdhci_host *host, u8 val, int reg)
+{
+	pr_debug("$$$ writeb(0x%02x, 0x%02x)\n", val, reg);
+	writeb(val, host->ioaddr + reg);
+}
+#endif
+
+/*
+ * If DMA addr spans 128MB boundary, we split the DMA transfer into two
+ * so that each DMA transfer doesn't exceed the boundary.
+ */
+static void sdhci_sparx5_adma_write_desc(struct sdhci_host *host, void **desc,
+					  dma_addr_t addr, int len,
+					  unsigned int cmd)
+{
+	int tmplen, offset;
+
+	pr_debug("write_desc: cmd %02x: len %d, offset 0x%0llx\n",
+		 cmd, len, addr);
+
+	if (likely(!len || BOUNDARY_OK(addr, len))) {
+		sdhci_adma_write_desc(host, desc, addr, len, cmd);
+		return;
+	}
+
+	pr_debug("write_desc: splitting dma len %d, offset 0x%0llx\n",
+		 len, addr);
+
+	offset = addr & (SZ_128M - 1);
+	tmplen = SZ_128M - offset;
+	sdhci_adma_write_desc(host, desc, addr, tmplen, cmd);
+
+	addr += tmplen;
+	len -= tmplen;
+	sdhci_adma_write_desc(host, desc, addr, len, cmd);
+}
+
+static void sparx5_set_cacheable(struct sdhci_host *host, u32 value)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sparx5_data *sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host);
+
+	pr_debug("%s: Set Cacheable = 0x%x\n", mmc_hostname(host->mmc), value);
+
+	/* Update ACP caching attributes in HW */
+	regmap_update_bits(sdhci_sparx5->cpu_ctrl,
+			   CPU_REGS_PROC_CTRL, ACP_CACHE_MASK, value);
+}
+
+static void sparx5_set_delay(struct sdhci_host *host, u8 value)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_sparx5_data *sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host);
+
+	pr_debug("%s: Set DLY_CC = %u\n", mmc_hostname(host->mmc), value);
+
+	/* Update DLY_CC in HW */
+	regmap_update_bits(sdhci_sparx5->cpu_ctrl,
+			   CPU_REGS_GENERAL_CTRL,
+			   MSHC_DLY_CC_MASK,
+			   (value << MSHC_DLY_CC_SHIFT));
+}
+
+static void sdhci_sparx5_set_emmc(struct sdhci_host *host)
+{
+	if (!mmc_card_is_removable(host->mmc)) {
+		u8 value;
+
+		value = sdhci_readb(host, MSHC2_EMMC_CTRL);
+		if (!(value & MSHC2_EMMC_CTRL_IS_EMMC)) {
+			pr_debug("Get EMMC_CTRL: 0x%08x\n", value);
+			value |= MSHC2_EMMC_CTRL_IS_EMMC;
+			pr_debug("Set EMMC_CTRL: 0x%08x\n", value);
+			sdhci_writeb(host, value, MSHC2_EMMC_CTRL);
+		}
+	}
+}
+
+static void sdhci_sparx5_reset_emmc(struct sdhci_host *host)
+{
+	u8 value;
+
+	pr_debug("Toggle EMMC_CTRL.EMMC_RST_N\n");
+	value = sdhci_readb(host, MSHC2_EMMC_CTRL) &
+		~MSHC2_EMMC_CTRL_EMMC_RST_N;
+	sdhci_writeb(host, value, MSHC2_EMMC_CTRL);
+	/* For eMMC, minimum is 1us but give it 10us for good measure */
+	udelay(10);
+	sdhci_writeb(host, value | MSHC2_EMMC_CTRL_EMMC_RST_N,
+		     MSHC2_EMMC_CTRL);
+	/* For eMMC, minimum is 200us but give it 300us for good measure */
+	udelay(300);
+}
+
+static void sdhci_sparx5_reset(struct sdhci_host *host, u8 mask)
+{
+	pr_debug("*** RESET: mask %d\n", mask);
+
+	sdhci_reset(host, mask);
+
+	/* Be sure CARD_IS_EMMC stays set */
+	sdhci_sparx5_set_emmc(host);
+}
+
+static const struct sdhci_ops sdhci_sparx5_ops = {
+#if defined(TRACE_REGISTER)
+	.write_l		= sdhci_sparx5_writel,
+	.write_w		= sdhci_sparx5_writew,
+	.write_b		= sdhci_sparx5_writeb,
+#endif
+	.set_clock		= sdhci_set_clock,
+	.set_bus_width		= sdhci_set_bus_width,
+	.set_uhs_signaling	= sdhci_set_uhs_signaling,
+	.get_max_clock		= sdhci_pltfm_clk_get_max_clock,
+	.reset			= sdhci_sparx5_reset,
+	.adma_write_desc	= sdhci_sparx5_adma_write_desc,
+};
+
+static const struct sdhci_pltfm_data sdhci_sparx5_pdata = {
+	.quirks  = 0,
+	.quirks2 = SDHCI_QUIRK2_HOST_NO_CMD23 | /* Card quirk */
+		   SDHCI_QUIRK2_NO_1_8_V, /* No sdr104, ddr50, etc */
+	.ops = &sdhci_sparx5_ops,
+};
+
+static ssize_t sparx5_delay_clock_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct sdhci_sparx5_data *sdhci_sparx5;
+
+	sdhci_sparx5 = container_of(attr, struct sdhci_sparx5_data,
+				     dev_delay_clock);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", sdhci_sparx5->delay_clock);
+}
+
+static ssize_t sparx5_delay_clock_store(struct device *dev,
+					 struct device_attribute *attr,
+					 const char *buf, size_t count)
+{
+	unsigned int delay_clock;
+	struct sdhci_sparx5_data *sdhci_sparx5;
+
+	sdhci_sparx5 = container_of(attr, struct sdhci_sparx5_data,
+				     dev_delay_clock);
+
+	if (kstrtoint(buf, 10, &delay_clock) ||
+	    delay_clock > MSHC_DLY_CC_MAX) {
+		dev_err(dev, "sdhci-of-sparx5: wrong parameter format.\n");
+		return -EINVAL;
+	}
+
+	sdhci_sparx5->delay_clock = delay_clock;
+	sparx5_set_delay(sdhci_sparx5->host, sdhci_sparx5->delay_clock);
+
+	return strlen(buf);
+}
+
+int sdhci_sparx5_probe(struct platform_device *pdev)
+{
+	int ret;
+	const char *syscon = "microchip,sparx5-cpu-syscon";
+	struct sdhci_host *host;
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_sparx5_data *sdhci_sparx5;
+	struct device_node *np = pdev->dev.of_node;
+	u32 value;
+	u32 extra;
+
+	host = sdhci_pltfm_init(pdev, &sdhci_sparx5_pdata,
+				sizeof(*sdhci_sparx5));
+
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	/*
+	 * extra adma table cnt for cross 128M boundary handling.
+	 */
+	extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M);
+	if (extra > SDHCI_MAX_SEGS)
+		extra = SDHCI_MAX_SEGS;
+	host->adma_table_cnt += extra;
+
+	pltfm_host = sdhci_priv(host);
+	sdhci_sparx5 = sdhci_pltfm_priv(pltfm_host);
+	sdhci_sparx5->host = host;
+
+	pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
+	if (IS_ERR(pltfm_host->clk)) {
+		ret = PTR_ERR(pltfm_host->clk);
+		dev_err(&pdev->dev, "failed to get core clk: %d\n", ret);
+		goto free_pltfm;
+	}
+	ret = clk_prepare_enable(pltfm_host->clk);
+	if (ret)
+		goto free_pltfm;
+
+	if (!of_property_read_u32(np, "microchip,clock-delay", &value) &&
+	    value <= MSHC_DLY_CC_MAX)
+		sdhci_sparx5->delay_clock = value;
+	else
+		sdhci_sparx5->delay_clock = -1; /* Autotune */
+
+	/* Sysfs delay_clock interface */
+	sdhci_sparx5->dev_delay_clock.show = sparx5_delay_clock_show;
+	sdhci_sparx5->dev_delay_clock.store = sparx5_delay_clock_store;
+	sysfs_attr_init(&sdhci_sparx5->dev_delay_clock.attr);
+	sdhci_sparx5->dev_delay_clock.attr.name = "delay_clock";
+	sdhci_sparx5->dev_delay_clock.attr.mode = 0644;
+	ret = device_create_file(&pdev->dev, &sdhci_sparx5->dev_delay_clock);
+	if (ret)
+		dev_err(&pdev->dev, "failure creating '%s' device file",
+			sdhci_sparx5->dev_delay_clock.attr.name);
+
+	sdhci_get_of_property(pdev);
+
+	ret = mmc_of_parse(host->mmc);
+	if (ret)
+		goto err_clk;
+
+	sdhci_sparx5->cpu_ctrl = syscon_regmap_lookup_by_compatible(syscon);
+	if (IS_ERR(sdhci_sparx5->cpu_ctrl)) {
+		dev_err(&pdev->dev, "No CPU syscon regmap !\n");
+		ret = PTR_ERR(sdhci_sparx5->cpu_ctrl);
+		goto err_clk;
+	}
+
+	if (sdhci_sparx5->delay_clock >= 0)
+		sparx5_set_delay(host, sdhci_sparx5->delay_clock);
+
+	if (!mmc_card_is_removable(host->mmc)) {
+		/* Do a HW reset of eMMC card */
+		sdhci_sparx5_reset_emmc(host);
+		/* Update EMMC_CTRL */
+		sdhci_sparx5_set_emmc(host);
+		/* If eMMC, disable SD and SDIO */
+		host->mmc->caps2 |= (MMC_CAP2_NO_SDIO|MMC_CAP2_NO_SD);
+	}
+
+	/* Enable v4 mode */
+	//sdhci_enable_v4_mode(host);
+
+	ret = sdhci_add_host(host);
+	if (ret)
+		dev_err(&pdev->dev, "sdhci_add_host() failed (%d)\n", ret);
+
+	/* Set AXI bus master to use un-cached access (for DMA) */
+	if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA) &&
+	    IS_ENABLED(CONFIG_DMA_DECLARE_COHERENT))
+		sparx5_set_cacheable(host, ACP_CACHE_FORCE_ENA);
+
+	pr_debug("SDHC version: 0x%08x\n", sdhci_readl(host, MSHC2_VERSION));
+	pr_debug("SDHC type:    0x%08x\n", sdhci_readl(host, MSHC2_TYPE));
+
+	return ret;
+
+err_clk:
+	clk_disable_unprepare(pltfm_host->clk);
+free_pltfm:
+	sdhci_pltfm_free(pdev);
+	return ret;
+}
+
+static const struct of_device_id sdhci_sparx5_of_match[] = {
+	{ .compatible = "microchip,dw-sparx5-sdhci" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sdhci_sparx5_of_match);
+
+static struct platform_driver sdhci_sparx5_driver = {
+	.driver = {
+		.name = "sdhci-sparx5",
+		.of_match_table = sdhci_sparx5_of_match,
+		.pm = &sdhci_pltfm_pmops,
+	},
+	.probe = sdhci_sparx5_probe,
+	.remove = sdhci_pltfm_unregister,
+};
+
+module_platform_driver(sdhci_sparx5_driver);
+
+MODULE_DESCRIPTION("Sparx5 SDHCI OF driver");
+MODULE_AUTHOR("Lars Povlsen <lars.povlsen@microchip.com>");
+MODULE_LICENSE("GPL v2");
--
2.26.2

^ permalink raw reply related

* Re: [PATCH v2] dt-bindings: timer: renesas: tmu: Convert to json-schema
From: Geert Uytterhoeven @ 2020-05-13 13:37 UTC (permalink / raw)
  To: Daniel Lezcano, Thomas Gleixner, Rob Herring
  Cc: Linux Kernel Mailing List,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Renesas, Geert Uytterhoeven
In-Reply-To: <20200505154944.4598-1-geert+renesas@glider.be>

On Tue, May 5, 2020 at 5:50 PM Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> Convert the Renesas R-Mobile/R-Car Timer Unit (TMU) Device Tree binding
> documentation to json-schema.
>
> Document missing properties.
> Update the example to match reality.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Reviewed-by: Rob Herring <robh@kernel.org>

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml

> +  '#renesas,channels':
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +      - enum: [ 2, 3 ]
> +      - default: 3

The "allOf" is no longer needed.  Will remove for v3.

> +    description:
> +      Number of channels implemented by the timer.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@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

* Re: [PATCH] i2c: pxa: implement generic i2c bus recovery
From: Russell King - ARM Linux admin @ 2020-05-13 13:37 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: linux-i2c, devicetree, Gregory Clement, Jason Cooper,
	linux-arm-kernel, Rob Herring, Sebastian Hesselbarth,
	Vladimir Vid
In-Reply-To: <20200513131843.GB499265@lunn.ch>

On Wed, May 13, 2020 at 03:18:43PM +0200, Andrew Lunn wrote:
> On Wed, May 13, 2020 at 10:33:12AM +0100, Russell King wrote:
> > Implement generic GPIO-based I2C bus recovery for the PXA I2C driver.
> 
> Hi Russell
> 
> I assume this is going to be merged via i2c? So Wolfram Sang?  He is
> not on To: or Cc:

Yes, just as my other patches I've posted to the linux-i2c list that
Wolfram has picked up.  I think he works from patchwork.

I assume Wolfram doesn't want to be Cc'd, as per the current setup in
MAINTAINERS.  If that's not the case, MAINTAINERS needs to be fixed.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 10.2Mbps down 587kbps up

^ permalink raw reply

* Re: [PATCH net-next v1] net: phy: tja11xx: add cable-test support
From: Andrew Lunn @ 2020-05-13 13:39 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Florian Fainelli, Heiner Kallweit, Mark Rutland, Rob Herring,
	Pengutronix Kernel Team, linux-kernel, David S. Miller, netdev,
	Marek Vasut, David Jander, devicetree
In-Reply-To: <20200513123440.19580-1-o.rempel@pengutronix.de>

On Wed, May 13, 2020 at 02:34:40PM +0200, Oleksij Rempel wrote:
> Add initial cable testing support.
> This PHY needs only 100usec for this test and it is recommended to run it
> before the link is up. For now, provide at least ethtool support, so it
> can be tested by more developers.
> 
> This patch was tested with TJA1102 PHY with following results:
> - No cable, is detected as open
> - 1m cable, with no connected other end and detected as open
> - a 40m cable (out of spec, max lenght should be 15m) is detected as OK.
> 
> Current patch do not provide polarity test support. This test would
> indicate not proper wire connection, where "+" wire of main phy is
> connected to the "-" wire of the link partner.
> 
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/net/phy/nxp-tja11xx.c | 106 +++++++++++++++++++++++++++++++++-
>  1 file changed, 105 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/phy/nxp-tja11xx.c b/drivers/net/phy/nxp-tja11xx.c
> index ca5f9d4dc57ed..8b743d25002b9 100644
> --- a/drivers/net/phy/nxp-tja11xx.c
> +++ b/drivers/net/phy/nxp-tja11xx.c
> @@ -5,6 +5,7 @@
>   */
>  #include <linux/delay.h>
>  #include <linux/ethtool.h>
> +#include <linux/ethtool_netlink.h>
>  #include <linux/kernel.h>
>  #include <linux/mdio.h>
>  #include <linux/mii.h>
> @@ -26,6 +27,7 @@
>  #define MII_ECTRL_POWER_MODE_NO_CHANGE	(0x0 << 11)
>  #define MII_ECTRL_POWER_MODE_NORMAL	(0x3 << 11)
>  #define MII_ECTRL_POWER_MODE_STANDBY	(0xc << 11)
> +#define MII_ECTRL_CABLE_TEST		BIT(5)
>  #define MII_ECTRL_CONFIG_EN		BIT(2)
>  #define MII_ECTRL_WAKE_REQUEST		BIT(0)
>  
> @@ -55,6 +57,11 @@
>  #define MII_GENSTAT			24
>  #define MII_GENSTAT_PLL_LOCKED		BIT(14)
>  
> +#define MII_EXTSTAT			25
> +#define MII_EXTSTAT_SHORT_DETECT	BIT(8)
> +#define MII_EXTSTAT_OPEN_DETECT		BIT(7)
> +#define MII_EXTSTAT_POLARITY_DETECT	BIT(6)
> +

Do these registers all conform to the standard? Can we pull this code
out into a library which all standards conformant PHY drivers can use?

The code itself looks O.K.

    Andrew

^ permalink raw reply

* [PATCH 0/3] hwmon: Adding support for Microchip Sparx5 SoC
From: Lars Povlsen @ 2020-05-13 13:41 UTC (permalink / raw)
  To: Guenter Roeck, SoC Team
  Cc: Lars Povlsen, Jean Delvare, Microchip Linux Driver Support,
	linux-hwmon, devicetree, linux-arm-kernel, linux-kernel

This is an add-on series to the main SoC Sparx5 series
(Message-ID: <20200513125532.24585-1-lars.povlsen@microchip.com>).

It is expected that the DT patches are to be taken directly by the arm-soc
maintainers.

Lars Povlsen (3):
  dt-bindings: hwmon: Add Sparx5 temperature sensor
  arm64: dts: sparx5: Add hwmon temperature sensor
  hwmon: sparx5: Add Sparx5 SoC temperature driver

 .../bindings/hwmon/microchip,sparx5-temp.yaml |  39 +++++
 arch/arm64/boot/dts/microchip/sparx5.dtsi     |   6 +
 drivers/hwmon/Kconfig                         |  10 ++
 drivers/hwmon/Makefile                        |   2 +-
 drivers/hwmon/sparx5-temp.c                   | 154 ++++++++++++++++++
 5 files changed, 210 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,sparx5-temp.yaml
 create mode 100644 drivers/hwmon/sparx5-temp.c

--
2.26.2

^ permalink raw reply

* [PATCH 1/3] dt-bindings: hwmon: Add Sparx5 temperature sensor
From: Lars Povlsen @ 2020-05-13 13:41 UTC (permalink / raw)
  To: Guenter Roeck, SoC Team, Rob Herring
  Cc: Lars Povlsen, Jean Delvare, Microchip Linux Driver Support,
	linux-hwmon, devicetree, linux-arm-kernel, linux-kernel,
	Alexandre Belloni
In-Reply-To: <20200513134140.25357-1-lars.povlsen@microchip.com>

This add the DT binding specification for the Sparx5 temperature
sensor.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 .../bindings/hwmon/microchip,sparx5-temp.yaml | 39 +++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/hwmon/microchip,sparx5-temp.yaml

diff --git a/Documentation/devicetree/bindings/hwmon/microchip,sparx5-temp.yaml b/Documentation/devicetree/bindings/hwmon/microchip,sparx5-temp.yaml
new file mode 100644
index 0000000000000..0df4813fd7b24
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwmon/microchip,sparx5-temp.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwmon/microchip,sparx5-temp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip Sparx5 Temperature Monitor
+
+maintainers:
+  - Lars Povlsen <lars.povlsen@microchip.com>
+
+description: |
+  Microchip Sparx5 embedded temperature monitor
+
+properties:
+  compatible:
+    enum:
+      - microchip,sparx5-temp
+
+  reg:
+    maxItems: 1
+
+  '#thermal-sensor-cells':
+    const: 0
+
+required:
+  - compatible
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    tmon0: tmon@610508110 {
+        compatible = "microchip,sparx5-temp";
+        reg = <0x10508110 0xc>;
+        #thermal-sensor-cells = <0>;
+    };
+
--
2.26.2

^ permalink raw reply related

* [PATCH 3/3] hwmon: sparx5: Add Sparx5 SoC temperature driver
From: Lars Povlsen @ 2020-05-13 13:41 UTC (permalink / raw)
  To: Guenter Roeck, SoC Team
  Cc: Lars Povlsen, Jean Delvare, Microchip Linux Driver Support,
	linux-hwmon, devicetree, linux-arm-kernel, linux-kernel,
	Alexandre Belloni
In-Reply-To: <20200513134140.25357-1-lars.povlsen@microchip.com>

This patch adds a temperature sensor driver to the Sparx5 SoC.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 drivers/hwmon/Kconfig       |  10 +++
 drivers/hwmon/Makefile      |   2 +-
 drivers/hwmon/sparx5-temp.c | 154 ++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+), 1 deletion(-)
 create mode 100644 drivers/hwmon/sparx5-temp.c

diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 4c62f900bf7e8..130cb1f1748ff 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -480,6 +480,16 @@ config SENSORS_I5K_AMB
 	  This driver can also be built as a module. If so, the module
 	  will be called i5k_amb.

+config SENSORS_SPARX5
+	tristate "Sparx5 SoC temperature sensor"
+	depends on ARCH_SPARX5
+	help
+	  If you say yes here you get support for temperature monitoring
+	  with the Microchip Sparx5 SoC.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called sparx5-temp.
+
 config SENSORS_F71805F
 	tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
 	depends on !PPC
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index b0b9c8e571762..28a09986b7a62 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -64,6 +64,7 @@ obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EMC1403)	+= emc1403.o
 obj-$(CONFIG_SENSORS_EMC2103)	+= emc2103.o
 obj-$(CONFIG_SENSORS_EMC6W201)	+= emc6w201.o
+obj-$(CONFIG_SENSORS_SPARX5)	+= sparx5-temp.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
@@ -190,4 +191,3 @@ obj-$(CONFIG_SENSORS_OCC)	+= occ/
 obj-$(CONFIG_PMBUS)		+= pmbus/

 ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
-
diff --git a/drivers/hwmon/sparx5-temp.c b/drivers/hwmon/sparx5-temp.c
new file mode 100644
index 0000000000000..bf9dd102a9825
--- /dev/null
+++ b/drivers/hwmon/sparx5-temp.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Sparx5 SoC temperature sensor driver
+ *
+ * Copyright (C) 2020 Lars Povlsen <lars.povlsen@microchip.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+#define TEMP_CTRL		0
+#define TEMP_CFG		4
+#define  TEMP_CFG_CYCLES	GENMASK(24, 15)
+#define  TEMP_CFG_CYCLES_OFF	15
+#define  TEMP_CFG_ENA		BIT(0)
+#define TEMP_STAT		8
+#define  TEMP_STAT_VALID	BIT(12)
+#define  TEMP_STAT_TEMP		GENMASK(11, 0)
+
+struct s5_hwmon {
+	void __iomem *base;
+};
+
+static void s5_temp_enable(struct s5_hwmon *hwmon)
+{
+	u32 val = readl(hwmon->base + TEMP_CFG);
+	u32 clk = 250;
+
+	val &= ~TEMP_CFG_CYCLES;
+	val |= (clk << TEMP_CFG_CYCLES_OFF);
+	val |= TEMP_CFG_ENA;
+
+	writel(val, hwmon->base + TEMP_CFG);
+}
+
+static void s5_temp_disable(void *data)
+{
+	struct s5_hwmon *hwmon = data;
+	u32 val = readl(hwmon->base + TEMP_CFG);
+
+	val &= ~TEMP_CFG_ENA;
+
+	writel(val, hwmon->base + TEMP_CFG);
+}
+
+static int s5_read(struct device *dev, enum hwmon_sensor_types type,
+		   u32 attr, int channel, long *temp)
+{
+	struct s5_hwmon *hwmon = dev_get_drvdata(dev);
+	int rc = 0, value;
+	u32 stat;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		stat = readl_relaxed(hwmon->base + TEMP_STAT);
+		if (stat & TEMP_STAT_VALID) {
+			value = (stat & TEMP_STAT_TEMP);
+			value = DIV_ROUND_CLOSEST(value * 3522, 4096) - 1094;
+			value *= 100;
+			*temp = value;
+		} else
+			rc = -EINVAL;
+		break;
+	default:
+		rc = -EOPNOTSUPP;
+	}
+
+	return rc;
+}
+
+static umode_t s5_is_visible(const void *_data, enum hwmon_sensor_types type,
+			     u32 attr, int channel)
+{
+	if (type != hwmon_temp)
+		return 0;
+
+	switch (attr) {
+	case hwmon_temp_input:
+		return 0444;
+	default:
+		return 0;
+	}
+}
+
+static const struct hwmon_channel_info *s5_info[] = {
+	HWMON_CHANNEL_INFO(chip,
+			   HWMON_C_REGISTER_TZ),
+	HWMON_CHANNEL_INFO(temp,
+			   HWMON_T_INPUT),
+	NULL
+};
+
+static const struct hwmon_ops s5_hwmon_ops = {
+	.is_visible = s5_is_visible,
+	.read = s5_read,
+};
+
+static const struct hwmon_chip_info s5_chip_info = {
+	.ops = &s5_hwmon_ops,
+	.info = s5_info,
+};
+
+static int s5_temp_probe(struct platform_device *pdev)
+{
+	struct device *hwmon_dev;
+	struct s5_hwmon *hwmon;
+	int err = 0;
+
+	hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL);
+	if (!hwmon)
+		return -ENOMEM;
+
+	hwmon->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(hwmon->base))
+		return PTR_ERR(hwmon->base);
+
+	err = devm_add_action(&pdev->dev, s5_temp_disable, hwmon);
+	if (err)
+		return err;
+
+	s5_temp_enable(hwmon);
+
+	hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev,
+							 "s5_temp",
+							 hwmon,
+							 &s5_chip_info,
+							 NULL);
+
+	return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+const struct of_device_id s5_temp_match[] = {
+	{ .compatible = "microchip,sparx5-temp" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s5_temp_match);
+
+static struct platform_driver s5_temp_driver = {
+	.probe = s5_temp_probe,
+	.driver = {
+		.name = "sparx5-temp",
+		.of_match_table = s5_temp_match,
+	},
+};
+
+module_platform_driver(s5_temp_driver);
+
+MODULE_AUTHOR("Lars Povlsen <lars.povlsen@microchip.com>");
+MODULE_DESCRIPTION("Sparx5 SoC temperature sensor driver");
+MODULE_LICENSE("GPL");
--
2.26.2

^ permalink raw reply related

* [PATCH 2/3] arm64: dts: sparx5: Add hwmon temperature sensor
From: Lars Povlsen @ 2020-05-13 13:41 UTC (permalink / raw)
  To: Guenter Roeck, SoC Team
  Cc: Lars Povlsen, Jean Delvare, Microchip Linux Driver Support,
	linux-hwmon, devicetree, linux-arm-kernel, linux-kernel,
	Alexandre Belloni
In-Reply-To: <20200513134140.25357-1-lars.povlsen@microchip.com>

This adds a hwmon temperature node sensor to the Sparx5 SoC.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 arch/arm64/boot/dts/microchip/sparx5.dtsi | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm64/boot/dts/microchip/sparx5.dtsi b/arch/arm64/boot/dts/microchip/sparx5.dtsi
index f09a49c41ce19..b5f2d088af30e 100644
--- a/arch/arm64/boot/dts/microchip/sparx5.dtsi
+++ b/arch/arm64/boot/dts/microchip/sparx5.dtsi
@@ -233,5 +233,11 @@ i2c1: i2c@600103000 {
 			clock-frequency = <100000>;
 			clocks = <&ahb_clk>;
 		};
+
+		tmon0: tmon@610508110 {
+			compatible = "microchip,sparx5-temp";
+			reg = <0x6 0x10508110 0xc>;
+			#thermal-sensor-cells = <0>;
+		};
 	};
 };
--
2.26.2

^ permalink raw reply related

* Re: [PATCH v3] dt-bindings: irqchip: renesas-intc-irqpin: Convert to json-schema
From: Geert Uytterhoeven @ 2020-05-13 13:42 UTC (permalink / raw)
  To: Rob Herring
  Cc: Thomas Gleixner, Jason Cooper, Marc Zyngier, Yoshihiro Kaneko,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Linux-Renesas, Linux Kernel Mailing List, Geert Uytterhoeven
In-Reply-To: <20200507075503.32291-1-geert+renesas@glider.be>

On Thu, May 7, 2020 at 9:55 AM Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> From: Yoshihiro Kaneko <ykaneko0929@gmail.com>
>
> Convert the Renesas Interrupt Controller (INTC) for external pins Device
> Tree binding documentation to json-schema.
>
> Signed-off-by: Yoshihiro Kaneko <ykaneko0929@gmail.com>
> Co-developed-by: Geert Uytterhoeven <geert+renesas@glider.be>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/interrupt-controller/renesas,intc-irqpin.yaml

> +  sense-bitfield-width:
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +      - enum: [2, 4]
> +        default: 4

The "allOf" is no longer needed.  Will remove for v4.

> +    description:
> +      Width of a single sense bitfield in the SENSE register, if different from the
> +      default.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@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

* Re: [PATCH] dt-bindings: clock: renesas: cpg: Convert to json-schema
From: Geert Uytterhoeven @ 2020-05-13 13:43 UTC (permalink / raw)
  To: Rob Herring
  Cc: Michael Turquette, Stephen Boyd,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	linux-clk, Linux-Renesas
In-Reply-To: <20200508100231.6575-1-geert+renesas@glider.be>

On Fri, May 8, 2020 at 12:02 PM Geert Uytterhoeven
<geert+renesas@glider.be> wrote:
> Convert the Renesas Clock Pulse Generator (CPG) Device Tree
> binding documentation to json-schema, combining support for:
>   - R-Mobile APE6 (R8A73A4) and A1 (R8A7740),
>   - R-Car M1 (R8A7778) and H1 (R8A7779),
>   - RZ/A1 (R7S72100),
>   - SH-Mobile AG5 (SH73A0).
>
> Keep the example for R-Mobile A1, which shows most properties.
> Drop the consumer examples, as they do not belong here.
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>

> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-clocks.yaml

> +  renesas,mode:
> +    description: Board-specific settings of the MD_CK* bits on R-Mobile A1
> +    allOf:
> +      - $ref: /schemas/types.yaml#/definitions/uint32
> +      - minimum: 0
> +        maximum: 7

The "allOf" is no longer needed.  Will remove for v2.

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@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

* Re: [PATCH] of/fdt: Remove redundant kbasename function call
From: Qi Zheng @ 2020-05-13 13:44 UTC (permalink / raw)
  To: robh+dt, frowand.list, robh; +Cc: devicetree, linux-kernel
In-Reply-To: <20200512154909.279788-1-arch0.zheng@gmail.com>

On 2020/5/12 下午11:49, Qi Zheng wrote:
> For version 1 to 3 of the device tree, this is the node full
> path as a zero terminated string, starting with "/". The
> following equation will not hold, since the node name has
> been processed in the fdt_get_name().
> 
> 	*pathp == '/'
> 
> For version 16 and later, this is the node unit name only
> (or an empty string for the root node). So the above
> equation will still not hold.
> 
> So the kbasename() is redundant, just remove it.
> 
> Signed-off-by: Qi Zheng <arch0.zheng@gmail.com>
> ---
>   drivers/of/fdt.c | 2 --
>   1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
> index 8a8e07a8f03d..ea31b2ae8474 100644
> --- a/drivers/of/fdt.c
> +++ b/drivers/of/fdt.c
> @@ -643,8 +643,6 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
>   	     offset = fdt_next_node(blob, offset, &depth)) {
>   
>   		pathp = fdt_get_name(blob, offset, NULL);
> -		if (*pathp == '/')
> -			pathp = kbasename(pathp);
>   		rc = it(offset, pathp, depth, data);
>   	}
>   	return rc;
> 

add Rob Herring <robh@kernel.org>.

^ permalink raw reply

* Re: [PATCH] video: fbdev: ssd1307fb: Added support to Column offset
From: Geert Uytterhoeven @ 2020-05-13 13:45 UTC (permalink / raw)
  To: Rodrigo Rolim Mendes de Alencar
  Cc: Linux Fbdev development list, Linux Kernel Mailing List,
	alencar.fmce, Andy Shevchenko, Rob Herring,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS
In-Reply-To: <1589370694-14327-1-git-send-email-alencar.fmce@imbel.gov.br>

CC dt

On Wed, May 13, 2020 at 1:52 PM Rodrigo Rolim Mendes de Alencar
<455.rodrigo.alencar@gmail.com> wrote:
> This patch provides support for displays like VGM128064B0W10,
> which requires a column offset of 2, i.e., its segments starts
> in SEG2 and ends in SEG129.
>
> Signed-off-by: Rodrigo Alencar <455.rodrigo.alencar@gmail.com>
> ---
>  Documentation/devicetree/bindings/display/ssd1307fb.txt | 1 +
>  drivers/video/fbdev/ssd1307fb.c                         | 8 ++++++--
>  2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/display/ssd1307fb.txt b/Documentation/devicetree/bindings/display/ssd1307fb.txt
> index 27333b9551b3..a9b51fd724a9 100644
> --- a/Documentation/devicetree/bindings/display/ssd1307fb.txt
> +++ b/Documentation/devicetree/bindings/display/ssd1307fb.txt
> @@ -19,6 +19,7 @@ Optional properties:
>    - vbat-supply: The supply for VBAT
>    - solomon,segment-no-remap: Display needs normal (non-inverted) data column
>                                to segment mapping
> +  - solomon,col-offset: Offset of columns (SEG) that the screen is mapped to.
>    - solomon,com-seq: Display uses sequential COM pin configuration
>    - solomon,com-lrremap: Display uses left-right COM pin remap
>    - solomon,com-invdir: Display uses inverted COM pin scan direction
> diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c
> index 8e06ba912d60..0241585bfbcc 100644
> --- a/drivers/video/fbdev/ssd1307fb.c
> +++ b/drivers/video/fbdev/ssd1307fb.c
> @@ -74,6 +74,7 @@ struct ssd1307fb_par {
>         struct fb_info *info;
>         u8 lookup_table[4];
>         u32 page_offset;
> +       u32 col_offset;
>         u32 prechargep1;
>         u32 prechargep2;
>         struct pwm_device *pwm;
> @@ -458,11 +459,11 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
>         if (ret < 0)
>                 return ret;
>
> -       ret = ssd1307fb_write_cmd(par->client, 0x0);
> +       ret = ssd1307fb_write_cmd(par->client, par->col_offset);
>         if (ret < 0)
>                 return ret;
>
> -       ret = ssd1307fb_write_cmd(par->client, par->width - 1);
> +       ret = ssd1307fb_write_cmd(par->client, par->col_offset + par->width - 1);
>         if (ret < 0)
>                 return ret;
>
> @@ -626,6 +627,9 @@ static int ssd1307fb_probe(struct i2c_client *client)
>         if (device_property_read_u32(dev, "solomon,page-offset", &par->page_offset))
>                 par->page_offset = 1;
>
> +       if (of_property_read_u32(node, "solomon,col-offset", &par->col_offset))
> +               par->col_offset = 0;
> +
>         if (device_property_read_u32(dev, "solomon,com-offset", &par->com_offset))
>                 par->com_offset = 0;

^ permalink raw reply

* Re: R: [PATCH v3 09/11] PCI: qcom: add ipq8064 rev2 variant and set tx term offset
From: Stanimir Varbanov @ 2020-05-13 13:49 UTC (permalink / raw)
  To: ansuelsmth, 'Bjorn Andersson'
  Cc: 'Sham Muthayyan', 'Andy Gross',
	'Bjorn Helgaas', 'Rob Herring',
	'Mark Rutland', 'Lorenzo Pieralisi',
	'Andrew Murray', 'Philipp Zabel', linux-arm-msm,
	linux-pci, devicetree, linux-kernel
In-Reply-To: <02df01d62925$acd160a0$067421e0$@gmail.com>



On 5/13/20 3:54 PM, ansuelsmth@gmail.com wrote:
>> Hi Ansuel,
>>
>> On 5/1/20 1:06 AM, Ansuel Smith wrote:
>>> From: Sham Muthayyan <smuthayy@codeaurora.org>
>>>
>>> Add tx term offset support to pcie qcom driver need in some revision of
>>> the ipq806x SoC.
>>> Ipq8064 have tx term offset set to 7.
>>> Ipq8064-v2 revision and ipq8065 have the tx term offset set to 0.
>>>
>>> Signed-off-by: Sham Muthayyan <smuthayy@codeaurora.org>
>>> Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
>>> ---
>>>  drivers/pci/controller/dwc/pcie-qcom.c | 15 +++++++++++++++
>>>  1 file changed, 15 insertions(+)
>>>
>>> diff --git a/drivers/pci/controller/dwc/pcie-qcom.c
>> b/drivers/pci/controller/dwc/pcie-qcom.c
>>> index da8058fd1925..372d2c8508b5 100644
>>> --- a/drivers/pci/controller/dwc/pcie-qcom.c
>>> +++ b/drivers/pci/controller/dwc/pcie-qcom.c
>>> @@ -45,6 +45,9 @@
>>>  #define PCIE_CAP_CPL_TIMEOUT_DISABLE		0x10
>>>
>>>  #define PCIE20_PARF_PHY_CTRL			0x40
>>> +#define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK	GENMASK(12,
>> 16)
>>
>> The mask definition is not correct. Should be GENMASK(20, 16)
>>
>>> +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x)		((x) << 16)
>>> +
>>>  #define PCIE20_PARF_PHY_REFCLK			0x4C
>>>  #define PHY_REFCLK_SSP_EN			BIT(16)
>>>  #define PHY_REFCLK_USE_PAD			BIT(12)
>>> @@ -118,6 +121,7 @@ struct qcom_pcie_resources_2_1_0 {
>>>  	u32 tx_swing_full;
>>>  	u32 tx_swing_low;
>>>  	u32 rx0_eq;
>>> +	u8 phy_tx0_term_offset;
>>>  };
>>>
>>>  struct qcom_pcie_resources_1_0_0 {
>>> @@ -318,6 +322,11 @@ static int
>> qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie)
>>>  	if (IS_ERR(res->ext_reset))
>>>  		return PTR_ERR(res->ext_reset);
>>>
>>> +	if (of_device_is_compatible(dev->of_node, "qcom,pcie-ipq8064"))
>>> +		res->phy_tx0_term_offset = 7;
>>
>> Before your change the phy_tx0_term_offser was 0 for apq8064, but here
>> you change it to 7, why?
>>
> 
> apq8064 board should use qcom,pcie-apq8064 right? This should be set to 0
> only with pcie-ipq8064 compatible. Tell me if I'm wrong.

Sorry, my fault. I read the compatible check above as apq8064 but it is ipq.

-- 
regards,
Stan

^ permalink raw reply

* [PATCH v1 0/3] fix macb phy probe failure if phy-reset is not handled
From: Sagar Shrikant Kadam @ 2020-05-13 13:56 UTC (permalink / raw)
  To: linux-kernel, linux-riscv, devicetree, robh+dt
  Cc: palmer, paul.walmsley, atish.patra, Sagar Shrikant Kadam

HiFive Unleashed is having VSC8541-01 ethernet phy device and requires a
specific reset sequence of 0-1-0-1 in order to use it in unmanaged mode.
This series addresses a corner case where phy reset is not handled by boot
stages prior to linux.
Somewhat similar unreliable phy probe failure was reported and discussed
here [1].
The macb driver fails to detect the ethernet phy device if the bootloader
doesn't provide a proper reset sequence to the phy device or the phy itself
is in some invalid state. Currently, the FSBL is resetting the phy device,
and so there is no issue observed in the linux network setup.

The series is based on linux-5.7-rc5.
Patch 1: Add the OUI to the phy dt node to fix issue of missing mdio device
Patch 2 and 3:
	Resetting phy needs GPIO support so add to dt and defconfig.

[1] https://lkml.org/lkml/2018/11/29/154

To reproduce the issue: 
1. Comment out VSC8541 reset sequence in fsbl/main.c
   from within the freedom-u540-c000-bootloader.
2. Build and flash fsbl.bin to micro sdcard.

Boot the board and bootlog will show network setup failure messages as:

[  1.069474] libphy: MACB_mii_bus: probed
[  1.073092] mdio_bus 10090000.ethernet-ffffffff: MDIO device at address 0
	       is missing 
.....
[  1.979252] macb 10090000.ethernet eth0: Could not attach PHY (-19)

3. Now apply the series build, and boot kernel.
4. MACB and VSC8541 driver get successfully probed and the network is set
   without any failure.


So irrespective of whether the prior stages handle the phy reset sequence,
the probing is successful in both the cases of cold boot and warm boot.

Change History:
===============================
V1:
-Ignore 4th patch as suggested and so removed it from the series.
-Verified this series on 5.7-rc5.

V0: Base RFC patch. Verified on 5.7-rc2


Sagar Shrikant Kadam (3):
  dts: phy: fix missing mdio device and probe failure of vsc8541-01
    device
  dts: phy: add GPIO number and active state used for phy reset
  riscv: defconfig: enable gpio support for HiFive Unleashed

 arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 2 ++
 arch/riscv/configs/defconfig                        | 2 ++
 2 files changed, 4 insertions(+)

-- 
2.7.4


^ permalink raw reply

* [PATCH v1 1/3] dts: phy: fix missing mdio device and probe failure of vsc8541-01 device
From: Sagar Shrikant Kadam @ 2020-05-13 13:56 UTC (permalink / raw)
  To: linux-kernel, linux-riscv, devicetree, robh+dt
  Cc: palmer, paul.walmsley, atish.patra, Sagar Shrikant Kadam
In-Reply-To: <1589378222-15238-1-git-send-email-sagar.kadam@sifive.com>

HiFive unleashed A00 board has VSC8541-01 ethernet phy, this device is
identified as a Revision B device as described in device identification
registers. In order to use this phy in the unmanaged mode, it requires
a specific reset sequence of logical 0-1-0-1 transition on the NRESET pin
as documented here [1].

Currently, the bootloader (fsbl) takes care of the phy reset. If due to
some reason the phy device hasn't received the reset by the prior stages
before the linux macb driver comes into the picture, the MACB mii bus gets
probed but the mdio scan fails and is not even able to read the phy ID
registers. It gives an error message:

"libphy: MACB_mii_bus: probed
mdio_bus 10090000.ethernet-ffffffff: MDIO device at address 0 is missing."

Thus adding the device OUI (Organizationally Unique Identifier) to the phy
device node helps to probe the phy device.

[1]: VSC8541-01 datasheet:
https://www.mouser.com/ds/2/523/Microsemi_VSC8541-01_Datasheet_10496_V40-1148034.pdf

Signed-off-by: Sagar Shrikant Kadam <sagar.kadam@sifive.com>
---
 arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
index 4a2729f..60846e8 100644
--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
@@ -88,6 +88,7 @@
 	phy-mode = "gmii";
 	phy-handle = <&phy0>;
 	phy0: ethernet-phy@0 {
+		compatible = "ethernet-phy-id0007.0771";
 		reg = <0>;
 	};
 };
-- 
2.7.4


^ permalink raw reply related

* [PATCH v1 2/3] dts: phy: add GPIO number and active state used for phy reset
From: Sagar Shrikant Kadam @ 2020-05-13 13:57 UTC (permalink / raw)
  To: linux-kernel, linux-riscv, devicetree, robh+dt
  Cc: palmer, paul.walmsley, atish.patra, Sagar Shrikant Kadam
In-Reply-To: <1589378222-15238-1-git-send-email-sagar.kadam@sifive.com>

The GEMGXL_RST line on HiFive Unleashed is pulled low and is
using GPIO number 12. Add these reset-gpio details to dt-node
using which the linux phylib can reset the phy.

Signed-off-by: Sagar Shrikant Kadam <sagar.kadam@sifive.com>
---
 arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
index 60846e8..24d75a1 100644
--- a/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
+++ b/arch/riscv/boot/dts/sifive/hifive-unleashed-a00.dts
@@ -90,6 +90,7 @@
 	phy0: ethernet-phy@0 {
 		compatible = "ethernet-phy-id0007.0771";
 		reg = <0>;
+		reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
 	};
 };
 
-- 
2.7.4


^ permalink raw reply related

* [PATCH v1 3/3] riscv: defconfig: enable gpio support for HiFive Unleashed
From: Sagar Shrikant Kadam @ 2020-05-13 13:57 UTC (permalink / raw)
  To: linux-kernel, linux-riscv, devicetree, robh+dt
  Cc: palmer, paul.walmsley, atish.patra, Sagar Shrikant Kadam
In-Reply-To: <1589378222-15238-1-git-send-email-sagar.kadam@sifive.com>

Ethernet phy VSC8541-01 on HiFive Unleashed has its reset line
connected to a gpio, so enable GPIO driver's required to reset
the phy.

Signed-off-by: Sagar Shrikant Kadam <sagar.kadam@sifive.com>
---
 arch/riscv/configs/defconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 4da4886..20c38b59 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -63,6 +63,8 @@ CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_VIRTIO=y
 CONFIG_SPI=y
 CONFIG_SPI_SIFIVE=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SIFIVE=y
 # CONFIG_PTP_1588_CLOCK is not set
 CONFIG_POWER_RESET=y
 CONFIG_DRM=y
-- 
2.7.4


^ permalink raw reply related

* [PATCH 00/10] spi: Adding support for Microchip Sparx5 SoC
From: Lars Povlsen @ 2020-05-13 14:00 UTC (permalink / raw)
  To: Mark Brown, SoC Team
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-spi,
	devicetree, linux-kernel, linux-arm-kernel

This is an add-on series to the main SoC Sparx5 series
(Message-ID: <20200513125532.24585-1-lars.povlsen@microchip.com>).

The series add support for Sparx5 on top of the existing
ocelot/jaguar2 spi driver.

It spins off the existing support for the MSCC platforms into a
separate driver, as adding new platforms from the MSCC/Microchip
product lines will further complicate (clutter) the original driver.

New YAML dt-bindings are provided for the resulting driver.

It is expected that the DT patches are to be taken directly by the arm-soc
maintainers.

Lars Povlsen (10):
  spi: dw: Add support for polled operation via no IRQ specified in DT
  spi: dw: Add support for RX sample delay register
  spi: dw: Add support for client driver memory operations
  dt-bindings: spi: Add bindings for spi-dw-mchp
  spi: spi-dw-mmio: Spin off MSCC platforms into spi-dw-mchp
  dt-bindings: spi: spi-dw-mchp: Add Sparx5 support
  spi: spi-dw-mchp: Add Sparx5 support
  arm64: dts: sparx5: Add SPI controller
  arm64: dts: sparx5: Add spi-nor support
  arm64: dts: sparx5: Add spi-nand devices

 .../bindings/spi/mscc,ocelot-spi.yaml         |  89 ++++
 .../bindings/spi/snps,dw-apb-ssi.txt          |   7 +-
 MAINTAINERS                                   |   2 +
 arch/arm64/boot/dts/microchip/sparx5.dtsi     |  37 ++
 .../boot/dts/microchip/sparx5_pcb125.dts      |  16 +
 .../boot/dts/microchip/sparx5_pcb134.dts      |  22 +
 .../dts/microchip/sparx5_pcb134_board.dtsi    |   9 +
 .../boot/dts/microchip/sparx5_pcb135.dts      |  23 +
 .../dts/microchip/sparx5_pcb135_board.dtsi    |   9 +
 arch/mips/configs/generic/board-ocelot.config |   2 +-
 drivers/spi/Kconfig                           |   7 +
 drivers/spi/Makefile                          |   1 +
 drivers/spi/spi-dw-mchp.c                     | 399 ++++++++++++++++++
 drivers/spi/spi-dw-mmio.c                     |  93 ----
 drivers/spi/spi-dw.c                          |  31 +-
 drivers/spi/spi-dw.h                          |   4 +
 16 files changed, 644 insertions(+), 107 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/spi/mscc,ocelot-spi.yaml
 create mode 100644 drivers/spi/spi-dw-mchp.c

--
2.26.2

^ permalink raw reply

* [PATCH 01/10] spi: dw: Add support for polled operation via no IRQ specified in DT
From: Lars Povlsen @ 2020-05-13 14:00 UTC (permalink / raw)
  To: Mark Brown, SoC Team
  Cc: Lars Povlsen, Microchip Linux Driver Support, linux-spi,
	devicetree, linux-kernel, linux-arm-kernel, Alexandre Belloni
In-Reply-To: <20200513140031.25633-1-lars.povlsen@microchip.com>

With this change a SPI controller can be added without having a IRQ
associated, and causing all transfers to be polled. For SPI controllers
without DMA, this can significantly improve performance by less
interrupt handling overhead.

Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Lars Povlsen <lars.povlsen@microchip.com>
---
 drivers/spi/spi-dw.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 31e3f866d11a7..e572eb34a3c1a 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -19,6 +19,8 @@
 #include <linux/debugfs.h>
 #endif

+#define VALID_IRQ(i) (i >= 0)
+
 /* Slave spi_dev related */
 struct chip_data {
 	u8 tmode;		/* TR/TO/RO/EEPROM */
@@ -359,7 +361,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
 			spi_enable_chip(dws, 1);
 			return ret;
 		}
-	} else if (!chip->poll_mode) {
+	} else if (!chip->poll_mode && VALID_IRQ(dws->irq)) {
 		txlevel = min_t(u16, dws->fifo_len / 2, dws->len / dws->n_bytes);
 		dw_writel(dws, DW_SPI_TXFLTR, txlevel);

@@ -379,7 +381,7 @@ static int dw_spi_transfer_one(struct spi_controller *master,
 			return ret;
 	}

-	if (chip->poll_mode)
+	if (chip->poll_mode || !VALID_IRQ(dws->irq))
 		return poll_transfer(dws);

 	return 1;
@@ -487,11 +489,13 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)

 	spi_controller_set_devdata(master, dws);

-	ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED, dev_name(dev),
-			  master);
-	if (ret < 0) {
-		dev_err(dev, "can not get IRQ\n");
-		goto err_free_master;
+	if (VALID_IRQ(dws->irq)) {
+		ret = request_irq(dws->irq, dw_spi_irq, IRQF_SHARED,
+				  dev_name(dev), master);
+		if (ret < 0) {
+			dev_err(dev, "can not get IRQ\n");
+			goto err_free_master;
+		}
 	}

 	master->use_gpio_descriptors = true;
@@ -539,7 +543,8 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
 	if (dws->dma_ops && dws->dma_ops->dma_exit)
 		dws->dma_ops->dma_exit(dws);
 	spi_enable_chip(dws, 0);
-	free_irq(dws->irq, master);
+	if (VALID_IRQ(dws->irq))
+		free_irq(dws->irq, master);
 err_free_master:
 	spi_controller_put(master);
 	return ret;
--
2.26.2

^ 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