All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/32] RISC-V Kendryte K210 support improvments
@ 2020-11-07  8:13 ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

This series of patches improves support for boards based on the Kendryte
K210 RISC-V dual core SoC. Minimal support for this SoC is already
included in the kernel. These patches complete it, enabling support for
most peripherals present on the SoC, as well as introducing device trees
for the various boards available on the market today from SiPeed and
Kendryte.

The first patch of this series is a fix of the device tree parsing code.
Without this fix, a warning is generated when parsing Designware gpio
controller nodes.

The following 6 patches are fixes and improvements to the Designware SPI
driver to enable support for the MMC-spi slot found on all K210 boards.

Pathes 8 to 13 are various fixes for riscv arch code and riscv
dependent devices. Of not here is patch 11 which fix system call
execution in the no MMU case, and patch 13 which simplifies DTB builtin
handling.

The following patches 14 to 25 implement and document idevice tree
mapping of several drivers for the K210 SoC: clock driver, reset
controller and pin function management (pinctrl).

Patches 26 to 31 update the existing K210 device tree and device new
device tree files for several K210 based boards: the MAIX Bit,
MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
development board from Kendryte.

Finally the last patch updates the k210 nommu defconfig to include
the newly implemented drivers.

A lot of the work on the device tree and on the K210 drivers come from
the work of Sean Anderson for the U-Boot project support of the K210
SoC. Sean also helped with debugging the idriver for the DesignWare SPIi
controller of the SoC.

A tree with all patches applied is available here:
https://github.com/damien-lemoal/linux (use the latest k210-sysctl-vXX
branch). A demonstration of this series used on a SiPeed MAIX Dock
board together with an I2C servo controller can be seen here:
https://damien-lemoal.github.io/linux-robot-arm/#example

This tree was used to build userspace busybox environment image that is
then copied onto SD card with ext2:
https://github.com/damien-lemoal/buildroot
Of note is that running this userspace environment requires a revert of
commit 2217b982624680d19a80ebb4600d05c8586c4f96 introduced during the
5.9 development cycle. Without this revert, execution of the init
process fails. A problem with the riscv port of elf2flt is suspected but
not confirmed. I am now starting to investigate this problem.

Reviews and comments are as always much welcome.


Damien Le Moal (32):
  of: Fix property supplier parsing
  spi: dw: Add support for 32-bits ctrlr0 layout
  spi: dw: Fix driving MOSI low while recieving
  spi: dw: Introduce polling device tree property
  spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
  spi: dw: Add support for the Kendryte K210 SoC
  dt-bindings: Update DW SPI device tree bindings
  riscv: Fix kernel time_init()
  riscv: Fix SiFive gpio probe
  riscv: Fix sifive serial driver
  riscv: Enable interrupts during syscalls with M-Mode
  riscv: Automatically select sysctl config options
  riscv: Fix builtin DTB handling
  dt-bindings: Define all Kendryte K210 clock IDs
  dt-bindings: Define Kendryte K210 sysctl registers
  dt-bindings: Define Kendryte K210 pin functions
  dt-bindings: Define Kendryte K210 reset signals
  riscv: Add Kendryte K210 SoC clock driver
  riscv: Add Kendryte K210 SoC reset controller
  riscv: Add Kendryte K210 FPIOA pinctrl driver
  dt-bindings: Add Kendryte and Canaan vendor prefix
  dt-binding: Document kendryte,k210-sysctl bindings
  dt-binding: Document kendryte,k210-clk bindings
  dt-bindings: Document kendryte,k210-fpioa bindings
  dt-bindings: Document kendryte,k210-rst bindings
  riscv: Update Kendryte K210 device tree
  riscv: Add SiPeed MAIX BiT board device tree
  riscv: Add SiPeed MAIX DOCK board device tree
  riscv: Add SiPeed MAIX GO board device tree
  riscv: Add SiPeed MAIXDUINO board device tree
  riscv: Add Kendryte KD233 board device tree
  riscv: Update Kendryte K210 defconfig

 .../bindings/clock/kendryte,k210-clk.yaml     |  70 ++
 .../bindings/mfd/kendryte,k210-sysctl.yaml    |  65 ++
 .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++
 .../bindings/reset/kendryte,k210-rst.yaml     |  78 ++
 .../bindings/spi/snps,dw-apb-ssi.yaml         |   5 +
 .../devicetree/bindings/vendor-prefixes.yaml  |   4 +
 arch/riscv/Kconfig.socs                       |  29 +-
 arch/riscv/boot/dts/kendryte/Makefile         |   5 +-
 arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
 arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++-
 arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 +
 arch/riscv/boot/dts/kendryte/k210_kd233.dts   | 177 ++++
 .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++
 .../boot/dts/kendryte/k210_maix_dock.dts      | 229 ++++
 arch/riscv/boot/dts/kendryte/k210_maix_go.dts | 237 +++++
 .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++
 arch/riscv/configs/nommu_k210_defconfig       |  45 +-
 arch/riscv/include/asm/soc.h                  |  38 -
 arch/riscv/kernel/entry.S                     |   9 +
 arch/riscv/kernel/soc.c                       |  27 -
 arch/riscv/kernel/time.c                      |   3 +
 arch/riscv/mm/init.c                          |   6 +-
 drivers/clk/Kconfig                           |   9 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-k210.c                        | 962 +++++++++++++++++
 drivers/gpio/gpio-sifive.c                    |   2 +-
 drivers/of/property.c                         |  17 +-
 drivers/pinctrl/Kconfig                       |  15 +
 drivers/pinctrl/Makefile                      |   1 +
 drivers/pinctrl/pinctrl-k210.c                | 999 ++++++++++++++++++
 drivers/reset/Kconfig                         |   9 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-k210.c                    | 186 ++++
 drivers/soc/Kconfig                           |   2 +-
 drivers/soc/kendryte/Kconfig                  |  19 +-
 drivers/soc/kendryte/Makefile                 |   2 +-
 drivers/soc/kendryte/k210-sysctl.c            | 253 +----
 drivers/spi/spi-dw-core.c                     |  22 +-
 drivers/spi/spi-dw-mmio.c                     |  20 +-
 drivers/spi/spi-dw.h                          |  10 +
 drivers/tty/serial/sifive.c                   |   1 +
 include/dt-bindings/clock/k210-clk.h          |  61 +-
 include/dt-bindings/mfd/k210-sysctl.h         |  41 +
 include/dt-bindings/pinctrl/k210-pinctrl.h    | 277 +++++
 include/dt-bindings/reset/k210-rst.h          |  42 +
 include/soc/kendryte/k210-sysctl.h            |  11 +
 46 files changed, 4770 insertions(+), 388 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
 create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
 delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_kd233.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_go.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts
 create mode 100644 drivers/clk/clk-k210.c
 create mode 100644 drivers/pinctrl/pinctrl-k210.c
 create mode 100644 drivers/reset/reset-k210.c
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
 create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h
 create mode 100644 include/dt-bindings/reset/k210-rst.h
 create mode 100644 include/soc/kendryte/k210-sysctl.h

-- 
2.28.0


^ permalink raw reply	[flat|nested] 297+ messages in thread

* [PATCH 00/32] RISC-V Kendryte K210 support improvments
@ 2020-11-07  8:13 ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

This series of patches improves support for boards based on the Kendryte
K210 RISC-V dual core SoC. Minimal support for this SoC is already
included in the kernel. These patches complete it, enabling support for
most peripherals present on the SoC, as well as introducing device trees
for the various boards available on the market today from SiPeed and
Kendryte.

The first patch of this series is a fix of the device tree parsing code.
Without this fix, a warning is generated when parsing Designware gpio
controller nodes.

The following 6 patches are fixes and improvements to the Designware SPI
driver to enable support for the MMC-spi slot found on all K210 boards.

Pathes 8 to 13 are various fixes for riscv arch code and riscv
dependent devices. Of not here is patch 11 which fix system call
execution in the no MMU case, and patch 13 which simplifies DTB builtin
handling.

The following patches 14 to 25 implement and document idevice tree
mapping of several drivers for the K210 SoC: clock driver, reset
controller and pin function management (pinctrl).

Patches 26 to 31 update the existing K210 device tree and device new
device tree files for several K210 based boards: the MAIX Bit,
MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
development board from Kendryte.

Finally the last patch updates the k210 nommu defconfig to include
the newly implemented drivers.

A lot of the work on the device tree and on the K210 drivers come from
the work of Sean Anderson for the U-Boot project support of the K210
SoC. Sean also helped with debugging the idriver for the DesignWare SPIi
controller of the SoC.

A tree with all patches applied is available here:
https://github.com/damien-lemoal/linux (use the latest k210-sysctl-vXX
branch). A demonstration of this series used on a SiPeed MAIX Dock
board together with an I2C servo controller can be seen here:
https://damien-lemoal.github.io/linux-robot-arm/#example

This tree was used to build userspace busybox environment image that is
then copied onto SD card with ext2:
https://github.com/damien-lemoal/buildroot
Of note is that running this userspace environment requires a revert of
commit 2217b982624680d19a80ebb4600d05c8586c4f96 introduced during the
5.9 development cycle. Without this revert, execution of the init
process fails. A problem with the riscv port of elf2flt is suspected but
not confirmed. I am now starting to investigate this problem.

Reviews and comments are as always much welcome.


Damien Le Moal (32):
  of: Fix property supplier parsing
  spi: dw: Add support for 32-bits ctrlr0 layout
  spi: dw: Fix driving MOSI low while recieving
  spi: dw: Introduce polling device tree property
  spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
  spi: dw: Add support for the Kendryte K210 SoC
  dt-bindings: Update DW SPI device tree bindings
  riscv: Fix kernel time_init()
  riscv: Fix SiFive gpio probe
  riscv: Fix sifive serial driver
  riscv: Enable interrupts during syscalls with M-Mode
  riscv: Automatically select sysctl config options
  riscv: Fix builtin DTB handling
  dt-bindings: Define all Kendryte K210 clock IDs
  dt-bindings: Define Kendryte K210 sysctl registers
  dt-bindings: Define Kendryte K210 pin functions
  dt-bindings: Define Kendryte K210 reset signals
  riscv: Add Kendryte K210 SoC clock driver
  riscv: Add Kendryte K210 SoC reset controller
  riscv: Add Kendryte K210 FPIOA pinctrl driver
  dt-bindings: Add Kendryte and Canaan vendor prefix
  dt-binding: Document kendryte,k210-sysctl bindings
  dt-binding: Document kendryte,k210-clk bindings
  dt-bindings: Document kendryte,k210-fpioa bindings
  dt-bindings: Document kendryte,k210-rst bindings
  riscv: Update Kendryte K210 device tree
  riscv: Add SiPeed MAIX BiT board device tree
  riscv: Add SiPeed MAIX DOCK board device tree
  riscv: Add SiPeed MAIX GO board device tree
  riscv: Add SiPeed MAIXDUINO board device tree
  riscv: Add Kendryte KD233 board device tree
  riscv: Update Kendryte K210 defconfig

 .../bindings/clock/kendryte,k210-clk.yaml     |  70 ++
 .../bindings/mfd/kendryte,k210-sysctl.yaml    |  65 ++
 .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++
 .../bindings/reset/kendryte,k210-rst.yaml     |  78 ++
 .../bindings/spi/snps,dw-apb-ssi.yaml         |   5 +
 .../devicetree/bindings/vendor-prefixes.yaml  |   4 +
 arch/riscv/Kconfig.socs                       |  29 +-
 arch/riscv/boot/dts/kendryte/Makefile         |   5 +-
 arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
 arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++-
 arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 +
 arch/riscv/boot/dts/kendryte/k210_kd233.dts   | 177 ++++
 .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++
 .../boot/dts/kendryte/k210_maix_dock.dts      | 229 ++++
 arch/riscv/boot/dts/kendryte/k210_maix_go.dts | 237 +++++
 .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++
 arch/riscv/configs/nommu_k210_defconfig       |  45 +-
 arch/riscv/include/asm/soc.h                  |  38 -
 arch/riscv/kernel/entry.S                     |   9 +
 arch/riscv/kernel/soc.c                       |  27 -
 arch/riscv/kernel/time.c                      |   3 +
 arch/riscv/mm/init.c                          |   6 +-
 drivers/clk/Kconfig                           |   9 +
 drivers/clk/Makefile                          |   1 +
 drivers/clk/clk-k210.c                        | 962 +++++++++++++++++
 drivers/gpio/gpio-sifive.c                    |   2 +-
 drivers/of/property.c                         |  17 +-
 drivers/pinctrl/Kconfig                       |  15 +
 drivers/pinctrl/Makefile                      |   1 +
 drivers/pinctrl/pinctrl-k210.c                | 999 ++++++++++++++++++
 drivers/reset/Kconfig                         |   9 +
 drivers/reset/Makefile                        |   1 +
 drivers/reset/reset-k210.c                    | 186 ++++
 drivers/soc/Kconfig                           |   2 +-
 drivers/soc/kendryte/Kconfig                  |  19 +-
 drivers/soc/kendryte/Makefile                 |   2 +-
 drivers/soc/kendryte/k210-sysctl.c            | 253 +----
 drivers/spi/spi-dw-core.c                     |  22 +-
 drivers/spi/spi-dw-mmio.c                     |  20 +-
 drivers/spi/spi-dw.h                          |  10 +
 drivers/tty/serial/sifive.c                   |   1 +
 include/dt-bindings/clock/k210-clk.h          |  61 +-
 include/dt-bindings/mfd/k210-sysctl.h         |  41 +
 include/dt-bindings/pinctrl/k210-pinctrl.h    | 277 +++++
 include/dt-bindings/reset/k210-rst.h          |  42 +
 include/soc/kendryte/k210-sysctl.h            |  11 +
 46 files changed, 4770 insertions(+), 388 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
 create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
 create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
 delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_kd233.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_go.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts
 create mode 100644 drivers/clk/clk-k210.c
 create mode 100644 drivers/pinctrl/pinctrl-k210.c
 create mode 100644 drivers/reset/reset-k210.c
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
 create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h
 create mode 100644 include/dt-bindings/reset/k210-rst.h
 create mode 100644 include/soc/kendryte/k210-sysctl.h

-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* [PATCH 01/32] of: Fix property supplier parsing
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

The DesignWare GPIO driver gpio-dwapb ("snps,dw-apb-gpio" or
"apm,xgene-gpio-v2" compatible string) defines the property
"snps,nr-gpios" for the user to specify the number of GPIOs available
on a port. The "-gpios" suffix of this property name ends up being
interpreted as a cell reference when properties are parsed in
of_link_to_suppliers(), leading to error messages such as:

OF: /soc/bus@50200000/gpio-controller@50200000/gpio-port@0: could not
find phandle

Fix this by manually defining a parse_gpios() function which ignores
this property, skipping the search for the supplier and thus avoiding
the device tree parsing error.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/of/property.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 408a7b5f06a9..d16111c0d6da 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
 DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
 DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
 DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
-DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
 
 static struct device_node *parse_iommu_maps(struct device_node *np,
 					    const char *prop_name, int index)
@@ -1319,6 +1318,22 @@ static struct device_node *parse_iommu_maps(struct device_node *np,
 	return of_parse_phandle(np, prop_name, (index * 4) + 1);
 }
 
+static struct device_node *parse_gpios(struct device_node *np,
+				       const char *prop_name, int index)
+{
+	/*
+	 * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
+	 * the "snps,nr-gpios" property to indicate the total number of GPIOs
+	 * available. As this conflict with "xx-gpios" reference properties,
+	 * ignore it.
+	 */
+	if (strcmp(prop_name, "snps,nr-gpios") == 0)
+		return NULL;
+
+	return parse_suffix_prop_cells(np, prop_name, index,
+				       "-gpios", "#gpio-cells");
+}
+
 static const struct supplier_bindings of_supplier_bindings[] = {
 	{ .parse_prop = parse_clocks, },
 	{ .parse_prop = parse_interconnects, },
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

The DesignWare GPIO driver gpio-dwapb ("snps,dw-apb-gpio" or
"apm,xgene-gpio-v2" compatible string) defines the property
"snps,nr-gpios" for the user to specify the number of GPIOs available
on a port. The "-gpios" suffix of this property name ends up being
interpreted as a cell reference when properties are parsed in
of_link_to_suppliers(), leading to error messages such as:

OF: /soc/bus@50200000/gpio-controller@50200000/gpio-port@0: could not
find phandle

Fix this by manually defining a parse_gpios() function which ignores
this property, skipping the search for the supplier and thus avoiding
the device tree parsing error.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/of/property.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/of/property.c b/drivers/of/property.c
index 408a7b5f06a9..d16111c0d6da 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
 DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
 DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
 DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
-DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
 
 static struct device_node *parse_iommu_maps(struct device_node *np,
 					    const char *prop_name, int index)
@@ -1319,6 +1318,22 @@ static struct device_node *parse_iommu_maps(struct device_node *np,
 	return of_parse_phandle(np, prop_name, (index * 4) + 1);
 }
 
+static struct device_node *parse_gpios(struct device_node *np,
+				       const char *prop_name, int index)
+{
+	/*
+	 * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
+	 * the "snps,nr-gpios" property to indicate the total number of GPIOs
+	 * available. As this conflict with "xx-gpios" reference properties,
+	 * ignore it.
+	 */
+	if (strcmp(prop_name, "snps,nr-gpios") == 0)
+		return NULL;
+
+	return parse_suffix_prop_cells(np, prop_name, index,
+				       "-gpios", "#gpio-cells");
+}
+
 static const struct supplier_bindings of_supplier_bindings[] = {
 	{ .parse_prop = parse_clocks, },
 	{ .parse_prop = parse_interconnects, },
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
the ctrlr0 register for SPI masters. The layout of ctrlr0 is:

|   31 .. 23  | 22 .. 21 | 20 .. 16 |
| other stuff | spi_frf  |  dfs_32  |

|   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
| other stuff |  tmod  |  mode  |  frf   |  dfs   |

Th main difference of this layout with the 16-bits version is the data
frame format field which resides in bits 16..20 instead of bits 3..0.

Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
platform signal that this layout is in use. Modify
dw_spi_update_config() to test this capability flag to set the data
frame format field at the correct register location.

Suggested-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 8 ++++++--
 drivers/spi/spi-dw.h      | 9 +++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 2e50cc0a9291..841c85247f01 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
 	u32 speed_hz;
 	u16 clk_div;
 
-	/* CTRLR0[ 4/3: 0] Data Frame Size */
-	cr0 |= (cfg->dfs - 1);
+	if (!(dws->caps & DW_SPI_CAP_DFS_32))
+		/* CTRLR0[ 4/3: 0] Data Frame Size */
+		cr0 |= (cfg->dfs - 1);
+	else
+		/* CTRLR0[20: 16] Data Frame Size */
+		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
 
 	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
 		/* CTRLR0[ 9:8] Transfer Mode */
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index faf40cb66498..48a11a51a407 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -9,6 +9,7 @@
 #include <linux/io.h>
 #include <linux/scatterlist.h>
 #include <linux/spi/spi-mem.h>
+#include <linux/bitfield.h>
 
 /* Register offsets */
 #define DW_SPI_CTRLR0			0x00
@@ -72,6 +73,13 @@
 #define DWC_SSI_CTRLR0_FRF_OFFSET	6
 #define DWC_SSI_CTRLR0_DFS_OFFSET	0
 
+/*
+ * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
+ * Based on DW_apb_ssi Databook v4.02a.
+ */
+#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
+#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
+
 /*
  * For Keem Bay, CTRLR0[31] is used to select controller mode.
  * 0: SSI is slave
@@ -121,6 +129,7 @@ enum dw_ssi_type {
 #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
 #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
 #define DW_SPI_CAP_DWC_SSI		BIT(2)
+#define DW_SPI_CAP_DFS_32		BIT(3)
 
 /* Slave spi_transfer/spi_mem_op related */
 struct dw_spi_cfg {
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
the ctrlr0 register for SPI masters. The layout of ctrlr0 is:

|   31 .. 23  | 22 .. 21 | 20 .. 16 |
| other stuff | spi_frf  |  dfs_32  |

|   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
| other stuff |  tmod  |  mode  |  frf   |  dfs   |

Th main difference of this layout with the 16-bits version is the data
frame format field which resides in bits 16..20 instead of bits 3..0.

Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
platform signal that this layout is in use. Modify
dw_spi_update_config() to test this capability flag to set the data
frame format field at the correct register location.

Suggested-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 8 ++++++--
 drivers/spi/spi-dw.h      | 9 +++++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 2e50cc0a9291..841c85247f01 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
 	u32 speed_hz;
 	u16 clk_div;
 
-	/* CTRLR0[ 4/3: 0] Data Frame Size */
-	cr0 |= (cfg->dfs - 1);
+	if (!(dws->caps & DW_SPI_CAP_DFS_32))
+		/* CTRLR0[ 4/3: 0] Data Frame Size */
+		cr0 |= (cfg->dfs - 1);
+	else
+		/* CTRLR0[20: 16] Data Frame Size */
+		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
 
 	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
 		/* CTRLR0[ 9:8] Transfer Mode */
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index faf40cb66498..48a11a51a407 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -9,6 +9,7 @@
 #include <linux/io.h>
 #include <linux/scatterlist.h>
 #include <linux/spi/spi-mem.h>
+#include <linux/bitfield.h>
 
 /* Register offsets */
 #define DW_SPI_CTRLR0			0x00
@@ -72,6 +73,13 @@
 #define DWC_SSI_CTRLR0_FRF_OFFSET	6
 #define DWC_SSI_CTRLR0_DFS_OFFSET	0
 
+/*
+ * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
+ * Based on DW_apb_ssi Databook v4.02a.
+ */
+#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
+#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
+
 /*
  * For Keem Bay, CTRLR0[31] is used to select controller mode.
  * 0: SSI is slave
@@ -121,6 +129,7 @@ enum dw_ssi_type {
 #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
 #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
 #define DW_SPI_CAP_DWC_SSI		BIT(2)
+#define DW_SPI_CAP_DFS_32		BIT(3)
 
 /* Slave spi_transfer/spi_mem_op related */
 struct dw_spi_cfg {
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Fix for the Synopsis DesignWare SPI mmio driver taken from the work
by Sean Anderson for the U-Boot project. Sean comments:

The resting state of MOSI is high when nothing is driving it. If we
drive it low while recieving, it looks like we are transmitting 0x00
instead of transmitting nothing. This can confuse slaves (like SD cards)
which allow new commands to be sent over MOSI while they are returning
data over MISO. The return of MOSI from 0 to 1 at the end of recieving
a byte can look like a start bit and a transmission bit to an SD card.
This will cause the card to become out-of-sync with the SPI device, as
it thinks the device has already started transmitting two bytes of a new
command. The mmc-spi driver will not detect the R1 response from the SD
card, since it is sent too early, and offset by two bits. This patch
fixes transfer errors when using SD cards with dw spi.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 841c85247f01..c2ef1d8d46d5 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -137,7 +137,7 @@ static inline u32 rx_max(struct dw_spi *dws)
 static void dw_writer(struct dw_spi *dws)
 {
 	u32 max = tx_max(dws);
-	u16 txw = 0;
+	u16 txw = 0xffff;
 
 	while (max--) {
 		if (dws->tx) {
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Fix for the Synopsis DesignWare SPI mmio driver taken from the work
by Sean Anderson for the U-Boot project. Sean comments:

The resting state of MOSI is high when nothing is driving it. If we
drive it low while recieving, it looks like we are transmitting 0x00
instead of transmitting nothing. This can confuse slaves (like SD cards)
which allow new commands to be sent over MOSI while they are returning
data over MISO. The return of MOSI from 0 to 1 at the end of recieving
a byte can look like a start bit and a transmission bit to an SD card.
This will cause the card to become out-of-sync with the SPI device, as
it thinks the device has already started transmitting two bytes of a new
command. The mmc-spi driver will not detect the R1 response from the SD
card, since it is sent too early, and offset by two bits. This patch
fixes transfer errors when using SD cards with dw spi.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 841c85247f01..c2ef1d8d46d5 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -137,7 +137,7 @@ static inline u32 rx_max(struct dw_spi *dws)
 static void dw_writer(struct dw_spi *dws)
 {
 	u32 max = tx_max(dws);
-	u16 txw = 0;
+	u16 txw = 0xffff;
 
 	while (max--) {
 		if (dws->tx) {
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

With boards that have slow interrupts context switch, and a fast device
connected to a spi master, e.g. an SD card through mmc-spi, using
dw_spi_poll_transfer() intead of the regular interrupt based
dw_spi_transfer_handler() function is more efficient and can avoid a lot
of RX FIFO overflow errors while keeping the device SPI frequency
reasonnably high (for speed). Introduce the "polling" device tree
property to allow requesting polled processing of transfer depending on
the connected device while keeping the spi master interrupts property
unschanged. E.g. device trees such as:

Generic soc.dtsi dts:

spi0: spi@53000000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "snps,dw-apb-ssi";
	reg = <0x53000000 0x100>;
	interrupts = <2>;
	...
}

Board specific dts:

...
&spi0 {
	polling;
	status = "okay";

	slot@0 {
		compatible = "mmc-spi-slot";
		reg = <0>;
		voltage-ranges = <3300 3300>;
		spi-max-frequency = <4000000>;
	};
}

will result in using polled transfers for the SD card while other boards
using spi0 for different peripherals can use interrupt based transfers
without needing to change the generic base soc dts.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-mmio.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..3f1bc384cb45 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -20,6 +20,7 @@
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
+#include <linux/interrupt.h>
 
 #include "spi-dw.h"
 
@@ -246,9 +247,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 
 	dws->paddr = mem->start;
 
-	dws->irq = platform_get_irq(pdev, 0);
-	if (dws->irq < 0)
-		return dws->irq; /* -ENXIO */
+	if (device_property_read_bool(&pdev->dev, "polling")) {
+		dws->irq = IRQ_NOTCONNECTED;
+	} else {
+		dws->irq = platform_get_irq(pdev, 0);
+		if (dws->irq < 0)
+			return dws->irq; /* -ENXIO */
+	}
 
 	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dwsmmio->clk))
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

With boards that have slow interrupts context switch, and a fast device
connected to a spi master, e.g. an SD card through mmc-spi, using
dw_spi_poll_transfer() intead of the regular interrupt based
dw_spi_transfer_handler() function is more efficient and can avoid a lot
of RX FIFO overflow errors while keeping the device SPI frequency
reasonnably high (for speed). Introduce the "polling" device tree
property to allow requesting polled processing of transfer depending on
the connected device while keeping the spi master interrupts property
unschanged. E.g. device trees such as:

Generic soc.dtsi dts:

spi0: spi@53000000 {
	#address-cells = <1>;
	#size-cells = <0>;
	compatible = "snps,dw-apb-ssi";
	reg = <0x53000000 0x100>;
	interrupts = <2>;
	...
}

Board specific dts:

...
&spi0 {
	polling;
	status = "okay";

	slot@0 {
		compatible = "mmc-spi-slot";
		reg = <0>;
		voltage-ranges = <3300 3300>;
		spi-max-frequency = <4000000>;
	};
}

will result in using polled transfers for the SD card while other boards
using spi0 for different peripherals can use interrupt based transfers
without needing to change the generic base soc dts.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-mmio.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..3f1bc384cb45 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -20,6 +20,7 @@
 #include <linux/property.h>
 #include <linux/regmap.h>
 #include <linux/reset.h>
+#include <linux/interrupt.h>
 
 #include "spi-dw.h"
 
@@ -246,9 +247,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
 
 	dws->paddr = mem->start;
 
-	dws->irq = platform_get_irq(pdev, 0);
-	if (dws->irq < 0)
-		return dws->irq; /* -ENXIO */
+	if (device_property_read_bool(&pdev->dev, "polling")) {
+		dws->irq = IRQ_NOTCONNECTED;
+	} else {
+		dws->irq = platform_get_irq(pdev, 0);
+		if (dws->irq < 0)
+			return dws->irq; /* -ENXIO */
+	}
 
 	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(dwsmmio->clk))
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

On slow systems, i.e. systems with a slow CPU resulting in slow context
switches, calling spi_delay_exec() when executing polled transfers
using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
platforms to opt out of delayed polling by introducing the
DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
the execution of spi_delay_exec() in dw_spi_poll_transfer().

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 12 ++++++++----
 drivers/spi/spi-dw.h      |  1 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index c2ef1d8d46d5..16a6fd569145 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -385,14 +385,18 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
 	u16 nbits;
 	int ret;
 
-	delay.unit = SPI_DELAY_UNIT_SCK;
-	nbits = dws->n_bytes * BITS_PER_BYTE;
+	if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
+		delay.unit = SPI_DELAY_UNIT_SCK;
+		nbits = dws->n_bytes * BITS_PER_BYTE;
+	}
 
 	do {
 		dw_writer(dws);
 
-		delay.value = nbits * (dws->rx_len - dws->tx_len);
-		spi_delay_exec(&delay, transfer);
+		if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
+			delay.value = nbits * (dws->rx_len - dws->tx_len);
+			spi_delay_exec(&delay, transfer);
+		}
 
 		dw_reader(dws);
 
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 48a11a51a407..25f6372b993a 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -130,6 +130,7 @@ enum dw_ssi_type {
 #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
 #define DW_SPI_CAP_DWC_SSI		BIT(2)
 #define DW_SPI_CAP_DFS_32		BIT(3)
+#define DW_SPI_CAP_POLL_NODELAY		BIT(4)
 
 /* Slave spi_transfer/spi_mem_op related */
 struct dw_spi_cfg {
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

On slow systems, i.e. systems with a slow CPU resulting in slow context
switches, calling spi_delay_exec() when executing polled transfers
using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
platforms to opt out of delayed polling by introducing the
DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
the execution of spi_delay_exec() in dw_spi_poll_transfer().

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-core.c | 12 ++++++++----
 drivers/spi/spi-dw.h      |  1 +
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index c2ef1d8d46d5..16a6fd569145 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -385,14 +385,18 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
 	u16 nbits;
 	int ret;
 
-	delay.unit = SPI_DELAY_UNIT_SCK;
-	nbits = dws->n_bytes * BITS_PER_BYTE;
+	if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
+		delay.unit = SPI_DELAY_UNIT_SCK;
+		nbits = dws->n_bytes * BITS_PER_BYTE;
+	}
 
 	do {
 		dw_writer(dws);
 
-		delay.value = nbits * (dws->rx_len - dws->tx_len);
-		spi_delay_exec(&delay, transfer);
+		if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
+			delay.value = nbits * (dws->rx_len - dws->tx_len);
+			spi_delay_exec(&delay, transfer);
+		}
 
 		dw_reader(dws);
 
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 48a11a51a407..25f6372b993a 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -130,6 +130,7 @@ enum dw_ssi_type {
 #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
 #define DW_SPI_CAP_DWC_SSI		BIT(2)
 #define DW_SPI_CAP_DFS_32		BIT(3)
+#define DW_SPI_CAP_POLL_NODELAY		BIT(4)
 
 /* Slave spi_transfer/spi_mem_op related */
 struct dw_spi_cfg {
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
ctrlr0 register format. This SoC is also quite slow and gets significant
SD card performance improvements from using no-delay polled transfers.
Add the dw_spi_k210_init() function tied to the
"canaan,kendryte-k210-spi" compatible string to set the
DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
for this SoC.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-mmio.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 3f1bc384cb45..a00def6c5b39 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
 	return 0;
 }
 
+static int dw_spi_k210_init(struct platform_device *pdev,
+			    struct dw_spi_mmio *dwsmmio)
+{
+	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
+
+	return 0;
+}
+
 static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
 	int (*init_func)(struct platform_device *pdev,
@@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
 	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
 	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
 	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
+	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
 	{ /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
ctrlr0 register format. This SoC is also quite slow and gets significant
SD card performance improvements from using no-delay polled transfers.
Add the dw_spi_k210_init() function tied to the
"canaan,kendryte-k210-spi" compatible string to set the
DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
for this SoC.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/spi/spi-dw-mmio.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 3f1bc384cb45..a00def6c5b39 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
 	return 0;
 }
 
+static int dw_spi_k210_init(struct platform_device *pdev,
+			    struct dw_spi_mmio *dwsmmio)
+{
+	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
+
+	return 0;
+}
+
 static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
 	int (*init_func)(struct platform_device *pdev,
@@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
 	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
 	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
 	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
+	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
 	{ /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 07/32] dt-bindings: Update DW SPI device tree bindings
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the polling propetry which is used to force the use of polled
transfers, ignoring the device interrupt property.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
index 99ed9b416e94..890a160a253f 100644
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -120,6 +120,11 @@ properties:
       This value will be used if the property is not explicitly defined
       for a SPI slave device. See below.
 
+  polling:
+    default: false
+    description: Ignore the device interrupt and force the use of polled
+      transfers.
+
 patternProperties:
   "^.*@[0-9a-f]+$":
     type: object
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 07/32] dt-bindings: Update DW SPI device tree bindings
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the polling propetry which is used to force the use of polled
transfers, ignoring the device interrupt property.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
index 99ed9b416e94..890a160a253f 100644
--- a/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
+++ b/Documentation/devicetree/bindings/spi/snps,dw-apb-ssi.yaml
@@ -120,6 +120,11 @@ properties:
       This value will be used if the property is not explicitly defined
       for a SPI slave device. See below.
 
+  polling:
+    default: false
+    description: Ignore the device interrupt and force the use of polled
+      transfers.
+
 patternProperties:
   "^.*@[0-9a-f]+$":
     type: object
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

If of_clk_init() is not called in time_init(), clock providers defined
in the system device tree are not initialized, resulting in failures for
other devices to initialize due to missing clocks.
Similarly to other architectures and to the default kernel time_init()
implementation, call of_clk_init() before executing timer_probe() in
time_init().

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/kernel/time.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
index 4d3a1048ad8b..8a5cf99c0776 100644
--- a/arch/riscv/kernel/time.c
+++ b/arch/riscv/kernel/time.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/of_clk.h>
 #include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <asm/sbi.h>
@@ -24,6 +25,8 @@ void __init time_init(void)
 	riscv_timebase = prop;
 
 	lpj_fine = riscv_timebase / HZ;
+
+	of_clk_init(NULL);
 	timer_probe();
 }
 
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

If of_clk_init() is not called in time_init(), clock providers defined
in the system device tree are not initialized, resulting in failures for
other devices to initialize due to missing clocks.
Similarly to other architectures and to the default kernel time_init()
implementation, call of_clk_init() before executing timer_probe() in
time_init().

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/kernel/time.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
index 4d3a1048ad8b..8a5cf99c0776 100644
--- a/arch/riscv/kernel/time.c
+++ b/arch/riscv/kernel/time.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2017 SiFive
  */
 
+#include <linux/of_clk.h>
 #include <linux/clocksource.h>
 #include <linux/delay.h>
 #include <asm/sbi.h>
@@ -24,6 +25,8 @@ void __init time_init(void)
 	riscv_timebase = prop;
 
 	lpj_fine = riscv_timebase / HZ;
+
+	of_clk_init(NULL);
 	timer_probe();
 }
 
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 09/32] riscv: Fix SiFive gpio probe
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Fix the check on the number of IRQs to allow up to the maximum (32)
instead of only the maximum minus one.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/gpio/gpio-sifive.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index c54dd08f2cbf..d5eb9ca11901 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -183,7 +183,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
 		return PTR_ERR(chip->regs);
 
 	ngpio = of_irq_count(node);
-	if (ngpio >= SIFIVE_GPIO_MAX) {
+	if (ngpio > SIFIVE_GPIO_MAX) {
 		dev_err(dev, "Too many GPIO interrupts (max=%d)\n",
 			SIFIVE_GPIO_MAX);
 		return -ENXIO;
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 09/32] riscv: Fix SiFive gpio probe
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Fix the check on the number of IRQs to allow up to the maximum (32)
instead of only the maximum minus one.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/gpio/gpio-sifive.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c
index c54dd08f2cbf..d5eb9ca11901 100644
--- a/drivers/gpio/gpio-sifive.c
+++ b/drivers/gpio/gpio-sifive.c
@@ -183,7 +183,7 @@ static int sifive_gpio_probe(struct platform_device *pdev)
 		return PTR_ERR(chip->regs);
 
 	ngpio = of_irq_count(node);
-	if (ngpio >= SIFIVE_GPIO_MAX) {
+	if (ngpio > SIFIVE_GPIO_MAX) {
 		dev_err(dev, "Too many GPIO interrupts (max=%d)\n",
 			SIFIVE_GPIO_MAX);
 		return -ENXIO;
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 10/32] riscv: Fix sifive serial driver
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Setup the port uartclk in sifive_serial_probe() so that the base baud
rate is correctly printed during device probe instead of always showing
"0".  I.e. the probe message is changed from

38000000.serial: ttySIF0 at MMIO 0x38000000 (irq = 1,
base_baud = 0) is a SiFive UART v0

to the correct:

38000000.serial: ttySIF0 at MMIO 0x38000000 (irq = 1,
base_baud = 115200) is a SiFive UART v0

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/tty/serial/sifive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index 13eadcb8aec4..214bf3086c68 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -999,6 +999,7 @@ static int sifive_serial_probe(struct platform_device *pdev)
 	/* Set up clock divider */
 	ssp->clkin_rate = clk_get_rate(ssp->clk);
 	ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
+	ssp->port.uartclk = ssp->baud_rate * 16;
 	__ssp_update_div(ssp);
 
 	platform_set_drvdata(pdev, ssp);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 10/32] riscv: Fix sifive serial driver
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Setup the port uartclk in sifive_serial_probe() so that the base baud
rate is correctly printed during device probe instead of always showing
"0".  I.e. the probe message is changed from

38000000.serial: ttySIF0 at MMIO 0x38000000 (irq = 1,
base_baud = 0) is a SiFive UART v0

to the correct:

38000000.serial: ttySIF0 at MMIO 0x38000000 (irq = 1,
base_baud = 115200) is a SiFive UART v0

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 drivers/tty/serial/sifive.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index 13eadcb8aec4..214bf3086c68 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -999,6 +999,7 @@ static int sifive_serial_probe(struct platform_device *pdev)
 	/* Set up clock divider */
 	ssp->clkin_rate = clk_get_rate(ssp->clk);
 	ssp->baud_rate = SIFIVE_DEFAULT_BAUD_RATE;
+	ssp->port.uartclk = ssp->baud_rate * 16;
 	__ssp_update_div(ssp);
 
 	platform_set_drvdata(pdev, ssp);
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 11/32] riscv: Enable interrupts during syscalls with M-Mode
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:13   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

When running is M-Mode (no MMU config), MPIE does not get set. This
results in all syscalls being executed with interrupts disabled as
handle_exception never sets SR_IE as it always sees SR_PIE being
cleared. Fix this by always force enabling interrupts in
handle_syscall when CONFIG_RISCV_M_MODE is enabled.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/kernel/entry.S | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 524d918f3601..080eb8d78589 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -155,6 +155,15 @@ skip_context_tracking:
 	tail do_trap_unknown
 
 handle_syscall:
+#ifdef CONFIG_RISCV_M_MODE
+	/*
+	 * When running is M-Mode (no MMU config), MPIE does not get set.
+	 * As a result, we need to force enable interrupts here because
+	 * handle_exception did not do set SR_IE as it always sees SR_PIE
+	 * being cleared.
+	 */
+	csrs CSR_STATUS, SR_IE
+#endif
 #if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
 	/* Recover a0 - a7 for system calls */
 	REG_L a0, PT_A0(sp)
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 11/32] riscv: Enable interrupts during syscalls with M-Mode
@ 2020-11-07  8:13   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:13 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

When running is M-Mode (no MMU config), MPIE does not get set. This
results in all syscalls being executed with interrupts disabled as
handle_exception never sets SR_IE as it always sees SR_PIE being
cleared. Fix this by always force enabling interrupts in
handle_syscall when CONFIG_RISCV_M_MODE is enabled.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/kernel/entry.S | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S
index 524d918f3601..080eb8d78589 100644
--- a/arch/riscv/kernel/entry.S
+++ b/arch/riscv/kernel/entry.S
@@ -155,6 +155,15 @@ skip_context_tracking:
 	tail do_trap_unknown
 
 handle_syscall:
+#ifdef CONFIG_RISCV_M_MODE
+	/*
+	 * When running is M-Mode (no MMU config), MPIE does not get set.
+	 * As a result, we need to force enable interrupts here because
+	 * handle_exception did not do set SR_IE as it always sees SR_PIE
+	 * being cleared.
+	 */
+	csrs CSR_STATUS, SR_IE
+#endif
 #if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
 	/* Recover a0 - a7 for system calls */
 	REG_L a0, PT_A0(sp)
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 12/32] riscv: Automatically select sysctl config options
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

With the device tree update for the Kendryte K210 SoC, most peripherals
are now defined under one of 3 advanced power buses (apb0, apb1 and
apb2) compatible with the simple-pm-bus driver. The sysctl SoC device
is defined as a syscon/simple-mfd device. Enable the configuration
options PM, SIMPLE_PM_BUS, SYSCON and MFD_SYSCON to enable drivers for
these device tree nodes.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs       |  1 +
 drivers/soc/Kconfig           |  2 +-
 drivers/soc/kendryte/Kconfig  | 19 +++++++------------
 drivers/soc/kendryte/Makefile |  2 +-
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 8a55f6156661..e724fddc44ba 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -29,6 +29,7 @@ config SOC_KENDRYTE
 	select SERIAL_SIFIVE if TTY
 	select SERIAL_SIFIVE_CONSOLE if TTY
 	select SIFIVE_PLIC
+	select SOC_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 425ab6f7e375..f511cad87a0e 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -9,6 +9,7 @@ source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/imx/Kconfig"
 source "drivers/soc/ixp4xx/Kconfig"
+source "drivers/soc/kendryte/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
@@ -22,6 +23,5 @@ source "drivers/soc/ux500/Kconfig"
 source "drivers/soc/versatile/Kconfig"
 source "drivers/soc/xilinx/Kconfig"
 source "drivers/soc/zte/Kconfig"
-source "drivers/soc/kendryte/Kconfig"
 
 endmenu
diff --git a/drivers/soc/kendryte/Kconfig b/drivers/soc/kendryte/Kconfig
index 49785b1b0217..11579139ede6 100644
--- a/drivers/soc/kendryte/Kconfig
+++ b/drivers/soc/kendryte/Kconfig
@@ -1,14 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 
-if SOC_KENDRYTE
-
-config K210_SYSCTL
-	bool "Kendryte K210 system controller"
-	default y
-	depends on RISCV
-	help
-	  Enables controlling the K210 various clocks and to enable
-	  general purpose use of the extra 2MB of SRAM normally
-	  reserved for the AI engine.
-
-endif
+config SOC_K210
+	bool "Kendryte K210 SoC drivers"
+	depends on RISCV && SOC_KENDRYTE && OF
+        select PM
+        select SIMPLE_PM_BUS
+        select SYSCON
+        select MFD_SYSCON
diff --git a/drivers/soc/kendryte/Makefile b/drivers/soc/kendryte/Makefile
index 002d9ce95c0d..e67425707484 100644
--- a/drivers/soc/kendryte/Makefile
+++ b/drivers/soc/kendryte/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_K210_SYSCTL)	+= k210-sysctl.o
+obj-$(CONFIG_SOC_K210)	+= k210-sysctl.o
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 12/32] riscv: Automatically select sysctl config options
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

With the device tree update for the Kendryte K210 SoC, most peripherals
are now defined under one of 3 advanced power buses (apb0, apb1 and
apb2) compatible with the simple-pm-bus driver. The sysctl SoC device
is defined as a syscon/simple-mfd device. Enable the configuration
options PM, SIMPLE_PM_BUS, SYSCON and MFD_SYSCON to enable drivers for
these device tree nodes.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs       |  1 +
 drivers/soc/Kconfig           |  2 +-
 drivers/soc/kendryte/Kconfig  | 19 +++++++------------
 drivers/soc/kendryte/Makefile |  2 +-
 4 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 8a55f6156661..e724fddc44ba 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -29,6 +29,7 @@ config SOC_KENDRYTE
 	select SERIAL_SIFIVE if TTY
 	select SERIAL_SIFIVE_CONSOLE if TTY
 	select SIFIVE_PLIC
+	select SOC_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 425ab6f7e375..f511cad87a0e 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -9,6 +9,7 @@ source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
 source "drivers/soc/imx/Kconfig"
 source "drivers/soc/ixp4xx/Kconfig"
+source "drivers/soc/kendryte/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
@@ -22,6 +23,5 @@ source "drivers/soc/ux500/Kconfig"
 source "drivers/soc/versatile/Kconfig"
 source "drivers/soc/xilinx/Kconfig"
 source "drivers/soc/zte/Kconfig"
-source "drivers/soc/kendryte/Kconfig"
 
 endmenu
diff --git a/drivers/soc/kendryte/Kconfig b/drivers/soc/kendryte/Kconfig
index 49785b1b0217..11579139ede6 100644
--- a/drivers/soc/kendryte/Kconfig
+++ b/drivers/soc/kendryte/Kconfig
@@ -1,14 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 
-if SOC_KENDRYTE
-
-config K210_SYSCTL
-	bool "Kendryte K210 system controller"
-	default y
-	depends on RISCV
-	help
-	  Enables controlling the K210 various clocks and to enable
-	  general purpose use of the extra 2MB of SRAM normally
-	  reserved for the AI engine.
-
-endif
+config SOC_K210
+	bool "Kendryte K210 SoC drivers"
+	depends on RISCV && SOC_KENDRYTE && OF
+        select PM
+        select SIMPLE_PM_BUS
+        select SYSCON
+        select MFD_SYSCON
diff --git a/drivers/soc/kendryte/Makefile b/drivers/soc/kendryte/Makefile
index 002d9ce95c0d..e67425707484 100644
--- a/drivers/soc/kendryte/Makefile
+++ b/drivers/soc/kendryte/Makefile
@@ -1,3 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_K210_SYSCTL)	+= k210-sysctl.o
+obj-$(CONFIG_SOC_K210)	+= k210-sysctl.o
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 13/32] riscv: Fix builtin DTB handling
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

All SiPeed K210 boards have the exact same vendor, arch and
implementation IDs, preventing differentiation of the device tree to use
through the SOC_BUILTIN_DTB_DECLARE() macro. This result in this macro,
used only for Kendryte, to be useless and to prevent changing the
builtin device tree without also changing the code of the sysctl soc
driver.

Fix this problem by removing the SOC_BUILTIN_DTB_DECLARE() macro and
associated code, falling back to a simpler, and more traditional
handling of builtin DTB similar to other architectures.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs               | 22 ++++++++++++----
 arch/riscv/boot/dts/kendryte/Makefile |  5 ++--
 arch/riscv/include/asm/soc.h          | 38 ---------------------------
 arch/riscv/kernel/soc.c               | 27 -------------------
 arch/riscv/mm/init.c                  |  6 +----
 drivers/soc/kendryte/k210-sysctl.c    | 12 ---------
 6 files changed, 21 insertions(+), 89 deletions(-)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index e724fddc44ba..97ef393d0ed0 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -33,9 +33,10 @@ config SOC_KENDRYTE
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
-config SOC_KENDRYTE_K210_DTB
-	def_bool y
-	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
+config BUILTIN_DTB
+	def_bool n
+
+if SOC_KENDRYTE
 
 config SOC_KENDRYTE_K210_DTB_BUILTIN
 	bool "Builtin device tree for the Kendryte K210"
@@ -43,10 +44,21 @@ config SOC_KENDRYTE_K210_DTB_BUILTIN
 	default y
 	select OF
 	select BUILTIN_DTB
-	select SOC_KENDRYTE_K210_DTB
 	help
-	  Builds a device tree for the Kendryte K210 into the Linux image.
+	  Build a device tree for the Kendryte K210 into the Linux image.
 	  This option should be selected if no bootloader is being used.
 	  If unsure, say Y.
 
+config SOC_KENDRYTE_K210_DTB_SOURCE
+	string "Source file for the Kendryte K210 builtin DTB"
+	depends on SOC_KENDRYTE
+	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
+	default "k210"
+	help
+	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
+	  for the DTS file that will be used to produce the DTB linked into the
+	  kernel.
+
+endif
+
 endmenu
diff --git a/arch/riscv/boot/dts/kendryte/Makefile b/arch/riscv/boot/dts/kendryte/Makefile
index 1a88e616f18e..83636693166d 100644
--- a/arch/riscv/boot/dts/kendryte/Makefile
+++ b/arch/riscv/boot/dts/kendryte/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_SOC_KENDRYTE_K210_DTB) += k210.dtb
-
+ifneq ($(CONFIG_SOC_KENDRYTE_K210_DTB_SOURCE),"")
+dtb-y += $(strip $(shell echo $(CONFIG_SOC_KENDRYTE_K210_DTB_SOURCE))).dtb
 obj-$(CONFIG_SOC_KENDRYTE_K210_DTB_BUILTIN) += $(addsuffix .o, $(dtb-y))
+endif
diff --git a/arch/riscv/include/asm/soc.h b/arch/riscv/include/asm/soc.h
index 6c8363b1f327..f494066051a2 100644
--- a/arch/riscv/include/asm/soc.h
+++ b/arch/riscv/include/asm/soc.h
@@ -21,42 +21,4 @@ void soc_early_init(void);
 extern unsigned long __soc_early_init_table_start;
 extern unsigned long __soc_early_init_table_end;
 
-/*
- * Allows Linux to provide a device tree, which is necessary for SOCs that
- * don't provide a useful one on their own.
- */
-struct soc_builtin_dtb {
-	unsigned long vendor_id;
-	unsigned long arch_id;
-	unsigned long imp_id;
-	void *(*dtb_func)(void);
-};
-
-/*
- * The argument name must specify a valid DTS file name without the dts
- * extension.
- */
-#define SOC_BUILTIN_DTB_DECLARE(name, vendor, arch, impl)		\
-	extern void *__dtb_##name##_begin;				\
-									\
-	static __init __used						\
-	void *__soc_builtin_dtb_f__##name(void)				\
-	{								\
-		return (void *)&__dtb_##name##_begin;			\
-	}								\
-									\
-	static const struct soc_builtin_dtb __soc_builtin_dtb__##name	\
-		__used __section("__soc_builtin_dtb_table") =		\
-	{								\
-		.vendor_id = vendor,					\
-		.arch_id   = arch,					\
-		.imp_id    = impl,					\
-		.dtb_func  = __soc_builtin_dtb_f__##name,		\
-	}
-
-extern unsigned long __soc_builtin_dtb_table_start;
-extern unsigned long __soc_builtin_dtb_table_end;
-
-void *soc_lookup_builtin_dtb(void);
-
 #endif
diff --git a/arch/riscv/kernel/soc.c b/arch/riscv/kernel/soc.c
index c7b0a73e382e..a0516172a33c 100644
--- a/arch/riscv/kernel/soc.c
+++ b/arch/riscv/kernel/soc.c
@@ -26,30 +26,3 @@ void __init soc_early_init(void)
 		}
 	}
 }
-
-static bool soc_builtin_dtb_match(unsigned long vendor_id,
-				unsigned long arch_id, unsigned long imp_id,
-				const struct soc_builtin_dtb *entry)
-{
-	return entry->vendor_id == vendor_id &&
-	       entry->arch_id == arch_id &&
-	       entry->imp_id == imp_id;
-}
-
-void * __init soc_lookup_builtin_dtb(void)
-{
-	unsigned long vendor_id, arch_id, imp_id;
-	const struct soc_builtin_dtb *s;
-
-	__asm__ ("csrr %0, mvendorid" : "=r"(vendor_id));
-	__asm__ ("csrr %0, marchid" : "=r"(arch_id));
-	__asm__ ("csrr %0, mimpid" : "=r"(imp_id));
-
-	for (s = (void *)&__soc_builtin_dtb_table_start;
-	     (void *)s < (void *)&__soc_builtin_dtb_table_end; s++) {
-		if (soc_builtin_dtb_match(vendor_id, arch_id, imp_id, s))
-			return s->dtb_func();
-	}
-
-	return NULL;
-}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index ea933b789a88..d9c8d8819ed8 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -591,11 +591,7 @@ static void __init setup_vm_final(void)
 asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 {
 #ifdef CONFIG_BUILTIN_DTB
-	dtb_early_va = soc_lookup_builtin_dtb();
-	if (!dtb_early_va) {
-		/* Fallback to first available DTS */
-		dtb_early_va = (void *) __dtb_start;
-	}
+	dtb_early_va = (void *) __dtb_start;
 #else
 	dtb_early_va = (void *)dtb_pa;
 #endif
diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
index 707019223dd8..4608fbca20e1 100644
--- a/drivers/soc/kendryte/k210-sysctl.c
+++ b/drivers/soc/kendryte/k210-sysctl.c
@@ -246,15 +246,3 @@ static void __init k210_soc_early_init(const void *fdt)
 	iounmap(regs);
 }
 SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
-
-#ifdef CONFIG_SOC_KENDRYTE_K210_DTB_BUILTIN
-/*
- * Generic entry for the default k210.dtb embedded DTB for boards with:
- *   - Vendor ID: 0x4B5
- *   - Arch ID: 0xE59889E6A5A04149 (= "Canaan AI" in UTF-8 encoded Chinese)
- *   - Impl ID:	0x4D41495832303030 (= "MAIX2000")
- * These values are reported by the SiPEED MAXDUINO, SiPEED MAIX GO and
- * SiPEED Dan dock boards.
- */
-SOC_BUILTIN_DTB_DECLARE(k210, 0x4B5, 0xE59889E6A5A04149, 0x4D41495832303030);
-#endif
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 13/32] riscv: Fix builtin DTB handling
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

All SiPeed K210 boards have the exact same vendor, arch and
implementation IDs, preventing differentiation of the device tree to use
through the SOC_BUILTIN_DTB_DECLARE() macro. This result in this macro,
used only for Kendryte, to be useless and to prevent changing the
builtin device tree without also changing the code of the sysctl soc
driver.

Fix this problem by removing the SOC_BUILTIN_DTB_DECLARE() macro and
associated code, falling back to a simpler, and more traditional
handling of builtin DTB similar to other architectures.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs               | 22 ++++++++++++----
 arch/riscv/boot/dts/kendryte/Makefile |  5 ++--
 arch/riscv/include/asm/soc.h          | 38 ---------------------------
 arch/riscv/kernel/soc.c               | 27 -------------------
 arch/riscv/mm/init.c                  |  6 +----
 drivers/soc/kendryte/k210-sysctl.c    | 12 ---------
 6 files changed, 21 insertions(+), 89 deletions(-)

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index e724fddc44ba..97ef393d0ed0 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -33,9 +33,10 @@ config SOC_KENDRYTE
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
-config SOC_KENDRYTE_K210_DTB
-	def_bool y
-	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
+config BUILTIN_DTB
+	def_bool n
+
+if SOC_KENDRYTE
 
 config SOC_KENDRYTE_K210_DTB_BUILTIN
 	bool "Builtin device tree for the Kendryte K210"
@@ -43,10 +44,21 @@ config SOC_KENDRYTE_K210_DTB_BUILTIN
 	default y
 	select OF
 	select BUILTIN_DTB
-	select SOC_KENDRYTE_K210_DTB
 	help
-	  Builds a device tree for the Kendryte K210 into the Linux image.
+	  Build a device tree for the Kendryte K210 into the Linux image.
 	  This option should be selected if no bootloader is being used.
 	  If unsure, say Y.
 
+config SOC_KENDRYTE_K210_DTB_SOURCE
+	string "Source file for the Kendryte K210 builtin DTB"
+	depends on SOC_KENDRYTE
+	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
+	default "k210"
+	help
+	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
+	  for the DTS file that will be used to produce the DTB linked into the
+	  kernel.
+
+endif
+
 endmenu
diff --git a/arch/riscv/boot/dts/kendryte/Makefile b/arch/riscv/boot/dts/kendryte/Makefile
index 1a88e616f18e..83636693166d 100644
--- a/arch/riscv/boot/dts/kendryte/Makefile
+++ b/arch/riscv/boot/dts/kendryte/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_SOC_KENDRYTE_K210_DTB) += k210.dtb
-
+ifneq ($(CONFIG_SOC_KENDRYTE_K210_DTB_SOURCE),"")
+dtb-y += $(strip $(shell echo $(CONFIG_SOC_KENDRYTE_K210_DTB_SOURCE))).dtb
 obj-$(CONFIG_SOC_KENDRYTE_K210_DTB_BUILTIN) += $(addsuffix .o, $(dtb-y))
+endif
diff --git a/arch/riscv/include/asm/soc.h b/arch/riscv/include/asm/soc.h
index 6c8363b1f327..f494066051a2 100644
--- a/arch/riscv/include/asm/soc.h
+++ b/arch/riscv/include/asm/soc.h
@@ -21,42 +21,4 @@ void soc_early_init(void);
 extern unsigned long __soc_early_init_table_start;
 extern unsigned long __soc_early_init_table_end;
 
-/*
- * Allows Linux to provide a device tree, which is necessary for SOCs that
- * don't provide a useful one on their own.
- */
-struct soc_builtin_dtb {
-	unsigned long vendor_id;
-	unsigned long arch_id;
-	unsigned long imp_id;
-	void *(*dtb_func)(void);
-};
-
-/*
- * The argument name must specify a valid DTS file name without the dts
- * extension.
- */
-#define SOC_BUILTIN_DTB_DECLARE(name, vendor, arch, impl)		\
-	extern void *__dtb_##name##_begin;				\
-									\
-	static __init __used						\
-	void *__soc_builtin_dtb_f__##name(void)				\
-	{								\
-		return (void *)&__dtb_##name##_begin;			\
-	}								\
-									\
-	static const struct soc_builtin_dtb __soc_builtin_dtb__##name	\
-		__used __section("__soc_builtin_dtb_table") =		\
-	{								\
-		.vendor_id = vendor,					\
-		.arch_id   = arch,					\
-		.imp_id    = impl,					\
-		.dtb_func  = __soc_builtin_dtb_f__##name,		\
-	}
-
-extern unsigned long __soc_builtin_dtb_table_start;
-extern unsigned long __soc_builtin_dtb_table_end;
-
-void *soc_lookup_builtin_dtb(void);
-
 #endif
diff --git a/arch/riscv/kernel/soc.c b/arch/riscv/kernel/soc.c
index c7b0a73e382e..a0516172a33c 100644
--- a/arch/riscv/kernel/soc.c
+++ b/arch/riscv/kernel/soc.c
@@ -26,30 +26,3 @@ void __init soc_early_init(void)
 		}
 	}
 }
-
-static bool soc_builtin_dtb_match(unsigned long vendor_id,
-				unsigned long arch_id, unsigned long imp_id,
-				const struct soc_builtin_dtb *entry)
-{
-	return entry->vendor_id == vendor_id &&
-	       entry->arch_id == arch_id &&
-	       entry->imp_id == imp_id;
-}
-
-void * __init soc_lookup_builtin_dtb(void)
-{
-	unsigned long vendor_id, arch_id, imp_id;
-	const struct soc_builtin_dtb *s;
-
-	__asm__ ("csrr %0, mvendorid" : "=r"(vendor_id));
-	__asm__ ("csrr %0, marchid" : "=r"(arch_id));
-	__asm__ ("csrr %0, mimpid" : "=r"(imp_id));
-
-	for (s = (void *)&__soc_builtin_dtb_table_start;
-	     (void *)s < (void *)&__soc_builtin_dtb_table_end; s++) {
-		if (soc_builtin_dtb_match(vendor_id, arch_id, imp_id, s))
-			return s->dtb_func();
-	}
-
-	return NULL;
-}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index ea933b789a88..d9c8d8819ed8 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -591,11 +591,7 @@ static void __init setup_vm_final(void)
 asmlinkage void __init setup_vm(uintptr_t dtb_pa)
 {
 #ifdef CONFIG_BUILTIN_DTB
-	dtb_early_va = soc_lookup_builtin_dtb();
-	if (!dtb_early_va) {
-		/* Fallback to first available DTS */
-		dtb_early_va = (void *) __dtb_start;
-	}
+	dtb_early_va = (void *) __dtb_start;
 #else
 	dtb_early_va = (void *)dtb_pa;
 #endif
diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
index 707019223dd8..4608fbca20e1 100644
--- a/drivers/soc/kendryte/k210-sysctl.c
+++ b/drivers/soc/kendryte/k210-sysctl.c
@@ -246,15 +246,3 @@ static void __init k210_soc_early_init(const void *fdt)
 	iounmap(regs);
 }
 SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
-
-#ifdef CONFIG_SOC_KENDRYTE_K210_DTB_BUILTIN
-/*
- * Generic entry for the default k210.dtb embedded DTB for boards with:
- *   - Vendor ID: 0x4B5
- *   - Arch ID: 0xE59889E6A5A04149 (= "Canaan AI" in UTF-8 encoded Chinese)
- *   - Impl ID:	0x4D41495832303030 (= "MAIX2000")
- * These values are reported by the SiPEED MAXDUINO, SiPEED MAIX GO and
- * SiPEED Dan dock boards.
- */
-SOC_BUILTIN_DTB_DECLARE(k210, 0x4B5, 0xE59889E6A5A04149, 0x4D41495832303030);
-#endif
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 14/32] dt-bindings: Define all Kendryte K210 clock IDs
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Define unique arbitrary IDs for all 44 clocks available on the Kendryte
K210 RISC-V SoC in the header file include/dt-bindings/clock/k210-clk.h.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/clock/k210-clk.h | 61 +++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 11 deletions(-)

diff --git a/include/dt-bindings/clock/k210-clk.h b/include/dt-bindings/clock/k210-clk.h
index 5a2fd64d1a49..8d7ab2f0737c 100644
--- a/include/dt-bindings/clock/k210-clk.h
+++ b/include/dt-bindings/clock/k210-clk.h
@@ -3,18 +3,57 @@
  * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  * Copyright (c) 2020 Western Digital Corporation or its affiliates.
  */
-#ifndef K210_CLK_H
-#define K210_CLK_H
+#ifndef CLOCK_K210_CLK_H
+#define CLOCK_K210_CLK_H
 
 /*
- * Arbitrary identifiers for clocks.
- * The structure is: in0 -> pll0 -> aclk -> cpu
- *
- * Since we use the hardware defaults for now, set all these to the same clock.
+ * Kendryte K210 SoC clock identifiers (arbitrary values).
  */
-#define K210_CLK_PLL0   0
-#define K210_CLK_PLL1   0
-#define K210_CLK_ACLK   0
-#define K210_CLK_CPU    0
+#define K210_CLK_IN0	0
+#define K210_CLK_PLL0	1
+#define K210_CLK_PLL1	2
+#define K210_CLK_PLL2	3
+#define K210_CLK_ACLK	4
+#define K210_CLK_CPU	5
+#define K210_CLK_CLINT	6
+#define K210_CLK_DMA	7
+#define K210_CLK_FFT	8
+#define K210_CLK_SRAM0	9
+#define K210_CLK_SRAM1	10
+#define K210_CLK_ROM	11
+#define K210_CLK_DVP	12
+#define K210_CLK_APB0	13
+#define K210_CLK_APB1	14
+#define K210_CLK_APB2	15
+#define K210_CLK_AI	16
+#define K210_CLK_I2S0	17
+#define K210_CLK_I2S1	18
+#define K210_CLK_I2S2	19
+#define K210_CLK_I2S0_M	20
+#define K210_CLK_I2S1_M	21
+#define K210_CLK_I2S2_M	22
+#define K210_CLK_WDT0	23
+#define K210_CLK_WDT1	24
+#define K210_CLK_SPI0	25
+#define K210_CLK_SPI1	26
+#define K210_CLK_SPI2	27
+#define K210_CLK_I2C0	28
+#define K210_CLK_I2C1	29
+#define K210_CLK_I2C2	30
+#define K210_CLK_SPI3	31
+#define K210_CLK_TIMER0	32
+#define K210_CLK_TIMER1	33
+#define K210_CLK_TIMER2	34
+#define K210_CLK_GPIO	35
+#define K210_CLK_UART1	36
+#define K210_CLK_UART2	37
+#define K210_CLK_UART3	38
+#define K210_CLK_FPIOA	39
+#define K210_CLK_SHA	40
+#define K210_CLK_AES	41
+#define K210_CLK_OTP	42
+#define K210_CLK_RTC	43
 
-#endif /* K210_CLK_H */
+#define K210_NUM_CLKS	44
+
+#endif /* CLOCK_K210_CLK_H */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 14/32] dt-bindings: Define all Kendryte K210 clock IDs
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Define unique arbitrary IDs for all 44 clocks available on the Kendryte
K210 RISC-V SoC in the header file include/dt-bindings/clock/k210-clk.h.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/clock/k210-clk.h | 61 +++++++++++++++++++++++-----
 1 file changed, 50 insertions(+), 11 deletions(-)

diff --git a/include/dt-bindings/clock/k210-clk.h b/include/dt-bindings/clock/k210-clk.h
index 5a2fd64d1a49..8d7ab2f0737c 100644
--- a/include/dt-bindings/clock/k210-clk.h
+++ b/include/dt-bindings/clock/k210-clk.h
@@ -3,18 +3,57 @@
  * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  * Copyright (c) 2020 Western Digital Corporation or its affiliates.
  */
-#ifndef K210_CLK_H
-#define K210_CLK_H
+#ifndef CLOCK_K210_CLK_H
+#define CLOCK_K210_CLK_H
 
 /*
- * Arbitrary identifiers for clocks.
- * The structure is: in0 -> pll0 -> aclk -> cpu
- *
- * Since we use the hardware defaults for now, set all these to the same clock.
+ * Kendryte K210 SoC clock identifiers (arbitrary values).
  */
-#define K210_CLK_PLL0   0
-#define K210_CLK_PLL1   0
-#define K210_CLK_ACLK   0
-#define K210_CLK_CPU    0
+#define K210_CLK_IN0	0
+#define K210_CLK_PLL0	1
+#define K210_CLK_PLL1	2
+#define K210_CLK_PLL2	3
+#define K210_CLK_ACLK	4
+#define K210_CLK_CPU	5
+#define K210_CLK_CLINT	6
+#define K210_CLK_DMA	7
+#define K210_CLK_FFT	8
+#define K210_CLK_SRAM0	9
+#define K210_CLK_SRAM1	10
+#define K210_CLK_ROM	11
+#define K210_CLK_DVP	12
+#define K210_CLK_APB0	13
+#define K210_CLK_APB1	14
+#define K210_CLK_APB2	15
+#define K210_CLK_AI	16
+#define K210_CLK_I2S0	17
+#define K210_CLK_I2S1	18
+#define K210_CLK_I2S2	19
+#define K210_CLK_I2S0_M	20
+#define K210_CLK_I2S1_M	21
+#define K210_CLK_I2S2_M	22
+#define K210_CLK_WDT0	23
+#define K210_CLK_WDT1	24
+#define K210_CLK_SPI0	25
+#define K210_CLK_SPI1	26
+#define K210_CLK_SPI2	27
+#define K210_CLK_I2C0	28
+#define K210_CLK_I2C1	29
+#define K210_CLK_I2C2	30
+#define K210_CLK_SPI3	31
+#define K210_CLK_TIMER0	32
+#define K210_CLK_TIMER1	33
+#define K210_CLK_TIMER2	34
+#define K210_CLK_GPIO	35
+#define K210_CLK_UART1	36
+#define K210_CLK_UART2	37
+#define K210_CLK_UART3	38
+#define K210_CLK_FPIOA	39
+#define K210_CLK_SHA	40
+#define K210_CLK_AES	41
+#define K210_CLK_OTP	42
+#define K210_CLK_RTC	43
 
-#endif /* K210_CLK_H */
+#define K210_NUM_CLKS	44
+
+#endif /* CLOCK_K210_CLK_H */
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
define the offset of all registers of the K210 system controller.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h

diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
new file mode 100644
index 000000000000..5cc386d3c9ca
--- /dev/null
+++ b/include/dt-bindings/mfd/k210-sysctl.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef MFD_K210_SYSCTL_H
+#define MFD_K210_SYSCTL_H
+
+/*
+ * Kendryte K210 SoC system controller registers offsets.
+ * Taken from Kendryte SDK (kendryte-standalone-sdk).
+ */
+#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
+#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
+#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
+#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
+#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
+#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
+#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
+#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
+#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
+#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
+#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
+#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
+#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
+#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
+#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
+#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
+#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
+#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
+#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
+#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
+#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
+#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
+#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
+#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
+#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
+#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
+#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
+
+#endif /* MFD_K210_SYSCTL_H */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
define the offset of all registers of the K210 system controller.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 include/dt-bindings/mfd/k210-sysctl.h

diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
new file mode 100644
index 000000000000..5cc386d3c9ca
--- /dev/null
+++ b/include/dt-bindings/mfd/k210-sysctl.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef MFD_K210_SYSCTL_H
+#define MFD_K210_SYSCTL_H
+
+/*
+ * Kendryte K210 SoC system controller registers offsets.
+ * Taken from Kendryte SDK (kendryte-standalone-sdk).
+ */
+#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
+#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
+#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
+#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
+#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
+#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
+#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
+#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
+#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
+#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
+#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
+#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
+#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
+#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
+#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
+#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
+#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
+#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
+#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
+#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
+#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
+#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
+#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
+#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
+#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
+#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
+#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
+
+#endif /* MFD_K210_SYSCTL_H */
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 16/32] dt-bindings: Define Kendryte K210 pin functions
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file
include/dt-bindings/pinctrl/k210_pinctrl.h to define all possible 255
functions that can be assigned to any of the 48 programmable pins of the
SoC. Macros allowing a device tree to define a pinmux mapping are also
introduced.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/pinctrl/k210-pinctrl.h | 277 +++++++++++++++++++++
 1 file changed, 277 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h

diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h
new file mode 100644
index 000000000000..0b797a4a245e
--- /dev/null
+++ b/include/dt-bindings/pinctrl/k210-pinctrl.h
@@ -0,0 +1,277 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef PINCTRL_K210_SYSCTL_H
+#define PINCTRL_K210_SYSCTL_H
+
+/*
+ * Full list of FPIOA functions from
+ * kendryte-standalone-sdk/lib/drivers/include/fpioa.h
+ */
+#define K210_PCF_MASK		GENMASK(7, 0)
+#define K210_PCF_JTAG_TCLK	0   /* JTAG Test Clock */
+#define K210_PCF_JTAG_TDI	1   /* JTAG Test Data In */
+#define K210_PCF_JTAG_TMS	2   /* JTAG Test Mode Select */
+#define K210_PCF_JTAG_TDO	3   /* JTAG Test Data Out */
+#define K210_PCF_SPI0_D0	4   /* SPI0 Data 0 */
+#define K210_PCF_SPI0_D1	5   /* SPI0 Data 1 */
+#define K210_PCF_SPI0_D2	6   /* SPI0 Data 2 */
+#define K210_PCF_SPI0_D3	7   /* SPI0 Data 3 */
+#define K210_PCF_SPI0_D4	8   /* SPI0 Data 4 */
+#define K210_PCF_SPI0_D5	9   /* SPI0 Data 5 */
+#define K210_PCF_SPI0_D6	10  /* SPI0 Data 6 */
+#define K210_PCF_SPI0_D7	11  /* SPI0 Data 7 */
+#define K210_PCF_SPI0_SS0	12  /* SPI0 Chip Select 0 */
+#define K210_PCF_SPI0_SS1	13  /* SPI0 Chip Select 1 */
+#define K210_PCF_SPI0_SS2	14  /* SPI0 Chip Select 2 */
+#define K210_PCF_SPI0_SS3	15  /* SPI0 Chip Select 3 */
+#define K210_PCF_SPI0_ARB	16  /* SPI0 Arbitration */
+#define K210_PCF_SPI0_SCLK	17  /* SPI0 Serial Clock */
+#define K210_PCF_UARTHS_RX	18  /* UART High speed Receiver */
+#define K210_PCF_UARTHS_TX	19  /* UART High speed Transmitter */
+#define K210_PCF_RESV6		20  /* Reserved function */
+#define K210_PCF_RESV7		21  /* Reserved function */
+#define K210_PCF_CLK_SPI1	22  /* Clock SPI1 */
+#define K210_PCF_CLK_I2C1	23  /* Clock I2C1 */
+#define K210_PCF_GPIOHS0	24  /* GPIO High speed 0 */
+#define K210_PCF_GPIOHS1	25  /* GPIO High speed 1 */
+#define K210_PCF_GPIOHS2	26  /* GPIO High speed 2 */
+#define K210_PCF_GPIOHS3	27  /* GPIO High speed 3 */
+#define K210_PCF_GPIOHS4	28  /* GPIO High speed 4 */
+#define K210_PCF_GPIOHS5	29  /* GPIO High speed 5 */
+#define K210_PCF_GPIOHS6	30  /* GPIO High speed 6 */
+#define K210_PCF_GPIOHS7	31  /* GPIO High speed 7 */
+#define K210_PCF_GPIOHS8	32  /* GPIO High speed 8 */
+#define K210_PCF_GPIOHS9	33  /* GPIO High speed 9 */
+#define K210_PCF_GPIOHS10	34  /* GPIO High speed 10 */
+#define K210_PCF_GPIOHS11	35  /* GPIO High speed 11 */
+#define K210_PCF_GPIOHS12	36  /* GPIO High speed 12 */
+#define K210_PCF_GPIOHS13	37  /* GPIO High speed 13 */
+#define K210_PCF_GPIOHS14	38  /* GPIO High speed 14 */
+#define K210_PCF_GPIOHS15	39  /* GPIO High speed 15 */
+#define K210_PCF_GPIOHS16	40  /* GPIO High speed 16 */
+#define K210_PCF_GPIOHS17	41  /* GPIO High speed 17 */
+#define K210_PCF_GPIOHS18	42  /* GPIO High speed 18 */
+#define K210_PCF_GPIOHS19	43  /* GPIO High speed 19 */
+#define K210_PCF_GPIOHS20	44  /* GPIO High speed 20 */
+#define K210_PCF_GPIOHS21	45  /* GPIO High speed 21 */
+#define K210_PCF_GPIOHS22	46  /* GPIO High speed 22 */
+#define K210_PCF_GPIOHS23	47  /* GPIO High speed 23 */
+#define K210_PCF_GPIOHS24	48  /* GPIO High speed 24 */
+#define K210_PCF_GPIOHS25	49  /* GPIO High speed 25 */
+#define K210_PCF_GPIOHS26	50  /* GPIO High speed 26 */
+#define K210_PCF_GPIOHS27	51  /* GPIO High speed 27 */
+#define K210_PCF_GPIOHS28	52  /* GPIO High speed 28 */
+#define K210_PCF_GPIOHS29	53  /* GPIO High speed 29 */
+#define K210_PCF_GPIOHS30	54  /* GPIO High speed 30 */
+#define K210_PCF_GPIOHS31	55  /* GPIO High speed 31 */
+#define K210_PCF_GPIO0		56  /* GPIO pin 0 */
+#define K210_PCF_GPIO1		57  /* GPIO pin 1 */
+#define K210_PCF_GPIO2		58  /* GPIO pin 2 */
+#define K210_PCF_GPIO3		59  /* GPIO pin 3 */
+#define K210_PCF_GPIO4		60  /* GPIO pin 4 */
+#define K210_PCF_GPIO5		61  /* GPIO pin 5 */
+#define K210_PCF_GPIO6		62  /* GPIO pin 6 */
+#define K210_PCF_GPIO7		63  /* GPIO pin 7 */
+#define K210_PCF_UART1_RX	64  /* UART1 Receiver */
+#define K210_PCF_UART1_TX	65  /* UART1 Transmitter */
+#define K210_PCF_UART2_RX	66  /* UART2 Receiver */
+#define K210_PCF_UART2_TX	67  /* UART2 Transmitter */
+#define K210_PCF_UART3_RX	68  /* UART3 Receiver */
+#define K210_PCF_UART3_TX	69  /* UART3 Transmitter */
+#define K210_PCF_SPI1_D0	70  /* SPI1 Data 0 */
+#define K210_PCF_SPI1_D1	71  /* SPI1 Data 1 */
+#define K210_PCF_SPI1_D2	72  /* SPI1 Data 2 */
+#define K210_PCF_SPI1_D3	73  /* SPI1 Data 3 */
+#define K210_PCF_SPI1_D4	74  /* SPI1 Data 4 */
+#define K210_PCF_SPI1_D5	75  /* SPI1 Data 5 */
+#define K210_PCF_SPI1_D6	76  /* SPI1 Data 6 */
+#define K210_PCF_SPI1_D7	77  /* SPI1 Data 7 */
+#define K210_PCF_SPI1_SS0	78  /* SPI1 Chip Select 0 */
+#define K210_PCF_SPI1_SS1	79  /* SPI1 Chip Select 1 */
+#define K210_PCF_SPI1_SS2	80  /* SPI1 Chip Select 2 */
+#define K210_PCF_SPI1_SS3	81  /* SPI1 Chip Select 3 */
+#define K210_PCF_SPI1_ARB	82  /* SPI1 Arbitration */
+#define K210_PCF_SPI1_SCLK	83  /* SPI1 Serial Clock */
+#define K210_PCF_SPI2_D0	84  /* SPI2 Data 0 */
+#define K210_PCF_SPI2_SS	85  /* SPI2 Select */
+#define K210_PCF_SPI2_SCLK	86  /* SPI2 Serial Clock */
+#define K210_PCF_I2S0_MCLK	87  /* I2S0 Master Clock */
+#define K210_PCF_I2S0_SCLK	88  /* I2S0 Serial Clock(BCLK) */
+#define K210_PCF_I2S0_WS	89  /* I2S0 Word Select(LRCLK) */
+#define K210_PCF_I2S0_IN_D0	90  /* I2S0 Serial Data Input 0 */
+#define K210_PCF_I2S0_IN_D1	91  /* I2S0 Serial Data Input 1 */
+#define K210_PCF_I2S0_IN_D2	92  /* I2S0 Serial Data Input 2 */
+#define K210_PCF_I2S0_IN_D3	93  /* I2S0 Serial Data Input 3 */
+#define K210_PCF_I2S0_OUT_D0	94  /* I2S0 Serial Data Output 0 */
+#define K210_PCF_I2S0_OUT_D1	95  /* I2S0 Serial Data Output 1 */
+#define K210_PCF_I2S0_OUT_D2	96  /* I2S0 Serial Data Output 2 */
+#define K210_PCF_I2S0_OUT_D3	97  /* I2S0 Serial Data Output 3 */
+#define K210_PCF_I2S1_MCLK	98  /* I2S1 Master Clock */
+#define K210_PCF_I2S1_SCLK	99  /* I2S1 Serial Clock(BCLK) */
+#define K210_PCF_I2S1_WS	100 /* I2S1 Word Select(LRCLK) */
+#define K210_PCF_I2S1_IN_D0	101 /* I2S1 Serial Data Input 0 */
+#define K210_PCF_I2S1_IN_D1	102 /* I2S1 Serial Data Input 1 */
+#define K210_PCF_I2S1_IN_D2	103 /* I2S1 Serial Data Input 2 */
+#define K210_PCF_I2S1_IN_D3	104 /* I2S1 Serial Data Input 3 */
+#define K210_PCF_I2S1_OUT_D0	105 /* I2S1 Serial Data Output 0 */
+#define K210_PCF_I2S1_OUT_D1	106 /* I2S1 Serial Data Output 1 */
+#define K210_PCF_I2S1_OUT_D2	107 /* I2S1 Serial Data Output 2 */
+#define K210_PCF_I2S1_OUT_D3	108 /* I2S1 Serial Data Output 3 */
+#define K210_PCF_I2S2_MCLK	109 /* I2S2 Master Clock */
+#define K210_PCF_I2S2_SCLK	110 /* I2S2 Serial Clock(BCLK) */
+#define K210_PCF_I2S2_WS	111 /* I2S2 Word Select(LRCLK) */
+#define K210_PCF_I2S2_IN_D0	112 /* I2S2 Serial Data Input 0 */
+#define K210_PCF_I2S2_IN_D1	113 /* I2S2 Serial Data Input 1 */
+#define K210_PCF_I2S2_IN_D2	114 /* I2S2 Serial Data Input 2 */
+#define K210_PCF_I2S2_IN_D3	115 /* I2S2 Serial Data Input 3 */
+#define K210_PCF_I2S2_OUT_D0	116 /* I2S2 Serial Data Output 0 */
+#define K210_PCF_I2S2_OUT_D1	117 /* I2S2 Serial Data Output 1 */
+#define K210_PCF_I2S2_OUT_D2	118 /* I2S2 Serial Data Output 2 */
+#define K210_PCF_I2S2_OUT_D3	119 /* I2S2 Serial Data Output 3 */
+#define K210_PCF_RESV0		120 /* Reserved function */
+#define K210_PCF_RESV1		121 /* Reserved function */
+#define K210_PCF_RESV2		122 /* Reserved function */
+#define K210_PCF_RESV3		123 /* Reserved function */
+#define K210_PCF_RESV4		124 /* Reserved function */
+#define K210_PCF_RESV5		125 /* Reserved function */
+#define K210_PCF_I2C0_SCLK	126 /* I2C0 Serial Clock */
+#define K210_PCF_I2C0_SDA	127 /* I2C0 Serial Data */
+#define K210_PCF_I2C1_SCLK	128 /* I2C1 Serial Clock */
+#define K210_PCF_I2C1_SDA	129 /* I2C1 Serial Data */
+#define K210_PCF_I2C2_SCLK	130 /* I2C2 Serial Clock */
+#define K210_PCF_I2C2_SDA	131 /* I2C2 Serial Data */
+#define K210_PCF_DVP_XCLK	132 /* DVP System Clock */
+#define K210_PCF_DVP_RST	133 /* DVP System Reset */
+#define K210_PCF_DVP_PWDN	134 /* DVP Power Down Mode */
+#define K210_PCF_DVP_VSYNC	135 /* DVP Vertical Sync */
+#define K210_PCF_DVP_HSYNC	136 /* DVP Horizontal Sync */
+#define K210_PCF_DVP_PCLK	137 /* Pixel Clock */
+#define K210_PCF_DVP_D0		138 /* Data Bit 0 */
+#define K210_PCF_DVP_D1		139 /* Data Bit 1 */
+#define K210_PCF_DVP_D2		140 /* Data Bit 2 */
+#define K210_PCF_DVP_D3		141 /* Data Bit 3 */
+#define K210_PCF_DVP_D4		142 /* Data Bit 4 */
+#define K210_PCF_DVP_D5		143 /* Data Bit 5 */
+#define K210_PCF_DVP_D6		144 /* Data Bit 6 */
+#define K210_PCF_DVP_D7		145 /* Data Bit 7 */
+#define K210_PCF_SCCB_SCLK	146 /* Serial Camera Control Bus Clock */
+#define K210_PCF_SCCB_SDA	147 /* Serial Camera Control Bus Data */
+#define K210_PCF_UART1_CTS	148 /* UART1 Clear To Send */
+#define K210_PCF_UART1_DSR	149 /* UART1 Data Set Ready */
+#define K210_PCF_UART1_DCD	150 /* UART1 Data Carrier Detect */
+#define K210_PCF_UART1_RI	151 /* UART1 Ring Indicator */
+#define K210_PCF_UART1_SIR_IN	152 /* UART1 Serial Infrared Input */
+#define K210_PCF_UART1_DTR	153 /* UART1 Data Terminal Ready */
+#define K210_PCF_UART1_RTS	154 /* UART1 Request To Send */
+#define K210_PCF_UART1_OUT2	155 /* UART1 User-designated Output 2 */
+#define K210_PCF_UART1_OUT1	156 /* UART1 User-designated Output 1 */
+#define K210_PCF_UART1_SIR_OUT	157 /* UART1 Serial Infrared Output */
+#define K210_PCF_UART1_BAUD	158 /* UART1 Transmit Clock Output */
+#define K210_PCF_UART1_RE	159 /* UART1 Receiver Output Enable */
+#define K210_PCF_UART1_DE	160 /* UART1 Driver Output Enable */
+#define K210_PCF_UART1_RS485_EN	161 /* UART1 RS485 Enable */
+#define K210_PCF_UART2_CTS	162 /* UART2 Clear To Send */
+#define K210_PCF_UART2_DSR	163 /* UART2 Data Set Ready */
+#define K210_PCF_UART2_DCD	164 /* UART2 Data Carrier Detect */
+#define K210_PCF_UART2_RI	165 /* UART2 Ring Indicator */
+#define K210_PCF_UART2_SIR_IN	166 /* UART2 Serial Infrared Input */
+#define K210_PCF_UART2_DTR	167 /* UART2 Data Terminal Ready */
+#define K210_PCF_UART2_RTS	168 /* UART2 Request To Send */
+#define K210_PCF_UART2_OUT2	169 /* UART2 User-designated Output 2 */
+#define K210_PCF_UART2_OUT1	170 /* UART2 User-designated Output 1 */
+#define K210_PCF_UART2_SIR_OUT	171 /* UART2 Serial Infrared Output */
+#define K210_PCF_UART2_BAUD	172 /* UART2 Transmit Clock Output */
+#define K210_PCF_UART2_RE	173 /* UART2 Receiver Output Enable */
+#define K210_PCF_UART2_DE	174 /* UART2 Driver Output Enable */
+#define K210_PCF_UART2_RS485_EN	175 /* UART2 RS485 Enable */
+#define K210_PCF_UART3_CTS	176 /* UART3 Clear To Send */
+#define K210_PCF_UART3_DSR	177 /* UART3 Data Set Ready */
+#define K210_PCF_UART3_DCD	178 /* UART3 Data Carrier Detect */
+#define K210_PCF_UART3_RI	179 /* UART3 Ring Indicator */
+#define K210_PCF_UART3_SIR_IN	180 /* UART3 Serial Infrared Input */
+#define K210_PCF_UART3_DTR	181 /* UART3 Data Terminal Ready */
+#define K210_PCF_UART3_RTS	182 /* UART3 Request To Send */
+#define K210_PCF_UART3_OUT2	183 /* UART3 User-designated Output 2 */
+#define K210_PCF_UART3_OUT1	184 /* UART3 User-designated Output 1 */
+#define K210_PCF_UART3_SIR_OUT	185 /* UART3 Serial Infrared Output */
+#define K210_PCF_UART3_BAUD	186 /* UART3 Transmit Clock Output */
+#define K210_PCF_UART3_RE	187 /* UART3 Receiver Output Enable */
+#define K210_PCF_UART3_DE	188 /* UART3 Driver Output Enable */
+#define K210_PCF_UART3_RS485_EN	189 /* UART3 RS485 Enable */
+#define K210_PCF_TIMER0_TOGGLE1	190 /* TIMER0 Toggle Output 1 */
+#define K210_PCF_TIMER0_TOGGLE2	191 /* TIMER0 Toggle Output 2 */
+#define K210_PCF_TIMER0_TOGGLE3	192 /* TIMER0 Toggle Output 3 */
+#define K210_PCF_TIMER0_TOGGLE4	193 /* TIMER0 Toggle Output 4 */
+#define K210_PCF_TIMER1_TOGGLE1	194 /* TIMER1 Toggle Output 1 */
+#define K210_PCF_TIMER1_TOGGLE2	195 /* TIMER1 Toggle Output 2 */
+#define K210_PCF_TIMER1_TOGGLE3	196 /* TIMER1 Toggle Output 3 */
+#define K210_PCF_TIMER1_TOGGLE4	197 /* TIMER1 Toggle Output 4 */
+#define K210_PCF_TIMER2_TOGGLE1	198 /* TIMER2 Toggle Output 1 */
+#define K210_PCF_TIMER2_TOGGLE2	199 /* TIMER2 Toggle Output 2 */
+#define K210_PCF_TIMER2_TOGGLE3	200 /* TIMER2 Toggle Output 3 */
+#define K210_PCF_TIMER2_TOGGLE4	201 /* TIMER2 Toggle Output 4 */
+#define K210_PCF_CLK_SPI2	202 /* Clock SPI2 */
+#define K210_PCF_CLK_I2C2	203 /* Clock I2C2 */
+#define K210_PCF_INTERNAL0	204 /* Internal function signal 0 */
+#define K210_PCF_INTERNAL1	205 /* Internal function signal 1 */
+#define K210_PCF_INTERNAL2	206 /* Internal function signal 2 */
+#define K210_PCF_INTERNAL3	207 /* Internal function signal 3 */
+#define K210_PCF_INTERNAL4	208 /* Internal function signal 4 */
+#define K210_PCF_INTERNAL5	209 /* Internal function signal 5 */
+#define K210_PCF_INTERNAL6	210 /* Internal function signal 6 */
+#define K210_PCF_INTERNAL7	211 /* Internal function signal 7 */
+#define K210_PCF_INTERNAL8	212 /* Internal function signal 8 */
+#define K210_PCF_INTERNAL9	213 /* Internal function signal 9 */
+#define K210_PCF_INTERNAL10	214 /* Internal function signal 10 */
+#define K210_PCF_INTERNAL11	215 /* Internal function signal 11 */
+#define K210_PCF_INTERNAL12	216 /* Internal function signal 12 */
+#define K210_PCF_INTERNAL13	217 /* Internal function signal 13 */
+#define K210_PCF_INTERNAL14	218 /* Internal function signal 14 */
+#define K210_PCF_INTERNAL15	219 /* Internal function signal 15 */
+#define K210_PCF_INTERNAL16	220 /* Internal function signal 16 */
+#define K210_PCF_INTERNAL17	221 /* Internal function signal 17 */
+#define K210_PCF_CONSTANT	222 /* Constant function */
+#define K210_PCF_INTERNAL18	223 /* Internal function signal 18 */
+#define K210_PCF_DEBUG0		224 /* Debug function 0 */
+#define K210_PCF_DEBUG1		225 /* Debug function 1 */
+#define K210_PCF_DEBUG2		226 /* Debug function 2 */
+#define K210_PCF_DEBUG3		227 /* Debug function 3 */
+#define K210_PCF_DEBUG4		228 /* Debug function 4 */
+#define K210_PCF_DEBUG5		229 /* Debug function 5 */
+#define K210_PCF_DEBUG6		230 /* Debug function 6 */
+#define K210_PCF_DEBUG7		231 /* Debug function 7 */
+#define K210_PCF_DEBUG8		232 /* Debug function 8 */
+#define K210_PCF_DEBUG9		233 /* Debug function 9 */
+#define K210_PCF_DEBUG10	234 /* Debug function 10 */
+#define K210_PCF_DEBUG11	235 /* Debug function 11 */
+#define K210_PCF_DEBUG12	236 /* Debug function 12 */
+#define K210_PCF_DEBUG13	237 /* Debug function 13 */
+#define K210_PCF_DEBUG14	238 /* Debug function 14 */
+#define K210_PCF_DEBUG15	239 /* Debug function 15 */
+#define K210_PCF_DEBUG16	240 /* Debug function 16 */
+#define K210_PCF_DEBUG17	241 /* Debug function 17 */
+#define K210_PCF_DEBUG18	242 /* Debug function 18 */
+#define K210_PCF_DEBUG19	243 /* Debug function 19 */
+#define K210_PCF_DEBUG20	244 /* Debug function 20 */
+#define K210_PCF_DEBUG21	245 /* Debug function 21 */
+#define K210_PCF_DEBUG22	246 /* Debug function 22 */
+#define K210_PCF_DEBUG23	247 /* Debug function 23 */
+#define K210_PCF_DEBUG24	248 /* Debug function 24 */
+#define K210_PCF_DEBUG25	249 /* Debug function 25 */
+#define K210_PCF_DEBUG26	250 /* Debug function 26 */
+#define K210_PCF_DEBUG27	251 /* Debug function 27 */
+#define K210_PCF_DEBUG28	252 /* Debug function 28 */
+#define K210_PCF_DEBUG29	253 /* Debug function 29 */
+#define K210_PCF_DEBUG30	254 /* Debug function 30 */
+#define K210_PCF_DEBUG31	255 /* Debug function 31 */
+
+#define K210_FPIOA(pin, func)		(((pin) << 16) | (func))
+#define K210_FPIOA_DO(pin, func)	(((pin) << 16) | (1 << 8) | (func))
+
+#define K210_PC_POWER_3V3	0
+#define K210_PC_POWER_1V8	1
+
+#endif /* PINCTRL_K210_SYSCTL_H */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 16/32] dt-bindings: Define Kendryte K210 pin functions
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file
include/dt-bindings/pinctrl/k210_pinctrl.h to define all possible 255
functions that can be assigned to any of the 48 programmable pins of the
SoC. Macros allowing a device tree to define a pinmux mapping are also
introduced.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/pinctrl/k210-pinctrl.h | 277 +++++++++++++++++++++
 1 file changed, 277 insertions(+)
 create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h

diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h
new file mode 100644
index 000000000000..0b797a4a245e
--- /dev/null
+++ b/include/dt-bindings/pinctrl/k210-pinctrl.h
@@ -0,0 +1,277 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef PINCTRL_K210_SYSCTL_H
+#define PINCTRL_K210_SYSCTL_H
+
+/*
+ * Full list of FPIOA functions from
+ * kendryte-standalone-sdk/lib/drivers/include/fpioa.h
+ */
+#define K210_PCF_MASK		GENMASK(7, 0)
+#define K210_PCF_JTAG_TCLK	0   /* JTAG Test Clock */
+#define K210_PCF_JTAG_TDI	1   /* JTAG Test Data In */
+#define K210_PCF_JTAG_TMS	2   /* JTAG Test Mode Select */
+#define K210_PCF_JTAG_TDO	3   /* JTAG Test Data Out */
+#define K210_PCF_SPI0_D0	4   /* SPI0 Data 0 */
+#define K210_PCF_SPI0_D1	5   /* SPI0 Data 1 */
+#define K210_PCF_SPI0_D2	6   /* SPI0 Data 2 */
+#define K210_PCF_SPI0_D3	7   /* SPI0 Data 3 */
+#define K210_PCF_SPI0_D4	8   /* SPI0 Data 4 */
+#define K210_PCF_SPI0_D5	9   /* SPI0 Data 5 */
+#define K210_PCF_SPI0_D6	10  /* SPI0 Data 6 */
+#define K210_PCF_SPI0_D7	11  /* SPI0 Data 7 */
+#define K210_PCF_SPI0_SS0	12  /* SPI0 Chip Select 0 */
+#define K210_PCF_SPI0_SS1	13  /* SPI0 Chip Select 1 */
+#define K210_PCF_SPI0_SS2	14  /* SPI0 Chip Select 2 */
+#define K210_PCF_SPI0_SS3	15  /* SPI0 Chip Select 3 */
+#define K210_PCF_SPI0_ARB	16  /* SPI0 Arbitration */
+#define K210_PCF_SPI0_SCLK	17  /* SPI0 Serial Clock */
+#define K210_PCF_UARTHS_RX	18  /* UART High speed Receiver */
+#define K210_PCF_UARTHS_TX	19  /* UART High speed Transmitter */
+#define K210_PCF_RESV6		20  /* Reserved function */
+#define K210_PCF_RESV7		21  /* Reserved function */
+#define K210_PCF_CLK_SPI1	22  /* Clock SPI1 */
+#define K210_PCF_CLK_I2C1	23  /* Clock I2C1 */
+#define K210_PCF_GPIOHS0	24  /* GPIO High speed 0 */
+#define K210_PCF_GPIOHS1	25  /* GPIO High speed 1 */
+#define K210_PCF_GPIOHS2	26  /* GPIO High speed 2 */
+#define K210_PCF_GPIOHS3	27  /* GPIO High speed 3 */
+#define K210_PCF_GPIOHS4	28  /* GPIO High speed 4 */
+#define K210_PCF_GPIOHS5	29  /* GPIO High speed 5 */
+#define K210_PCF_GPIOHS6	30  /* GPIO High speed 6 */
+#define K210_PCF_GPIOHS7	31  /* GPIO High speed 7 */
+#define K210_PCF_GPIOHS8	32  /* GPIO High speed 8 */
+#define K210_PCF_GPIOHS9	33  /* GPIO High speed 9 */
+#define K210_PCF_GPIOHS10	34  /* GPIO High speed 10 */
+#define K210_PCF_GPIOHS11	35  /* GPIO High speed 11 */
+#define K210_PCF_GPIOHS12	36  /* GPIO High speed 12 */
+#define K210_PCF_GPIOHS13	37  /* GPIO High speed 13 */
+#define K210_PCF_GPIOHS14	38  /* GPIO High speed 14 */
+#define K210_PCF_GPIOHS15	39  /* GPIO High speed 15 */
+#define K210_PCF_GPIOHS16	40  /* GPIO High speed 16 */
+#define K210_PCF_GPIOHS17	41  /* GPIO High speed 17 */
+#define K210_PCF_GPIOHS18	42  /* GPIO High speed 18 */
+#define K210_PCF_GPIOHS19	43  /* GPIO High speed 19 */
+#define K210_PCF_GPIOHS20	44  /* GPIO High speed 20 */
+#define K210_PCF_GPIOHS21	45  /* GPIO High speed 21 */
+#define K210_PCF_GPIOHS22	46  /* GPIO High speed 22 */
+#define K210_PCF_GPIOHS23	47  /* GPIO High speed 23 */
+#define K210_PCF_GPIOHS24	48  /* GPIO High speed 24 */
+#define K210_PCF_GPIOHS25	49  /* GPIO High speed 25 */
+#define K210_PCF_GPIOHS26	50  /* GPIO High speed 26 */
+#define K210_PCF_GPIOHS27	51  /* GPIO High speed 27 */
+#define K210_PCF_GPIOHS28	52  /* GPIO High speed 28 */
+#define K210_PCF_GPIOHS29	53  /* GPIO High speed 29 */
+#define K210_PCF_GPIOHS30	54  /* GPIO High speed 30 */
+#define K210_PCF_GPIOHS31	55  /* GPIO High speed 31 */
+#define K210_PCF_GPIO0		56  /* GPIO pin 0 */
+#define K210_PCF_GPIO1		57  /* GPIO pin 1 */
+#define K210_PCF_GPIO2		58  /* GPIO pin 2 */
+#define K210_PCF_GPIO3		59  /* GPIO pin 3 */
+#define K210_PCF_GPIO4		60  /* GPIO pin 4 */
+#define K210_PCF_GPIO5		61  /* GPIO pin 5 */
+#define K210_PCF_GPIO6		62  /* GPIO pin 6 */
+#define K210_PCF_GPIO7		63  /* GPIO pin 7 */
+#define K210_PCF_UART1_RX	64  /* UART1 Receiver */
+#define K210_PCF_UART1_TX	65  /* UART1 Transmitter */
+#define K210_PCF_UART2_RX	66  /* UART2 Receiver */
+#define K210_PCF_UART2_TX	67  /* UART2 Transmitter */
+#define K210_PCF_UART3_RX	68  /* UART3 Receiver */
+#define K210_PCF_UART3_TX	69  /* UART3 Transmitter */
+#define K210_PCF_SPI1_D0	70  /* SPI1 Data 0 */
+#define K210_PCF_SPI1_D1	71  /* SPI1 Data 1 */
+#define K210_PCF_SPI1_D2	72  /* SPI1 Data 2 */
+#define K210_PCF_SPI1_D3	73  /* SPI1 Data 3 */
+#define K210_PCF_SPI1_D4	74  /* SPI1 Data 4 */
+#define K210_PCF_SPI1_D5	75  /* SPI1 Data 5 */
+#define K210_PCF_SPI1_D6	76  /* SPI1 Data 6 */
+#define K210_PCF_SPI1_D7	77  /* SPI1 Data 7 */
+#define K210_PCF_SPI1_SS0	78  /* SPI1 Chip Select 0 */
+#define K210_PCF_SPI1_SS1	79  /* SPI1 Chip Select 1 */
+#define K210_PCF_SPI1_SS2	80  /* SPI1 Chip Select 2 */
+#define K210_PCF_SPI1_SS3	81  /* SPI1 Chip Select 3 */
+#define K210_PCF_SPI1_ARB	82  /* SPI1 Arbitration */
+#define K210_PCF_SPI1_SCLK	83  /* SPI1 Serial Clock */
+#define K210_PCF_SPI2_D0	84  /* SPI2 Data 0 */
+#define K210_PCF_SPI2_SS	85  /* SPI2 Select */
+#define K210_PCF_SPI2_SCLK	86  /* SPI2 Serial Clock */
+#define K210_PCF_I2S0_MCLK	87  /* I2S0 Master Clock */
+#define K210_PCF_I2S0_SCLK	88  /* I2S0 Serial Clock(BCLK) */
+#define K210_PCF_I2S0_WS	89  /* I2S0 Word Select(LRCLK) */
+#define K210_PCF_I2S0_IN_D0	90  /* I2S0 Serial Data Input 0 */
+#define K210_PCF_I2S0_IN_D1	91  /* I2S0 Serial Data Input 1 */
+#define K210_PCF_I2S0_IN_D2	92  /* I2S0 Serial Data Input 2 */
+#define K210_PCF_I2S0_IN_D3	93  /* I2S0 Serial Data Input 3 */
+#define K210_PCF_I2S0_OUT_D0	94  /* I2S0 Serial Data Output 0 */
+#define K210_PCF_I2S0_OUT_D1	95  /* I2S0 Serial Data Output 1 */
+#define K210_PCF_I2S0_OUT_D2	96  /* I2S0 Serial Data Output 2 */
+#define K210_PCF_I2S0_OUT_D3	97  /* I2S0 Serial Data Output 3 */
+#define K210_PCF_I2S1_MCLK	98  /* I2S1 Master Clock */
+#define K210_PCF_I2S1_SCLK	99  /* I2S1 Serial Clock(BCLK) */
+#define K210_PCF_I2S1_WS	100 /* I2S1 Word Select(LRCLK) */
+#define K210_PCF_I2S1_IN_D0	101 /* I2S1 Serial Data Input 0 */
+#define K210_PCF_I2S1_IN_D1	102 /* I2S1 Serial Data Input 1 */
+#define K210_PCF_I2S1_IN_D2	103 /* I2S1 Serial Data Input 2 */
+#define K210_PCF_I2S1_IN_D3	104 /* I2S1 Serial Data Input 3 */
+#define K210_PCF_I2S1_OUT_D0	105 /* I2S1 Serial Data Output 0 */
+#define K210_PCF_I2S1_OUT_D1	106 /* I2S1 Serial Data Output 1 */
+#define K210_PCF_I2S1_OUT_D2	107 /* I2S1 Serial Data Output 2 */
+#define K210_PCF_I2S1_OUT_D3	108 /* I2S1 Serial Data Output 3 */
+#define K210_PCF_I2S2_MCLK	109 /* I2S2 Master Clock */
+#define K210_PCF_I2S2_SCLK	110 /* I2S2 Serial Clock(BCLK) */
+#define K210_PCF_I2S2_WS	111 /* I2S2 Word Select(LRCLK) */
+#define K210_PCF_I2S2_IN_D0	112 /* I2S2 Serial Data Input 0 */
+#define K210_PCF_I2S2_IN_D1	113 /* I2S2 Serial Data Input 1 */
+#define K210_PCF_I2S2_IN_D2	114 /* I2S2 Serial Data Input 2 */
+#define K210_PCF_I2S2_IN_D3	115 /* I2S2 Serial Data Input 3 */
+#define K210_PCF_I2S2_OUT_D0	116 /* I2S2 Serial Data Output 0 */
+#define K210_PCF_I2S2_OUT_D1	117 /* I2S2 Serial Data Output 1 */
+#define K210_PCF_I2S2_OUT_D2	118 /* I2S2 Serial Data Output 2 */
+#define K210_PCF_I2S2_OUT_D3	119 /* I2S2 Serial Data Output 3 */
+#define K210_PCF_RESV0		120 /* Reserved function */
+#define K210_PCF_RESV1		121 /* Reserved function */
+#define K210_PCF_RESV2		122 /* Reserved function */
+#define K210_PCF_RESV3		123 /* Reserved function */
+#define K210_PCF_RESV4		124 /* Reserved function */
+#define K210_PCF_RESV5		125 /* Reserved function */
+#define K210_PCF_I2C0_SCLK	126 /* I2C0 Serial Clock */
+#define K210_PCF_I2C0_SDA	127 /* I2C0 Serial Data */
+#define K210_PCF_I2C1_SCLK	128 /* I2C1 Serial Clock */
+#define K210_PCF_I2C1_SDA	129 /* I2C1 Serial Data */
+#define K210_PCF_I2C2_SCLK	130 /* I2C2 Serial Clock */
+#define K210_PCF_I2C2_SDA	131 /* I2C2 Serial Data */
+#define K210_PCF_DVP_XCLK	132 /* DVP System Clock */
+#define K210_PCF_DVP_RST	133 /* DVP System Reset */
+#define K210_PCF_DVP_PWDN	134 /* DVP Power Down Mode */
+#define K210_PCF_DVP_VSYNC	135 /* DVP Vertical Sync */
+#define K210_PCF_DVP_HSYNC	136 /* DVP Horizontal Sync */
+#define K210_PCF_DVP_PCLK	137 /* Pixel Clock */
+#define K210_PCF_DVP_D0		138 /* Data Bit 0 */
+#define K210_PCF_DVP_D1		139 /* Data Bit 1 */
+#define K210_PCF_DVP_D2		140 /* Data Bit 2 */
+#define K210_PCF_DVP_D3		141 /* Data Bit 3 */
+#define K210_PCF_DVP_D4		142 /* Data Bit 4 */
+#define K210_PCF_DVP_D5		143 /* Data Bit 5 */
+#define K210_PCF_DVP_D6		144 /* Data Bit 6 */
+#define K210_PCF_DVP_D7		145 /* Data Bit 7 */
+#define K210_PCF_SCCB_SCLK	146 /* Serial Camera Control Bus Clock */
+#define K210_PCF_SCCB_SDA	147 /* Serial Camera Control Bus Data */
+#define K210_PCF_UART1_CTS	148 /* UART1 Clear To Send */
+#define K210_PCF_UART1_DSR	149 /* UART1 Data Set Ready */
+#define K210_PCF_UART1_DCD	150 /* UART1 Data Carrier Detect */
+#define K210_PCF_UART1_RI	151 /* UART1 Ring Indicator */
+#define K210_PCF_UART1_SIR_IN	152 /* UART1 Serial Infrared Input */
+#define K210_PCF_UART1_DTR	153 /* UART1 Data Terminal Ready */
+#define K210_PCF_UART1_RTS	154 /* UART1 Request To Send */
+#define K210_PCF_UART1_OUT2	155 /* UART1 User-designated Output 2 */
+#define K210_PCF_UART1_OUT1	156 /* UART1 User-designated Output 1 */
+#define K210_PCF_UART1_SIR_OUT	157 /* UART1 Serial Infrared Output */
+#define K210_PCF_UART1_BAUD	158 /* UART1 Transmit Clock Output */
+#define K210_PCF_UART1_RE	159 /* UART1 Receiver Output Enable */
+#define K210_PCF_UART1_DE	160 /* UART1 Driver Output Enable */
+#define K210_PCF_UART1_RS485_EN	161 /* UART1 RS485 Enable */
+#define K210_PCF_UART2_CTS	162 /* UART2 Clear To Send */
+#define K210_PCF_UART2_DSR	163 /* UART2 Data Set Ready */
+#define K210_PCF_UART2_DCD	164 /* UART2 Data Carrier Detect */
+#define K210_PCF_UART2_RI	165 /* UART2 Ring Indicator */
+#define K210_PCF_UART2_SIR_IN	166 /* UART2 Serial Infrared Input */
+#define K210_PCF_UART2_DTR	167 /* UART2 Data Terminal Ready */
+#define K210_PCF_UART2_RTS	168 /* UART2 Request To Send */
+#define K210_PCF_UART2_OUT2	169 /* UART2 User-designated Output 2 */
+#define K210_PCF_UART2_OUT1	170 /* UART2 User-designated Output 1 */
+#define K210_PCF_UART2_SIR_OUT	171 /* UART2 Serial Infrared Output */
+#define K210_PCF_UART2_BAUD	172 /* UART2 Transmit Clock Output */
+#define K210_PCF_UART2_RE	173 /* UART2 Receiver Output Enable */
+#define K210_PCF_UART2_DE	174 /* UART2 Driver Output Enable */
+#define K210_PCF_UART2_RS485_EN	175 /* UART2 RS485 Enable */
+#define K210_PCF_UART3_CTS	176 /* UART3 Clear To Send */
+#define K210_PCF_UART3_DSR	177 /* UART3 Data Set Ready */
+#define K210_PCF_UART3_DCD	178 /* UART3 Data Carrier Detect */
+#define K210_PCF_UART3_RI	179 /* UART3 Ring Indicator */
+#define K210_PCF_UART3_SIR_IN	180 /* UART3 Serial Infrared Input */
+#define K210_PCF_UART3_DTR	181 /* UART3 Data Terminal Ready */
+#define K210_PCF_UART3_RTS	182 /* UART3 Request To Send */
+#define K210_PCF_UART3_OUT2	183 /* UART3 User-designated Output 2 */
+#define K210_PCF_UART3_OUT1	184 /* UART3 User-designated Output 1 */
+#define K210_PCF_UART3_SIR_OUT	185 /* UART3 Serial Infrared Output */
+#define K210_PCF_UART3_BAUD	186 /* UART3 Transmit Clock Output */
+#define K210_PCF_UART3_RE	187 /* UART3 Receiver Output Enable */
+#define K210_PCF_UART3_DE	188 /* UART3 Driver Output Enable */
+#define K210_PCF_UART3_RS485_EN	189 /* UART3 RS485 Enable */
+#define K210_PCF_TIMER0_TOGGLE1	190 /* TIMER0 Toggle Output 1 */
+#define K210_PCF_TIMER0_TOGGLE2	191 /* TIMER0 Toggle Output 2 */
+#define K210_PCF_TIMER0_TOGGLE3	192 /* TIMER0 Toggle Output 3 */
+#define K210_PCF_TIMER0_TOGGLE4	193 /* TIMER0 Toggle Output 4 */
+#define K210_PCF_TIMER1_TOGGLE1	194 /* TIMER1 Toggle Output 1 */
+#define K210_PCF_TIMER1_TOGGLE2	195 /* TIMER1 Toggle Output 2 */
+#define K210_PCF_TIMER1_TOGGLE3	196 /* TIMER1 Toggle Output 3 */
+#define K210_PCF_TIMER1_TOGGLE4	197 /* TIMER1 Toggle Output 4 */
+#define K210_PCF_TIMER2_TOGGLE1	198 /* TIMER2 Toggle Output 1 */
+#define K210_PCF_TIMER2_TOGGLE2	199 /* TIMER2 Toggle Output 2 */
+#define K210_PCF_TIMER2_TOGGLE3	200 /* TIMER2 Toggle Output 3 */
+#define K210_PCF_TIMER2_TOGGLE4	201 /* TIMER2 Toggle Output 4 */
+#define K210_PCF_CLK_SPI2	202 /* Clock SPI2 */
+#define K210_PCF_CLK_I2C2	203 /* Clock I2C2 */
+#define K210_PCF_INTERNAL0	204 /* Internal function signal 0 */
+#define K210_PCF_INTERNAL1	205 /* Internal function signal 1 */
+#define K210_PCF_INTERNAL2	206 /* Internal function signal 2 */
+#define K210_PCF_INTERNAL3	207 /* Internal function signal 3 */
+#define K210_PCF_INTERNAL4	208 /* Internal function signal 4 */
+#define K210_PCF_INTERNAL5	209 /* Internal function signal 5 */
+#define K210_PCF_INTERNAL6	210 /* Internal function signal 6 */
+#define K210_PCF_INTERNAL7	211 /* Internal function signal 7 */
+#define K210_PCF_INTERNAL8	212 /* Internal function signal 8 */
+#define K210_PCF_INTERNAL9	213 /* Internal function signal 9 */
+#define K210_PCF_INTERNAL10	214 /* Internal function signal 10 */
+#define K210_PCF_INTERNAL11	215 /* Internal function signal 11 */
+#define K210_PCF_INTERNAL12	216 /* Internal function signal 12 */
+#define K210_PCF_INTERNAL13	217 /* Internal function signal 13 */
+#define K210_PCF_INTERNAL14	218 /* Internal function signal 14 */
+#define K210_PCF_INTERNAL15	219 /* Internal function signal 15 */
+#define K210_PCF_INTERNAL16	220 /* Internal function signal 16 */
+#define K210_PCF_INTERNAL17	221 /* Internal function signal 17 */
+#define K210_PCF_CONSTANT	222 /* Constant function */
+#define K210_PCF_INTERNAL18	223 /* Internal function signal 18 */
+#define K210_PCF_DEBUG0		224 /* Debug function 0 */
+#define K210_PCF_DEBUG1		225 /* Debug function 1 */
+#define K210_PCF_DEBUG2		226 /* Debug function 2 */
+#define K210_PCF_DEBUG3		227 /* Debug function 3 */
+#define K210_PCF_DEBUG4		228 /* Debug function 4 */
+#define K210_PCF_DEBUG5		229 /* Debug function 5 */
+#define K210_PCF_DEBUG6		230 /* Debug function 6 */
+#define K210_PCF_DEBUG7		231 /* Debug function 7 */
+#define K210_PCF_DEBUG8		232 /* Debug function 8 */
+#define K210_PCF_DEBUG9		233 /* Debug function 9 */
+#define K210_PCF_DEBUG10	234 /* Debug function 10 */
+#define K210_PCF_DEBUG11	235 /* Debug function 11 */
+#define K210_PCF_DEBUG12	236 /* Debug function 12 */
+#define K210_PCF_DEBUG13	237 /* Debug function 13 */
+#define K210_PCF_DEBUG14	238 /* Debug function 14 */
+#define K210_PCF_DEBUG15	239 /* Debug function 15 */
+#define K210_PCF_DEBUG16	240 /* Debug function 16 */
+#define K210_PCF_DEBUG17	241 /* Debug function 17 */
+#define K210_PCF_DEBUG18	242 /* Debug function 18 */
+#define K210_PCF_DEBUG19	243 /* Debug function 19 */
+#define K210_PCF_DEBUG20	244 /* Debug function 20 */
+#define K210_PCF_DEBUG21	245 /* Debug function 21 */
+#define K210_PCF_DEBUG22	246 /* Debug function 22 */
+#define K210_PCF_DEBUG23	247 /* Debug function 23 */
+#define K210_PCF_DEBUG24	248 /* Debug function 24 */
+#define K210_PCF_DEBUG25	249 /* Debug function 25 */
+#define K210_PCF_DEBUG26	250 /* Debug function 26 */
+#define K210_PCF_DEBUG27	251 /* Debug function 27 */
+#define K210_PCF_DEBUG28	252 /* Debug function 28 */
+#define K210_PCF_DEBUG29	253 /* Debug function 29 */
+#define K210_PCF_DEBUG30	254 /* Debug function 30 */
+#define K210_PCF_DEBUG31	255 /* Debug function 31 */
+
+#define K210_FPIOA(pin, func)		(((pin) << 16) | (func))
+#define K210_FPIOA_DO(pin, func)	(((pin) << 16) | (1 << 8) | (func))
+
+#define K210_PC_POWER_3V3	0
+#define K210_PC_POWER_1V8	1
+
+#endif /* PINCTRL_K210_SYSCTL_H */
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 17/32] dt-bindings: Define Kendryte K210 reset signals
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file include/dt-bindings/reset/k210_sysctl.h
to define IDs for all 30 reset signals available on the Kendryte K210
RISC-V SoC.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/reset/k210-rst.h | 42 ++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 include/dt-bindings/reset/k210-rst.h

diff --git a/include/dt-bindings/reset/k210-rst.h b/include/dt-bindings/reset/k210-rst.h
new file mode 100644
index 000000000000..883c1aed50e8
--- /dev/null
+++ b/include/dt-bindings/reset/k210-rst.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef RESET_K210_SYSCTL_H
+#define RESET_K210_SYSCTL_H
+
+/*
+ * Kendryte K210 SoC system controller K210_SYSCTL_SOFT_RESET register bits.
+ * Taken from Kendryte SDK (kendryte-standalone-sdk).
+ */
+#define K210_RST_ROM	0
+#define K210_RST_DMA	1
+#define K210_RST_AI	2
+#define K210_RST_DVP	3
+#define K210_RST_FFT	4
+#define K210_RST_GPIO	5
+#define K210_RST_SPI0	6
+#define K210_RST_SPI1	7
+#define K210_RST_SPI2	8
+#define K210_RST_SPI3	9
+#define K210_RST_I2S0	10
+#define K210_RST_I2S1	11
+#define K210_RST_I2S2	12
+#define K210_RST_I2C0	13
+#define K210_RST_I2C1	14
+#define K210_RST_I2C2	15
+#define K210_RST_UART1	16
+#define K210_RST_UART2	17
+#define K210_RST_UART3	18
+#define K210_RST_AES	19
+#define K210_RST_FPIOA	20
+#define K210_RST_TIMER0	21
+#define K210_RST_TIMER1	22
+#define K210_RST_TIMER2	23
+#define K210_RST_WDT0	24
+#define K210_RST_WDT1	25
+#define K210_RST_SHA	26
+#define K210_RST_RTC	29
+
+#endif /* RESET_K210_SYSCTL_H */
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 17/32] dt-bindings: Define Kendryte K210 reset signals
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Introduce the dt-bindings file include/dt-bindings/reset/k210_sysctl.h
to define IDs for all 30 reset signals available on the Kendryte K210
RISC-V SoC.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 include/dt-bindings/reset/k210-rst.h | 42 ++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)
 create mode 100644 include/dt-bindings/reset/k210-rst.h

diff --git a/include/dt-bindings/reset/k210-rst.h b/include/dt-bindings/reset/k210-rst.h
new file mode 100644
index 000000000000..883c1aed50e8
--- /dev/null
+++ b/include/dt-bindings/reset/k210-rst.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef RESET_K210_SYSCTL_H
+#define RESET_K210_SYSCTL_H
+
+/*
+ * Kendryte K210 SoC system controller K210_SYSCTL_SOFT_RESET register bits.
+ * Taken from Kendryte SDK (kendryte-standalone-sdk).
+ */
+#define K210_RST_ROM	0
+#define K210_RST_DMA	1
+#define K210_RST_AI	2
+#define K210_RST_DVP	3
+#define K210_RST_FFT	4
+#define K210_RST_GPIO	5
+#define K210_RST_SPI0	6
+#define K210_RST_SPI1	7
+#define K210_RST_SPI2	8
+#define K210_RST_SPI3	9
+#define K210_RST_I2S0	10
+#define K210_RST_I2S1	11
+#define K210_RST_I2S2	12
+#define K210_RST_I2C0	13
+#define K210_RST_I2C1	14
+#define K210_RST_I2C2	15
+#define K210_RST_UART1	16
+#define K210_RST_UART2	17
+#define K210_RST_UART3	18
+#define K210_RST_AES	19
+#define K210_RST_FPIOA	20
+#define K210_RST_TIMER0	21
+#define K210_RST_TIMER1	22
+#define K210_RST_TIMER2	23
+#define K210_RST_WDT0	24
+#define K210_RST_WDT1	25
+#define K210_RST_SHA	26
+#define K210_RST_RTC	29
+
+#endif /* RESET_K210_SYSCTL_H */
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a clock provider driver for the Kendryte K210 RISC-V SoC. This new
driver with compatible string "kendryte,k210-clk", implements the full
clock structure of the K210 SoC. Since it is required for the correct
operation of the SoC, this driver is automatically selected for
compilation when the SOC_KENDRYTE option is selected.

With this change, the k210-sysctl driver is turned into a simple
platform driver which enables its power bus clock and triggers
populating its child nodes. The sysctl soc driver retains the SOC early
initialization code, but the implementation now relies on the new
function k210_clk_early_init() provided by the new clk-k210 driver.
This function declaration is done using the new header file
include/soc/kendryte/k210-sysctl.h.

The clock structure implemented and many of the coding ideas for the
driver come from the work by Sean Anderson on the Kendryte K210 support
for the U-Boot project.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs            |   1 +
 drivers/clk/Kconfig                |   9 +
 drivers/clk/Makefile               |   1 +
 drivers/clk/clk-k210.c             | 962 +++++++++++++++++++++++++++++
 drivers/soc/kendryte/k210-sysctl.c | 241 ++------
 include/soc/kendryte/k210-sysctl.h |  11 +
 6 files changed, 1025 insertions(+), 200 deletions(-)
 create mode 100644 drivers/clk/clk-k210.c
 create mode 100644 include/soc/kendryte/k210-sysctl.h

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 97ef393d0ed0..a4c851ffc6b0 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -30,6 +30,7 @@ config SOC_KENDRYTE
 	select SERIAL_SIFIVE_CONSOLE if TTY
 	select SIFIVE_PLIC
 	select SOC_K210
+	select CLK_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c715d4681a0b..07a30a7b90b1 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -359,6 +359,15 @@ config COMMON_CLK_FIXED_MMIO
 	help
 	  Support for Memory Mapped IO Fixed clocks
 
+config CLK_K210
+	bool "Clock driver for the Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on COMMON_CLK && OF
+	help
+	  Support for the Kendryte K210 RISC-V SoC clocks. This option
+	  is automatically selected when the SOC_KENDRYTE option is selected
+	  in the "SOC selection" menu.
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index da8fcf147eb1..ccac89e0fdfe 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
+obj-$(CONFIG_CLK_K210)			+= clk-k210.o
 
 # please keep this section sorted lexicographically by directory path name
 obj-y					+= actions/
diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
new file mode 100644
index 000000000000..7be5a8cdfef6
--- /dev/null
+++ b/drivers/clk/clk-k210.c
@@ -0,0 +1,962 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ */
+#define pr_fmt(fmt)     "k210-clk: " fmt
+
+#include <soc/kendryte/k210-sysctl.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <asm/soc.h>
+
+#include <dt-bindings/clock/k210-clk.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+
+/*
+ * in0: fixed-rate 26MHz oscillator base clock.
+ */
+#define K210_IN0_RATE		26000000UL
+
+/*
+ * Clocks parameters.
+ */
+struct k210_clk_cfg {
+	u8 gate_reg;
+	u8 gate_bit;
+	u8 div_reg;
+	u8 div_shift;
+	u8 div_width;
+	u8 div_type;
+	u8 mux_reg;
+	u8 mux_bit;
+};
+
+enum k210_clk_div_type {
+	DIV_NONE,
+	DIV_ONE_BASED,
+	DIV_DOUBLE_ONE_BASED,
+	DIV_POWER_OF_TWO,
+};
+
+#define GATE(_reg, _bit)	\
+	.gate_reg = (_reg),	\
+	.gate_bit = (_bit)
+#define DIV(_reg, _shift, _width, _type)	\
+	.div_reg = (_reg),			\
+	.div_shift = (_shift),			\
+	.div_width = (_width),			\
+	.div_type = (_type)
+#define MUX(_reg, _bit)		\
+	.mux_reg = (_reg),	\
+	.mux_bit = (_bit)
+
+static struct k210_clk_cfg k210_clks[K210_NUM_CLKS] = {
+
+	/* Gated clocks, no mux, no divider */
+	[K210_CLK_CPU] = { GATE(K210_SYSCTL_EN_CENT, 0) },
+	[K210_CLK_DMA] = { GATE(K210_SYSCTL_EN_PERI, 1) },
+	[K210_CLK_FFT] = { GATE(K210_SYSCTL_EN_PERI, 4) },
+	[K210_CLK_GPIO] = { GATE(K210_SYSCTL_EN_PERI, 5) },
+	[K210_CLK_UART1] = { GATE(K210_SYSCTL_EN_PERI, 16) },
+	[K210_CLK_UART2] = { GATE(K210_SYSCTL_EN_PERI, 17) },
+	[K210_CLK_UART3] = { GATE(K210_SYSCTL_EN_PERI, 18) },
+	[K210_CLK_FPIOA] = { GATE(K210_SYSCTL_EN_PERI, 20) },
+	[K210_CLK_SHA] = { GATE(K210_SYSCTL_EN_PERI, 26) },
+	[K210_CLK_AES] = { GATE(K210_SYSCTL_EN_PERI, 19) },
+	[K210_CLK_OTP] = { GATE(K210_SYSCTL_EN_PERI, 27) },
+	[K210_CLK_RTC] = { GATE(K210_SYSCTL_EN_PERI, 29) },
+
+	/* Gated divider clocks */
+	[K210_CLK_SRAM0] = {
+		GATE(K210_SYSCTL_EN_CENT, 1),
+		DIV(K210_SYSCTL_THR0, 0, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_SRAM1] = {
+		GATE(K210_SYSCTL_EN_CENT, 2),
+		DIV(K210_SYSCTL_THR0, 4, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_ROM] = {
+		GATE(K210_SYSCTL_EN_PERI, 0),
+		DIV(K210_SYSCTL_THR0, 16, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_DVP] = {
+		GATE(K210_SYSCTL_EN_PERI, 3),
+		DIV(K210_SYSCTL_THR0, 12, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB0] = {
+		GATE(K210_SYSCTL_EN_CENT, 3),
+		DIV(K210_SYSCTL_SEL0, 3, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB1] = {
+		GATE(K210_SYSCTL_EN_CENT, 4),
+		DIV(K210_SYSCTL_SEL0, 6, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB2] = {
+		GATE(K210_SYSCTL_EN_CENT, 5),
+		DIV(K210_SYSCTL_SEL0, 9, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_AI] = {
+		GATE(K210_SYSCTL_EN_PERI, 2),
+		DIV(K210_SYSCTL_THR0, 8, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_SPI0] = {
+		GATE(K210_SYSCTL_EN_PERI, 6),
+		DIV(K210_SYSCTL_THR1, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI1] = {
+		GATE(K210_SYSCTL_EN_PERI, 7),
+		DIV(K210_SYSCTL_THR1, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI2] = {
+		GATE(K210_SYSCTL_EN_PERI, 8),
+		DIV(K210_SYSCTL_THR1, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C0] = {
+		GATE(K210_SYSCTL_EN_PERI, 13),
+		DIV(K210_SYSCTL_THR5, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C1] = {
+		GATE(K210_SYSCTL_EN_PERI, 14),
+		DIV(K210_SYSCTL_THR5, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C2] = {
+		GATE(K210_SYSCTL_EN_PERI, 15),
+		DIV(K210_SYSCTL_THR5, 24, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT0] = {
+		GATE(K210_SYSCTL_EN_PERI, 24),
+		DIV(K210_SYSCTL_THR6, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT1] = {
+		GATE(K210_SYSCTL_EN_PERI, 25),
+		DIV(K210_SYSCTL_THR6, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S0] = {
+		GATE(K210_SYSCTL_EN_PERI, 10),
+		DIV(K210_SYSCTL_THR3, 0, 16, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1] = {
+		GATE(K210_SYSCTL_EN_PERI, 11),
+		DIV(K210_SYSCTL_THR3, 16, 16, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2] = {
+		GATE(K210_SYSCTL_EN_PERI, 12),
+		DIV(K210_SYSCTL_THR4, 0, 16, DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Divider clocks, no gate, no mux */
+	[K210_CLK_I2S0_M] = {
+		DIV(K210_SYSCTL_THR4, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1_M] = {
+		DIV(K210_SYSCTL_THR4, 24, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2_M] = {
+		DIV(K210_SYSCTL_THR4, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Muxed gated divider clocks */
+	[K210_CLK_SPI3] = {
+		GATE(K210_SYSCTL_EN_PERI, 9),
+		DIV(K210_SYSCTL_THR1, 24, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 12)
+	},
+	[K210_CLK_TIMER0] = {
+		GATE(K210_SYSCTL_EN_PERI, 21),
+		DIV(K210_SYSCTL_THR2,  0, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 13)
+	},
+	[K210_CLK_TIMER1] = {
+		GATE(K210_SYSCTL_EN_PERI, 22),
+		DIV(K210_SYSCTL_THR2, 8, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 14)
+	},
+	[K210_CLK_TIMER2] = {
+		GATE(K210_SYSCTL_EN_PERI, 23),
+		DIV(K210_SYSCTL_THR2, 16, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 15)
+	},
+};
+
+/*
+ * PLL control register bits.
+ */
+#define K210_PLL_CLKR		GENMASK(3, 0)
+#define K210_PLL_CLKF		GENMASK(9, 4)
+#define K210_PLL_CLKOD		GENMASK(13, 10)
+#define K210_PLL_BWADJ		GENMASK(19, 14)
+#define K210_PLL_RESET		(1 << 20)
+#define K210_PLL_PWRD		(1 << 21)
+#define K210_PLL_INTFB		(1 << 22)
+#define K210_PLL_BYPASS		(1 << 23)
+#define K210_PLL_TEST		(1 << 24)
+#define K210_PLL_EN		(1 << 25)
+#define K210_PLL_SEL		GENMASK(27, 26) /* PLL2 only */
+
+/*
+ * PLL lock register bits.
+ */
+#define K210_PLL_LOCK		0
+#define K210_PLL_CLEAR_SLIP	2
+#define K210_PLL_TEST_OUT	3
+
+/*
+ * Clock selector register bits.
+ */
+#define K210_ACLK_SEL		BIT(0)
+#define K210_ACLK_DIV		GENMASK(2, 1)
+
+/*
+ * PLLs.
+ */
+enum k210_pll_id {
+	K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM
+};
+
+struct k210_pll {
+enum k210_pll_id id;
+	/* PLL setup register */
+	void __iomem *reg;
+
+	/* Common lock register */
+	void __iomem *lock;
+
+	/* Offset and width of lock bits */
+	u8 lock_shift;
+	u8 lock_width;
+
+	struct clk_hw hw;
+};
+#define to_k210_pll(hw)	container_of(hw, struct k210_pll, hw)
+
+struct k210_pll_cfg {
+	/* PLL setup register offset */
+	u32 reg;
+
+	/* Offset and width fo the lock bits */
+	u8 lock_shift;
+	u8 lock_width;
+
+	/* PLL setup initial factors */
+	u32 r, f, od, bwadj;
+};
+
+/*
+ * PLL factors:
+ * By default, PLL0 runs at 780 MHz and PLL1 at 299 MHz.
+ * The first 2 sram banks depend on ACLK/CPU clock which is by default
+ * PLL0 rate divided by 2. Set PLL1 to 390 MHz so that the third sram
+ * bank has the same clock.
+ */
+static struct k210_pll_cfg k210_plls_cfg[] = {
+	{ K210_SYSCTL_PLL0,  0, 2, 0, 59, 1, 59 }, /* 780 MHz */
+	{ K210_SYSCTL_PLL1,  8, 1, 0, 59, 3, 59 }, /* 390 MHz */
+	{ K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */
+};
+
+/*
+ * Clocks data.
+ */
+struct k210_clk {
+	void __iomem			*regs;
+	spinlock_t			clk_lock;
+	struct k210_pll			plls[K210_PLL_NUM];
+	struct clk_hw			aclk;
+	struct clk_hw			clks[K210_NUM_CLKS];
+	struct clk_hw_onecell_data	*clk_data;
+};
+
+static struct k210_clk *kcl;
+
+/*
+ * Set ACLK parent selector: 0 for IN0, 1 for PLL0.
+ */
+static void k210_aclk_set_selector(u8 sel)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+
+	if (sel)
+		reg |= K210_ACLK_SEL;
+	else
+		reg &= K210_ACLK_SEL;
+	writel(reg, kcl->regs + K210_SYSCTL_SEL0);
+}
+
+static void k210_init_pll(struct k210_pll *pll, enum k210_pll_id id,
+			  void __iomem *base)
+{
+	pll->id = id;
+	pll->lock = base + K210_SYSCTL_PLL_LOCK;
+	pll->reg = base + k210_plls_cfg[id].reg;
+	pll->lock_shift = k210_plls_cfg[id].lock_shift;
+	pll->lock_width = k210_plls_cfg[id].lock_width;
+}
+
+static void k210_pll_wait_for_lock(struct k210_pll *pll)
+{
+	u32 reg, mask = GENMASK(pll->lock_width - 1, 0) << pll->lock_shift;
+
+	while (true) {
+		reg = readl(pll->lock);
+		if ((reg & mask) == mask)
+			break;
+
+		reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP);
+		writel(reg, pll->lock);
+	}
+}
+
+static bool k210_pll_hw_is_enabled(struct k210_pll *pll)
+{
+	u32 reg = readl(pll->reg);
+	u32 mask = K210_PLL_PWRD | K210_PLL_EN;
+
+	if (reg & K210_PLL_RESET)
+		return false;
+
+	return (reg & mask) == mask;
+}
+
+static void k210_pll_enable_hw(struct k210_pll *pll)
+{
+	struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id];
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	if (k210_pll_hw_is_enabled(pll))
+		goto unlock;
+
+	if (pll->id == K210_PLL0) {
+		/* Re-parent aclk to IN0 to keep the CPUs running */
+		k210_aclk_set_selector(0);
+	}
+
+	/* Set factors */
+	reg = readl(pll->reg);
+	reg &= ~GENMASK(19, 0);
+	reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r);
+	reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f);
+	reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od);
+	reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj);
+	reg |= K210_PLL_PWRD;
+	writel(reg, pll->reg);
+
+	/* Ensure reset is low before asserting it */
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+	reg |= K210_PLL_RESET;
+	writel(reg, pll->reg);
+	nop();
+	nop();
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+
+	k210_pll_wait_for_lock(pll);
+
+	reg &= ~K210_PLL_BYPASS;
+	reg |= K210_PLL_EN;
+	writel(reg, pll->reg);
+
+	if (pll->id == K210_PLL0) {
+		/* Re-parent aclk back to PLL0 */
+		k210_aclk_set_selector(1);
+	}
+unlock:
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static void k210_pll_disable_hw(struct k210_pll *pll)
+{
+	unsigned long flags;
+	u32 reg;
+
+	/*
+	 * Bypassing before powering off is important so child clocks don't stop
+	 * working. This is especially important for pll0, the indirect parent
+	 * of the cpu clock.
+	 */
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(pll->reg);
+	reg |= K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	reg &= ~K210_PLL_PWRD;
+	reg &= ~K210_PLL_EN;
+	writel(reg, pll->reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_pll_enable(struct clk_hw *hw)
+{
+	k210_pll_enable_hw(to_k210_pll(hw));
+
+	return 0;
+}
+
+static void k210_pll_disable(struct clk_hw *hw)
+{
+	k210_pll_disable_hw(to_k210_pll(hw));
+}
+
+static int k210_pll_is_enabled(struct clk_hw *hw)
+{
+	return k210_pll_hw_is_enabled(to_k210_pll(hw));
+}
+
+static int k210_pll_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	unsigned long flags;
+	int ret = 0;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	switch (pll->id) {
+	case K210_PLL0:
+	case K210_PLL1:
+		if (WARN_ON(index != 0))
+			ret = -EINVAL;
+		break;
+	case K210_PLL2:
+		if (WARN_ON(index > 2)) {
+			ret = -EINVAL;
+			break;
+		}
+		reg = readl(pll->reg);
+		reg &= ~K210_PLL_SEL;
+		reg |= FIELD_PREP(K210_PLL_SEL, index);
+		writel(reg, pll->reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return ret;
+}
+
+static u8 k210_pll_get_parent(struct clk_hw *hw)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg;
+
+	switch (pll->id) {
+	case K210_PLL0:
+	case K210_PLL1:
+		return 0;
+	case K210_PLL2:
+		reg = readl(pll->reg);
+		return FIELD_GET(K210_PLL_SEL, reg);
+	default:
+		return 0;
+	}
+}
+
+static unsigned long k210_pll_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg = readl(pll->reg);
+	u32 r, f, od;
+
+	if (reg & K210_PLL_BYPASS)
+		return parent_rate;
+
+	if (!(reg & K210_PLL_PWRD))
+		return 0;
+
+	r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
+	f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
+	od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
+
+	return (u64)parent_rate * f / (r * od);
+}
+
+static const struct clk_ops k210_pll_ops = {
+	.enable		= k210_pll_enable,
+	.disable	= k210_pll_disable,
+	.is_enabled	= k210_pll_is_enabled,
+	.set_parent	= k210_pll_set_parent,
+	.get_parent	= k210_pll_get_parent,
+	.recalc_rate	= k210_pll_get_rate,
+};
+
+static const char *pll_parents[] = { NULL, "pll0", "pll1" };
+
+static struct clk_hw *k210_register_pll(enum k210_pll_id id, const char *name,
+				const char **parent_names, int num_parents,
+				unsigned long flags)
+{
+	struct k210_pll *pll = &kcl->plls[id];
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = name;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.flags = flags;
+	init.ops = &k210_pll_ops;
+	pll->hw.init = &init;
+
+	ret = clk_hw_register(NULL, &pll->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &pll->hw;
+}
+
+static int k210_aclk_set_parent(struct clk_hw *hw, u8 index)
+{
+	if (WARN_ON(index > 1))
+		return -EINVAL;
+
+	k210_aclk_set_selector(index);
+
+	return 0;
+}
+
+static u8 k210_aclk_get_parent(struct clk_hw *hw)
+{
+	u32 sel = readl(kcl->regs + K210_SYSCTL_SEL0);
+
+	return (sel & K210_ACLK_SEL) ? 1 : 0;
+}
+
+static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+	unsigned int shift;
+
+	if (!(reg & 0x1))
+		return parent_rate;
+
+	shift = FIELD_GET(K210_ACLK_DIV, reg);
+
+	return parent_rate / (2UL << shift);
+}
+
+static const struct clk_ops k210_aclk_ops = {
+	.set_parent	= k210_aclk_set_parent,
+	.get_parent	= k210_aclk_get_parent,
+	.recalc_rate	= k210_aclk_get_rate,
+};
+
+static const char *aclk_parents[] = { NULL, "pll0" };
+
+static struct clk_hw *k210_register_aclk(void)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = "aclk";
+	init.parent_names = aclk_parents;
+	init.num_parents = 2;
+	init.flags = 0;
+	init.ops = &k210_aclk_ops;
+	kcl->aclk.init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->aclk);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &kcl->aclk;
+}
+
+#define to_k210_clk_id(hw)	((unsigned int)((hw) - &kcl->clks[0]))
+#define to_k210_clk_cfg(hw)	(&k210_clks[to_k210_clk_id(hw)])
+
+static u32 k210_clk_get_div_val(struct k210_clk_cfg *kclk)
+{
+	u32 reg = readl(kcl->regs + kclk->div_reg);
+
+	return (reg >> kclk->div_shift) & GENMASK(kclk->div_width - 1, 0);
+}
+
+static unsigned long k210_clk_divider(struct k210_clk_cfg *kclk,
+				      u32 div_val)
+{
+	switch (kclk->div_type) {
+	case DIV_ONE_BASED:
+		return div_val + 1;
+	case DIV_DOUBLE_ONE_BASED:
+		return (div_val + 1) * 2;
+	case DIV_POWER_OF_TWO:
+		return 2UL << div_val;
+	case DIV_NONE:
+	default:
+		return 0;
+	}
+}
+
+static int k210_clk_enable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg |= BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static void k210_clk_disable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg &= ~BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_clk_is_enabled(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+
+	if (!kclk->gate_reg)
+		return 1;
+
+	return readl(kcl->regs + kclk->gate_reg) & BIT(kclk->gate_bit);
+}
+
+static int k210_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->mux_reg) {
+		if (WARN_ON(index != 0))
+			return -EINVAL;
+		return 0;
+	}
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	if (index)
+		reg |= BIT(kclk->mux_bit);
+	else
+		reg &= ~BIT(kclk->mux_bit);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static u8 k210_clk_get_parent(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg, idx;
+
+	if (!kclk->mux_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	idx = (reg & BIT(kclk->mux_bit)) ? 1 : 0;
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return idx;
+}
+
+static unsigned long k210_clk_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long divider;
+
+	if (!kclk->div_reg)
+		return parent_rate;
+
+	divider = k210_clk_divider(kclk, k210_clk_get_div_val(kclk));
+	if (WARN_ON(!divider))
+		return 0;
+
+	return parent_rate / divider;
+}
+
+static const struct clk_ops k210_clk_ops = {
+	.enable		= k210_clk_enable,
+	.is_enabled	= k210_clk_is_enabled,
+	.disable	= k210_clk_disable,
+	.set_parent	= k210_clk_set_parent,
+	.get_parent	= k210_clk_get_parent,
+	.recalc_rate	= k210_clk_get_rate,
+};
+
+static const char *mux_parents[] = { NULL, "pll0" };
+
+static struct clk_hw *k210_register_clk(int id, const char *name,
+					const char *parent, unsigned long flags)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = name;
+	if (parent) {
+		init.parent_names = &parent;
+		init.num_parents = 1;
+	} else {
+		init.parent_names = mux_parents;
+		init.num_parents = 2;
+	}
+	init.flags = flags;
+	init.ops = &k210_clk_ops;
+	kcl->clks[id].init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->clks[id]);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &kcl->clks[id];
+}
+
+static void __init k210_clk_init(struct device_node *np)
+{
+	struct device_node *sysctl_np;
+	struct clk *in0_clk;
+	const char *in0;
+	struct clk_hw **hws;
+	int i, ret;
+
+	pr_info("%pOFP\n", np);
+
+	kcl = kzalloc(sizeof(*kcl), GFP_KERNEL);
+	if (!kcl)
+		return;
+
+	sysctl_np = of_find_compatible_node(NULL, NULL, "kendryte,k210-sysctl");
+	if (!sysctl_np)
+		goto err;
+
+	kcl->regs = of_iomap(sysctl_np, 0);
+	if (!kcl->regs)
+		goto err;
+
+	kcl->clk_data = kzalloc(struct_size(kcl->clk_data, hws, K210_NUM_CLKS),
+				GFP_KERNEL);
+	if (!kcl->clk_data)
+		goto err;
+
+	for (i = 0; i < K210_PLL_NUM; i++)
+		k210_init_pll(&kcl->plls[i], i, kcl->regs);
+	spin_lock_init(&kcl->clk_lock);
+	kcl->clk_data->num = K210_NUM_CLKS;
+	hws = kcl->clk_data->hws;
+	for (i = 1; i < K210_NUM_CLKS; i++)
+		hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	/*
+	 * in0 is the system base fixed-rate 26MHz oscillator which
+	 * should already be defined by the device tree. If it is not,
+	 * create it here.
+	 */
+	in0_clk = of_clk_get(np, 0);
+	if (IS_ERR(in0_clk)) {
+		pr_warn("%pOFP: in0 oscillator not found\n", np);
+		hws[K210_CLK_IN0] =
+			clk_hw_register_fixed_rate(NULL, "in0", NULL,
+						   0, K210_IN0_RATE);
+	} else {
+		hws[K210_CLK_IN0] = __clk_get_hw(in0_clk);
+	}
+	if (IS_ERR(hws[K210_CLK_IN0])) {
+		pr_err("%pOFP: failed to get base oscillator\n", np);
+		goto err;
+	}
+
+	in0 = clk_hw_get_name(hws[K210_CLK_IN0]);
+	aclk_parents[0] = in0;
+	pll_parents[0] = in0;
+	mux_parents[0] = in0;
+
+	pr_info("%pOFP: fixed-rate %lu MHz %s base clock\n",
+		np, clk_hw_get_rate(hws[K210_CLK_IN0]) / 1000000, in0);
+
+	/* PLLs */
+	hws[K210_CLK_PLL0] =
+		k210_register_pll(K210_PLL0, "pll0", pll_parents, 1, 0);
+	hws[K210_CLK_PLL1] =
+		k210_register_pll(K210_PLL1, "pll1", pll_parents, 1, 0);
+	hws[K210_CLK_PLL2] =
+		k210_register_pll(K210_PLL2, "pll2", pll_parents, 3, 0);
+
+	/* aclk: muxed of in0 and pll0_d, no gate */
+	hws[K210_CLK_ACLK] = k210_register_aclk();
+
+	/*
+	 * Clocks with aclk as source: the CPU clock is obviously critical.
+	 * So is the CLINT clock as the scheduler clocksource.
+	 */
+	hws[K210_CLK_CPU] =
+		k210_register_clk(K210_CLK_CPU, "cpu", "aclk", CLK_IS_CRITICAL);
+	hws[K210_CLK_CLINT] =
+		clk_hw_register_fixed_factor(NULL, "clint", "aclk",
+					     CLK_IS_CRITICAL, 1, 50);
+	hws[K210_CLK_DMA] =
+		k210_register_clk(K210_CLK_DMA, "dma", "aclk", 0);
+	hws[K210_CLK_FFT] =
+		k210_register_clk(K210_CLK_FFT, "fft", "aclk", 0);
+	hws[K210_CLK_ROM] =
+		k210_register_clk(K210_CLK_ROM, "rom", "aclk", 0);
+	hws[K210_CLK_DVP] =
+		k210_register_clk(K210_CLK_DVP, "dvp", "aclk", 0);
+	hws[K210_CLK_APB0] =
+		k210_register_clk(K210_CLK_APB0, "apb0", "aclk", 0);
+	hws[K210_CLK_APB1] =
+		k210_register_clk(K210_CLK_APB1, "apb1", "aclk", 0);
+	hws[K210_CLK_APB2] =
+		k210_register_clk(K210_CLK_APB2, "apb2", "aclk", 0);
+
+	/*
+	 * There is no sram driver taking a ref on the sram banks clocks.
+	 * So make them critical so they are not disabled due to being unused
+	 * as seen by the clock infrastructure.
+	 */
+	hws[K210_CLK_SRAM0] =
+		k210_register_clk(K210_CLK_SRAM0,
+				  "sram0", "aclk", CLK_IS_CRITICAL);
+	hws[K210_CLK_SRAM1] =
+		k210_register_clk(K210_CLK_SRAM1,
+				  "sram1", "aclk", CLK_IS_CRITICAL);
+
+	/* Clocks with PLL0 as source */
+	hws[K210_CLK_SPI0] =
+		k210_register_clk(K210_CLK_SPI0, "spi0", "pll0", 0);
+	hws[K210_CLK_SPI1] =
+		 k210_register_clk(K210_CLK_SPI1, "spi1", "pll0", 0);
+	hws[K210_CLK_SPI2] =
+		 k210_register_clk(K210_CLK_SPI2, "spi2", "pll0", 0);
+	hws[K210_CLK_I2C0] =
+		 k210_register_clk(K210_CLK_I2C0, "i2c0", "pll0", 0);
+	hws[K210_CLK_I2C1] =
+		 k210_register_clk(K210_CLK_I2C1, "i2c1", "pll0", 0);
+	hws[K210_CLK_I2C2] =
+		 k210_register_clk(K210_CLK_I2C2, "i2c2", "pll0", 0);
+
+	/*
+	 * Clocks with PLL1 as source: there is only the AI clock for the
+	 * (unused) KPU device. As this clock also drives the aisram bank
+	 * which is used as general memory, make it critical.
+	 */
+	 hws[K210_CLK_AI] =
+		 k210_register_clk(K210_CLK_AI, "ai", "pll1", CLK_IS_CRITICAL);
+
+	/* Clocks with PLL2 as source */
+	hws[K210_CLK_I2S0] =
+		 k210_register_clk(K210_CLK_I2S0, "i2s0", "pll2", 0);
+	hws[K210_CLK_I2S1] =
+		 k210_register_clk(K210_CLK_I2S1, "i2s1", "pll2", 0);
+	hws[K210_CLK_I2S2] =
+		k210_register_clk(K210_CLK_I2S2, "i2s2", "pll2", 0);
+	hws[K210_CLK_I2S0_M] =
+		k210_register_clk(K210_CLK_I2S0_M, "i2s0_m", "pll2", 0);
+	hws[K210_CLK_I2S1_M] =
+		k210_register_clk(K210_CLK_I2S1_M, "i2s1_m", "pll2", 0);
+	hws[K210_CLK_I2S2_M] =
+		k210_register_clk(K210_CLK_I2S2_M, "i2s2_m", "pll2", 0);
+
+	/* Clocks with IN0 as source */
+	hws[K210_CLK_WDT0] =
+		k210_register_clk(K210_CLK_WDT0, "wdt0", in0, 0);
+	hws[K210_CLK_WDT1] =
+		 k210_register_clk(K210_CLK_WDT1, "wdt1", in0, 0);
+	hws[K210_CLK_RTC] =
+		 k210_register_clk(K210_CLK_RTC, "rtc", in0, 0);
+
+	/* Clocks with APB0 as source */
+	hws[K210_CLK_GPIO] =
+		k210_register_clk(K210_CLK_GPIO, "gpio", "apb0", 0);
+	hws[K210_CLK_UART1] =
+		k210_register_clk(K210_CLK_UART1, "uart1", "apb0", 0);
+	hws[K210_CLK_UART2] =
+		k210_register_clk(K210_CLK_UART2, "uart2", "apb0", 0);
+	hws[K210_CLK_UART3] =
+		k210_register_clk(K210_CLK_UART3, "uart3", "apb0", 0);
+	hws[K210_CLK_FPIOA] =
+		k210_register_clk(K210_CLK_FPIOA, "fpioa", "apb0", 0);
+	hws[K210_CLK_SHA] =
+		k210_register_clk(K210_CLK_SHA, "sha", "apb0", 0);
+
+	/* Clocks with APB1 as source */
+	hws[K210_CLK_AES] =
+		 k210_register_clk(K210_CLK_AES, "aes", "apb1", 0);
+	hws[K210_CLK_OTP] =
+		 k210_register_clk(K210_CLK_OTP, "otp", "apb1", 0);
+
+	/* Muxed clocks with in0/pll0 as source */
+	hws[K210_CLK_SPI3] =
+		k210_register_clk(K210_CLK_SPI3, "spi3", NULL, 0);
+	hws[K210_CLK_TIMER0] =
+		k210_register_clk(K210_CLK_TIMER0, "timer0", NULL, 0);
+	hws[K210_CLK_TIMER1] =
+		k210_register_clk(K210_CLK_TIMER1, "timer1", NULL, 0);
+	hws[K210_CLK_TIMER2] =
+		k210_register_clk(K210_CLK_TIMER2, "timer2", NULL, 0);
+
+	for (i = 0; i < K210_NUM_CLKS; i++) {
+		if (IS_ERR(hws[i])) {
+			pr_err("%pOFP: register clock %d failed %ld\n",
+			       np, i, PTR_ERR(hws[i]));
+			goto err;
+		}
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, kcl->clk_data);
+	if (ret)
+		pr_err("%pOFP: add clock provider failed %d\n", np, ret);
+
+	return;
+err:
+	pr_err("%pOFP: clock initialization failed\n", np);
+	iounmap(kcl->regs);
+	kfree(kcl->clk_data);
+	kfree(kcl);
+	kcl = NULL;
+}
+
+CLK_OF_DECLARE_DRIVER(k210_clk, "kendryte,k210-clk", k210_clk_init);
+
+/*
+ * Enable PLL1 to be able to use the AI SRAM.
+ */
+void k210_clk_early_init(void __iomem *regs)
+{
+	struct k210_pll pll1;
+
+	/* Make sure aclk selector is set to PLL0 */
+	k210_aclk_set_selector(1);
+
+	/* Startup PLL1 to enable the aisram bank for general memory use */
+	k210_init_pll(&pll1, K210_PLL1, regs);
+	k210_pll_enable_hw(&pll1);
+}
diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
index 4608fbca20e1..336f4b119bdd 100644
--- a/drivers/soc/kendryte/k210-sysctl.c
+++ b/drivers/soc/kendryte/k210-sysctl.c
@@ -3,201 +3,41 @@
  * Copyright (c) 2019 Christoph Hellwig.
  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  */
-#include <linux/types.h>
 #include <linux/io.h>
-#include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/bitfield.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 #include <asm/soc.h>
 
-#define K210_SYSCTL_CLK0_FREQ		26000000UL
+#include <soc/kendryte/k210-sysctl.h>
 
-/* Registers base address */
-#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
-
-/* Registers */
-#define K210_SYSCTL_PLL0		0x08
-#define K210_SYSCTL_PLL1		0x0c
-/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
-#define   PLL_RESET		(1 << 20)
-#define   PLL_PWR		(1 << 21)
-#define   PLL_INTFB		(1 << 22)
-#define   PLL_BYPASS		(1 << 23)
-#define   PLL_TEST		(1 << 24)
-#define   PLL_OUT_EN		(1 << 25)
-#define   PLL_TEST_EN		(1 << 26)
-#define K210_SYSCTL_PLL_LOCK		0x18
-#define   PLL0_LOCK1		(1 << 0)
-#define   PLL0_LOCK2		(1 << 1)
-#define   PLL0_SLIP_CLEAR	(1 << 2)
-#define   PLL0_TEST_CLK_OUT	(1 << 3)
-#define   PLL1_LOCK1		(1 << 8)
-#define   PLL1_LOCK2		(1 << 9)
-#define   PLL1_SLIP_CLEAR	(1 << 10)
-#define   PLL1_TEST_CLK_OUT	(1 << 11)
-#define   PLL2_LOCK1		(1 << 16)
-#define   PLL2_LOCK2		(1 << 16)
-#define   PLL2_SLIP_CLEAR	(1 << 18)
-#define   PLL2_TEST_CLK_OUT	(1 << 19)
-#define K210_SYSCTL_CLKSEL0	0x20
-#define   CLKSEL_ACLK		(1 << 0)
-#define K210_SYSCTL_CLKEN_CENT		0x28
-#define   CLKEN_CPU		(1 << 0)
-#define   CLKEN_SRAM0		(1 << 1)
-#define   CLKEN_SRAM1		(1 << 2)
-#define   CLKEN_APB0		(1 << 3)
-#define   CLKEN_APB1		(1 << 4)
-#define   CLKEN_APB2		(1 << 5)
-#define K210_SYSCTL_CLKEN_PERI		0x2c
-#define   CLKEN_ROM		(1 << 0)
-#define   CLKEN_DMA		(1 << 1)
-#define   CLKEN_AI		(1 << 2)
-#define   CLKEN_DVP		(1 << 3)
-#define   CLKEN_FFT		(1 << 4)
-#define   CLKEN_GPIO		(1 << 5)
-#define   CLKEN_SPI0		(1 << 6)
-#define   CLKEN_SPI1		(1 << 7)
-#define   CLKEN_SPI2		(1 << 8)
-#define   CLKEN_SPI3		(1 << 9)
-#define   CLKEN_I2S0		(1 << 10)
-#define   CLKEN_I2S1		(1 << 11)
-#define   CLKEN_I2S2		(1 << 12)
-#define   CLKEN_I2C0		(1 << 13)
-#define   CLKEN_I2C1		(1 << 14)
-#define   CLKEN_I2C2		(1 << 15)
-#define   CLKEN_UART1		(1 << 16)
-#define   CLKEN_UART2		(1 << 17)
-#define   CLKEN_UART3		(1 << 18)
-#define   CLKEN_AES		(1 << 19)
-#define   CLKEN_FPIO		(1 << 20)
-#define   CLKEN_TIMER0		(1 << 21)
-#define   CLKEN_TIMER1		(1 << 22)
-#define   CLKEN_TIMER2		(1 << 23)
-#define   CLKEN_WDT0		(1 << 24)
-#define   CLKEN_WDT1		(1 << 25)
-#define   CLKEN_SHA		(1 << 26)
-#define   CLKEN_OTP		(1 << 27)
-#define   CLKEN_RTC		(1 << 29)
-
-struct k210_sysctl {
-	void __iomem		*regs;
-	struct clk_hw		hw;
-};
-
-static void k210_set_bits(u32 val, void __iomem *reg)
-{
-	writel(readl(reg) | val, reg);
-}
-
-static void k210_clear_bits(u32 val, void __iomem *reg)
-{
-	writel(readl(reg) & ~val, reg);
-}
-
-static void k210_pll1_enable(void __iomem *regs)
+static int __init k210_sysctl_probe(struct platform_device *pdev)
 {
-	u32 val;
+	struct device *dev = &pdev->dev;
+	struct clk *pclk;
+	int ret;
 
-	val = readl(regs + K210_SYSCTL_PLL1);
-	val &= ~GENMASK(19, 0);				/* clkr1 = 0 */
-	val |= FIELD_PREP(GENMASK(9, 4), 0x3B);		/* clkf1 = 59 */
-	val |= FIELD_PREP(GENMASK(13, 10), 0x3);	/* clkod1 = 3 */
-	val |= FIELD_PREP(GENMASK(19, 14), 0x3B);	/* bwadj1 = 59 */
-	writel(val, regs + K210_SYSCTL_PLL1);
+	dev_info(dev, "K210 system controller\n");
 
-	k210_clear_bits(PLL_BYPASS, regs + K210_SYSCTL_PLL1);
-	k210_set_bits(PLL_PWR, regs + K210_SYSCTL_PLL1);
-
-	/*
-	 * Reset the pll. The magic NOPs come from the Kendryte reference SDK.
-	 */
-	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-	k210_set_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-	nop();
-	nop();
-	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-
-	for (;;) {
-		val = readl(regs + K210_SYSCTL_PLL_LOCK);
-		if (val & PLL1_LOCK2)
-			break;
-		writel(val | PLL1_SLIP_CLEAR, regs + K210_SYSCTL_PLL_LOCK);
+	/* Get power bus clock */
+	pclk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pclk)) {
+		dev_err(dev, "Get bus clock failed\n");
+		return PTR_ERR(pclk);
 	}
 
-	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL1);
-}
-
-static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct k210_sysctl *s = container_of(hw, struct k210_sysctl, hw);
-	u32 clksel0, pll0;
-	u64 pll0_freq, clkr0, clkf0, clkod0;
-
-	/*
-	 * If the clock selector is not set, use the base frequency.
-	 * Otherwise, use PLL0 frequency with a frequency divisor.
-	 */
-	clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0);
-	if (!(clksel0 & CLKSEL_ACLK))
-		return K210_SYSCTL_CLK0_FREQ;
-
-	/*
-	 * Get PLL0 frequency:
-	 * freq = base frequency * clkf0 / (clkr0 * clkod0)
-	 */
-	pll0 = readl(s->regs + K210_SYSCTL_PLL0);
-	clkr0 = 1 + FIELD_GET(GENMASK(3, 0), pll0);
-	clkf0 = 1 + FIELD_GET(GENMASK(9, 4), pll0);
-	clkod0 = 1 + FIELD_GET(GENMASK(13, 10), pll0);
-	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
-
-	/* Get the frequency divisor from the clock selector */
-	return pll0_freq / (2ULL << FIELD_GET(0x00000006, clksel0));
-}
-
-static const struct clk_ops k210_sysctl_clk_ops = {
-	.recalc_rate	= k210_sysctl_clk_recalc_rate,
-};
-
-static const struct clk_init_data k210_clk_init_data = {
-	.name		= "k210-sysctl-pll1",
-	.ops		= &k210_sysctl_clk_ops,
-};
-
-static int k210_sysctl_probe(struct platform_device *pdev)
-{
-	struct k210_sysctl *s;
-	int error;
-
-	pr_info("Kendryte K210 SoC sysctl\n");
-
-	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
-	if (!s)
-		return -ENOMEM;
-
-	s->regs = devm_ioremap_resource(&pdev->dev,
-			platform_get_resource(pdev, IORESOURCE_MEM, 0));
-	if (IS_ERR(s->regs))
-		return PTR_ERR(s->regs);
-
-	s->hw.init = &k210_clk_init_data;
-	error = devm_clk_hw_register(&pdev->dev, &s->hw);
-	if (error) {
-		dev_err(&pdev->dev, "failed to register clk");
-		return error;
+	ret = clk_prepare_enable(pclk);
+	if (ret) {
+		dev_err(dev, "Enable bus clock failed\n");
+		return ret;
 	}
 
-	error = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
-					    &s->hw);
-	if (error) {
-		dev_err(&pdev->dev, "adding clk provider failed\n");
-		return error;
-	}
+	/* Populate children */
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		dev_err(dev, "Populate platform failed %d\n", ret);
 
-	return 0;
+	return ret;
 }
 
 static const struct of_device_id k210_sysctl_of_match[] = {
@@ -213,11 +53,22 @@ static struct platform_driver k210_sysctl_driver = {
 	.probe			= k210_sysctl_probe,
 };
 
+/*
+ * Most devices on the K210 SoC depend on the early initialization of sysctl
+ * fpioa and reset child nodes. So initialize this driver early as part of
+ * the post core initialization.
+ */
 static int __init k210_sysctl_init(void)
 {
 	return platform_driver_register(&k210_sysctl_driver);
 }
-core_initcall(k210_sysctl_init);
+postcore_initcall(k210_sysctl_init);
+
+/*
+ * System controller registers base address and size.
+ */
+#define K210_SYSCTL_BASE_ADDR	0x50440000ULL
+#define K210_SYSCTL_BASE_SIZE	0x1000
 
 /*
  * This needs to be called very early during initialization, given that
@@ -225,24 +76,14 @@ core_initcall(k210_sysctl_init);
  */
 static void __init k210_soc_early_init(const void *fdt)
 {
-	void __iomem *regs;
-
-	regs = ioremap(K210_SYSCTL_SYSCTL_BASE_ADDR, 0x1000);
-	if (!regs)
-		panic("K210 sysctl ioremap");
-
-	/* Enable PLL1 to make the KPU SRAM useable */
-	k210_pll1_enable(regs);
-
-	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0);
+	void __iomem *sysctl_base;
 
-	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
-		      regs + K210_SYSCTL_CLKEN_CENT);
-	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
-		      regs + K210_SYSCTL_CLKEN_PERI);
+	sysctl_base = ioremap(K210_SYSCTL_BASE_ADDR, K210_SYSCTL_BASE_SIZE);
+	if (!sysctl_base)
+		panic("k210-sysctl: ioremap failed");
 
-	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0);
+	k210_clk_early_init(sysctl_base);
 
-	iounmap(regs);
+	iounmap(sysctl_base);
 }
-SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
+SOC_EARLY_INIT_DECLARE(k210_soc, "kendryte,k210", k210_soc_early_init);
diff --git a/include/soc/kendryte/k210-sysctl.h b/include/soc/kendryte/k210-sysctl.h
new file mode 100644
index 000000000000..73e38a8fc31d
--- /dev/null
+++ b/include/soc/kendryte/k210-sysctl.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef K210_SYSCTL_H
+#define K210_SYSCTL_H
+
+void k210_clk_early_init(void __iomem *regs);
+
+#endif
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a clock provider driver for the Kendryte K210 RISC-V SoC. This new
driver with compatible string "kendryte,k210-clk", implements the full
clock structure of the K210 SoC. Since it is required for the correct
operation of the SoC, this driver is automatically selected for
compilation when the SOC_KENDRYTE option is selected.

With this change, the k210-sysctl driver is turned into a simple
platform driver which enables its power bus clock and triggers
populating its child nodes. The sysctl soc driver retains the SOC early
initialization code, but the implementation now relies on the new
function k210_clk_early_init() provided by the new clk-k210 driver.
This function declaration is done using the new header file
include/soc/kendryte/k210-sysctl.h.

The clock structure implemented and many of the coding ideas for the
driver come from the work by Sean Anderson on the Kendryte K210 support
for the U-Boot project.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs            |   1 +
 drivers/clk/Kconfig                |   9 +
 drivers/clk/Makefile               |   1 +
 drivers/clk/clk-k210.c             | 962 +++++++++++++++++++++++++++++
 drivers/soc/kendryte/k210-sysctl.c | 241 ++------
 include/soc/kendryte/k210-sysctl.h |  11 +
 6 files changed, 1025 insertions(+), 200 deletions(-)
 create mode 100644 drivers/clk/clk-k210.c
 create mode 100644 include/soc/kendryte/k210-sysctl.h

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 97ef393d0ed0..a4c851ffc6b0 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -30,6 +30,7 @@ config SOC_KENDRYTE
 	select SERIAL_SIFIVE_CONSOLE if TTY
 	select SIFIVE_PLIC
 	select SOC_K210
+	select CLK_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index c715d4681a0b..07a30a7b90b1 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -359,6 +359,15 @@ config COMMON_CLK_FIXED_MMIO
 	help
 	  Support for Memory Mapped IO Fixed clocks
 
+config CLK_K210
+	bool "Clock driver for the Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on COMMON_CLK && OF
+	help
+	  Support for the Kendryte K210 RISC-V SoC clocks. This option
+	  is automatically selected when the SOC_KENDRYTE option is selected
+	  in the "SOC selection" menu.
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/analogbits/Kconfig"
 source "drivers/clk/baikal-t1/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index da8fcf147eb1..ccac89e0fdfe 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
 obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
 obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
+obj-$(CONFIG_CLK_K210)			+= clk-k210.o
 
 # please keep this section sorted lexicographically by directory path name
 obj-y					+= actions/
diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
new file mode 100644
index 000000000000..7be5a8cdfef6
--- /dev/null
+++ b/drivers/clk/clk-k210.c
@@ -0,0 +1,962 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
+ */
+#define pr_fmt(fmt)     "k210-clk: " fmt
+
+#include <soc/kendryte/k210-sysctl.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <asm/soc.h>
+
+#include <dt-bindings/clock/k210-clk.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+
+/*
+ * in0: fixed-rate 26MHz oscillator base clock.
+ */
+#define K210_IN0_RATE		26000000UL
+
+/*
+ * Clocks parameters.
+ */
+struct k210_clk_cfg {
+	u8 gate_reg;
+	u8 gate_bit;
+	u8 div_reg;
+	u8 div_shift;
+	u8 div_width;
+	u8 div_type;
+	u8 mux_reg;
+	u8 mux_bit;
+};
+
+enum k210_clk_div_type {
+	DIV_NONE,
+	DIV_ONE_BASED,
+	DIV_DOUBLE_ONE_BASED,
+	DIV_POWER_OF_TWO,
+};
+
+#define GATE(_reg, _bit)	\
+	.gate_reg = (_reg),	\
+	.gate_bit = (_bit)
+#define DIV(_reg, _shift, _width, _type)	\
+	.div_reg = (_reg),			\
+	.div_shift = (_shift),			\
+	.div_width = (_width),			\
+	.div_type = (_type)
+#define MUX(_reg, _bit)		\
+	.mux_reg = (_reg),	\
+	.mux_bit = (_bit)
+
+static struct k210_clk_cfg k210_clks[K210_NUM_CLKS] = {
+
+	/* Gated clocks, no mux, no divider */
+	[K210_CLK_CPU] = { GATE(K210_SYSCTL_EN_CENT, 0) },
+	[K210_CLK_DMA] = { GATE(K210_SYSCTL_EN_PERI, 1) },
+	[K210_CLK_FFT] = { GATE(K210_SYSCTL_EN_PERI, 4) },
+	[K210_CLK_GPIO] = { GATE(K210_SYSCTL_EN_PERI, 5) },
+	[K210_CLK_UART1] = { GATE(K210_SYSCTL_EN_PERI, 16) },
+	[K210_CLK_UART2] = { GATE(K210_SYSCTL_EN_PERI, 17) },
+	[K210_CLK_UART3] = { GATE(K210_SYSCTL_EN_PERI, 18) },
+	[K210_CLK_FPIOA] = { GATE(K210_SYSCTL_EN_PERI, 20) },
+	[K210_CLK_SHA] = { GATE(K210_SYSCTL_EN_PERI, 26) },
+	[K210_CLK_AES] = { GATE(K210_SYSCTL_EN_PERI, 19) },
+	[K210_CLK_OTP] = { GATE(K210_SYSCTL_EN_PERI, 27) },
+	[K210_CLK_RTC] = { GATE(K210_SYSCTL_EN_PERI, 29) },
+
+	/* Gated divider clocks */
+	[K210_CLK_SRAM0] = {
+		GATE(K210_SYSCTL_EN_CENT, 1),
+		DIV(K210_SYSCTL_THR0, 0, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_SRAM1] = {
+		GATE(K210_SYSCTL_EN_CENT, 2),
+		DIV(K210_SYSCTL_THR0, 4, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_ROM] = {
+		GATE(K210_SYSCTL_EN_PERI, 0),
+		DIV(K210_SYSCTL_THR0, 16, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_DVP] = {
+		GATE(K210_SYSCTL_EN_PERI, 3),
+		DIV(K210_SYSCTL_THR0, 12, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB0] = {
+		GATE(K210_SYSCTL_EN_CENT, 3),
+		DIV(K210_SYSCTL_SEL0, 3, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB1] = {
+		GATE(K210_SYSCTL_EN_CENT, 4),
+		DIV(K210_SYSCTL_SEL0, 6, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_APB2] = {
+		GATE(K210_SYSCTL_EN_CENT, 5),
+		DIV(K210_SYSCTL_SEL0, 9, 3, DIV_ONE_BASED)
+	},
+	[K210_CLK_AI] = {
+		GATE(K210_SYSCTL_EN_PERI, 2),
+		DIV(K210_SYSCTL_THR0, 8, 4, DIV_ONE_BASED)
+	},
+	[K210_CLK_SPI0] = {
+		GATE(K210_SYSCTL_EN_PERI, 6),
+		DIV(K210_SYSCTL_THR1, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI1] = {
+		GATE(K210_SYSCTL_EN_PERI, 7),
+		DIV(K210_SYSCTL_THR1, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_SPI2] = {
+		GATE(K210_SYSCTL_EN_PERI, 8),
+		DIV(K210_SYSCTL_THR1, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C0] = {
+		GATE(K210_SYSCTL_EN_PERI, 13),
+		DIV(K210_SYSCTL_THR5, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C1] = {
+		GATE(K210_SYSCTL_EN_PERI, 14),
+		DIV(K210_SYSCTL_THR5, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2C2] = {
+		GATE(K210_SYSCTL_EN_PERI, 15),
+		DIV(K210_SYSCTL_THR5, 24, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT0] = {
+		GATE(K210_SYSCTL_EN_PERI, 24),
+		DIV(K210_SYSCTL_THR6, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_WDT1] = {
+		GATE(K210_SYSCTL_EN_PERI, 25),
+		DIV(K210_SYSCTL_THR6, 8, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S0] = {
+		GATE(K210_SYSCTL_EN_PERI, 10),
+		DIV(K210_SYSCTL_THR3, 0, 16, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1] = {
+		GATE(K210_SYSCTL_EN_PERI, 11),
+		DIV(K210_SYSCTL_THR3, 16, 16, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2] = {
+		GATE(K210_SYSCTL_EN_PERI, 12),
+		DIV(K210_SYSCTL_THR4, 0, 16, DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Divider clocks, no gate, no mux */
+	[K210_CLK_I2S0_M] = {
+		DIV(K210_SYSCTL_THR4, 16, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S1_M] = {
+		DIV(K210_SYSCTL_THR4, 24, 8, DIV_DOUBLE_ONE_BASED)
+	},
+	[K210_CLK_I2S2_M] = {
+		DIV(K210_SYSCTL_THR4, 0, 8, DIV_DOUBLE_ONE_BASED)
+	},
+
+	/* Muxed gated divider clocks */
+	[K210_CLK_SPI3] = {
+		GATE(K210_SYSCTL_EN_PERI, 9),
+		DIV(K210_SYSCTL_THR1, 24, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 12)
+	},
+	[K210_CLK_TIMER0] = {
+		GATE(K210_SYSCTL_EN_PERI, 21),
+		DIV(K210_SYSCTL_THR2,  0, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 13)
+	},
+	[K210_CLK_TIMER1] = {
+		GATE(K210_SYSCTL_EN_PERI, 22),
+		DIV(K210_SYSCTL_THR2, 8, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 14)
+	},
+	[K210_CLK_TIMER2] = {
+		GATE(K210_SYSCTL_EN_PERI, 23),
+		DIV(K210_SYSCTL_THR2, 16, 8, DIV_DOUBLE_ONE_BASED),
+		MUX(K210_SYSCTL_SEL0, 15)
+	},
+};
+
+/*
+ * PLL control register bits.
+ */
+#define K210_PLL_CLKR		GENMASK(3, 0)
+#define K210_PLL_CLKF		GENMASK(9, 4)
+#define K210_PLL_CLKOD		GENMASK(13, 10)
+#define K210_PLL_BWADJ		GENMASK(19, 14)
+#define K210_PLL_RESET		(1 << 20)
+#define K210_PLL_PWRD		(1 << 21)
+#define K210_PLL_INTFB		(1 << 22)
+#define K210_PLL_BYPASS		(1 << 23)
+#define K210_PLL_TEST		(1 << 24)
+#define K210_PLL_EN		(1 << 25)
+#define K210_PLL_SEL		GENMASK(27, 26) /* PLL2 only */
+
+/*
+ * PLL lock register bits.
+ */
+#define K210_PLL_LOCK		0
+#define K210_PLL_CLEAR_SLIP	2
+#define K210_PLL_TEST_OUT	3
+
+/*
+ * Clock selector register bits.
+ */
+#define K210_ACLK_SEL		BIT(0)
+#define K210_ACLK_DIV		GENMASK(2, 1)
+
+/*
+ * PLLs.
+ */
+enum k210_pll_id {
+	K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM
+};
+
+struct k210_pll {
+enum k210_pll_id id;
+	/* PLL setup register */
+	void __iomem *reg;
+
+	/* Common lock register */
+	void __iomem *lock;
+
+	/* Offset and width of lock bits */
+	u8 lock_shift;
+	u8 lock_width;
+
+	struct clk_hw hw;
+};
+#define to_k210_pll(hw)	container_of(hw, struct k210_pll, hw)
+
+struct k210_pll_cfg {
+	/* PLL setup register offset */
+	u32 reg;
+
+	/* Offset and width fo the lock bits */
+	u8 lock_shift;
+	u8 lock_width;
+
+	/* PLL setup initial factors */
+	u32 r, f, od, bwadj;
+};
+
+/*
+ * PLL factors:
+ * By default, PLL0 runs at 780 MHz and PLL1 at 299 MHz.
+ * The first 2 sram banks depend on ACLK/CPU clock which is by default
+ * PLL0 rate divided by 2. Set PLL1 to 390 MHz so that the third sram
+ * bank has the same clock.
+ */
+static struct k210_pll_cfg k210_plls_cfg[] = {
+	{ K210_SYSCTL_PLL0,  0, 2, 0, 59, 1, 59 }, /* 780 MHz */
+	{ K210_SYSCTL_PLL1,  8, 1, 0, 59, 3, 59 }, /* 390 MHz */
+	{ K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */
+};
+
+/*
+ * Clocks data.
+ */
+struct k210_clk {
+	void __iomem			*regs;
+	spinlock_t			clk_lock;
+	struct k210_pll			plls[K210_PLL_NUM];
+	struct clk_hw			aclk;
+	struct clk_hw			clks[K210_NUM_CLKS];
+	struct clk_hw_onecell_data	*clk_data;
+};
+
+static struct k210_clk *kcl;
+
+/*
+ * Set ACLK parent selector: 0 for IN0, 1 for PLL0.
+ */
+static void k210_aclk_set_selector(u8 sel)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+
+	if (sel)
+		reg |= K210_ACLK_SEL;
+	else
+		reg &= K210_ACLK_SEL;
+	writel(reg, kcl->regs + K210_SYSCTL_SEL0);
+}
+
+static void k210_init_pll(struct k210_pll *pll, enum k210_pll_id id,
+			  void __iomem *base)
+{
+	pll->id = id;
+	pll->lock = base + K210_SYSCTL_PLL_LOCK;
+	pll->reg = base + k210_plls_cfg[id].reg;
+	pll->lock_shift = k210_plls_cfg[id].lock_shift;
+	pll->lock_width = k210_plls_cfg[id].lock_width;
+}
+
+static void k210_pll_wait_for_lock(struct k210_pll *pll)
+{
+	u32 reg, mask = GENMASK(pll->lock_width - 1, 0) << pll->lock_shift;
+
+	while (true) {
+		reg = readl(pll->lock);
+		if ((reg & mask) == mask)
+			break;
+
+		reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP);
+		writel(reg, pll->lock);
+	}
+}
+
+static bool k210_pll_hw_is_enabled(struct k210_pll *pll)
+{
+	u32 reg = readl(pll->reg);
+	u32 mask = K210_PLL_PWRD | K210_PLL_EN;
+
+	if (reg & K210_PLL_RESET)
+		return false;
+
+	return (reg & mask) == mask;
+}
+
+static void k210_pll_enable_hw(struct k210_pll *pll)
+{
+	struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id];
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	if (k210_pll_hw_is_enabled(pll))
+		goto unlock;
+
+	if (pll->id == K210_PLL0) {
+		/* Re-parent aclk to IN0 to keep the CPUs running */
+		k210_aclk_set_selector(0);
+	}
+
+	/* Set factors */
+	reg = readl(pll->reg);
+	reg &= ~GENMASK(19, 0);
+	reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r);
+	reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f);
+	reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od);
+	reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj);
+	reg |= K210_PLL_PWRD;
+	writel(reg, pll->reg);
+
+	/* Ensure reset is low before asserting it */
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+	reg |= K210_PLL_RESET;
+	writel(reg, pll->reg);
+	nop();
+	nop();
+	reg &= ~K210_PLL_RESET;
+	writel(reg, pll->reg);
+
+	k210_pll_wait_for_lock(pll);
+
+	reg &= ~K210_PLL_BYPASS;
+	reg |= K210_PLL_EN;
+	writel(reg, pll->reg);
+
+	if (pll->id == K210_PLL0) {
+		/* Re-parent aclk back to PLL0 */
+		k210_aclk_set_selector(1);
+	}
+unlock:
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static void k210_pll_disable_hw(struct k210_pll *pll)
+{
+	unsigned long flags;
+	u32 reg;
+
+	/*
+	 * Bypassing before powering off is important so child clocks don't stop
+	 * working. This is especially important for pll0, the indirect parent
+	 * of the cpu clock.
+	 */
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(pll->reg);
+	reg |= K210_PLL_BYPASS;
+	writel(reg, pll->reg);
+
+	reg &= ~K210_PLL_PWRD;
+	reg &= ~K210_PLL_EN;
+	writel(reg, pll->reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_pll_enable(struct clk_hw *hw)
+{
+	k210_pll_enable_hw(to_k210_pll(hw));
+
+	return 0;
+}
+
+static void k210_pll_disable(struct clk_hw *hw)
+{
+	k210_pll_disable_hw(to_k210_pll(hw));
+}
+
+static int k210_pll_is_enabled(struct clk_hw *hw)
+{
+	return k210_pll_hw_is_enabled(to_k210_pll(hw));
+}
+
+static int k210_pll_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	unsigned long flags;
+	int ret = 0;
+	u32 reg;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+
+	switch (pll->id) {
+	case K210_PLL0:
+	case K210_PLL1:
+		if (WARN_ON(index != 0))
+			ret = -EINVAL;
+		break;
+	case K210_PLL2:
+		if (WARN_ON(index > 2)) {
+			ret = -EINVAL;
+			break;
+		}
+		reg = readl(pll->reg);
+		reg &= ~K210_PLL_SEL;
+		reg |= FIELD_PREP(K210_PLL_SEL, index);
+		writel(reg, pll->reg);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return ret;
+}
+
+static u8 k210_pll_get_parent(struct clk_hw *hw)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg;
+
+	switch (pll->id) {
+	case K210_PLL0:
+	case K210_PLL1:
+		return 0;
+	case K210_PLL2:
+		reg = readl(pll->reg);
+		return FIELD_GET(K210_PLL_SEL, reg);
+	default:
+		return 0;
+	}
+}
+
+static unsigned long k210_pll_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_pll *pll = to_k210_pll(hw);
+	u32 reg = readl(pll->reg);
+	u32 r, f, od;
+
+	if (reg & K210_PLL_BYPASS)
+		return parent_rate;
+
+	if (!(reg & K210_PLL_PWRD))
+		return 0;
+
+	r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
+	f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
+	od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
+
+	return (u64)parent_rate * f / (r * od);
+}
+
+static const struct clk_ops k210_pll_ops = {
+	.enable		= k210_pll_enable,
+	.disable	= k210_pll_disable,
+	.is_enabled	= k210_pll_is_enabled,
+	.set_parent	= k210_pll_set_parent,
+	.get_parent	= k210_pll_get_parent,
+	.recalc_rate	= k210_pll_get_rate,
+};
+
+static const char *pll_parents[] = { NULL, "pll0", "pll1" };
+
+static struct clk_hw *k210_register_pll(enum k210_pll_id id, const char *name,
+				const char **parent_names, int num_parents,
+				unsigned long flags)
+{
+	struct k210_pll *pll = &kcl->plls[id];
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = name;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+	init.flags = flags;
+	init.ops = &k210_pll_ops;
+	pll->hw.init = &init;
+
+	ret = clk_hw_register(NULL, &pll->hw);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &pll->hw;
+}
+
+static int k210_aclk_set_parent(struct clk_hw *hw, u8 index)
+{
+	if (WARN_ON(index > 1))
+		return -EINVAL;
+
+	k210_aclk_set_selector(index);
+
+	return 0;
+}
+
+static u8 k210_aclk_get_parent(struct clk_hw *hw)
+{
+	u32 sel = readl(kcl->regs + K210_SYSCTL_SEL0);
+
+	return (sel & K210_ACLK_SEL) ? 1 : 0;
+}
+
+static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
+					unsigned long parent_rate)
+{
+	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
+	unsigned int shift;
+
+	if (!(reg & 0x1))
+		return parent_rate;
+
+	shift = FIELD_GET(K210_ACLK_DIV, reg);
+
+	return parent_rate / (2UL << shift);
+}
+
+static const struct clk_ops k210_aclk_ops = {
+	.set_parent	= k210_aclk_set_parent,
+	.get_parent	= k210_aclk_get_parent,
+	.recalc_rate	= k210_aclk_get_rate,
+};
+
+static const char *aclk_parents[] = { NULL, "pll0" };
+
+static struct clk_hw *k210_register_aclk(void)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = "aclk";
+	init.parent_names = aclk_parents;
+	init.num_parents = 2;
+	init.flags = 0;
+	init.ops = &k210_aclk_ops;
+	kcl->aclk.init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->aclk);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &kcl->aclk;
+}
+
+#define to_k210_clk_id(hw)	((unsigned int)((hw) - &kcl->clks[0]))
+#define to_k210_clk_cfg(hw)	(&k210_clks[to_k210_clk_id(hw)])
+
+static u32 k210_clk_get_div_val(struct k210_clk_cfg *kclk)
+{
+	u32 reg = readl(kcl->regs + kclk->div_reg);
+
+	return (reg >> kclk->div_shift) & GENMASK(kclk->div_width - 1, 0);
+}
+
+static unsigned long k210_clk_divider(struct k210_clk_cfg *kclk,
+				      u32 div_val)
+{
+	switch (kclk->div_type) {
+	case DIV_ONE_BASED:
+		return div_val + 1;
+	case DIV_DOUBLE_ONE_BASED:
+		return (div_val + 1) * 2;
+	case DIV_POWER_OF_TWO:
+		return 2UL << div_val;
+	case DIV_NONE:
+	default:
+		return 0;
+	}
+}
+
+static int k210_clk_enable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg |= BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static void k210_clk_disable(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->gate_reg)
+		return;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->gate_reg);
+	reg &= ~BIT(kclk->gate_bit);
+	writel(reg, kcl->regs + kclk->gate_reg);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+}
+
+static int k210_clk_is_enabled(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+
+	if (!kclk->gate_reg)
+		return 1;
+
+	return readl(kcl->regs + kclk->gate_reg) & BIT(kclk->gate_bit);
+}
+
+static int k210_clk_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg;
+
+	if (!kclk->mux_reg) {
+		if (WARN_ON(index != 0))
+			return -EINVAL;
+		return 0;
+	}
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	if (index)
+		reg |= BIT(kclk->mux_bit);
+	else
+		reg &= ~BIT(kclk->mux_bit);
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return 0;
+}
+
+static u8 k210_clk_get_parent(struct clk_hw *hw)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long flags;
+	u32 reg, idx;
+
+	if (!kclk->mux_reg)
+		return 0;
+
+	spin_lock_irqsave(&kcl->clk_lock, flags);
+	reg = readl(kcl->regs + kclk->mux_reg);
+	idx = (reg & BIT(kclk->mux_bit)) ? 1 : 0;
+	spin_unlock_irqrestore(&kcl->clk_lock, flags);
+
+	return idx;
+}
+
+static unsigned long k210_clk_get_rate(struct clk_hw *hw,
+				       unsigned long parent_rate)
+{
+	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
+	unsigned long divider;
+
+	if (!kclk->div_reg)
+		return parent_rate;
+
+	divider = k210_clk_divider(kclk, k210_clk_get_div_val(kclk));
+	if (WARN_ON(!divider))
+		return 0;
+
+	return parent_rate / divider;
+}
+
+static const struct clk_ops k210_clk_ops = {
+	.enable		= k210_clk_enable,
+	.is_enabled	= k210_clk_is_enabled,
+	.disable	= k210_clk_disable,
+	.set_parent	= k210_clk_set_parent,
+	.get_parent	= k210_clk_get_parent,
+	.recalc_rate	= k210_clk_get_rate,
+};
+
+static const char *mux_parents[] = { NULL, "pll0" };
+
+static struct clk_hw *k210_register_clk(int id, const char *name,
+					const char *parent, unsigned long flags)
+{
+	struct clk_init_data init = {};
+	int ret;
+
+	init.name = name;
+	if (parent) {
+		init.parent_names = &parent;
+		init.num_parents = 1;
+	} else {
+		init.parent_names = mux_parents;
+		init.num_parents = 2;
+	}
+	init.flags = flags;
+	init.ops = &k210_clk_ops;
+	kcl->clks[id].init = &init;
+
+	ret = clk_hw_register(NULL, &kcl->clks[id]);
+	if (ret)
+		return ERR_PTR(ret);
+
+	return &kcl->clks[id];
+}
+
+static void __init k210_clk_init(struct device_node *np)
+{
+	struct device_node *sysctl_np;
+	struct clk *in0_clk;
+	const char *in0;
+	struct clk_hw **hws;
+	int i, ret;
+
+	pr_info("%pOFP\n", np);
+
+	kcl = kzalloc(sizeof(*kcl), GFP_KERNEL);
+	if (!kcl)
+		return;
+
+	sysctl_np = of_find_compatible_node(NULL, NULL, "kendryte,k210-sysctl");
+	if (!sysctl_np)
+		goto err;
+
+	kcl->regs = of_iomap(sysctl_np, 0);
+	if (!kcl->regs)
+		goto err;
+
+	kcl->clk_data = kzalloc(struct_size(kcl->clk_data, hws, K210_NUM_CLKS),
+				GFP_KERNEL);
+	if (!kcl->clk_data)
+		goto err;
+
+	for (i = 0; i < K210_PLL_NUM; i++)
+		k210_init_pll(&kcl->plls[i], i, kcl->regs);
+	spin_lock_init(&kcl->clk_lock);
+	kcl->clk_data->num = K210_NUM_CLKS;
+	hws = kcl->clk_data->hws;
+	for (i = 1; i < K210_NUM_CLKS; i++)
+		hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+	/*
+	 * in0 is the system base fixed-rate 26MHz oscillator which
+	 * should already be defined by the device tree. If it is not,
+	 * create it here.
+	 */
+	in0_clk = of_clk_get(np, 0);
+	if (IS_ERR(in0_clk)) {
+		pr_warn("%pOFP: in0 oscillator not found\n", np);
+		hws[K210_CLK_IN0] =
+			clk_hw_register_fixed_rate(NULL, "in0", NULL,
+						   0, K210_IN0_RATE);
+	} else {
+		hws[K210_CLK_IN0] = __clk_get_hw(in0_clk);
+	}
+	if (IS_ERR(hws[K210_CLK_IN0])) {
+		pr_err("%pOFP: failed to get base oscillator\n", np);
+		goto err;
+	}
+
+	in0 = clk_hw_get_name(hws[K210_CLK_IN0]);
+	aclk_parents[0] = in0;
+	pll_parents[0] = in0;
+	mux_parents[0] = in0;
+
+	pr_info("%pOFP: fixed-rate %lu MHz %s base clock\n",
+		np, clk_hw_get_rate(hws[K210_CLK_IN0]) / 1000000, in0);
+
+	/* PLLs */
+	hws[K210_CLK_PLL0] =
+		k210_register_pll(K210_PLL0, "pll0", pll_parents, 1, 0);
+	hws[K210_CLK_PLL1] =
+		k210_register_pll(K210_PLL1, "pll1", pll_parents, 1, 0);
+	hws[K210_CLK_PLL2] =
+		k210_register_pll(K210_PLL2, "pll2", pll_parents, 3, 0);
+
+	/* aclk: muxed of in0 and pll0_d, no gate */
+	hws[K210_CLK_ACLK] = k210_register_aclk();
+
+	/*
+	 * Clocks with aclk as source: the CPU clock is obviously critical.
+	 * So is the CLINT clock as the scheduler clocksource.
+	 */
+	hws[K210_CLK_CPU] =
+		k210_register_clk(K210_CLK_CPU, "cpu", "aclk", CLK_IS_CRITICAL);
+	hws[K210_CLK_CLINT] =
+		clk_hw_register_fixed_factor(NULL, "clint", "aclk",
+					     CLK_IS_CRITICAL, 1, 50);
+	hws[K210_CLK_DMA] =
+		k210_register_clk(K210_CLK_DMA, "dma", "aclk", 0);
+	hws[K210_CLK_FFT] =
+		k210_register_clk(K210_CLK_FFT, "fft", "aclk", 0);
+	hws[K210_CLK_ROM] =
+		k210_register_clk(K210_CLK_ROM, "rom", "aclk", 0);
+	hws[K210_CLK_DVP] =
+		k210_register_clk(K210_CLK_DVP, "dvp", "aclk", 0);
+	hws[K210_CLK_APB0] =
+		k210_register_clk(K210_CLK_APB0, "apb0", "aclk", 0);
+	hws[K210_CLK_APB1] =
+		k210_register_clk(K210_CLK_APB1, "apb1", "aclk", 0);
+	hws[K210_CLK_APB2] =
+		k210_register_clk(K210_CLK_APB2, "apb2", "aclk", 0);
+
+	/*
+	 * There is no sram driver taking a ref on the sram banks clocks.
+	 * So make them critical so they are not disabled due to being unused
+	 * as seen by the clock infrastructure.
+	 */
+	hws[K210_CLK_SRAM0] =
+		k210_register_clk(K210_CLK_SRAM0,
+				  "sram0", "aclk", CLK_IS_CRITICAL);
+	hws[K210_CLK_SRAM1] =
+		k210_register_clk(K210_CLK_SRAM1,
+				  "sram1", "aclk", CLK_IS_CRITICAL);
+
+	/* Clocks with PLL0 as source */
+	hws[K210_CLK_SPI0] =
+		k210_register_clk(K210_CLK_SPI0, "spi0", "pll0", 0);
+	hws[K210_CLK_SPI1] =
+		 k210_register_clk(K210_CLK_SPI1, "spi1", "pll0", 0);
+	hws[K210_CLK_SPI2] =
+		 k210_register_clk(K210_CLK_SPI2, "spi2", "pll0", 0);
+	hws[K210_CLK_I2C0] =
+		 k210_register_clk(K210_CLK_I2C0, "i2c0", "pll0", 0);
+	hws[K210_CLK_I2C1] =
+		 k210_register_clk(K210_CLK_I2C1, "i2c1", "pll0", 0);
+	hws[K210_CLK_I2C2] =
+		 k210_register_clk(K210_CLK_I2C2, "i2c2", "pll0", 0);
+
+	/*
+	 * Clocks with PLL1 as source: there is only the AI clock for the
+	 * (unused) KPU device. As this clock also drives the aisram bank
+	 * which is used as general memory, make it critical.
+	 */
+	 hws[K210_CLK_AI] =
+		 k210_register_clk(K210_CLK_AI, "ai", "pll1", CLK_IS_CRITICAL);
+
+	/* Clocks with PLL2 as source */
+	hws[K210_CLK_I2S0] =
+		 k210_register_clk(K210_CLK_I2S0, "i2s0", "pll2", 0);
+	hws[K210_CLK_I2S1] =
+		 k210_register_clk(K210_CLK_I2S1, "i2s1", "pll2", 0);
+	hws[K210_CLK_I2S2] =
+		k210_register_clk(K210_CLK_I2S2, "i2s2", "pll2", 0);
+	hws[K210_CLK_I2S0_M] =
+		k210_register_clk(K210_CLK_I2S0_M, "i2s0_m", "pll2", 0);
+	hws[K210_CLK_I2S1_M] =
+		k210_register_clk(K210_CLK_I2S1_M, "i2s1_m", "pll2", 0);
+	hws[K210_CLK_I2S2_M] =
+		k210_register_clk(K210_CLK_I2S2_M, "i2s2_m", "pll2", 0);
+
+	/* Clocks with IN0 as source */
+	hws[K210_CLK_WDT0] =
+		k210_register_clk(K210_CLK_WDT0, "wdt0", in0, 0);
+	hws[K210_CLK_WDT1] =
+		 k210_register_clk(K210_CLK_WDT1, "wdt1", in0, 0);
+	hws[K210_CLK_RTC] =
+		 k210_register_clk(K210_CLK_RTC, "rtc", in0, 0);
+
+	/* Clocks with APB0 as source */
+	hws[K210_CLK_GPIO] =
+		k210_register_clk(K210_CLK_GPIO, "gpio", "apb0", 0);
+	hws[K210_CLK_UART1] =
+		k210_register_clk(K210_CLK_UART1, "uart1", "apb0", 0);
+	hws[K210_CLK_UART2] =
+		k210_register_clk(K210_CLK_UART2, "uart2", "apb0", 0);
+	hws[K210_CLK_UART3] =
+		k210_register_clk(K210_CLK_UART3, "uart3", "apb0", 0);
+	hws[K210_CLK_FPIOA] =
+		k210_register_clk(K210_CLK_FPIOA, "fpioa", "apb0", 0);
+	hws[K210_CLK_SHA] =
+		k210_register_clk(K210_CLK_SHA, "sha", "apb0", 0);
+
+	/* Clocks with APB1 as source */
+	hws[K210_CLK_AES] =
+		 k210_register_clk(K210_CLK_AES, "aes", "apb1", 0);
+	hws[K210_CLK_OTP] =
+		 k210_register_clk(K210_CLK_OTP, "otp", "apb1", 0);
+
+	/* Muxed clocks with in0/pll0 as source */
+	hws[K210_CLK_SPI3] =
+		k210_register_clk(K210_CLK_SPI3, "spi3", NULL, 0);
+	hws[K210_CLK_TIMER0] =
+		k210_register_clk(K210_CLK_TIMER0, "timer0", NULL, 0);
+	hws[K210_CLK_TIMER1] =
+		k210_register_clk(K210_CLK_TIMER1, "timer1", NULL, 0);
+	hws[K210_CLK_TIMER2] =
+		k210_register_clk(K210_CLK_TIMER2, "timer2", NULL, 0);
+
+	for (i = 0; i < K210_NUM_CLKS; i++) {
+		if (IS_ERR(hws[i])) {
+			pr_err("%pOFP: register clock %d failed %ld\n",
+			       np, i, PTR_ERR(hws[i]));
+			goto err;
+		}
+	}
+
+	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, kcl->clk_data);
+	if (ret)
+		pr_err("%pOFP: add clock provider failed %d\n", np, ret);
+
+	return;
+err:
+	pr_err("%pOFP: clock initialization failed\n", np);
+	iounmap(kcl->regs);
+	kfree(kcl->clk_data);
+	kfree(kcl);
+	kcl = NULL;
+}
+
+CLK_OF_DECLARE_DRIVER(k210_clk, "kendryte,k210-clk", k210_clk_init);
+
+/*
+ * Enable PLL1 to be able to use the AI SRAM.
+ */
+void k210_clk_early_init(void __iomem *regs)
+{
+	struct k210_pll pll1;
+
+	/* Make sure aclk selector is set to PLL0 */
+	k210_aclk_set_selector(1);
+
+	/* Startup PLL1 to enable the aisram bank for general memory use */
+	k210_init_pll(&pll1, K210_PLL1, regs);
+	k210_pll_enable_hw(&pll1);
+}
diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
index 4608fbca20e1..336f4b119bdd 100644
--- a/drivers/soc/kendryte/k210-sysctl.c
+++ b/drivers/soc/kendryte/k210-sysctl.c
@@ -3,201 +3,41 @@
  * Copyright (c) 2019 Christoph Hellwig.
  * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  */
-#include <linux/types.h>
 #include <linux/io.h>
-#include <linux/of.h>
 #include <linux/platform_device.h>
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/bitfield.h>
+#include <linux/of_platform.h>
+#include <linux/clk.h>
 #include <asm/soc.h>
 
-#define K210_SYSCTL_CLK0_FREQ		26000000UL
+#include <soc/kendryte/k210-sysctl.h>
 
-/* Registers base address */
-#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
-
-/* Registers */
-#define K210_SYSCTL_PLL0		0x08
-#define K210_SYSCTL_PLL1		0x0c
-/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
-#define   PLL_RESET		(1 << 20)
-#define   PLL_PWR		(1 << 21)
-#define   PLL_INTFB		(1 << 22)
-#define   PLL_BYPASS		(1 << 23)
-#define   PLL_TEST		(1 << 24)
-#define   PLL_OUT_EN		(1 << 25)
-#define   PLL_TEST_EN		(1 << 26)
-#define K210_SYSCTL_PLL_LOCK		0x18
-#define   PLL0_LOCK1		(1 << 0)
-#define   PLL0_LOCK2		(1 << 1)
-#define   PLL0_SLIP_CLEAR	(1 << 2)
-#define   PLL0_TEST_CLK_OUT	(1 << 3)
-#define   PLL1_LOCK1		(1 << 8)
-#define   PLL1_LOCK2		(1 << 9)
-#define   PLL1_SLIP_CLEAR	(1 << 10)
-#define   PLL1_TEST_CLK_OUT	(1 << 11)
-#define   PLL2_LOCK1		(1 << 16)
-#define   PLL2_LOCK2		(1 << 16)
-#define   PLL2_SLIP_CLEAR	(1 << 18)
-#define   PLL2_TEST_CLK_OUT	(1 << 19)
-#define K210_SYSCTL_CLKSEL0	0x20
-#define   CLKSEL_ACLK		(1 << 0)
-#define K210_SYSCTL_CLKEN_CENT		0x28
-#define   CLKEN_CPU		(1 << 0)
-#define   CLKEN_SRAM0		(1 << 1)
-#define   CLKEN_SRAM1		(1 << 2)
-#define   CLKEN_APB0		(1 << 3)
-#define   CLKEN_APB1		(1 << 4)
-#define   CLKEN_APB2		(1 << 5)
-#define K210_SYSCTL_CLKEN_PERI		0x2c
-#define   CLKEN_ROM		(1 << 0)
-#define   CLKEN_DMA		(1 << 1)
-#define   CLKEN_AI		(1 << 2)
-#define   CLKEN_DVP		(1 << 3)
-#define   CLKEN_FFT		(1 << 4)
-#define   CLKEN_GPIO		(1 << 5)
-#define   CLKEN_SPI0		(1 << 6)
-#define   CLKEN_SPI1		(1 << 7)
-#define   CLKEN_SPI2		(1 << 8)
-#define   CLKEN_SPI3		(1 << 9)
-#define   CLKEN_I2S0		(1 << 10)
-#define   CLKEN_I2S1		(1 << 11)
-#define   CLKEN_I2S2		(1 << 12)
-#define   CLKEN_I2C0		(1 << 13)
-#define   CLKEN_I2C1		(1 << 14)
-#define   CLKEN_I2C2		(1 << 15)
-#define   CLKEN_UART1		(1 << 16)
-#define   CLKEN_UART2		(1 << 17)
-#define   CLKEN_UART3		(1 << 18)
-#define   CLKEN_AES		(1 << 19)
-#define   CLKEN_FPIO		(1 << 20)
-#define   CLKEN_TIMER0		(1 << 21)
-#define   CLKEN_TIMER1		(1 << 22)
-#define   CLKEN_TIMER2		(1 << 23)
-#define   CLKEN_WDT0		(1 << 24)
-#define   CLKEN_WDT1		(1 << 25)
-#define   CLKEN_SHA		(1 << 26)
-#define   CLKEN_OTP		(1 << 27)
-#define   CLKEN_RTC		(1 << 29)
-
-struct k210_sysctl {
-	void __iomem		*regs;
-	struct clk_hw		hw;
-};
-
-static void k210_set_bits(u32 val, void __iomem *reg)
-{
-	writel(readl(reg) | val, reg);
-}
-
-static void k210_clear_bits(u32 val, void __iomem *reg)
-{
-	writel(readl(reg) & ~val, reg);
-}
-
-static void k210_pll1_enable(void __iomem *regs)
+static int __init k210_sysctl_probe(struct platform_device *pdev)
 {
-	u32 val;
+	struct device *dev = &pdev->dev;
+	struct clk *pclk;
+	int ret;
 
-	val = readl(regs + K210_SYSCTL_PLL1);
-	val &= ~GENMASK(19, 0);				/* clkr1 = 0 */
-	val |= FIELD_PREP(GENMASK(9, 4), 0x3B);		/* clkf1 = 59 */
-	val |= FIELD_PREP(GENMASK(13, 10), 0x3);	/* clkod1 = 3 */
-	val |= FIELD_PREP(GENMASK(19, 14), 0x3B);	/* bwadj1 = 59 */
-	writel(val, regs + K210_SYSCTL_PLL1);
+	dev_info(dev, "K210 system controller\n");
 
-	k210_clear_bits(PLL_BYPASS, regs + K210_SYSCTL_PLL1);
-	k210_set_bits(PLL_PWR, regs + K210_SYSCTL_PLL1);
-
-	/*
-	 * Reset the pll. The magic NOPs come from the Kendryte reference SDK.
-	 */
-	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-	k210_set_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-	nop();
-	nop();
-	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
-
-	for (;;) {
-		val = readl(regs + K210_SYSCTL_PLL_LOCK);
-		if (val & PLL1_LOCK2)
-			break;
-		writel(val | PLL1_SLIP_CLEAR, regs + K210_SYSCTL_PLL_LOCK);
+	/* Get power bus clock */
+	pclk = devm_clk_get(dev, NULL);
+	if (IS_ERR(pclk)) {
+		dev_err(dev, "Get bus clock failed\n");
+		return PTR_ERR(pclk);
 	}
 
-	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL1);
-}
-
-static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct k210_sysctl *s = container_of(hw, struct k210_sysctl, hw);
-	u32 clksel0, pll0;
-	u64 pll0_freq, clkr0, clkf0, clkod0;
-
-	/*
-	 * If the clock selector is not set, use the base frequency.
-	 * Otherwise, use PLL0 frequency with a frequency divisor.
-	 */
-	clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0);
-	if (!(clksel0 & CLKSEL_ACLK))
-		return K210_SYSCTL_CLK0_FREQ;
-
-	/*
-	 * Get PLL0 frequency:
-	 * freq = base frequency * clkf0 / (clkr0 * clkod0)
-	 */
-	pll0 = readl(s->regs + K210_SYSCTL_PLL0);
-	clkr0 = 1 + FIELD_GET(GENMASK(3, 0), pll0);
-	clkf0 = 1 + FIELD_GET(GENMASK(9, 4), pll0);
-	clkod0 = 1 + FIELD_GET(GENMASK(13, 10), pll0);
-	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
-
-	/* Get the frequency divisor from the clock selector */
-	return pll0_freq / (2ULL << FIELD_GET(0x00000006, clksel0));
-}
-
-static const struct clk_ops k210_sysctl_clk_ops = {
-	.recalc_rate	= k210_sysctl_clk_recalc_rate,
-};
-
-static const struct clk_init_data k210_clk_init_data = {
-	.name		= "k210-sysctl-pll1",
-	.ops		= &k210_sysctl_clk_ops,
-};
-
-static int k210_sysctl_probe(struct platform_device *pdev)
-{
-	struct k210_sysctl *s;
-	int error;
-
-	pr_info("Kendryte K210 SoC sysctl\n");
-
-	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
-	if (!s)
-		return -ENOMEM;
-
-	s->regs = devm_ioremap_resource(&pdev->dev,
-			platform_get_resource(pdev, IORESOURCE_MEM, 0));
-	if (IS_ERR(s->regs))
-		return PTR_ERR(s->regs);
-
-	s->hw.init = &k210_clk_init_data;
-	error = devm_clk_hw_register(&pdev->dev, &s->hw);
-	if (error) {
-		dev_err(&pdev->dev, "failed to register clk");
-		return error;
+	ret = clk_prepare_enable(pclk);
+	if (ret) {
+		dev_err(dev, "Enable bus clock failed\n");
+		return ret;
 	}
 
-	error = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
-					    &s->hw);
-	if (error) {
-		dev_err(&pdev->dev, "adding clk provider failed\n");
-		return error;
-	}
+	/* Populate children */
+	ret = devm_of_platform_populate(dev);
+	if (ret)
+		dev_err(dev, "Populate platform failed %d\n", ret);
 
-	return 0;
+	return ret;
 }
 
 static const struct of_device_id k210_sysctl_of_match[] = {
@@ -213,11 +53,22 @@ static struct platform_driver k210_sysctl_driver = {
 	.probe			= k210_sysctl_probe,
 };
 
+/*
+ * Most devices on the K210 SoC depend on the early initialization of sysctl
+ * fpioa and reset child nodes. So initialize this driver early as part of
+ * the post core initialization.
+ */
 static int __init k210_sysctl_init(void)
 {
 	return platform_driver_register(&k210_sysctl_driver);
 }
-core_initcall(k210_sysctl_init);
+postcore_initcall(k210_sysctl_init);
+
+/*
+ * System controller registers base address and size.
+ */
+#define K210_SYSCTL_BASE_ADDR	0x50440000ULL
+#define K210_SYSCTL_BASE_SIZE	0x1000
 
 /*
  * This needs to be called very early during initialization, given that
@@ -225,24 +76,14 @@ core_initcall(k210_sysctl_init);
  */
 static void __init k210_soc_early_init(const void *fdt)
 {
-	void __iomem *regs;
-
-	regs = ioremap(K210_SYSCTL_SYSCTL_BASE_ADDR, 0x1000);
-	if (!regs)
-		panic("K210 sysctl ioremap");
-
-	/* Enable PLL1 to make the KPU SRAM useable */
-	k210_pll1_enable(regs);
-
-	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0);
+	void __iomem *sysctl_base;
 
-	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
-		      regs + K210_SYSCTL_CLKEN_CENT);
-	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
-		      regs + K210_SYSCTL_CLKEN_PERI);
+	sysctl_base = ioremap(K210_SYSCTL_BASE_ADDR, K210_SYSCTL_BASE_SIZE);
+	if (!sysctl_base)
+		panic("k210-sysctl: ioremap failed");
 
-	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0);
+	k210_clk_early_init(sysctl_base);
 
-	iounmap(regs);
+	iounmap(sysctl_base);
 }
-SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
+SOC_EARLY_INIT_DECLARE(k210_soc, "kendryte,k210", k210_soc_early_init);
diff --git a/include/soc/kendryte/k210-sysctl.h b/include/soc/kendryte/k210-sysctl.h
new file mode 100644
index 000000000000..73e38a8fc31d
--- /dev/null
+++ b/include/soc/kendryte/k210-sysctl.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#ifndef K210_SYSCTL_H
+#define K210_SYSCTL_H
+
+void k210_clk_early_init(void __iomem *regs);
+
+#endif
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 19/32] riscv: Add Kendryte K210 SoC reset controller
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a reset controller driver for the Kendryte K210 SoC. This driver
relies on its syscon compatible parent node for its register mapping.
Automatically select this driver for compilation when the SOC_KENDRYTE
option is selected.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs    |   3 +
 drivers/reset/Kconfig      |   9 ++
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-k210.c | 186 +++++++++++++++++++++++++++++++++++++
 4 files changed, 199 insertions(+)
 create mode 100644 drivers/reset/reset-k210.c

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index a4c851ffc6b0..4d8e66d0556a 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -31,6 +31,9 @@ config SOC_KENDRYTE
 	select SIFIVE_PLIC
 	select SOC_K210
 	select CLK_K210
+	select ARCH_HAS_RESET_CONTROLLER
+	select RESET_CONTROLLER
+	select RESET_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 07d162b179fc..c943051b5fc8 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -245,6 +245,15 @@ config RESET_ZYNQ
 	help
 	  This enables the reset controller driver for Xilinx Zynq SoCs.
 
+config RESET_K210
+	bool "Reset controller driver for Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on OF && MFD_SYSCON
+	help
+	  Support for the Kendryte K210 RISC-V SoC reset controller. If
+          Say Y if you want to control reset signals provided by this
+	  controller.
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
 source "drivers/reset/tegra/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 16947610cc3b..1730a31e6871 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -33,4 +33,5 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
+obj-$(CONFIG_RESET_K210) += reset-k210.o
 
diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c
new file mode 100644
index 000000000000..b6401aef2923
--- /dev/null
+++ b/drivers/reset/reset-k210.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dt-bindings/reset/k210-rst.h>
+
+struct k210_rst {
+	struct regmap *map;
+	u32 offset;
+	u32 mask;
+	u32 assert_high;
+	struct reset_controller_dev rcdev;
+};
+
+static inline struct k210_rst *
+to_k210_rst(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct k210_rst, rcdev);
+}
+
+static inline int k210_rst_assert(struct reset_controller_dev *rcdev,
+				  unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 bit = BIT(id);
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid assert id %lu\n", id);
+		return -EINVAL;
+	}
+
+	dev_dbg(rcdev->dev, "assert %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	regmap_update_bits(ksr->map, ksr->offset, bit,
+			   ksr->assert_high ? bit : 0);
+
+	return 0;
+}
+
+static inline int k210_rst_deassert(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 bit = BIT(id);
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid deassert id %lu\n", id);
+		return -EINVAL;
+	}
+
+	dev_dbg(rcdev->dev, "deassert %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	regmap_update_bits(ksr->map, ksr->offset, bit,
+			   ksr->assert_high ? 0 : bit);
+
+	return 0;
+}
+
+static int k210_rst_reset(struct reset_controller_dev *rcdev,
+			  unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	int ret;
+
+	dev_dbg(rcdev->dev, "reset %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	ret = k210_rst_assert(rcdev, id);
+	if (ret == 0) {
+		udelay(10);
+		ret = k210_rst_deassert(rcdev, id);
+	}
+
+	return ret;
+}
+
+static int k210_rst_status(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 reg, bit = BIT(id);
+	int ret;
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid reset %lx\n", id);
+		return -EINVAL;
+	}
+
+	ret = regmap_read(ksr->map, ksr->offset, &reg);
+	if (ret)
+		return ret;
+
+	if (ksr->assert_high)
+		return ret & bit;
+
+	return !(ret & bit);
+}
+
+static const struct reset_control_ops k210_rst_ops = {
+	.assert		= k210_rst_assert,
+	.deassert	= k210_rst_deassert,
+	.reset		= k210_rst_reset,
+	.status		= k210_rst_status,
+};
+
+static int __init k210_rst_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct k210_rst *ksr;
+	int ret, nr_resets;
+
+	dev_info(dev, "K210 reset controller\n");
+
+	ksr = devm_kzalloc(dev, sizeof(*ksr), GFP_KERNEL);
+	if (!ksr)
+		return -ENOMEM;
+
+	ksr->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
+	if (IS_ERR(ksr->map)) {
+		ksr->map = syscon_node_to_regmap(dev->parent->of_node);
+		if (IS_ERR(ksr->map)) {
+			dev_err(dev, "get register map failed\n");
+			return PTR_ERR(ksr->map);
+		}
+	}
+
+	ret = of_property_read_u32(dev->of_node, "offset", &ksr->offset);
+	ret = of_property_read_u32(dev->of_node, "assert-high",
+				   &ksr->assert_high);
+	if (ret) {
+		dev_err(dev, "unable to read 'offset' and 'assert-high'\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "mask", &ksr->mask);
+	if (ret) {
+		/* Use default mask */
+		ksr->mask = 0x27FFFFFF;
+	}
+	nr_resets = fls(ksr->mask);
+	if (!nr_resets) {
+		dev_err(dev, "Invalid mask 0x%08x\n", ksr->mask);
+		return -EINVAL;
+	}
+
+	ksr->rcdev.owner = THIS_MODULE;
+	ksr->rcdev.dev = dev;
+	ksr->rcdev.of_node = dev->of_node;
+	ksr->rcdev.nr_resets = nr_resets;
+	ksr->rcdev.ops = &k210_rst_ops;
+
+	return devm_reset_controller_register(dev, &ksr->rcdev);
+}
+
+static const struct of_device_id k210_rst_dt_ids[] = {
+	{ .compatible = "kendryte,k210-rst" },
+};
+
+static struct platform_driver k210_rst_driver = {
+	.probe	= k210_rst_probe,
+	.driver = {
+		.name		= "k210-rst",
+		.of_match_table	= k210_rst_dt_ids,
+	},
+};
+
+/*
+ * Most devices on the K210 SoC need reset as part of their initialization.
+ * So initialize this driver early as part of the post core initialization.
+ */
+static int __init k210_rst_init(void)
+{
+	return platform_driver_register(&k210_rst_driver);
+}
+postcore_initcall(k210_rst_init);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 19/32] riscv: Add Kendryte K210 SoC reset controller
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a reset controller driver for the Kendryte K210 SoC. This driver
relies on its syscon compatible parent node for its register mapping.
Automatically select this driver for compilation when the SOC_KENDRYTE
option is selected.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs    |   3 +
 drivers/reset/Kconfig      |   9 ++
 drivers/reset/Makefile     |   1 +
 drivers/reset/reset-k210.c | 186 +++++++++++++++++++++++++++++++++++++
 4 files changed, 199 insertions(+)
 create mode 100644 drivers/reset/reset-k210.c

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index a4c851ffc6b0..4d8e66d0556a 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -31,6 +31,9 @@ config SOC_KENDRYTE
 	select SIFIVE_PLIC
 	select SOC_K210
 	select CLK_K210
+	select ARCH_HAS_RESET_CONTROLLER
+	select RESET_CONTROLLER
+	select RESET_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 07d162b179fc..c943051b5fc8 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -245,6 +245,15 @@ config RESET_ZYNQ
 	help
 	  This enables the reset controller driver for Xilinx Zynq SoCs.
 
+config RESET_K210
+	bool "Reset controller driver for Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on OF && MFD_SYSCON
+	help
+	  Support for the Kendryte K210 RISC-V SoC reset controller. If
+          Say Y if you want to control reset signals provided by this
+	  controller.
+
 source "drivers/reset/sti/Kconfig"
 source "drivers/reset/hisilicon/Kconfig"
 source "drivers/reset/tegra/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 16947610cc3b..1730a31e6871 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -33,4 +33,5 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
+obj-$(CONFIG_RESET_K210) += reset-k210.o
 
diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c
new file mode 100644
index 000000000000..b6401aef2923
--- /dev/null
+++ b/drivers/reset/reset-k210.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dt-bindings/reset/k210-rst.h>
+
+struct k210_rst {
+	struct regmap *map;
+	u32 offset;
+	u32 mask;
+	u32 assert_high;
+	struct reset_controller_dev rcdev;
+};
+
+static inline struct k210_rst *
+to_k210_rst(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct k210_rst, rcdev);
+}
+
+static inline int k210_rst_assert(struct reset_controller_dev *rcdev,
+				  unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 bit = BIT(id);
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid assert id %lu\n", id);
+		return -EINVAL;
+	}
+
+	dev_dbg(rcdev->dev, "assert %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	regmap_update_bits(ksr->map, ksr->offset, bit,
+			   ksr->assert_high ? bit : 0);
+
+	return 0;
+}
+
+static inline int k210_rst_deassert(struct reset_controller_dev *rcdev,
+				    unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 bit = BIT(id);
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid deassert id %lu\n", id);
+		return -EINVAL;
+	}
+
+	dev_dbg(rcdev->dev, "deassert %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	regmap_update_bits(ksr->map, ksr->offset, bit,
+			   ksr->assert_high ? 0 : bit);
+
+	return 0;
+}
+
+static int k210_rst_reset(struct reset_controller_dev *rcdev,
+			  unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	int ret;
+
+	dev_dbg(rcdev->dev, "reset %s %lu\n",
+		ksr->assert_high ? "high" : "low", id);
+
+	ret = k210_rst_assert(rcdev, id);
+	if (ret == 0) {
+		udelay(10);
+		ret = k210_rst_deassert(rcdev, id);
+	}
+
+	return ret;
+}
+
+static int k210_rst_status(struct reset_controller_dev *rcdev,
+			   unsigned long id)
+{
+	struct k210_rst *ksr = to_k210_rst(rcdev);
+	u32 reg, bit = BIT(id);
+	int ret;
+
+	if (!(bit & ksr->mask)) {
+		dev_err(rcdev->dev, "Invalid reset %lx\n", id);
+		return -EINVAL;
+	}
+
+	ret = regmap_read(ksr->map, ksr->offset, &reg);
+	if (ret)
+		return ret;
+
+	if (ksr->assert_high)
+		return ret & bit;
+
+	return !(ret & bit);
+}
+
+static const struct reset_control_ops k210_rst_ops = {
+	.assert		= k210_rst_assert,
+	.deassert	= k210_rst_deassert,
+	.reset		= k210_rst_reset,
+	.status		= k210_rst_status,
+};
+
+static int __init k210_rst_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct k210_rst *ksr;
+	int ret, nr_resets;
+
+	dev_info(dev, "K210 reset controller\n");
+
+	ksr = devm_kzalloc(dev, sizeof(*ksr), GFP_KERNEL);
+	if (!ksr)
+		return -ENOMEM;
+
+	ksr->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
+	if (IS_ERR(ksr->map)) {
+		ksr->map = syscon_node_to_regmap(dev->parent->of_node);
+		if (IS_ERR(ksr->map)) {
+			dev_err(dev, "get register map failed\n");
+			return PTR_ERR(ksr->map);
+		}
+	}
+
+	ret = of_property_read_u32(dev->of_node, "offset", &ksr->offset);
+	ret = of_property_read_u32(dev->of_node, "assert-high",
+				   &ksr->assert_high);
+	if (ret) {
+		dev_err(dev, "unable to read 'offset' and 'assert-high'\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32(dev->of_node, "mask", &ksr->mask);
+	if (ret) {
+		/* Use default mask */
+		ksr->mask = 0x27FFFFFF;
+	}
+	nr_resets = fls(ksr->mask);
+	if (!nr_resets) {
+		dev_err(dev, "Invalid mask 0x%08x\n", ksr->mask);
+		return -EINVAL;
+	}
+
+	ksr->rcdev.owner = THIS_MODULE;
+	ksr->rcdev.dev = dev;
+	ksr->rcdev.of_node = dev->of_node;
+	ksr->rcdev.nr_resets = nr_resets;
+	ksr->rcdev.ops = &k210_rst_ops;
+
+	return devm_reset_controller_register(dev, &ksr->rcdev);
+}
+
+static const struct of_device_id k210_rst_dt_ids[] = {
+	{ .compatible = "kendryte,k210-rst" },
+};
+
+static struct platform_driver k210_rst_driver = {
+	.probe	= k210_rst_probe,
+	.driver = {
+		.name		= "k210-rst",
+		.of_match_table	= k210_rst_dt_ids,
+	},
+};
+
+/*
+ * Most devices on the K210 SoC need reset as part of their initialization.
+ * So initialize this driver early as part of the post core initialization.
+ */
+static int __init k210_rst_init(void)
+{
+	return platform_driver_register(&k210_rst_driver);
+}
+postcore_initcall(k210_rst_init);
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
(fully programmable IO array) to allow configuring the SoC pin
functions. The K210 has 48 programmable pins which can take any of 256
possible functions.

This patch is inspired from the k210 pinctrl driver for the u-boot
project and contains many direct contributions from Sean Anderson.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs        |   2 +
 drivers/pinctrl/Kconfig        |  15 +
 drivers/pinctrl/Makefile       |   1 +
 drivers/pinctrl/pinctrl-k210.c | 999 +++++++++++++++++++++++++++++++++
 4 files changed, 1017 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-k210.c

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 4d8e66d0556a..56ba82a64e18 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -34,6 +34,8 @@ config SOC_KENDRYTE
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
 	select RESET_K210
+	select PINCTRL
+	select PINCTRL_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 815095326e2d..a5073afb8bfe 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -374,6 +374,21 @@ config PINCTRL_OCELOT
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_K210
+	bool "Pinctrl driver for the Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on OF && HAS_IOMEM
+	select PINMUX
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select REGMAP_MMIO
+	help
+	  Add support for the Kendryte K210 RISC-V SOC Field Programmable
+	  IO Array (FPIOA) controller. Support for this controller is
+	  automatically selected when the SOC_KENDRYTE option is selected
+	  in the "SOC selection" menu.
+
 source "drivers/pinctrl/actions/Kconfig"
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f53933b2ff02..d6f913adb04a 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_PINCTRL_INGENIC)	+= pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
+obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
 
 obj-y				+= actions/
 obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
new file mode 100644
index 000000000000..48741023fcf7
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-k210.c
@@ -0,0 +1,999 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/k210-pinctrl.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+/*
+ * The K210 only implements 8 drive levels, even though
+ * there is register space for 16
+ */
+#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
+#define K210_PC_DRIVE_SHIFT	8
+#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_MAX	7
+#define K210_PC_MODE_MASK	GENMASK(23, 12)
+
+/*
+ * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
+ * where FUNCTION_OE is a physical signal from the function.
+ */
+#define K210_PC_OE		BIT(12) /* Output Enable */
+#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
+#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
+#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
+#define K210_PC_PU		BIT(16) /* Pull Up */
+#define K210_PC_PD		BIT(17) /* Pull Down */
+/* Strong pull up not implemented on K210 */
+#define K210_PC_SL		BIT(19) /* reduce SLew rate */
+/* Same semantics as OE above */
+#define K210_PC_IE		BIT(20) /* Input Enable */
+#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
+#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
+#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
+#define K210_PC_DI		BIT(31) /* raw Data Input */
+
+#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
+
+#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
+#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
+#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
+				 K210_PC_OE | K210_PC_PU)
+#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
+				 K210_PC_OE_INV | K210_PC_IE_INV)
+#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
+				 K210_PC_MODE_OUT | K210_PC_OE_INV)
+#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
+
+#define K210_PG_FUNC		GENMASK(7, 0)
+#define K210_PG_DO		BIT(8)
+#define K210_PG_PIN		GENMASK(22, 16)
+
+/*
+ * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
+ * @pins: 48 32-bits IO pin registers
+ * @tie_en: 256 (one per function) input tie enable bits
+ * @tie_val: 256 (one per function) input tie value bits
+ */
+struct k210_fpioa {
+	u32 pins[48];
+	u32 tie_en[8];
+	u32 tie_val[8];
+};
+
+struct k210_fpioa_data {
+
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+
+	struct k210_fpioa __iomem *fpioa;
+	struct regmap *sysctl_map;
+	u32 power_offset;
+	struct clk *clk;
+	struct clk *pclk;
+};
+
+#define K210_PIN(i)	[i] = PINCTRL_PIN(i, "IO_" #i)
+
+static const struct pinctrl_pin_desc k210_pins[] = {
+	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
+	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
+	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
+	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
+	K210_PIN(12), K210_PIN(13), K210_PIN(14),
+	K210_PIN(15), K210_PIN(16), K210_PIN(17),
+	K210_PIN(18), K210_PIN(19), K210_PIN(20),
+	K210_PIN(21), K210_PIN(22), K210_PIN(23),
+	K210_PIN(24), K210_PIN(25), K210_PIN(26),
+	K210_PIN(27), K210_PIN(28), K210_PIN(29),
+	K210_PIN(30), K210_PIN(31), K210_PIN(32),
+	K210_PIN(33), K210_PIN(34), K210_PIN(35),
+	K210_PIN(36), K210_PIN(37), K210_PIN(38),
+	K210_PIN(39), K210_PIN(40), K210_PIN(41),
+	K210_PIN(42), K210_PIN(43), K210_PIN(44),
+	K210_PIN(45), K210_PIN(46), K210_PIN(47)
+};
+
+#define K210_NPINS ARRAY_SIZE(k210_pins)
+
+/*
+ * Pin groups: each of the 48 programmable pins is a group.
+ * To this are added 8 power domain groups, which for the purposes of
+ * the pin subsystem, contain no pins. The power domain groups only exist
+ * to set the power level. The id should never be used (since there are
+ * no pins 48-55).
+ */
+#define K210_PIN_NAME(i)	[i] = k210_pins[i].name
+static const char *const k210_group_names[] = {
+	/* The first 48 groups are for pins, one each */
+	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
+	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
+	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
+	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
+	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
+	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
+	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
+	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
+	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
+	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
+	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
+	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
+	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
+	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
+	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
+	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
+	[48] = "A0", [49] = "A1", [50] = "A2",
+	[51] = "B3", [52] = "B4", [53] = "B5",
+	[54] = "C6", [55] = "C7"
+};
+
+#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
+
+enum k210_pinctrl_mode_id {
+	K210_PC_DEFAULT_DISABLED,
+	K210_PC_DEFAULT_IN,
+	K210_PC_DEFAULT_IN_TIE,
+	K210_PC_DEFAULT_OUT,
+	K210_PC_DEFAULT_I2C,
+	K210_PC_DEFAULT_SCCB,
+	K210_PC_DEFAULT_SPI,
+	K210_PC_DEFAULT_GPIO,
+	K210_PC_DEFAULT_INT13,
+};
+
+#define K210_PC_DEFAULT(mode) \
+	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
+
+static const u32 k210_pinconf_mode_id_to_mode[] = {
+	[K210_PC_DEFAULT_DISABLED] = 0,
+	K210_PC_DEFAULT(IN),
+	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
+	K210_PC_DEFAULT(OUT),
+	K210_PC_DEFAULT(I2C),
+	K210_PC_DEFAULT(SCCB),
+	K210_PC_DEFAULT(SPI),
+	K210_PC_DEFAULT(GPIO),
+	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
+};
+
+#undef DEFAULT
+
+/*
+ * Pin functions configuration information.
+ */
+struct k210_pcf_info {
+	char name[15];
+	u8 mode_id;
+};
+
+#define K210_FUNC(id, mode)				\
+	[K210_PCF_##id] = {				\
+		.name = #id,				\
+		.mode_id = K210_PC_DEFAULT_##mode	\
+	}
+
+static const struct k210_pcf_info k210_pcf_infos[] = {
+	K210_FUNC(JTAG_TCLK,		IN),
+	K210_FUNC(JTAG_TDI,		IN),
+	K210_FUNC(JTAG_TMS,		IN),
+	K210_FUNC(JTAG_TDO,		OUT),
+	K210_FUNC(SPI0_D0,		SPI),
+	K210_FUNC(SPI0_D1,		SPI),
+	K210_FUNC(SPI0_D2,		SPI),
+	K210_FUNC(SPI0_D3,		SPI),
+	K210_FUNC(SPI0_D4,		SPI),
+	K210_FUNC(SPI0_D5,		SPI),
+	K210_FUNC(SPI0_D6,		SPI),
+	K210_FUNC(SPI0_D7,		SPI),
+	K210_FUNC(SPI0_SS0,		OUT),
+	K210_FUNC(SPI0_SS1,		OUT),
+	K210_FUNC(SPI0_SS2,		OUT),
+	K210_FUNC(SPI0_SS3,		OUT),
+	K210_FUNC(SPI0_ARB,		IN_TIE),
+	K210_FUNC(SPI0_SCLK,		OUT),
+	K210_FUNC(UARTHS_RX,		IN),
+	K210_FUNC(UARTHS_TX,		OUT),
+	K210_FUNC(RESV6,		IN),
+	K210_FUNC(RESV7,		IN),
+	K210_FUNC(CLK_SPI1,		OUT),
+	K210_FUNC(CLK_I2C1,		OUT),
+	K210_FUNC(GPIOHS0,		GPIO),
+	K210_FUNC(GPIOHS1,		GPIO),
+	K210_FUNC(GPIOHS2,		GPIO),
+	K210_FUNC(GPIOHS3,		GPIO),
+	K210_FUNC(GPIOHS4,		GPIO),
+	K210_FUNC(GPIOHS5,		GPIO),
+	K210_FUNC(GPIOHS6,		GPIO),
+	K210_FUNC(GPIOHS7,		GPIO),
+	K210_FUNC(GPIOHS8,		GPIO),
+	K210_FUNC(GPIOHS9,		GPIO),
+	K210_FUNC(GPIOHS10,		GPIO),
+	K210_FUNC(GPIOHS11,		GPIO),
+	K210_FUNC(GPIOHS12,		GPIO),
+	K210_FUNC(GPIOHS13,		GPIO),
+	K210_FUNC(GPIOHS14,		GPIO),
+	K210_FUNC(GPIOHS15,		GPIO),
+	K210_FUNC(GPIOHS16,		GPIO),
+	K210_FUNC(GPIOHS17,		GPIO),
+	K210_FUNC(GPIOHS18,		GPIO),
+	K210_FUNC(GPIOHS19,		GPIO),
+	K210_FUNC(GPIOHS20,		GPIO),
+	K210_FUNC(GPIOHS21,		GPIO),
+	K210_FUNC(GPIOHS22,		GPIO),
+	K210_FUNC(GPIOHS23,		GPIO),
+	K210_FUNC(GPIOHS24,		GPIO),
+	K210_FUNC(GPIOHS25,		GPIO),
+	K210_FUNC(GPIOHS26,		GPIO),
+	K210_FUNC(GPIOHS27,		GPIO),
+	K210_FUNC(GPIOHS28,		GPIO),
+	K210_FUNC(GPIOHS29,		GPIO),
+	K210_FUNC(GPIOHS30,		GPIO),
+	K210_FUNC(GPIOHS31,		GPIO),
+	K210_FUNC(GPIO0,		GPIO),
+	K210_FUNC(GPIO1,		GPIO),
+	K210_FUNC(GPIO2,		GPIO),
+	K210_FUNC(GPIO3,		GPIO),
+	K210_FUNC(GPIO4,		GPIO),
+	K210_FUNC(GPIO5,		GPIO),
+	K210_FUNC(GPIO6,		GPIO),
+	K210_FUNC(GPIO7,		GPIO),
+	K210_FUNC(UART1_RX,		IN),
+	K210_FUNC(UART1_TX,		OUT),
+	K210_FUNC(UART2_RX,		IN),
+	K210_FUNC(UART2_TX,		OUT),
+	K210_FUNC(UART3_RX,		IN),
+	K210_FUNC(UART3_TX,		OUT),
+	K210_FUNC(SPI1_D0,		SPI),
+	K210_FUNC(SPI1_D1,		SPI),
+	K210_FUNC(SPI1_D2,		SPI),
+	K210_FUNC(SPI1_D3,		SPI),
+	K210_FUNC(SPI1_D4,		SPI),
+	K210_FUNC(SPI1_D5,		SPI),
+	K210_FUNC(SPI1_D6,		SPI),
+	K210_FUNC(SPI1_D7,		SPI),
+	K210_FUNC(SPI1_SS0,		OUT),
+	K210_FUNC(SPI1_SS1,		OUT),
+	K210_FUNC(SPI1_SS2,		OUT),
+	K210_FUNC(SPI1_SS3,		OUT),
+	K210_FUNC(SPI1_ARB,		IN_TIE),
+	K210_FUNC(SPI1_SCLK,		OUT),
+	K210_FUNC(SPI2_D0,		SPI),
+	K210_FUNC(SPI2_SS,		IN),
+	K210_FUNC(SPI2_SCLK,		IN),
+	K210_FUNC(I2S0_MCLK,		OUT),
+	K210_FUNC(I2S0_SCLK,		OUT),
+	K210_FUNC(I2S0_WS,		OUT),
+	K210_FUNC(I2S0_IN_D0,		IN),
+	K210_FUNC(I2S0_IN_D1,		IN),
+	K210_FUNC(I2S0_IN_D2,		IN),
+	K210_FUNC(I2S0_IN_D3,		IN),
+	K210_FUNC(I2S0_OUT_D0,		OUT),
+	K210_FUNC(I2S0_OUT_D1,		OUT),
+	K210_FUNC(I2S0_OUT_D2,		OUT),
+	K210_FUNC(I2S0_OUT_D3,		OUT),
+	K210_FUNC(I2S1_MCLK,		OUT),
+	K210_FUNC(I2S1_SCLK,		OUT),
+	K210_FUNC(I2S1_WS,		OUT),
+	K210_FUNC(I2S1_IN_D0,		IN),
+	K210_FUNC(I2S1_IN_D1,		IN),
+	K210_FUNC(I2S1_IN_D2,		IN),
+	K210_FUNC(I2S1_IN_D3,		IN),
+	K210_FUNC(I2S1_OUT_D0,		OUT),
+	K210_FUNC(I2S1_OUT_D1,		OUT),
+	K210_FUNC(I2S1_OUT_D2,		OUT),
+	K210_FUNC(I2S1_OUT_D3,		OUT),
+	K210_FUNC(I2S2_MCLK,		OUT),
+	K210_FUNC(I2S2_SCLK,		OUT),
+	K210_FUNC(I2S2_WS,		OUT),
+	K210_FUNC(I2S2_IN_D0,		IN),
+	K210_FUNC(I2S2_IN_D1,		IN),
+	K210_FUNC(I2S2_IN_D2,		IN),
+	K210_FUNC(I2S2_IN_D3,		IN),
+	K210_FUNC(I2S2_OUT_D0,		OUT),
+	K210_FUNC(I2S2_OUT_D1,		OUT),
+	K210_FUNC(I2S2_OUT_D2,		OUT),
+	K210_FUNC(I2S2_OUT_D3,		OUT),
+	K210_FUNC(RESV0,		DISABLED),
+	K210_FUNC(RESV1,		DISABLED),
+	K210_FUNC(RESV2,		DISABLED),
+	K210_FUNC(RESV3,		DISABLED),
+	K210_FUNC(RESV4,		DISABLED),
+	K210_FUNC(RESV5,		DISABLED),
+	K210_FUNC(I2C0_SCLK,		I2C),
+	K210_FUNC(I2C0_SDA,		I2C),
+	K210_FUNC(I2C1_SCLK,		I2C),
+	K210_FUNC(I2C1_SDA,		I2C),
+	K210_FUNC(I2C2_SCLK,		I2C),
+	K210_FUNC(I2C2_SDA,		I2C),
+	K210_FUNC(DVP_XCLK,		OUT),
+	K210_FUNC(DVP_RST,		OUT),
+	K210_FUNC(DVP_PWDN,		OUT),
+	K210_FUNC(DVP_VSYNC,		IN),
+	K210_FUNC(DVP_HSYNC,		IN),
+	K210_FUNC(DVP_PCLK,		IN),
+	K210_FUNC(DVP_D0,		IN),
+	K210_FUNC(DVP_D1,		IN),
+	K210_FUNC(DVP_D2,		IN),
+	K210_FUNC(DVP_D3,		IN),
+	K210_FUNC(DVP_D4,		IN),
+	K210_FUNC(DVP_D5,		IN),
+	K210_FUNC(DVP_D6,		IN),
+	K210_FUNC(DVP_D7,		IN),
+	K210_FUNC(SCCB_SCLK,		SCCB),
+	K210_FUNC(SCCB_SDA,		SCCB),
+	K210_FUNC(UART1_CTS,		IN),
+	K210_FUNC(UART1_DSR,		IN),
+	K210_FUNC(UART1_DCD,		IN),
+	K210_FUNC(UART1_RI,		IN),
+	K210_FUNC(UART1_SIR_IN,		IN),
+	K210_FUNC(UART1_DTR,		OUT),
+	K210_FUNC(UART1_RTS,		OUT),
+	K210_FUNC(UART1_OUT2,		OUT),
+	K210_FUNC(UART1_OUT1,		OUT),
+	K210_FUNC(UART1_SIR_OUT,	OUT),
+	K210_FUNC(UART1_BAUD,		OUT),
+	K210_FUNC(UART1_RE,		OUT),
+	K210_FUNC(UART1_DE,		OUT),
+	K210_FUNC(UART1_RS485_EN,	OUT),
+	K210_FUNC(UART2_CTS,		IN),
+	K210_FUNC(UART2_DSR,		IN),
+	K210_FUNC(UART2_DCD,		IN),
+	K210_FUNC(UART2_RI,		IN),
+	K210_FUNC(UART2_SIR_IN,		IN),
+	K210_FUNC(UART2_DTR,		OUT),
+	K210_FUNC(UART2_RTS,		OUT),
+	K210_FUNC(UART2_OUT2,		OUT),
+	K210_FUNC(UART2_OUT1,		OUT),
+	K210_FUNC(UART2_SIR_OUT,	OUT),
+	K210_FUNC(UART2_BAUD,		OUT),
+	K210_FUNC(UART2_RE,		OUT),
+	K210_FUNC(UART2_DE,		OUT),
+	K210_FUNC(UART2_RS485_EN,	OUT),
+	K210_FUNC(UART3_CTS,		IN),
+	K210_FUNC(UART3_DSR,		IN),
+	K210_FUNC(UART3_DCD,		IN),
+	K210_FUNC(UART3_RI,		IN),
+	K210_FUNC(UART3_SIR_IN,		IN),
+	K210_FUNC(UART3_DTR,		OUT),
+	K210_FUNC(UART3_RTS,		OUT),
+	K210_FUNC(UART3_OUT2,		OUT),
+	K210_FUNC(UART3_OUT1,		OUT),
+	K210_FUNC(UART3_SIR_OUT,	OUT),
+	K210_FUNC(UART3_BAUD,		OUT),
+	K210_FUNC(UART3_RE,		OUT),
+	K210_FUNC(UART3_DE,		OUT),
+	K210_FUNC(UART3_RS485_EN,	OUT),
+	K210_FUNC(TIMER0_TOGGLE1,	OUT),
+	K210_FUNC(TIMER0_TOGGLE2,	OUT),
+	K210_FUNC(TIMER0_TOGGLE3,	OUT),
+	K210_FUNC(TIMER0_TOGGLE4,	OUT),
+	K210_FUNC(TIMER1_TOGGLE1,	OUT),
+	K210_FUNC(TIMER1_TOGGLE2,	OUT),
+	K210_FUNC(TIMER1_TOGGLE3,	OUT),
+	K210_FUNC(TIMER1_TOGGLE4,	OUT),
+	K210_FUNC(TIMER2_TOGGLE1,	OUT),
+	K210_FUNC(TIMER2_TOGGLE2,	OUT),
+	K210_FUNC(TIMER2_TOGGLE3,	OUT),
+	K210_FUNC(TIMER2_TOGGLE4,	OUT),
+	K210_FUNC(CLK_SPI2,		OUT),
+	K210_FUNC(CLK_I2C2,		OUT),
+	K210_FUNC(INTERNAL0,		OUT),
+	K210_FUNC(INTERNAL1,		OUT),
+	K210_FUNC(INTERNAL2,		OUT),
+	K210_FUNC(INTERNAL3,		OUT),
+	K210_FUNC(INTERNAL4,		OUT),
+	K210_FUNC(INTERNAL5,		OUT),
+	K210_FUNC(INTERNAL6,		OUT),
+	K210_FUNC(INTERNAL7,		OUT),
+	K210_FUNC(INTERNAL8,		OUT),
+	K210_FUNC(INTERNAL9,		IN),
+	K210_FUNC(INTERNAL10,		IN),
+	K210_FUNC(INTERNAL11,		IN),
+	K210_FUNC(INTERNAL12,		IN),
+	K210_FUNC(INTERNAL13,		INT13),
+	K210_FUNC(INTERNAL14,		I2C),
+	K210_FUNC(INTERNAL15,		IN),
+	K210_FUNC(INTERNAL16,		IN),
+	K210_FUNC(INTERNAL17,		IN),
+	K210_FUNC(CONSTANT,		DISABLED),
+	K210_FUNC(INTERNAL18,		IN),
+	K210_FUNC(DEBUG0,		OUT),
+	K210_FUNC(DEBUG1,		OUT),
+	K210_FUNC(DEBUG2,		OUT),
+	K210_FUNC(DEBUG3,		OUT),
+	K210_FUNC(DEBUG4,		OUT),
+	K210_FUNC(DEBUG5,		OUT),
+	K210_FUNC(DEBUG6,		OUT),
+	K210_FUNC(DEBUG7,		OUT),
+	K210_FUNC(DEBUG8,		OUT),
+	K210_FUNC(DEBUG9,		OUT),
+	K210_FUNC(DEBUG10,		OUT),
+	K210_FUNC(DEBUG11,		OUT),
+	K210_FUNC(DEBUG12,		OUT),
+	K210_FUNC(DEBUG13,		OUT),
+	K210_FUNC(DEBUG14,		OUT),
+	K210_FUNC(DEBUG15,		OUT),
+	K210_FUNC(DEBUG16,		OUT),
+	K210_FUNC(DEBUG17,		OUT),
+	K210_FUNC(DEBUG18,		OUT),
+	K210_FUNC(DEBUG19,		OUT),
+	K210_FUNC(DEBUG20,		OUT),
+	K210_FUNC(DEBUG21,		OUT),
+	K210_FUNC(DEBUG22,		OUT),
+	K210_FUNC(DEBUG23,		OUT),
+	K210_FUNC(DEBUG24,		OUT),
+	K210_FUNC(DEBUG25,		OUT),
+	K210_FUNC(DEBUG26,		OUT),
+	K210_FUNC(DEBUG27,		OUT),
+	K210_FUNC(DEBUG28,		OUT),
+	K210_FUNC(DEBUG29,		OUT),
+	K210_FUNC(DEBUG30,		OUT),
+	K210_FUNC(DEBUG31,		OUT),
+};
+
+#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
+#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
+
+static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
+	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
+	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
+};
+
+/*
+ * Max drive strength in uA.
+ */
+static const int k210_pinconf_drive_strength[] = {
+	[0] = 11200,
+	[1] = 16800,
+	[2] = 22300,
+	[3] = 27800,
+	[4] = 33300,
+	[5] = 38700,
+	[6] = 44100,
+	[7] = 49500,
+};
+
+static int k210_pinconf_get_drive(unsigned int max_strength_ua)
+{
+	int i;
+
+	for (i = K210_PC_DRIVE_MAX; i; i--) {
+		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
+					 u32 pin, u32 func)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	const struct k210_pcf_info *info = &k210_pcf_infos[func];
+	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
+	u32 val = func | mode;
+
+	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
+		pin, info->name, func, val);
+
+	writel(val, &pdata->fpioa->pins[pin]);
+}
+
+static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
+				  unsigned int pin,
+				  unsigned int param, unsigned int arg)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	u32 val = readl(&pdata->fpioa->pins[pin]);
+	int drive;
+
+	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
+		pin, param, arg);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		val &= ~K210_PC_BIAS_MASK;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		arg *= 1000;
+		fallthrough;
+	case PIN_CONFIG_DRIVE_STRENGTH_UA:
+		drive = k210_pinconf_get_drive(arg);
+		if (drive < 0)
+			return drive;
+		val &= ~K210_PC_DRIVE_MASK;
+		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_IE;
+		else
+			val &= ~K210_PC_IE;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT:
+		arg = 1;
+		fallthrough;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		if (arg)
+			val |= K210_PC_ST;
+		else
+			val &= ~K210_PC_ST;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
+		val = readl(&pdata->fpioa->pins[pin]);
+		val |= K210_PC_MODE_OUT;
+		if (!arg)
+			val |= K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_OE;
+		else
+			val &= ~K210_PC_OE;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		if (arg)
+			val |= K210_PC_SL;
+		else
+			val &= ~K210_PC_SL;
+		break;
+	case PIN_CONFIG_OUTPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DO_INV;
+		else
+			val &= ~K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_INPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DI_INV;
+		else
+			val &= ~K210_PC_DI_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(val, &pdata->fpioa->pins[pin]);
+
+	return 0;
+}
+
+static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *configs, unsigned int num_configs)
+{
+	unsigned int param, arg;
+	int i, ret;
+
+	if (WARN_ON(pin >= K210_NPINS))
+		return -EINVAL;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				  struct seq_file *s, unsigned int pin)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
+}
+
+static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
+				  unsigned int selector, unsigned long *configs,
+				  unsigned int num_configs)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int param, arg;
+	u32 bit;
+	int i;
+
+	/* Pins should be configured with pinmux, not groups*/
+	if (selector < K210_NPINS)
+		return -EINVAL;
+
+	/* Otherwise it's a power domain */
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		if (param != PIN_CONFIG_POWER_SOURCE)
+			return -EINVAL;
+
+		arg = pinconf_to_config_argument(configs[i]);
+		bit = BIT(selector - K210_NPINS);
+		regmap_update_bits(pdata->sysctl_map,
+				   pdata->power_offset,
+				   bit, arg ? bit : 0);
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned int selector)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int ret;
+	u32 val;
+
+	if (selector < K210_NPINS)
+		return k210_pinconf_dbg_show(pctldev, s, selector);
+
+	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
+	if (ret) {
+		dev_err(pdata->dev, "Failed to read power reg\n");
+		return;
+	}
+
+	seq_printf(s, "%s: %s V", k210_group_names[selector],
+		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
+}
+
+static const struct pinconf_ops k210_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_set = k210_pinconf_set,
+	.pin_config_group_set = k210_pinconf_group_set,
+	.pin_config_dbg_show = k210_pinconf_dbg_show,
+	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
+};
+
+static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(k210_pcf_infos);
+}
+
+static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
+						 unsigned int selector)
+{
+	return k210_pcf_infos[selector].name;
+}
+
+static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+					   unsigned int selector,
+					   const char * const **groups,
+					   unsigned int * const num_groups)
+{
+	/* Any function can be mapped to any pin */
+	*groups = k210_group_names;
+	*num_groups = K210_NPINS;
+
+	return 0;
+}
+
+static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
+			       unsigned int function,
+			       unsigned int group)
+{
+	/* Can't mux power domains */
+	if (group >= K210_NPINS)
+		return -EINVAL;
+
+	k210_pinmux_set_pin_function(pctldev, group, function);
+
+	return 0;
+}
+
+static const struct pinmux_ops k210_pinmux_ops = {
+	.get_functions_count = k210_pinmux_get_function_count,
+	.get_function_name = k210_pinmux_get_function_name,
+	.get_function_groups = k210_pinmux_get_function_groups,
+	.set_mux = k210_pinmux_set_mux,
+	.strict = true,
+};
+
+static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return K210_NGROUPS;
+}
+
+static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+					       unsigned int group)
+{
+	return k210_group_names[group];
+}
+
+static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int group,
+				       const unsigned int **pins,
+				       unsigned int *npins)
+{
+	if (group >= K210_NPINS) {
+		*pins = NULL;
+		*npins = 0;
+		return 0;
+	}
+
+	*pins = &k210_pins[group].number;
+	*npins = 1;
+
+	return 0;
+}
+
+static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s, unsigned int offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+					  struct device_node *np,
+					  struct pinctrl_map **map,
+					  unsigned int *reserved_maps,
+					  unsigned int *num_maps)
+{
+	struct property *prop;
+	const __be32 *p;
+	int ret, pinmux_groups;
+	u32 pinmux_group;
+	unsigned long *configs = NULL;
+	unsigned int num_configs = 0;
+	unsigned int reserve = 0;
+
+	ret = of_property_count_strings(np, "groups");
+	if (!ret)
+		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
+						reserved_maps, num_maps,
+						PIN_MAP_TYPE_CONFIGS_GROUP);
+
+	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
+	if (pinmux_groups <= 0) {
+		/* Ignore this node */
+		return 0;
+	}
+
+	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+					      &num_configs);
+	if (ret < 0) {
+		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
+			np);
+		return ret;
+	}
+
+	reserve = pinmux_groups * (1 + num_configs);
+	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
+					reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
+		const char *group_name, *func_name;
+		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
+		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
+
+		if (pin >= K210_NPINS) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		group_name = k210_group_names[pin];
+		func_name = k210_pcf_infos[func].name;
+
+		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
+			np->name, pin, func_name);
+
+		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
+						num_maps, group_name,
+						func_name);
+		if (ret < 0) {
+			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
+				np, ret);
+			goto exit;
+		}
+
+		if (num_configs) {
+			ret = pinctrl_utils_add_map_configs(pctldev, map,
+					reserved_maps, num_maps, group_name,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_PIN);
+			if (ret < 0) {
+				dev_err(pctldev->dev,
+					"%pOF add configs map failed %d\n",
+					np, ret);
+				goto exit;
+			}
+		}
+	}
+
+	ret = 0;
+
+exit:
+	kfree(configs);
+	return ret;
+}
+
+int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np_config,
+			struct pinctrl_map **map, unsigned int *num_maps)
+{
+	unsigned int reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
+					     &reserved_maps, num_maps);
+	if (ret < 0)
+		goto err;
+
+	for_each_available_child_of_node(np_config, np) {
+		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
+						     &reserved_maps, num_maps);
+		if (ret < 0)
+			goto err;
+	}
+	return 0;
+
+err:
+	pinctrl_utils_free_map(pctldev, *map, *num_maps);
+	return ret;
+}
+
+
+static const struct pinctrl_ops k210_pinctrl_ops = {
+	.get_groups_count = k210_pinctrl_get_groups_count,
+	.get_group_name = k210_pinctrl_get_group_name,
+	.get_group_pins = k210_pinctrl_get_group_pins,
+	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
+	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static struct pinctrl_desc k210_pinctrl_desc = {
+	.name = "k210-pinctrl",
+	.pins = k210_pins,
+	.npins = K210_NPINS,
+	.pctlops = &k210_pinctrl_ops,
+	.pmxops = &k210_pinmux_ops,
+	.confops = &k210_pinconf_ops,
+	.custom_params = k210_pinconf_custom_params,
+	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
+};
+
+static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
+{
+	struct k210_fpioa *fpioa = pdata->fpioa;
+	u32 val;
+	int i, j;
+
+	dev_dbg(pdata->dev, "Init pin ties\n");
+
+	/* Init pin functions input ties */
+	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
+		val = 0;
+		for (j = 0; j < 32; j++) {
+			if (k210_pcf_infos[i * 32 + j].mode_id ==
+			    K210_PC_DEFAULT_IN_TIE) {
+				dev_dbg(pdata->dev,
+					"tie_en function %d (%s)\n",
+					i * 32 + j,
+					k210_pcf_infos[i * 32 + j].name);
+				val |= BIT(j);
+			}
+		}
+
+		/* Set value before enable */
+		writel(val, &fpioa->tie_val[i]);
+		writel(val, &fpioa->tie_en[i]);
+	}
+}
+
+static int k210_fpioa_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct k210_fpioa_data *pdata;
+	int ret;
+
+	dev_info(dev, "K210 FPIOA pin controller\n");
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = dev;
+	platform_set_drvdata(pdev, pdata);
+
+	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pdata->fpioa))
+		return PTR_ERR(pdata->fpioa);
+
+	pdata->clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(pdata->clk))
+		return PTR_ERR(pdata->clk);
+
+	ret = clk_prepare_enable(pdata->clk);
+	if (ret)
+		return ret;
+
+	pdata->pclk = devm_clk_get_optional(dev, "pclk");
+	if (!IS_ERR(pdata->pclk))
+		clk_prepare_enable(pdata->pclk);
+
+	pdata->sysctl_map =
+		syscon_regmap_lookup_by_phandle(np, "kendryte,sysctl");
+	if (IS_ERR(pdata->sysctl_map))
+		return PTR_ERR(pdata->sysctl_map);
+
+	ret = of_property_read_u32(np, "kendryte,power-offset",
+				   &pdata->power_offset);
+	if (ret)
+		return -EINVAL;
+
+	k210_fpioa_init_ties(pdata);
+
+	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
+	if (IS_ERR(pdata->pctl))
+		return PTR_ERR(pdata->pctl);
+
+	return 0;
+}
+
+static const struct of_device_id k210_fpioa_dt_ids[] = {
+	{ .compatible = "kendryte,k210-fpioa" },
+};
+
+static struct platform_driver k210_fpioa_driver = {
+	.probe	= k210_fpioa_probe,
+	.driver = {
+		.name		= "k210-fpioa",
+		.of_match_table	= k210_fpioa_dt_ids,
+	},
+};
+
+/*
+ * Most devices on the K210 SoC depend on pin mapping changes to initialize
+ * correctly. So initialize this driver early as part of the post core
+ * initialization.
+ */
+static int __init k210_fpioa_init(void)
+{
+	return platform_driver_register(&k210_fpioa_driver);
+}
+postcore_initcall(k210_fpioa_init);
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
(fully programmable IO array) to allow configuring the SoC pin
functions. The K210 has 48 programmable pins which can take any of 256
possible functions.

This patch is inspired from the k210 pinctrl driver for the u-boot
project and contains many direct contributions from Sean Anderson.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs        |   2 +
 drivers/pinctrl/Kconfig        |  15 +
 drivers/pinctrl/Makefile       |   1 +
 drivers/pinctrl/pinctrl-k210.c | 999 +++++++++++++++++++++++++++++++++
 4 files changed, 1017 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-k210.c

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 4d8e66d0556a..56ba82a64e18 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -34,6 +34,8 @@ config SOC_KENDRYTE
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
 	select RESET_K210
+	select PINCTRL
+	select PINCTRL_K210
 	help
 	  This enables support for Kendryte K210 SoC platform hardware.
 
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 815095326e2d..a5073afb8bfe 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -374,6 +374,21 @@ config PINCTRL_OCELOT
 	select OF_GPIO
 	select REGMAP_MMIO
 
+config PINCTRL_K210
+	bool "Pinctrl driver for the Kendryte K210 SoC"
+	depends on RISCV && SOC_KENDRYTE
+	depends on OF && HAS_IOMEM
+	select PINMUX
+	select GENERIC_PINCONF
+	select GPIOLIB
+	select OF_GPIO
+	select REGMAP_MMIO
+	help
+	  Add support for the Kendryte K210 RISC-V SOC Field Programmable
+	  IO Array (FPIOA) controller. Support for this controller is
+	  automatically selected when the SOC_KENDRYTE option is selected
+	  in the "SOC selection" menu.
+
 source "drivers/pinctrl/actions/Kconfig"
 source "drivers/pinctrl/aspeed/Kconfig"
 source "drivers/pinctrl/bcm/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index f53933b2ff02..d6f913adb04a 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -47,6 +47,7 @@ obj-$(CONFIG_PINCTRL_INGENIC)	+= pinctrl-ingenic.o
 obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_OCELOT)	+= pinctrl-ocelot.o
 obj-$(CONFIG_PINCTRL_EQUILIBRIUM)   += pinctrl-equilibrium.o
+obj-$(CONFIG_PINCTRL_K210)	+= pinctrl-k210.o
 
 obj-y				+= actions/
 obj-$(CONFIG_ARCH_ASPEED)	+= aspeed/
diff --git a/drivers/pinctrl/pinctrl-k210.c b/drivers/pinctrl/pinctrl-k210.c
new file mode 100644
index 000000000000..48741023fcf7
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-k210.c
@@ -0,0 +1,999 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
+ * Copyright (c) 2020 Western Digital Corporation or its affiliates.
+ */
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/bitfield.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/io.h>
+
+#include <dt-bindings/pinctrl/k210-pinctrl.h>
+
+#include "core.h"
+#include "pinconf.h"
+#include "pinctrl-utils.h"
+
+/*
+ * The K210 only implements 8 drive levels, even though
+ * there is register space for 16
+ */
+#define K210_PC_DRIVE_MASK	GENMASK(11, 8)
+#define K210_PC_DRIVE_SHIFT	8
+#define K210_PC_DRIVE_0		(0 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_1		(1 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_2		(2 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_3		(3 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_4		(4 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_5		(5 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_6		(6 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_7		(7 << K210_PC_DRIVE_SHIFT)
+#define K210_PC_DRIVE_MAX	7
+#define K210_PC_MODE_MASK	GENMASK(23, 12)
+
+/*
+ * output enabled == PC_OE & (PC_OE_INV ^ FUNCTION_OE)
+ * where FUNCTION_OE is a physical signal from the function.
+ */
+#define K210_PC_OE		BIT(12) /* Output Enable */
+#define K210_PC_OE_INV		BIT(13) /* INVert Output Enable */
+#define K210_PC_DO_OE		BIT(14) /* set Data Out to Output Enable sig */
+#define K210_PC_DO_INV		BIT(15) /* INVert final Data Output */
+#define K210_PC_PU		BIT(16) /* Pull Up */
+#define K210_PC_PD		BIT(17) /* Pull Down */
+/* Strong pull up not implemented on K210 */
+#define K210_PC_SL		BIT(19) /* reduce SLew rate */
+/* Same semantics as OE above */
+#define K210_PC_IE		BIT(20) /* Input Enable */
+#define K210_PC_IE_INV		BIT(21) /* INVert Input Enable */
+#define K210_PC_DI_INV		BIT(22) /* INVert Data Input */
+#define K210_PC_ST		BIT(23) /* Schmitt Trigger */
+#define K210_PC_DI		BIT(31) /* raw Data Input */
+
+#define K210_PC_BIAS_MASK	(K210_PC_PU & K210_PC_PD)
+
+#define K210_PC_MODE_IN		(K210_PC_IE | K210_PC_ST)
+#define K210_PC_MODE_OUT	(K210_PC_DRIVE_7 | K210_PC_OE)
+#define K210_PC_MODE_I2C	(K210_PC_MODE_IN | K210_PC_SL | \
+				 K210_PC_OE | K210_PC_PU)
+#define K210_PC_MODE_SCCB	(K210_PC_MODE_I2C | \
+				 K210_PC_OE_INV | K210_PC_IE_INV)
+#define K210_PC_MODE_SPI	(K210_PC_MODE_IN | K210_PC_IE_INV | \
+				 K210_PC_MODE_OUT | K210_PC_OE_INV)
+#define K210_PC_MODE_GPIO	(K210_PC_MODE_IN | K210_PC_MODE_OUT)
+
+#define K210_PG_FUNC		GENMASK(7, 0)
+#define K210_PG_DO		BIT(8)
+#define K210_PG_PIN		GENMASK(22, 16)
+
+/*
+ * struct k210_fpioa: Kendryte K210 FPIOA memory mapped registers
+ * @pins: 48 32-bits IO pin registers
+ * @tie_en: 256 (one per function) input tie enable bits
+ * @tie_val: 256 (one per function) input tie value bits
+ */
+struct k210_fpioa {
+	u32 pins[48];
+	u32 tie_en[8];
+	u32 tie_val[8];
+};
+
+struct k210_fpioa_data {
+
+	struct device *dev;
+	struct pinctrl_dev *pctl;
+
+	struct k210_fpioa __iomem *fpioa;
+	struct regmap *sysctl_map;
+	u32 power_offset;
+	struct clk *clk;
+	struct clk *pclk;
+};
+
+#define K210_PIN(i)	[i] = PINCTRL_PIN(i, "IO_" #i)
+
+static const struct pinctrl_pin_desc k210_pins[] = {
+	K210_PIN(0),  K210_PIN(1),  K210_PIN(2),
+	K210_PIN(3),  K210_PIN(4),  K210_PIN(5),
+	K210_PIN(6),  K210_PIN(7),  K210_PIN(8),
+	K210_PIN(9),  K210_PIN(10), K210_PIN(11),
+	K210_PIN(12), K210_PIN(13), K210_PIN(14),
+	K210_PIN(15), K210_PIN(16), K210_PIN(17),
+	K210_PIN(18), K210_PIN(19), K210_PIN(20),
+	K210_PIN(21), K210_PIN(22), K210_PIN(23),
+	K210_PIN(24), K210_PIN(25), K210_PIN(26),
+	K210_PIN(27), K210_PIN(28), K210_PIN(29),
+	K210_PIN(30), K210_PIN(31), K210_PIN(32),
+	K210_PIN(33), K210_PIN(34), K210_PIN(35),
+	K210_PIN(36), K210_PIN(37), K210_PIN(38),
+	K210_PIN(39), K210_PIN(40), K210_PIN(41),
+	K210_PIN(42), K210_PIN(43), K210_PIN(44),
+	K210_PIN(45), K210_PIN(46), K210_PIN(47)
+};
+
+#define K210_NPINS ARRAY_SIZE(k210_pins)
+
+/*
+ * Pin groups: each of the 48 programmable pins is a group.
+ * To this are added 8 power domain groups, which for the purposes of
+ * the pin subsystem, contain no pins. The power domain groups only exist
+ * to set the power level. The id should never be used (since there are
+ * no pins 48-55).
+ */
+#define K210_PIN_NAME(i)	[i] = k210_pins[i].name
+static const char *const k210_group_names[] = {
+	/* The first 48 groups are for pins, one each */
+	K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
+	K210_PIN_NAME(3),  K210_PIN_NAME(4),  K210_PIN_NAME(5),
+	K210_PIN_NAME(6),  K210_PIN_NAME(7),  K210_PIN_NAME(8),
+	K210_PIN_NAME(9),  K210_PIN_NAME(10), K210_PIN_NAME(11),
+	K210_PIN_NAME(12), K210_PIN_NAME(13), K210_PIN_NAME(14),
+	K210_PIN_NAME(15), K210_PIN_NAME(16), K210_PIN_NAME(17),
+	K210_PIN_NAME(18), K210_PIN_NAME(19), K210_PIN_NAME(20),
+	K210_PIN_NAME(21), K210_PIN_NAME(22), K210_PIN_NAME(23),
+	K210_PIN_NAME(24), K210_PIN_NAME(25), K210_PIN_NAME(26),
+	K210_PIN_NAME(27), K210_PIN_NAME(28), K210_PIN_NAME(29),
+	K210_PIN_NAME(30), K210_PIN_NAME(31), K210_PIN_NAME(32),
+	K210_PIN_NAME(33), K210_PIN_NAME(34), K210_PIN_NAME(35),
+	K210_PIN_NAME(36), K210_PIN_NAME(37), K210_PIN_NAME(38),
+	K210_PIN_NAME(39), K210_PIN_NAME(40), K210_PIN_NAME(41),
+	K210_PIN_NAME(42), K210_PIN_NAME(43), K210_PIN_NAME(44),
+	K210_PIN_NAME(45), K210_PIN_NAME(46), K210_PIN_NAME(47),
+	[48] = "A0", [49] = "A1", [50] = "A2",
+	[51] = "B3", [52] = "B4", [53] = "B5",
+	[54] = "C6", [55] = "C7"
+};
+
+#define K210_NGROUPS	ARRAY_SIZE(k210_group_names)
+
+enum k210_pinctrl_mode_id {
+	K210_PC_DEFAULT_DISABLED,
+	K210_PC_DEFAULT_IN,
+	K210_PC_DEFAULT_IN_TIE,
+	K210_PC_DEFAULT_OUT,
+	K210_PC_DEFAULT_I2C,
+	K210_PC_DEFAULT_SCCB,
+	K210_PC_DEFAULT_SPI,
+	K210_PC_DEFAULT_GPIO,
+	K210_PC_DEFAULT_INT13,
+};
+
+#define K210_PC_DEFAULT(mode) \
+	[K210_PC_DEFAULT_##mode] = K210_PC_MODE_##mode
+
+static const u32 k210_pinconf_mode_id_to_mode[] = {
+	[K210_PC_DEFAULT_DISABLED] = 0,
+	K210_PC_DEFAULT(IN),
+	[K210_PC_DEFAULT_IN_TIE] = K210_PC_MODE_IN,
+	K210_PC_DEFAULT(OUT),
+	K210_PC_DEFAULT(I2C),
+	K210_PC_DEFAULT(SCCB),
+	K210_PC_DEFAULT(SPI),
+	K210_PC_DEFAULT(GPIO),
+	[K210_PC_DEFAULT_INT13] = K210_PC_MODE_IN | K210_PC_PU,
+};
+
+#undef DEFAULT
+
+/*
+ * Pin functions configuration information.
+ */
+struct k210_pcf_info {
+	char name[15];
+	u8 mode_id;
+};
+
+#define K210_FUNC(id, mode)				\
+	[K210_PCF_##id] = {				\
+		.name = #id,				\
+		.mode_id = K210_PC_DEFAULT_##mode	\
+	}
+
+static const struct k210_pcf_info k210_pcf_infos[] = {
+	K210_FUNC(JTAG_TCLK,		IN),
+	K210_FUNC(JTAG_TDI,		IN),
+	K210_FUNC(JTAG_TMS,		IN),
+	K210_FUNC(JTAG_TDO,		OUT),
+	K210_FUNC(SPI0_D0,		SPI),
+	K210_FUNC(SPI0_D1,		SPI),
+	K210_FUNC(SPI0_D2,		SPI),
+	K210_FUNC(SPI0_D3,		SPI),
+	K210_FUNC(SPI0_D4,		SPI),
+	K210_FUNC(SPI0_D5,		SPI),
+	K210_FUNC(SPI0_D6,		SPI),
+	K210_FUNC(SPI0_D7,		SPI),
+	K210_FUNC(SPI0_SS0,		OUT),
+	K210_FUNC(SPI0_SS1,		OUT),
+	K210_FUNC(SPI0_SS2,		OUT),
+	K210_FUNC(SPI0_SS3,		OUT),
+	K210_FUNC(SPI0_ARB,		IN_TIE),
+	K210_FUNC(SPI0_SCLK,		OUT),
+	K210_FUNC(UARTHS_RX,		IN),
+	K210_FUNC(UARTHS_TX,		OUT),
+	K210_FUNC(RESV6,		IN),
+	K210_FUNC(RESV7,		IN),
+	K210_FUNC(CLK_SPI1,		OUT),
+	K210_FUNC(CLK_I2C1,		OUT),
+	K210_FUNC(GPIOHS0,		GPIO),
+	K210_FUNC(GPIOHS1,		GPIO),
+	K210_FUNC(GPIOHS2,		GPIO),
+	K210_FUNC(GPIOHS3,		GPIO),
+	K210_FUNC(GPIOHS4,		GPIO),
+	K210_FUNC(GPIOHS5,		GPIO),
+	K210_FUNC(GPIOHS6,		GPIO),
+	K210_FUNC(GPIOHS7,		GPIO),
+	K210_FUNC(GPIOHS8,		GPIO),
+	K210_FUNC(GPIOHS9,		GPIO),
+	K210_FUNC(GPIOHS10,		GPIO),
+	K210_FUNC(GPIOHS11,		GPIO),
+	K210_FUNC(GPIOHS12,		GPIO),
+	K210_FUNC(GPIOHS13,		GPIO),
+	K210_FUNC(GPIOHS14,		GPIO),
+	K210_FUNC(GPIOHS15,		GPIO),
+	K210_FUNC(GPIOHS16,		GPIO),
+	K210_FUNC(GPIOHS17,		GPIO),
+	K210_FUNC(GPIOHS18,		GPIO),
+	K210_FUNC(GPIOHS19,		GPIO),
+	K210_FUNC(GPIOHS20,		GPIO),
+	K210_FUNC(GPIOHS21,		GPIO),
+	K210_FUNC(GPIOHS22,		GPIO),
+	K210_FUNC(GPIOHS23,		GPIO),
+	K210_FUNC(GPIOHS24,		GPIO),
+	K210_FUNC(GPIOHS25,		GPIO),
+	K210_FUNC(GPIOHS26,		GPIO),
+	K210_FUNC(GPIOHS27,		GPIO),
+	K210_FUNC(GPIOHS28,		GPIO),
+	K210_FUNC(GPIOHS29,		GPIO),
+	K210_FUNC(GPIOHS30,		GPIO),
+	K210_FUNC(GPIOHS31,		GPIO),
+	K210_FUNC(GPIO0,		GPIO),
+	K210_FUNC(GPIO1,		GPIO),
+	K210_FUNC(GPIO2,		GPIO),
+	K210_FUNC(GPIO3,		GPIO),
+	K210_FUNC(GPIO4,		GPIO),
+	K210_FUNC(GPIO5,		GPIO),
+	K210_FUNC(GPIO6,		GPIO),
+	K210_FUNC(GPIO7,		GPIO),
+	K210_FUNC(UART1_RX,		IN),
+	K210_FUNC(UART1_TX,		OUT),
+	K210_FUNC(UART2_RX,		IN),
+	K210_FUNC(UART2_TX,		OUT),
+	K210_FUNC(UART3_RX,		IN),
+	K210_FUNC(UART3_TX,		OUT),
+	K210_FUNC(SPI1_D0,		SPI),
+	K210_FUNC(SPI1_D1,		SPI),
+	K210_FUNC(SPI1_D2,		SPI),
+	K210_FUNC(SPI1_D3,		SPI),
+	K210_FUNC(SPI1_D4,		SPI),
+	K210_FUNC(SPI1_D5,		SPI),
+	K210_FUNC(SPI1_D6,		SPI),
+	K210_FUNC(SPI1_D7,		SPI),
+	K210_FUNC(SPI1_SS0,		OUT),
+	K210_FUNC(SPI1_SS1,		OUT),
+	K210_FUNC(SPI1_SS2,		OUT),
+	K210_FUNC(SPI1_SS3,		OUT),
+	K210_FUNC(SPI1_ARB,		IN_TIE),
+	K210_FUNC(SPI1_SCLK,		OUT),
+	K210_FUNC(SPI2_D0,		SPI),
+	K210_FUNC(SPI2_SS,		IN),
+	K210_FUNC(SPI2_SCLK,		IN),
+	K210_FUNC(I2S0_MCLK,		OUT),
+	K210_FUNC(I2S0_SCLK,		OUT),
+	K210_FUNC(I2S0_WS,		OUT),
+	K210_FUNC(I2S0_IN_D0,		IN),
+	K210_FUNC(I2S0_IN_D1,		IN),
+	K210_FUNC(I2S0_IN_D2,		IN),
+	K210_FUNC(I2S0_IN_D3,		IN),
+	K210_FUNC(I2S0_OUT_D0,		OUT),
+	K210_FUNC(I2S0_OUT_D1,		OUT),
+	K210_FUNC(I2S0_OUT_D2,		OUT),
+	K210_FUNC(I2S0_OUT_D3,		OUT),
+	K210_FUNC(I2S1_MCLK,		OUT),
+	K210_FUNC(I2S1_SCLK,		OUT),
+	K210_FUNC(I2S1_WS,		OUT),
+	K210_FUNC(I2S1_IN_D0,		IN),
+	K210_FUNC(I2S1_IN_D1,		IN),
+	K210_FUNC(I2S1_IN_D2,		IN),
+	K210_FUNC(I2S1_IN_D3,		IN),
+	K210_FUNC(I2S1_OUT_D0,		OUT),
+	K210_FUNC(I2S1_OUT_D1,		OUT),
+	K210_FUNC(I2S1_OUT_D2,		OUT),
+	K210_FUNC(I2S1_OUT_D3,		OUT),
+	K210_FUNC(I2S2_MCLK,		OUT),
+	K210_FUNC(I2S2_SCLK,		OUT),
+	K210_FUNC(I2S2_WS,		OUT),
+	K210_FUNC(I2S2_IN_D0,		IN),
+	K210_FUNC(I2S2_IN_D1,		IN),
+	K210_FUNC(I2S2_IN_D2,		IN),
+	K210_FUNC(I2S2_IN_D3,		IN),
+	K210_FUNC(I2S2_OUT_D0,		OUT),
+	K210_FUNC(I2S2_OUT_D1,		OUT),
+	K210_FUNC(I2S2_OUT_D2,		OUT),
+	K210_FUNC(I2S2_OUT_D3,		OUT),
+	K210_FUNC(RESV0,		DISABLED),
+	K210_FUNC(RESV1,		DISABLED),
+	K210_FUNC(RESV2,		DISABLED),
+	K210_FUNC(RESV3,		DISABLED),
+	K210_FUNC(RESV4,		DISABLED),
+	K210_FUNC(RESV5,		DISABLED),
+	K210_FUNC(I2C0_SCLK,		I2C),
+	K210_FUNC(I2C0_SDA,		I2C),
+	K210_FUNC(I2C1_SCLK,		I2C),
+	K210_FUNC(I2C1_SDA,		I2C),
+	K210_FUNC(I2C2_SCLK,		I2C),
+	K210_FUNC(I2C2_SDA,		I2C),
+	K210_FUNC(DVP_XCLK,		OUT),
+	K210_FUNC(DVP_RST,		OUT),
+	K210_FUNC(DVP_PWDN,		OUT),
+	K210_FUNC(DVP_VSYNC,		IN),
+	K210_FUNC(DVP_HSYNC,		IN),
+	K210_FUNC(DVP_PCLK,		IN),
+	K210_FUNC(DVP_D0,		IN),
+	K210_FUNC(DVP_D1,		IN),
+	K210_FUNC(DVP_D2,		IN),
+	K210_FUNC(DVP_D3,		IN),
+	K210_FUNC(DVP_D4,		IN),
+	K210_FUNC(DVP_D5,		IN),
+	K210_FUNC(DVP_D6,		IN),
+	K210_FUNC(DVP_D7,		IN),
+	K210_FUNC(SCCB_SCLK,		SCCB),
+	K210_FUNC(SCCB_SDA,		SCCB),
+	K210_FUNC(UART1_CTS,		IN),
+	K210_FUNC(UART1_DSR,		IN),
+	K210_FUNC(UART1_DCD,		IN),
+	K210_FUNC(UART1_RI,		IN),
+	K210_FUNC(UART1_SIR_IN,		IN),
+	K210_FUNC(UART1_DTR,		OUT),
+	K210_FUNC(UART1_RTS,		OUT),
+	K210_FUNC(UART1_OUT2,		OUT),
+	K210_FUNC(UART1_OUT1,		OUT),
+	K210_FUNC(UART1_SIR_OUT,	OUT),
+	K210_FUNC(UART1_BAUD,		OUT),
+	K210_FUNC(UART1_RE,		OUT),
+	K210_FUNC(UART1_DE,		OUT),
+	K210_FUNC(UART1_RS485_EN,	OUT),
+	K210_FUNC(UART2_CTS,		IN),
+	K210_FUNC(UART2_DSR,		IN),
+	K210_FUNC(UART2_DCD,		IN),
+	K210_FUNC(UART2_RI,		IN),
+	K210_FUNC(UART2_SIR_IN,		IN),
+	K210_FUNC(UART2_DTR,		OUT),
+	K210_FUNC(UART2_RTS,		OUT),
+	K210_FUNC(UART2_OUT2,		OUT),
+	K210_FUNC(UART2_OUT1,		OUT),
+	K210_FUNC(UART2_SIR_OUT,	OUT),
+	K210_FUNC(UART2_BAUD,		OUT),
+	K210_FUNC(UART2_RE,		OUT),
+	K210_FUNC(UART2_DE,		OUT),
+	K210_FUNC(UART2_RS485_EN,	OUT),
+	K210_FUNC(UART3_CTS,		IN),
+	K210_FUNC(UART3_DSR,		IN),
+	K210_FUNC(UART3_DCD,		IN),
+	K210_FUNC(UART3_RI,		IN),
+	K210_FUNC(UART3_SIR_IN,		IN),
+	K210_FUNC(UART3_DTR,		OUT),
+	K210_FUNC(UART3_RTS,		OUT),
+	K210_FUNC(UART3_OUT2,		OUT),
+	K210_FUNC(UART3_OUT1,		OUT),
+	K210_FUNC(UART3_SIR_OUT,	OUT),
+	K210_FUNC(UART3_BAUD,		OUT),
+	K210_FUNC(UART3_RE,		OUT),
+	K210_FUNC(UART3_DE,		OUT),
+	K210_FUNC(UART3_RS485_EN,	OUT),
+	K210_FUNC(TIMER0_TOGGLE1,	OUT),
+	K210_FUNC(TIMER0_TOGGLE2,	OUT),
+	K210_FUNC(TIMER0_TOGGLE3,	OUT),
+	K210_FUNC(TIMER0_TOGGLE4,	OUT),
+	K210_FUNC(TIMER1_TOGGLE1,	OUT),
+	K210_FUNC(TIMER1_TOGGLE2,	OUT),
+	K210_FUNC(TIMER1_TOGGLE3,	OUT),
+	K210_FUNC(TIMER1_TOGGLE4,	OUT),
+	K210_FUNC(TIMER2_TOGGLE1,	OUT),
+	K210_FUNC(TIMER2_TOGGLE2,	OUT),
+	K210_FUNC(TIMER2_TOGGLE3,	OUT),
+	K210_FUNC(TIMER2_TOGGLE4,	OUT),
+	K210_FUNC(CLK_SPI2,		OUT),
+	K210_FUNC(CLK_I2C2,		OUT),
+	K210_FUNC(INTERNAL0,		OUT),
+	K210_FUNC(INTERNAL1,		OUT),
+	K210_FUNC(INTERNAL2,		OUT),
+	K210_FUNC(INTERNAL3,		OUT),
+	K210_FUNC(INTERNAL4,		OUT),
+	K210_FUNC(INTERNAL5,		OUT),
+	K210_FUNC(INTERNAL6,		OUT),
+	K210_FUNC(INTERNAL7,		OUT),
+	K210_FUNC(INTERNAL8,		OUT),
+	K210_FUNC(INTERNAL9,		IN),
+	K210_FUNC(INTERNAL10,		IN),
+	K210_FUNC(INTERNAL11,		IN),
+	K210_FUNC(INTERNAL12,		IN),
+	K210_FUNC(INTERNAL13,		INT13),
+	K210_FUNC(INTERNAL14,		I2C),
+	K210_FUNC(INTERNAL15,		IN),
+	K210_FUNC(INTERNAL16,		IN),
+	K210_FUNC(INTERNAL17,		IN),
+	K210_FUNC(CONSTANT,		DISABLED),
+	K210_FUNC(INTERNAL18,		IN),
+	K210_FUNC(DEBUG0,		OUT),
+	K210_FUNC(DEBUG1,		OUT),
+	K210_FUNC(DEBUG2,		OUT),
+	K210_FUNC(DEBUG3,		OUT),
+	K210_FUNC(DEBUG4,		OUT),
+	K210_FUNC(DEBUG5,		OUT),
+	K210_FUNC(DEBUG6,		OUT),
+	K210_FUNC(DEBUG7,		OUT),
+	K210_FUNC(DEBUG8,		OUT),
+	K210_FUNC(DEBUG9,		OUT),
+	K210_FUNC(DEBUG10,		OUT),
+	K210_FUNC(DEBUG11,		OUT),
+	K210_FUNC(DEBUG12,		OUT),
+	K210_FUNC(DEBUG13,		OUT),
+	K210_FUNC(DEBUG14,		OUT),
+	K210_FUNC(DEBUG15,		OUT),
+	K210_FUNC(DEBUG16,		OUT),
+	K210_FUNC(DEBUG17,		OUT),
+	K210_FUNC(DEBUG18,		OUT),
+	K210_FUNC(DEBUG19,		OUT),
+	K210_FUNC(DEBUG20,		OUT),
+	K210_FUNC(DEBUG21,		OUT),
+	K210_FUNC(DEBUG22,		OUT),
+	K210_FUNC(DEBUG23,		OUT),
+	K210_FUNC(DEBUG24,		OUT),
+	K210_FUNC(DEBUG25,		OUT),
+	K210_FUNC(DEBUG26,		OUT),
+	K210_FUNC(DEBUG27,		OUT),
+	K210_FUNC(DEBUG28,		OUT),
+	K210_FUNC(DEBUG29,		OUT),
+	K210_FUNC(DEBUG30,		OUT),
+	K210_FUNC(DEBUG31,		OUT),
+};
+
+#define PIN_CONFIG_OUTPUT_INVERT	(PIN_CONFIG_END + 1)
+#define PIN_CONFIG_INPUT_INVERT		(PIN_CONFIG_END + 2)
+
+static const struct pinconf_generic_params k210_pinconf_custom_params[] = {
+	{ "output-polarity-invert", PIN_CONFIG_OUTPUT_INVERT, 1 },
+	{ "input-polarity-invert",  PIN_CONFIG_INPUT_INVERT, 1 },
+};
+
+/*
+ * Max drive strength in uA.
+ */
+static const int k210_pinconf_drive_strength[] = {
+	[0] = 11200,
+	[1] = 16800,
+	[2] = 22300,
+	[3] = 27800,
+	[4] = 33300,
+	[5] = 38700,
+	[6] = 44100,
+	[7] = 49500,
+};
+
+static int k210_pinconf_get_drive(unsigned int max_strength_ua)
+{
+	int i;
+
+	for (i = K210_PC_DRIVE_MAX; i; i--) {
+		if (k210_pinconf_drive_strength[i] <= max_strength_ua)
+			return i;
+	}
+
+	return -EINVAL;
+}
+
+static void k210_pinmux_set_pin_function(struct pinctrl_dev *pctldev,
+					 u32 pin, u32 func)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	const struct k210_pcf_info *info = &k210_pcf_infos[func];
+	u32 mode = k210_pinconf_mode_id_to_mode[info->mode_id];
+	u32 val = func | mode;
+
+	dev_dbg(pdata->dev, "set pin %u function %s (%u) -> 0x%08x\n",
+		pin, info->name, func, val);
+
+	writel(val, &pdata->fpioa->pins[pin]);
+}
+
+static int k210_pinconf_set_param(struct pinctrl_dev *pctldev,
+				  unsigned int pin,
+				  unsigned int param, unsigned int arg)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	u32 val = readl(&pdata->fpioa->pins[pin]);
+	int drive;
+
+	dev_dbg(pdata->dev, "set pin %u param %u, arg 0x%x\n",
+		pin, param, arg);
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+		val &= ~K210_PC_BIAS_MASK;
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_BIAS_PULL_UP:
+		if (!arg)
+			return -EINVAL;
+		val |= K210_PC_PD;
+		break;
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		arg *= 1000;
+		fallthrough;
+	case PIN_CONFIG_DRIVE_STRENGTH_UA:
+		drive = k210_pinconf_get_drive(arg);
+		if (drive < 0)
+			return drive;
+		val &= ~K210_PC_DRIVE_MASK;
+		val |= FIELD_PREP(K210_PC_DRIVE_MASK, drive);
+		break;
+	case PIN_CONFIG_INPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_IE;
+		else
+			val &= ~K210_PC_IE;
+		break;
+	case PIN_CONFIG_INPUT_SCHMITT:
+		arg = 1;
+		fallthrough;
+	case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+		if (arg)
+			val |= K210_PC_ST;
+		else
+			val &= ~K210_PC_ST;
+		break;
+	case PIN_CONFIG_OUTPUT:
+		k210_pinmux_set_pin_function(pctldev, pin, K210_PCF_CONSTANT);
+		val = readl(&pdata->fpioa->pins[pin]);
+		val |= K210_PC_MODE_OUT;
+		if (!arg)
+			val |= K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_OUTPUT_ENABLE:
+		if (arg)
+			val |= K210_PC_OE;
+		else
+			val &= ~K210_PC_OE;
+		break;
+	case PIN_CONFIG_SLEW_RATE:
+		if (arg)
+			val |= K210_PC_SL;
+		else
+			val &= ~K210_PC_SL;
+		break;
+	case PIN_CONFIG_OUTPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DO_INV;
+		else
+			val &= ~K210_PC_DO_INV;
+		break;
+	case PIN_CONFIG_INPUT_INVERT:
+		if (arg)
+			val |= K210_PC_DI_INV;
+		else
+			val &= ~K210_PC_DI_INV;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(val, &pdata->fpioa->pins[pin]);
+
+	return 0;
+}
+
+static int k210_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
+			    unsigned long *configs, unsigned int num_configs)
+{
+	unsigned int param, arg;
+	int i, ret;
+
+	if (WARN_ON(pin >= K210_NPINS))
+		return -EINVAL;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+		ret = k210_pinconf_set_param(pctldev, pin, param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+				  struct seq_file *s, unsigned int pin)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+
+	seq_printf(s, "%#x", readl(&pdata->fpioa->pins[pin]));
+}
+
+static int k210_pinconf_group_set(struct pinctrl_dev *pctldev,
+				  unsigned int selector, unsigned long *configs,
+				  unsigned int num_configs)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int param, arg;
+	u32 bit;
+	int i;
+
+	/* Pins should be configured with pinmux, not groups*/
+	if (selector < K210_NPINS)
+		return -EINVAL;
+
+	/* Otherwise it's a power domain */
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		if (param != PIN_CONFIG_POWER_SOURCE)
+			return -EINVAL;
+
+		arg = pinconf_to_config_argument(configs[i]);
+		bit = BIT(selector - K210_NPINS);
+		regmap_update_bits(pdata->sysctl_map,
+				   pdata->power_offset,
+				   bit, arg ? bit : 0);
+	}
+
+	return 0;
+}
+
+static void k210_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s,
+					unsigned int selector)
+{
+	struct k210_fpioa_data *pdata = pinctrl_dev_get_drvdata(pctldev);
+	int ret;
+	u32 val;
+
+	if (selector < K210_NPINS)
+		return k210_pinconf_dbg_show(pctldev, s, selector);
+
+	ret = regmap_read(pdata->sysctl_map, pdata->power_offset, &val);
+	if (ret) {
+		dev_err(pdata->dev, "Failed to read power reg\n");
+		return;
+	}
+
+	seq_printf(s, "%s: %s V", k210_group_names[selector],
+		   val & BIT(selector - K210_NPINS) ? "1.8" : "3.3");
+}
+
+static const struct pinconf_ops k210_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_set = k210_pinconf_set,
+	.pin_config_group_set = k210_pinconf_group_set,
+	.pin_config_dbg_show = k210_pinconf_dbg_show,
+	.pin_config_group_dbg_show = k210_pinconf_group_dbg_show,
+};
+
+static int k210_pinmux_get_function_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(k210_pcf_infos);
+}
+
+static const char *k210_pinmux_get_function_name(struct pinctrl_dev *pctldev,
+						 unsigned int selector)
+{
+	return k210_pcf_infos[selector].name;
+}
+
+static int k210_pinmux_get_function_groups(struct pinctrl_dev *pctldev,
+					   unsigned int selector,
+					   const char * const **groups,
+					   unsigned int * const num_groups)
+{
+	/* Any function can be mapped to any pin */
+	*groups = k210_group_names;
+	*num_groups = K210_NPINS;
+
+	return 0;
+}
+
+static int k210_pinmux_set_mux(struct pinctrl_dev *pctldev,
+			       unsigned int function,
+			       unsigned int group)
+{
+	/* Can't mux power domains */
+	if (group >= K210_NPINS)
+		return -EINVAL;
+
+	k210_pinmux_set_pin_function(pctldev, group, function);
+
+	return 0;
+}
+
+static const struct pinmux_ops k210_pinmux_ops = {
+	.get_functions_count = k210_pinmux_get_function_count,
+	.get_function_name = k210_pinmux_get_function_name,
+	.get_function_groups = k210_pinmux_get_function_groups,
+	.set_mux = k210_pinmux_set_mux,
+	.strict = true,
+};
+
+static int k210_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return K210_NGROUPS;
+}
+
+static const char *k210_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
+					       unsigned int group)
+{
+	return k210_group_names[group];
+}
+
+static int k210_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
+				       unsigned int group,
+				       const unsigned int **pins,
+				       unsigned int *npins)
+{
+	if (group >= K210_NPINS) {
+		*pins = NULL;
+		*npins = 0;
+		return 0;
+	}
+
+	*pins = &k210_pins[group].number;
+	*npins = 1;
+
+	return 0;
+}
+
+static void k210_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
+				      struct seq_file *s, unsigned int offset)
+{
+	seq_printf(s, "%s", dev_name(pctldev->dev));
+}
+
+static int k210_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
+					  struct device_node *np,
+					  struct pinctrl_map **map,
+					  unsigned int *reserved_maps,
+					  unsigned int *num_maps)
+{
+	struct property *prop;
+	const __be32 *p;
+	int ret, pinmux_groups;
+	u32 pinmux_group;
+	unsigned long *configs = NULL;
+	unsigned int num_configs = 0;
+	unsigned int reserve = 0;
+
+	ret = of_property_count_strings(np, "groups");
+	if (!ret)
+		return pinconf_generic_dt_subnode_to_map(pctldev, np, map,
+						reserved_maps, num_maps,
+						PIN_MAP_TYPE_CONFIGS_GROUP);
+
+	pinmux_groups = of_property_count_u32_elems(np, "pinmux");
+	if (pinmux_groups <= 0) {
+		/* Ignore this node */
+		return 0;
+	}
+
+	ret = pinconf_generic_parse_dt_config(np, pctldev, &configs,
+					      &num_configs);
+	if (ret < 0) {
+		dev_err(pctldev->dev, "%pOF: could not parse node property\n",
+			np);
+		return ret;
+	}
+
+	reserve = pinmux_groups * (1 + num_configs);
+	ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
+					reserve);
+	if (ret < 0)
+		goto exit;
+
+	of_property_for_each_u32(np, "pinmux", prop, p, pinmux_group) {
+		const char *group_name, *func_name;
+		u32 pin = FIELD_GET(K210_PG_PIN, pinmux_group);
+		u32 func = FIELD_GET(K210_PG_FUNC, pinmux_group);
+
+		if (pin >= K210_NPINS) {
+			ret = -EINVAL;
+			goto exit;
+		}
+
+		group_name = k210_group_names[pin];
+		func_name = k210_pcf_infos[func].name;
+
+		dev_dbg(pctldev->dev, "Pinmux %s: pin %u func %s\n",
+			np->name, pin, func_name);
+
+		ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps,
+						num_maps, group_name,
+						func_name);
+		if (ret < 0) {
+			dev_err(pctldev->dev, "%pOF add mux map failed %d\n",
+				np, ret);
+			goto exit;
+		}
+
+		if (num_configs) {
+			ret = pinctrl_utils_add_map_configs(pctldev, map,
+					reserved_maps, num_maps, group_name,
+					configs, num_configs,
+					PIN_MAP_TYPE_CONFIGS_PIN);
+			if (ret < 0) {
+				dev_err(pctldev->dev,
+					"%pOF add configs map failed %d\n",
+					np, ret);
+				goto exit;
+			}
+		}
+	}
+
+	ret = 0;
+
+exit:
+	kfree(configs);
+	return ret;
+}
+
+int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
+			struct device_node *np_config,
+			struct pinctrl_map **map, unsigned int *num_maps)
+{
+	unsigned int reserved_maps;
+	struct device_node *np;
+	int ret;
+
+	reserved_maps = 0;
+	*map = NULL;
+	*num_maps = 0;
+
+	ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
+					     &reserved_maps, num_maps);
+	if (ret < 0)
+		goto err;
+
+	for_each_available_child_of_node(np_config, np) {
+		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
+						     &reserved_maps, num_maps);
+		if (ret < 0)
+			goto err;
+	}
+	return 0;
+
+err:
+	pinctrl_utils_free_map(pctldev, *map, *num_maps);
+	return ret;
+}
+
+
+static const struct pinctrl_ops k210_pinctrl_ops = {
+	.get_groups_count = k210_pinctrl_get_groups_count,
+	.get_group_name = k210_pinctrl_get_group_name,
+	.get_group_pins = k210_pinctrl_get_group_pins,
+	.pin_dbg_show = k210_pinctrl_pin_dbg_show,
+	.dt_node_to_map = k210_pinctrl_dt_node_to_map,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static struct pinctrl_desc k210_pinctrl_desc = {
+	.name = "k210-pinctrl",
+	.pins = k210_pins,
+	.npins = K210_NPINS,
+	.pctlops = &k210_pinctrl_ops,
+	.pmxops = &k210_pinmux_ops,
+	.confops = &k210_pinconf_ops,
+	.custom_params = k210_pinconf_custom_params,
+	.num_custom_params = ARRAY_SIZE(k210_pinconf_custom_params),
+};
+
+static void k210_fpioa_init_ties(struct k210_fpioa_data *pdata)
+{
+	struct k210_fpioa *fpioa = pdata->fpioa;
+	u32 val;
+	int i, j;
+
+	dev_dbg(pdata->dev, "Init pin ties\n");
+
+	/* Init pin functions input ties */
+	for (i = 0; i < ARRAY_SIZE(fpioa->tie_en); i++) {
+		val = 0;
+		for (j = 0; j < 32; j++) {
+			if (k210_pcf_infos[i * 32 + j].mode_id ==
+			    K210_PC_DEFAULT_IN_TIE) {
+				dev_dbg(pdata->dev,
+					"tie_en function %d (%s)\n",
+					i * 32 + j,
+					k210_pcf_infos[i * 32 + j].name);
+				val |= BIT(j);
+			}
+		}
+
+		/* Set value before enable */
+		writel(val, &fpioa->tie_val[i]);
+		writel(val, &fpioa->tie_en[i]);
+	}
+}
+
+static int k210_fpioa_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct k210_fpioa_data *pdata;
+	int ret;
+
+	dev_info(dev, "K210 FPIOA pin controller\n");
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return -ENOMEM;
+
+	pdata->dev = dev;
+	platform_set_drvdata(pdev, pdata);
+
+	pdata->fpioa = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pdata->fpioa))
+		return PTR_ERR(pdata->fpioa);
+
+	pdata->clk = devm_clk_get(dev, "ref");
+	if (IS_ERR(pdata->clk))
+		return PTR_ERR(pdata->clk);
+
+	ret = clk_prepare_enable(pdata->clk);
+	if (ret)
+		return ret;
+
+	pdata->pclk = devm_clk_get_optional(dev, "pclk");
+	if (!IS_ERR(pdata->pclk))
+		clk_prepare_enable(pdata->pclk);
+
+	pdata->sysctl_map =
+		syscon_regmap_lookup_by_phandle(np, "kendryte,sysctl");
+	if (IS_ERR(pdata->sysctl_map))
+		return PTR_ERR(pdata->sysctl_map);
+
+	ret = of_property_read_u32(np, "kendryte,power-offset",
+				   &pdata->power_offset);
+	if (ret)
+		return -EINVAL;
+
+	k210_fpioa_init_ties(pdata);
+
+	pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
+	if (IS_ERR(pdata->pctl))
+		return PTR_ERR(pdata->pctl);
+
+	return 0;
+}
+
+static const struct of_device_id k210_fpioa_dt_ids[] = {
+	{ .compatible = "kendryte,k210-fpioa" },
+};
+
+static struct platform_driver k210_fpioa_driver = {
+	.probe	= k210_fpioa_probe,
+	.driver = {
+		.name		= "k210-fpioa",
+		.of_match_table	= k210_fpioa_dt_ids,
+	},
+};
+
+/*
+ * Most devices on the K210 SoC depend on pin mapping changes to initialize
+ * correctly. So initialize this driver early as part of the post core
+ * initialization.
+ */
+static int __init k210_fpioa_init(void)
+{
+	return platform_driver_register(&k210_fpioa_driver);
+}
+postcore_initcall(k210_fpioa_init);
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
"Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 2735be1a8470..f53d4d8e7f2a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -179,6 +179,8 @@ patternProperties:
     description: CALAO Systems SAS
   "^calxeda,.*":
     description: Calxeda
+  "^canaan,.*":
+    description: Canaan, Inc.
   "^caninos,.*":
     description: Caninos Loucos Program
   "^capella,.*":
@@ -537,6 +539,8 @@ patternProperties:
     description: Ka-Ro electronics GmbH
   "^keithkoep,.*":
     description: Keith & Koep GmbH
+  "^kendryte,.*":
+    description: Canaan, Inc.
   "^keymile,.*":
     description: Keymile GmbH
   "^khadas,.*":
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
"Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 2735be1a8470..f53d4d8e7f2a 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -179,6 +179,8 @@ patternProperties:
     description: CALAO Systems SAS
   "^calxeda,.*":
     description: Calxeda
+  "^canaan,.*":
+    description: Canaan, Inc.
   "^caninos,.*":
     description: Caninos Loucos Program
   "^capella,.*":
@@ -537,6 +539,8 @@ patternProperties:
     description: Ka-Ro electronics GmbH
   "^keithkoep,.*":
     description: Keith & Koep GmbH
+  "^kendryte,.*":
+    description: Canaan, Inc.
   "^keymile,.*":
     description: Keymile GmbH
   "^khadas,.*":
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings of the Kendryte K210 SoC system
controller driver in
Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml

diff --git a/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
new file mode 100644
index 000000000000..8c002d2078f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/kendryte,k210-sysctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 System Controller Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 system controller driver which provides a register map for
+  clocks and peripherals within the SoC.
+
+  See also:
+  - dt-bindings/mfd/kendryte,k210-sysctl.h
+
+properties:
+  compatible:
+    allOf:
+      - items:
+        - const: kendryte,k210-sysctl
+        - const: syscon
+        - const: simple-mfd
+
+  clocks:
+    minItems: 1
+    maxItems: 1
+    items:
+      - description: APB interface clock source
+
+  clock-names:
+    minItems: 1
+    items:
+      - const: pclk
+
+  reg:
+    items:
+      - description: system controller register space base address and size
+
+  reg-io-width:
+    const: 4
+
+required:
+  - compatible
+  - clocks
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/k210-sysctl.h>
+
+    sysctl: system-controller@50440000 {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      compatible = "kendryte,k210-sysctl",
+                   "syscon", "simple-mfd";
+      reg = <0x50440000 0x1000>;
+      reg-io-width = <4>;
+      /* ... */
+    };
+
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings of the Kendryte K210 SoC system
controller driver in
Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
 1 file changed, 65 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml

diff --git a/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
new file mode 100644
index 000000000000..8c002d2078f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mfd/kendryte,k210-sysctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 System Controller Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 system controller driver which provides a register map for
+  clocks and peripherals within the SoC.
+
+  See also:
+  - dt-bindings/mfd/kendryte,k210-sysctl.h
+
+properties:
+  compatible:
+    allOf:
+      - items:
+        - const: kendryte,k210-sysctl
+        - const: syscon
+        - const: simple-mfd
+
+  clocks:
+    minItems: 1
+    maxItems: 1
+    items:
+      - description: APB interface clock source
+
+  clock-names:
+    minItems: 1
+    items:
+      - const: pclk
+
+  reg:
+    items:
+      - description: system controller register space base address and size
+
+  reg-io-width:
+    const: 4
+
+required:
+  - compatible
+  - clocks
+  - reg
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/k210-sysctl.h>
+
+    sysctl: system-controller@50440000 {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      compatible = "kendryte,k210-sysctl",
+                   "syscon", "simple-mfd";
+      reg = <0x50440000 0x1000>;
+      reg-io-width = <4>;
+      /* ... */
+    };
+
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings of the Kendryte K210 SoC clock driver
in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml

diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
new file mode 100644
index 000000000000..02f5f8a86bc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 Clock Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 clock controller driver which support the system controller
+  subsystem supplied clocks for the various controllers and peripherals within
+  the SoC.
+
+  See also:
+  - dt-bindings/clock/k210-clk.h
+
+properties:
+  compatible:
+    const: kendryte,k210-clk
+
+  clocks:
+    maxItems: 1
+    description: System fixed rate oscillator clock
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - '#clock-cells'
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/k210-clk.h>
+
+    clocks {
+      in0: oscillator {
+        compatible = "fixed-clock";
+        #clock-cells = <0>;
+        clock-frequency = <26000000>;
+      };
+    };
+
+    soc {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      /* ... */
+
+      sysctl: system-controller@50440000 {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        compatible = "kendryte,k210-sysctl",
+                     "syscon", "simple-mfd";
+        reg = <0x50440000 0x1000>;
+        /* ... */
+        sysclk: clock-controller {
+          #clock-cells = <1>;
+          compatible = "kendryte,k210-clk";
+          clocks = <&in0>;
+        };
+        /* ... */
+      };
+    };
+
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings of the Kendryte K210 SoC clock driver
in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
 1 file changed, 70 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml

diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
new file mode 100644
index 000000000000..02f5f8a86bc8
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 Clock Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 clock controller driver which support the system controller
+  subsystem supplied clocks for the various controllers and peripherals within
+  the SoC.
+
+  See also:
+  - dt-bindings/clock/k210-clk.h
+
+properties:
+  compatible:
+    const: kendryte,k210-clk
+
+  clocks:
+    maxItems: 1
+    description: System fixed rate oscillator clock
+
+  '#clock-cells':
+    const: 1
+
+required:
+  - compatible
+  - '#clock-cells'
+  - clocks
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/k210-clk.h>
+
+    clocks {
+      in0: oscillator {
+        compatible = "fixed-clock";
+        #clock-cells = <0>;
+        clock-frequency = <26000000>;
+      };
+    };
+
+    soc {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      /* ... */
+
+      sysctl: system-controller@50440000 {
+        #address-cells = <1>;
+        #size-cells = <1>;
+        compatible = "kendryte,k210-sysctl",
+                     "syscon", "simple-mfd";
+        reg = <0x50440000 0x1000>;
+        /* ... */
+        sysclk: clock-controller {
+          #clock-cells = <1>;
+          compatible = "kendryte,k210-clk";
+          clocks = <&in0>;
+        };
+        /* ... */
+      };
+    };
+
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings for the Kendryte K210 SoC Fully
Programmable IO Array (FPIOA) pinctrl driver in
Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
 1 file changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
new file mode 100644
index 000000000000..8730add88ee0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description:
+  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
+  any of 256 possible functions to any of 48 IO pins. Pin function configuration
+  is performed on a per-pin basis.
+
+properties:
+  compatible:
+    const: kendryte,k210-fpioa
+
+  reg:
+    description: FPIOA controller register space base address and size
+
+  clocks:
+    minItems: 2
+    maxItems: 2
+    items:
+      - description: Controller reference clock source
+      - description: APB interface clock source
+
+  clock-names:
+    minItems: 2
+    maxItems: 2
+    items:
+      - const: ref
+      - const: pclk
+
+  resets:
+    maxItems: 1
+
+  kendryte,sysctl:
+    minItems: 1
+    maxItems: 1
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: |
+      phandle to the system controller node
+
+  kendryte,power-offset:
+    minItems: 1
+    maxItems: 1
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Offset of the power domain control register of the system controller.
+      The value should be the macro K210_SYSCTL_POWER_SEL defined in
+      dt-bindings/mfd/k210-sysctl.h.
+
+patternProperties:
+  '^.*$':
+    if:
+      type: object
+    then:
+      patternProperties:
+        "^pinmux$":
+          $ref: /schemas/pinctrl/pincfg-node.yaml
+          description:
+            An array of IO pins alternate functions. The values for each
+            IO pin is a combination of an IO pin number (0 to 47) with the
+            desired function for the IO pin. Functions are defined as macros in
+            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
+            is provided to facilitate the combination of IO pin numbers and
+            functions.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - kendryte,sysctl
+  - kendryte,power-offset
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/pinctrl/k210-pinctrl.h>
+    #include <dt-bindings/mfd/k210-sysctl.h>
+    #include <dt-bindings/clock/k210-sysctl.h>
+    #include <dt-bindings/reset/k210-sysctl.h>
+
+    fpioa: pinmux@502B0000 {
+      compatible = "kendryte,k210-fpioa";
+      reg = <0x502B0000 0x100>;
+      clocks = <&sysclk K210_CLK_FPIOA>;
+      resets = <&sysrst K210_RST_FPIOA>;
+      kendryte,sysctl = <&sysctl>;
+      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
+      pinctrl-0 = <&fpioa_jtag>;
+      pinctrl-names = "default";
+
+      fpioa_jtag: jtag {
+        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+      };
+    };
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings for the Kendryte K210 SoC Fully
Programmable IO Array (FPIOA) pinctrl driver in
Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
 1 file changed, 106 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
new file mode 100644
index 000000000000..8730add88ee0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description:
+  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
+  any of 256 possible functions to any of 48 IO pins. Pin function configuration
+  is performed on a per-pin basis.
+
+properties:
+  compatible:
+    const: kendryte,k210-fpioa
+
+  reg:
+    description: FPIOA controller register space base address and size
+
+  clocks:
+    minItems: 2
+    maxItems: 2
+    items:
+      - description: Controller reference clock source
+      - description: APB interface clock source
+
+  clock-names:
+    minItems: 2
+    maxItems: 2
+    items:
+      - const: ref
+      - const: pclk
+
+  resets:
+    maxItems: 1
+
+  kendryte,sysctl:
+    minItems: 1
+    maxItems: 1
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    description: |
+      phandle to the system controller node
+
+  kendryte,power-offset:
+    minItems: 1
+    maxItems: 1
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description: |
+      Offset of the power domain control register of the system controller.
+      The value should be the macro K210_SYSCTL_POWER_SEL defined in
+      dt-bindings/mfd/k210-sysctl.h.
+
+patternProperties:
+  '^.*$':
+    if:
+      type: object
+    then:
+      patternProperties:
+        "^pinmux$":
+          $ref: /schemas/pinctrl/pincfg-node.yaml
+          description:
+            An array of IO pins alternate functions. The values for each
+            IO pin is a combination of an IO pin number (0 to 47) with the
+            desired function for the IO pin. Functions are defined as macros in
+            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
+            is provided to facilitate the combination of IO pin numbers and
+            functions.
+
+required:
+  - compatible
+  - reg
+  - clocks
+  - resets
+  - kendryte,sysctl
+  - kendryte,power-offset
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/pinctrl/k210-pinctrl.h>
+    #include <dt-bindings/mfd/k210-sysctl.h>
+    #include <dt-bindings/clock/k210-sysctl.h>
+    #include <dt-bindings/reset/k210-sysctl.h>
+
+    fpioa: pinmux@502B0000 {
+      compatible = "kendryte,k210-fpioa";
+      reg = <0x502B0000 0x100>;
+      clocks = <&sysclk K210_CLK_FPIOA>;
+      resets = <&sysrst K210_RST_FPIOA>;
+      kendryte,sysctl = <&sysctl>;
+      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
+      pinctrl-0 = <&fpioa_jtag>;
+      pinctrl-names = "default";
+
+      fpioa_jtag: jtag {
+        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+      };
+    };
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings for the Kendryte K210 SoC reset
controller driver in
Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml

diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
new file mode 100644
index 000000000000..bdd0bf37bdfb
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 Reset Controller Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 reset controller driver which support the system controller
+  subsystem supplied reset registers for the various peripherals within
+  the SoC.
+
+  See also:
+  - dt-bindings/reset/k210-rst.h
+
+properties:
+  compatible:
+    allOf:
+      - items:
+        - const: kendryte,k210-rst
+        - const: syscon-reset
+
+  regmap:
+    maxItems: 1
+    description: phandle of the system controller (sysctl) node
+
+  offset:
+    maxItems: 1
+    description: peripheral reset register offset in the system controller
+      controller register map
+
+  mask:
+    maxItems: 1
+    description: bit-mask indicating valid reset bits in the reset register
+
+  assert-high:
+    maxItems: 1
+    description: bit value to write when asserting a reset
+
+  '#reset-cells':
+    const: 1
+
+required:
+  - '#reset-cells'
+  - compatible
+  - regmap
+  - offset
+  - mask
+  - assert-high
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/k210-sysctl.h>
+    #include <dt-bindings/reset/k210-rst.h>
+
+    sysctl: system-controller@50440000 {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      compatible = "kendryte,k210-sysctl",
+                   "syscon", "simple-mfd";
+      reg = <0x50440000 0x1000>;
+      /* ... */
+      sysrst: reset-controller {
+        compatible = "kendryte,k210-rst",
+                      "syscon-reset";
+        #reset-cells = <1>;
+        regmap = <&sysctl>;
+        offset = <K210_SYSCTL_PERI_RESET>;
+        mask = <0x27FFFFFF>;
+        assert-high = <1>;
+      };
+    };
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Document the device tree bindings for the Kendryte K210 SoC reset
controller driver in
Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
 1 file changed, 78 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml

diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
new file mode 100644
index 000000000000..bdd0bf37bdfb
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
@@ -0,0 +1,78 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Kendryte K210 Reset Controller Device Tree Bindings
+
+maintainers:
+  - Damien Le Moal <damien.lemoal@wdc.com>
+
+description: |
+  Kendryte K210 reset controller driver which support the system controller
+  subsystem supplied reset registers for the various peripherals within
+  the SoC.
+
+  See also:
+  - dt-bindings/reset/k210-rst.h
+
+properties:
+  compatible:
+    allOf:
+      - items:
+        - const: kendryte,k210-rst
+        - const: syscon-reset
+
+  regmap:
+    maxItems: 1
+    description: phandle of the system controller (sysctl) node
+
+  offset:
+    maxItems: 1
+    description: peripheral reset register offset in the system controller
+      controller register map
+
+  mask:
+    maxItems: 1
+    description: bit-mask indicating valid reset bits in the reset register
+
+  assert-high:
+    maxItems: 1
+    description: bit value to write when asserting a reset
+
+  '#reset-cells':
+    const: 1
+
+required:
+  - '#reset-cells'
+  - compatible
+  - regmap
+  - offset
+  - mask
+  - assert-high
+
+additionalProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/mfd/k210-sysctl.h>
+    #include <dt-bindings/reset/k210-rst.h>
+
+    sysctl: system-controller@50440000 {
+      #address-cells = <1>;
+      #size-cells = <1>;
+      compatible = "kendryte,k210-sysctl",
+                   "syscon", "simple-mfd";
+      reg = <0x50440000 0x1000>;
+      /* ... */
+      sysrst: reset-controller {
+        compatible = "kendryte,k210-rst",
+                      "syscon-reset";
+        #reset-cells = <1>;
+        regmap = <&sysctl>;
+        offset = <K210_SYSCTL_PERI_RESET>;
+        mask = <0x27FFFFFF>;
+        assert-high = <1>;
+      };
+    };
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 26/32] riscv: Update Kendryte K210 device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update the Kendryte K210 base device tree k210.dtsi to define all
peripherals of the SoC, their clocks and reset lines. The device tree
file k210.dts is renamed to k210_generic.dts and becomes the default
dwivalue selection of the SOC_KENDRYTE_K210_DTB_BUILTIN_SOURCE
configuration option. No device beside the serial console is defined by
this device tree. This makes it suitable for all known K210 boards using
a builtin initramfs.

Most updates to the k210.dtsi file come from Sean Anderson's work on
U-Boot support for the Kendryte K210.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs                       |   2 +-
 arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
 arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++++++++++-
 arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 ++
 4 files changed, 583 insertions(+), 52 deletions(-)
 delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 56ba82a64e18..9230af7fb763 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -59,7 +59,7 @@ config SOC_KENDRYTE_K210_DTB_SOURCE
 	string "Source file for the Kendryte K210 builtin DTB"
 	depends on SOC_KENDRYTE
 	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
-	default "k210"
+	default "k210_generic"
 	help
 	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
 	  for the DTS file that will be used to produce the DTB linked into the
diff --git a/arch/riscv/boot/dts/kendryte/k210.dts b/arch/riscv/boot/dts/kendryte/k210.dts
deleted file mode 100644
index 0d1f28fce6b2..000000000000
--- a/arch/riscv/boot/dts/kendryte/k210.dts
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2020 Western Digital Corporation or its affiliates.
- */
-
-/dts-v1/;
-
-#include "k210.dtsi"
-
-/ {
-	model = "Kendryte K210 generic";
-	compatible = "kendryte,k210";
-
-	chosen {
-		bootargs = "earlycon console=ttySIF0";
-		stdout-path = "serial0";
-	};
-};
-
-&uarths0 {
-	status = "okay";
-};
-
diff --git a/arch/riscv/boot/dts/kendryte/k210.dtsi b/arch/riscv/boot/dts/kendryte/k210.dtsi
index d2d0ff645632..b8706fe78b21 100644
--- a/arch/riscv/boot/dts/kendryte/k210.dtsi
+++ b/arch/riscv/boot/dts/kendryte/k210.dtsi
@@ -1,9 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  */
 #include <dt-bindings/clock/k210-clk.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dt-bindings/pinctrl/k210-pinctrl.h>
+#include <dt-bindings/reset/k210-rst.h>
 
 / {
 	/*
@@ -15,7 +18,26 @@ / {
 	compatible = "kendryte,k210";
 
 	aliases {
+		cpu0 = &cpu0;
+		cpu1 = &cpu1;
+		dma0 = &dmac0;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1_0;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		pinctrl0 = &fpioa;
 		serial0 = &uarths0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		timer0 = &timer0;
+		timer1 = &timer1;
+		timer2 = &timer2;
 	};
 
 	/*
@@ -30,16 +52,15 @@ cpus {
 		timebase-frequency = <7800000>;
 		cpu0: cpu@0 {
 			device_type = "cpu";
-			reg = <0>;
 			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			reg = <0>;
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
-			clocks = <&sysctl K210_CLK_CPU>;
-			clock-frequency = <390000000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
 			cpu0_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -48,16 +69,15 @@ cpu0_intc: interrupt-controller {
 		};
 		cpu1: cpu@1 {
 			device_type = "cpu";
-			reg = <1>;
 			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			reg = <1>;
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
-			clocks = <&sysctl K210_CLK_CPU>;
-			clock-frequency = <390000000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
 			cpu1_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -68,14 +88,19 @@ cpu1_intc: interrupt-controller {
 
 	sram: memory@80000000 {
 		device_type = "memory";
+		compatible = "kendryte,k210-sram";
 		reg = <0x80000000 0x400000>,
 		      <0x80400000 0x200000>,
 		      <0x80600000 0x200000>;
 		reg-names = "sram0", "sram1", "aisram";
+		clocks = <&sysclk K210_CLK_SRAM0>,
+			 <&sysclk K210_CLK_SRAM1>,
+			 <&sysclk K210_CLK_AI>;
+		clock-names = "sram0", "sram1", "aisram";
 	};
 
 	clocks {
-		in0: oscillator {
+		in0: osc {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <26000000>;
@@ -89,28 +114,34 @@ soc {
 		ranges;
 		interrupt-parent = <&plic0>;
 
-		sysctl: sysctl@50440000 {
-			compatible = "kendryte,k210-sysctl", "simple-mfd";
-			reg = <0x50440000 0x1000>;
-			#clock-cells = <1>;
+		debug0: debug@0 {
+			compatible = "kendryte,k210-debug", "riscv,debug";
+			reg = <0x0 0x1000>;
+			status = "disabled";
+		};
+
+		rom0: nvmem@1000 {
+			reg = <0x1000 0x1000>;
+			read-only;
+			status = "disabled";
 		};
 
 		clint0: clint@2000000 {
 			#interrupt-cells = <1>;
-			compatible = "riscv,clint0";
+			compatible = "kendryte,k210-clint", "riscv,clint0";
 			reg = <0x2000000 0xC000>;
-			interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
-						&cpu1_intc 3 &cpu1_intc 7>;
-			clocks = <&sysctl K210_CLK_ACLK>;
+			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
+					      <&cpu1_intc 3>, <&cpu1_intc 7>;
+			clocks = <&sysclk K210_CLK_CLINT>;
 		};
 
-		plic0: interrupt-controller@c000000 {
+		plic0: interrupt-controller@C000000 {
 			#interrupt-cells = <1>;
-			interrupt-controller;
-			compatible = "kendryte,k210-plic0", "riscv,plic0";
+			compatible = "kendryte,k210-plic", "riscv,plic0";
 			reg = <0xC000000 0x4000000>;
-			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 0xffffffff>,
-					      <&cpu1_intc 11>, <&cpu1_intc 0xffffffff>;
+			interrupt-controller;
+			interrupts-extended = <&cpu0_intc 11>,
+					      <&cpu1_intc 11>;
 			riscv,ndev = <65>;
 			riscv,max-priority = <7>;
 		};
@@ -119,7 +150,484 @@ uarths0: serial@38000000 {
 			compatible = "kendryte,k210-uarths", "sifive,uart0";
 			reg = <0x38000000 0x1000>;
 			interrupts = <33>;
-			clocks = <&sysctl K210_CLK_CPU>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			status = "disabled";
+		};
+
+		gpio0: gpio-controller@38001000 {
+			#interrupt-cells = <2>;
+			#gpio-cells = <2>;
+			compatible = "kendryte,k210-gpiohs", "sifive,gpio0";
+			reg = <0x38001000 0x1000>;
+			interrupt-controller;
+			interrupts = <34 35 36 37 38 39 40 41
+				      42 43 44 45 46 47 48 49
+				      50 51 52 53 54 55 56 57
+				      58 59 60 61 62 63 64 65>;
+			gpio-controller;
+			ngpios = <32>;
+			status = "disabled";
+		};
+
+		kpu0: kpu@40800000 {
+			compatible = "kendryte,k210-kpu";
+			reg = <0x40800000 0xc00000>;
+			interrupts = <25>;
+			clocks = <&sysclk K210_CLK_AI>;
+			status = "disabled";
+		};
+
+		fft0: fft@42000000 {
+			compatible = "kendryte,k210-fft";
+			reg = <0x42000000 0x400000>;
+			interrupts = <26>;
+			clocks = <&sysclk K210_CLK_FFT>;
+			resets = <&sysrst K210_RST_FFT>;
+			status = "disabled";
+		};
+
+		dmac0: dma-controller@50000000 {
+			compatible = "kendryte,k210-dmac", "snps,axi-dma-1.01a";
+			reg = <0x50000000 0x1000>;
+			interrupts = <27 28 29 30 31 32>;
+			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
+			clock-names = "core-clk", "cfgr-clk";
+			resets = <&sysrst K210_RST_DMA>;
+			dma-channels = <6>;
+			snps,dma-masters = <2>;
+			snps,priority = <0 1 2 3 4 5>;
+			snps,data-width = <5>;
+			snps,block-size = <0x200000 0x200000 0x200000
+					   0x200000 0x200000 0x200000>;
+			snps,axi-max-burst-len = <256>;
+			status = "disabled";
+		};
+
+		apb0: bus@50200000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB0>;
+
+			gpio1: gpio-controller@50200000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "kendryte,k210-gpio",
+					     "snps,dw-apb-gpio";
+				reg = <0x50200000 0x80>;
+				clocks = <&sysclk K210_CLK_APB0>,
+					 <&sysclk K210_CLK_GPIO>;
+				clock-names = "bus", "db";
+				resets = <&sysrst K210_RST_GPIO>;
+				status = "disabled";
+
+				gpio1_0: gpio1@0 {
+					#gpio-cells = <2>;
+					#interrupt-cells = <2>;
+					compatible = "snps,dw-apb-gpio-port";
+					reg = <0>;
+					interrupt-controller;
+					interrupts = <23>;
+					gpio-controller;
+					snps,nr-gpios = <8>;
+				};
+			};
+
+			uart1: serial@50210000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50210000 0x100>;
+				interrupts = <11>;
+				clocks = <&sysclk K210_CLK_UART1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART1>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart2: serial@50220000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50220000 0x100>;
+				interrupts = <12>;
+				clocks = <&sysclk K210_CLK_UART2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART2>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart3: serial@50230000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50230000 0x100>;
+				interrupts = <13>;
+				clocks = <&sysclk K210_CLK_UART3>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART3>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			spi2: spi@50240000 {
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				spi-slave;
+				reg = <0x50240000 0x100>;
+				interrupts = <3>;
+				clocks = <&sysclk K210_CLK_SPI2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI2>;
+				spi-max-frequency = <25000000>;
+				status = "disabled";
+			};
+
+			i2s0: i2s@50250000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50250000 0x200>;
+				interrupts = <5>;
+				clocks = <&sysclk K210_CLK_I2S0>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S0>;
+				status = "disabled";
+			};
+
+			apu0: sound@520250200 {
+				compatible = "kendryte,k210-apu";
+				reg = <0x50250200 0x200>;
+				status = "disabled";
+			};
+
+			i2s1: i2s@50260000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50260000 0x200>;
+				interrupts = <6>;
+				clocks = <&sysclk K210_CLK_I2S1>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S1>;
+				status = "disabled";
+			};
+
+			i2s2: i2s@50270000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50270000 0x200>;
+				interrupts = <7>;
+				clocks = <&sysclk K210_CLK_I2S2>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S2>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@50280000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50280000 0x100>;
+				interrupts = <8>;
+				clocks = <&sysclk K210_CLK_I2C0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@50290000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50290000 0x100>;
+				interrupts = <9>;
+				clocks = <&sysclk K210_CLK_I2C1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C1>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@502A0000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x502A0000 0x100>;
+				interrupts = <10>;
+				clocks = <&sysclk K210_CLK_I2C2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C2>;
+				status = "disabled";
+			};
+
+			fpioa: pinmux@502B0000 {
+				compatible = "kendryte,k210-fpioa";
+				reg = <0x502B0000 0x100>;
+				clocks = <&sysclk K210_CLK_FPIOA>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_FPIOA>;
+				kendryte,sysctl = <&sysctl>;
+				kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
+				status = "disabled";
+			};
+
+			sha256: sha256@502C0000 {
+				compatible = "kendryte,k210-sha256";
+				reg = <0x502C0000 0x100>;
+				clocks = <&sysclk K210_CLK_SHA>;
+				resets = <&sysrst K210_RST_SHA>;
+				status = "disabled";
+			};
+
+			timer0: timer@502D0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502D0000 0x100>;
+				interrupts = <14 15>;
+				clocks = <&sysclk K210_CLK_TIMER0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER0>;
+				status = "disabled";
+			};
+
+			timer1: timer@502E0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502E0000 0x100>;
+				interrupts = <16 17>;
+				clocks = <&sysclk K210_CLK_TIMER1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER1>;
+				status = "disabled";
+			};
+
+			timer2: timer@502F0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502F0000 0x100>;
+				interrupts = <18 19>;
+				clocks = <&sysclk K210_CLK_TIMER2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER2>;
+				status = "disabled";
+			};
+		};
+
+		apb1: bus@50400000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB1>;
+
+			wdt0: watchdog@50400000 {
+				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
+				reg = <0x50400000 0x100>;
+				interrupts = <21>;
+				clocks = <&sysclk K210_CLK_WDT0>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT0>;
+				status = "disabled";
+			};
+
+			wdt1: watchdog@50410000 {
+				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
+				reg = <0x50410000 0x100>;
+				interrupts = <22>;
+				clocks = <&sysclk K210_CLK_WDT1>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT1>;
+				status = "disabled";
+			};
+
+			otp0: nvmem@50420000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "kendryte,k210-otp";
+				reg = <0x50420000 0x100>,
+				      <0x88000000 0x20000>;
+				reg-names = "reg", "mem";
+				clocks = <&sysclk K210_CLK_ROM>;
+				resets = <&sysrst K210_RST_ROM>;
+				read-only;
+				status = "disabled";
+
+				/* Bootloader */
+				firmware@00000 {
+					reg = <0x00000 0xC200>;
+				};
+
+				/*
+				 * config string as described in RISC-V
+				 * privileged spec 1.9
+				 */
+				config-1-9@1c000 {
+					reg = <0x1C000 0x1000>;
+				};
+
+				/*
+				 * Device tree containing only registers,
+				 * interrupts, and cpus
+				 */
+				fdt@1d000 {
+					reg = <0x1D000 0x2000>;
+				};
+
+				/* CPU/ROM credits */
+				credits@1f000 {
+					reg = <0x1F000 0x1000>;
+				};
+			};
+
+			dvp0: camera@50430000 {
+				compatible = "kendryte,k210-dvp";
+				reg = <0x50430000 0x100>;
+				interrupts = <24>;
+				clocks = <&sysclk K210_CLK_DVP>;
+				resets = <&sysrst K210_RST_DVP>;
+				kendryte,sysctl = <&sysctl>;
+				kendryte,misc-offset = <K210_SYSCTL_MISC>;
+				status = "disabled";
+			};
+
+			sysctl: syscon@50440000 {
+				compatible = "kendryte,k210-sysctl",
+					     "syscon", "simple-mfd";
+				reg = <0x50440000 0x100>;
+				reg-io-width = <4>;
+				clocks = <&sysclk K210_CLK_APB1>;
+				clock-names = "pclk";
+
+				sysclk: clock-controller {
+					#clock-cells = <1>;
+					compatible = "kendryte,k210-clk";
+					clocks = <&in0>;
+				};
+
+				sysrst: reset-controller {
+					compatible = "kendryte,k210-rst",
+						     "syscon-reset";
+					#reset-cells = <1>;
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_PERI_RESET>;
+					mask = <0x27FFFFFF>;
+					assert-high = <1>;
+				};
+
+				reboot {
+					compatible = "syscon-reboot";
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_SOFT_RESET>;
+					mask = <1>;
+					value = <1>;
+				};
+			};
+
+			aes0: aes@50450000 {
+				compatible = "kendryte,k210-aes";
+				reg = <0x50450000 0x100>;
+				clocks = <&sysclk K210_CLK_AES>;
+				resets = <&sysrst K210_RST_AES>;
+				status = "disabled";
+			};
+
+			rtc: rtc@50460000 {
+				compatible = "kendryte,k210-rtc";
+				reg = <0x50460000 0x100>;
+				clocks = <&in0>;
+				resets = <&sysrst K210_RST_RTC>;
+				interrupts = <20>;
+				status = "disabled";
+			};
+		};
+
+		apb2: bus@52000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB2>;
+
+			spi0: spi@52000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x52000000 0x100>;
+				interrupts = <1>;
+				clocks = <&sysclk K210_CLK_SPI0>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI0>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi1: spi@53000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x53000000 0x100>;
+				interrupts = <2>;
+				clocks = <&sysclk K210_CLK_SPI1>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI1>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi3: spi@54000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-ssi",
+					     "snps,dwc-ssi-1.01a";
+				reg = <0x54000000 0x200>;
+				interrupts = <4>;
+				clocks = <&sysclk K210_CLK_SPI3>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI3>;
+				reset-names = "spi";
+				/* Could possibly go up to 200 MHz */
+				spi-max-frequency = <100000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
 		};
 	};
 };
diff --git a/arch/riscv/boot/dts/kendryte/k210_generic.dts b/arch/riscv/boot/dts/kendryte/k210_generic.dts
new file mode 100644
index 000000000000..f336f60dc15d
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_generic.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte K210 generic";
+	compatible = "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 26/32] riscv: Update Kendryte K210 device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update the Kendryte K210 base device tree k210.dtsi to define all
peripherals of the SoC, their clocks and reset lines. The device tree
file k210.dts is renamed to k210_generic.dts and becomes the default
dwivalue selection of the SOC_KENDRYTE_K210_DTB_BUILTIN_SOURCE
configuration option. No device beside the serial console is defined by
this device tree. This makes it suitable for all known K210 boards using
a builtin initramfs.

Most updates to the k210.dtsi file come from Sean Anderson's work on
U-Boot support for the Kendryte K210.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/Kconfig.socs                       |   2 +-
 arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
 arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++++++++++-
 arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 ++
 4 files changed, 583 insertions(+), 52 deletions(-)
 delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts

diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 56ba82a64e18..9230af7fb763 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -59,7 +59,7 @@ config SOC_KENDRYTE_K210_DTB_SOURCE
 	string "Source file for the Kendryte K210 builtin DTB"
 	depends on SOC_KENDRYTE
 	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
-	default "k210"
+	default "k210_generic"
 	help
 	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
 	  for the DTS file that will be used to produce the DTB linked into the
diff --git a/arch/riscv/boot/dts/kendryte/k210.dts b/arch/riscv/boot/dts/kendryte/k210.dts
deleted file mode 100644
index 0d1f28fce6b2..000000000000
--- a/arch/riscv/boot/dts/kendryte/k210.dts
+++ /dev/null
@@ -1,23 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2020 Western Digital Corporation or its affiliates.
- */
-
-/dts-v1/;
-
-#include "k210.dtsi"
-
-/ {
-	model = "Kendryte K210 generic";
-	compatible = "kendryte,k210";
-
-	chosen {
-		bootargs = "earlycon console=ttySIF0";
-		stdout-path = "serial0";
-	};
-};
-
-&uarths0 {
-	status = "okay";
-};
-
diff --git a/arch/riscv/boot/dts/kendryte/k210.dtsi b/arch/riscv/boot/dts/kendryte/k210.dtsi
index d2d0ff645632..b8706fe78b21 100644
--- a/arch/riscv/boot/dts/kendryte/k210.dtsi
+++ b/arch/riscv/boot/dts/kendryte/k210.dtsi
@@ -1,9 +1,12 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
  * Copyright (C) 2020 Western Digital Corporation or its affiliates.
  */
 #include <dt-bindings/clock/k210-clk.h>
+#include <dt-bindings/mfd/k210-sysctl.h>
+#include <dt-bindings/pinctrl/k210-pinctrl.h>
+#include <dt-bindings/reset/k210-rst.h>
 
 / {
 	/*
@@ -15,7 +18,26 @@ / {
 	compatible = "kendryte,k210";
 
 	aliases {
+		cpu0 = &cpu0;
+		cpu1 = &cpu1;
+		dma0 = &dmac0;
+		gpio0 = &gpio0;
+		gpio1 = &gpio1_0;
+		i2c0 = &i2c0;
+		i2c1 = &i2c1;
+		i2c2 = &i2c2;
+		pinctrl0 = &fpioa;
 		serial0 = &uarths0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+		spi0 = &spi0;
+		spi1 = &spi1;
+		spi2 = &spi2;
+		spi3 = &spi3;
+		timer0 = &timer0;
+		timer1 = &timer1;
+		timer2 = &timer2;
 	};
 
 	/*
@@ -30,16 +52,15 @@ cpus {
 		timebase-frequency = <7800000>;
 		cpu0: cpu@0 {
 			device_type = "cpu";
-			reg = <0>;
 			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			reg = <0>;
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
-			clocks = <&sysctl K210_CLK_CPU>;
-			clock-frequency = <390000000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
 			cpu0_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -48,16 +69,15 @@ cpu0_intc: interrupt-controller {
 		};
 		cpu1: cpu@1 {
 			device_type = "cpu";
-			reg = <1>;
 			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
-			riscv,isa = "rv64imafdc";
+			reg = <1>;
+			riscv,isa = "rv64imafdgc";
 			mmu-type = "none";
-			i-cache-size = <0x8000>;
 			i-cache-block-size = <64>;
-			d-cache-size = <0x8000>;
+			i-cache-size = <0x8000>;
 			d-cache-block-size = <64>;
-			clocks = <&sysctl K210_CLK_CPU>;
-			clock-frequency = <390000000>;
+			d-cache-size = <0x8000>;
+			clocks = <&sysclk K210_CLK_CPU>;
 			cpu1_intc: interrupt-controller {
 				#interrupt-cells = <1>;
 				interrupt-controller;
@@ -68,14 +88,19 @@ cpu1_intc: interrupt-controller {
 
 	sram: memory@80000000 {
 		device_type = "memory";
+		compatible = "kendryte,k210-sram";
 		reg = <0x80000000 0x400000>,
 		      <0x80400000 0x200000>,
 		      <0x80600000 0x200000>;
 		reg-names = "sram0", "sram1", "aisram";
+		clocks = <&sysclk K210_CLK_SRAM0>,
+			 <&sysclk K210_CLK_SRAM1>,
+			 <&sysclk K210_CLK_AI>;
+		clock-names = "sram0", "sram1", "aisram";
 	};
 
 	clocks {
-		in0: oscillator {
+		in0: osc {
 			compatible = "fixed-clock";
 			#clock-cells = <0>;
 			clock-frequency = <26000000>;
@@ -89,28 +114,34 @@ soc {
 		ranges;
 		interrupt-parent = <&plic0>;
 
-		sysctl: sysctl@50440000 {
-			compatible = "kendryte,k210-sysctl", "simple-mfd";
-			reg = <0x50440000 0x1000>;
-			#clock-cells = <1>;
+		debug0: debug@0 {
+			compatible = "kendryte,k210-debug", "riscv,debug";
+			reg = <0x0 0x1000>;
+			status = "disabled";
+		};
+
+		rom0: nvmem@1000 {
+			reg = <0x1000 0x1000>;
+			read-only;
+			status = "disabled";
 		};
 
 		clint0: clint@2000000 {
 			#interrupt-cells = <1>;
-			compatible = "riscv,clint0";
+			compatible = "kendryte,k210-clint", "riscv,clint0";
 			reg = <0x2000000 0xC000>;
-			interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
-						&cpu1_intc 3 &cpu1_intc 7>;
-			clocks = <&sysctl K210_CLK_ACLK>;
+			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
+					      <&cpu1_intc 3>, <&cpu1_intc 7>;
+			clocks = <&sysclk K210_CLK_CLINT>;
 		};
 
-		plic0: interrupt-controller@c000000 {
+		plic0: interrupt-controller@C000000 {
 			#interrupt-cells = <1>;
-			interrupt-controller;
-			compatible = "kendryte,k210-plic0", "riscv,plic0";
+			compatible = "kendryte,k210-plic", "riscv,plic0";
 			reg = <0xC000000 0x4000000>;
-			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 0xffffffff>,
-					      <&cpu1_intc 11>, <&cpu1_intc 0xffffffff>;
+			interrupt-controller;
+			interrupts-extended = <&cpu0_intc 11>,
+					      <&cpu1_intc 11>;
 			riscv,ndev = <65>;
 			riscv,max-priority = <7>;
 		};
@@ -119,7 +150,484 @@ uarths0: serial@38000000 {
 			compatible = "kendryte,k210-uarths", "sifive,uart0";
 			reg = <0x38000000 0x1000>;
 			interrupts = <33>;
-			clocks = <&sysctl K210_CLK_CPU>;
+			clocks = <&sysclk K210_CLK_CPU>;
+			status = "disabled";
+		};
+
+		gpio0: gpio-controller@38001000 {
+			#interrupt-cells = <2>;
+			#gpio-cells = <2>;
+			compatible = "kendryte,k210-gpiohs", "sifive,gpio0";
+			reg = <0x38001000 0x1000>;
+			interrupt-controller;
+			interrupts = <34 35 36 37 38 39 40 41
+				      42 43 44 45 46 47 48 49
+				      50 51 52 53 54 55 56 57
+				      58 59 60 61 62 63 64 65>;
+			gpio-controller;
+			ngpios = <32>;
+			status = "disabled";
+		};
+
+		kpu0: kpu@40800000 {
+			compatible = "kendryte,k210-kpu";
+			reg = <0x40800000 0xc00000>;
+			interrupts = <25>;
+			clocks = <&sysclk K210_CLK_AI>;
+			status = "disabled";
+		};
+
+		fft0: fft@42000000 {
+			compatible = "kendryte,k210-fft";
+			reg = <0x42000000 0x400000>;
+			interrupts = <26>;
+			clocks = <&sysclk K210_CLK_FFT>;
+			resets = <&sysrst K210_RST_FFT>;
+			status = "disabled";
+		};
+
+		dmac0: dma-controller@50000000 {
+			compatible = "kendryte,k210-dmac", "snps,axi-dma-1.01a";
+			reg = <0x50000000 0x1000>;
+			interrupts = <27 28 29 30 31 32>;
+			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
+			clock-names = "core-clk", "cfgr-clk";
+			resets = <&sysrst K210_RST_DMA>;
+			dma-channels = <6>;
+			snps,dma-masters = <2>;
+			snps,priority = <0 1 2 3 4 5>;
+			snps,data-width = <5>;
+			snps,block-size = <0x200000 0x200000 0x200000
+					   0x200000 0x200000 0x200000>;
+			snps,axi-max-burst-len = <256>;
+			status = "disabled";
+		};
+
+		apb0: bus@50200000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB0>;
+
+			gpio1: gpio-controller@50200000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "kendryte,k210-gpio",
+					     "snps,dw-apb-gpio";
+				reg = <0x50200000 0x80>;
+				clocks = <&sysclk K210_CLK_APB0>,
+					 <&sysclk K210_CLK_GPIO>;
+				clock-names = "bus", "db";
+				resets = <&sysrst K210_RST_GPIO>;
+				status = "disabled";
+
+				gpio1_0: gpio1@0 {
+					#gpio-cells = <2>;
+					#interrupt-cells = <2>;
+					compatible = "snps,dw-apb-gpio-port";
+					reg = <0>;
+					interrupt-controller;
+					interrupts = <23>;
+					gpio-controller;
+					snps,nr-gpios = <8>;
+				};
+			};
+
+			uart1: serial@50210000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50210000 0x100>;
+				interrupts = <11>;
+				clocks = <&sysclk K210_CLK_UART1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART1>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart2: serial@50220000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50220000 0x100>;
+				interrupts = <12>;
+				clocks = <&sysclk K210_CLK_UART2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART2>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			uart3: serial@50230000 {
+				compatible = "kendryte,k210-uart",
+					     "snps,dw-apb-uart";
+				reg = <0x50230000 0x100>;
+				interrupts = <13>;
+				clocks = <&sysclk K210_CLK_UART3>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "baudclk", "apb_pclk";
+				resets = <&sysrst K210_RST_UART3>;
+				reg-io-width = <4>;
+				reg-shift = <2>;
+				dcd-override;
+				dsr-override;
+				cts-override;
+				ri-override;
+				status = "disabled";
+			};
+
+			spi2: spi@50240000 {
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				spi-slave;
+				reg = <0x50240000 0x100>;
+				interrupts = <3>;
+				clocks = <&sysclk K210_CLK_SPI2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI2>;
+				spi-max-frequency = <25000000>;
+				status = "disabled";
+			};
+
+			i2s0: i2s@50250000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50250000 0x200>;
+				interrupts = <5>;
+				clocks = <&sysclk K210_CLK_I2S0>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S0>;
+				status = "disabled";
+			};
+
+			apu0: sound@520250200 {
+				compatible = "kendryte,k210-apu";
+				reg = <0x50250200 0x200>;
+				status = "disabled";
+			};
+
+			i2s1: i2s@50260000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50260000 0x200>;
+				interrupts = <6>;
+				clocks = <&sysclk K210_CLK_I2S1>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S1>;
+				status = "disabled";
+			};
+
+			i2s2: i2s@50270000 {
+				compatible = "kendryte,k210-i2s",
+					     "snps,designware-i2s";
+				reg = <0x50270000 0x200>;
+				interrupts = <7>;
+				clocks = <&sysclk K210_CLK_I2S2>;
+				clock-names = "i2sclk";
+				resets = <&sysrst K210_RST_I2S2>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@50280000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50280000 0x100>;
+				interrupts = <8>;
+				clocks = <&sysclk K210_CLK_I2C0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@50290000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x50290000 0x100>;
+				interrupts = <9>;
+				clocks = <&sysclk K210_CLK_I2C1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C1>;
+				status = "disabled";
+			};
+
+			i2c2: i2c@502A0000 {
+				compatible = "kendryte,k210-i2c",
+					     "snps,designware-i2c";
+				reg = <0x502A0000 0x100>;
+				interrupts = <10>;
+				clocks = <&sysclk K210_CLK_I2C2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_I2C2>;
+				status = "disabled";
+			};
+
+			fpioa: pinmux@502B0000 {
+				compatible = "kendryte,k210-fpioa";
+				reg = <0x502B0000 0x100>;
+				clocks = <&sysclk K210_CLK_FPIOA>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "ref", "pclk";
+				resets = <&sysrst K210_RST_FPIOA>;
+				kendryte,sysctl = <&sysctl>;
+				kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
+				status = "disabled";
+			};
+
+			sha256: sha256@502C0000 {
+				compatible = "kendryte,k210-sha256";
+				reg = <0x502C0000 0x100>;
+				clocks = <&sysclk K210_CLK_SHA>;
+				resets = <&sysrst K210_RST_SHA>;
+				status = "disabled";
+			};
+
+			timer0: timer@502D0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502D0000 0x100>;
+				interrupts = <14 15>;
+				clocks = <&sysclk K210_CLK_TIMER0>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER0>;
+				status = "disabled";
+			};
+
+			timer1: timer@502E0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502E0000 0x100>;
+				interrupts = <16 17>;
+				clocks = <&sysclk K210_CLK_TIMER1>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER1>;
+				status = "disabled";
+			};
+
+			timer2: timer@502F0000 {
+				compatible = "kendryte,k210-timer",
+					     "snps,dw-apb-timer";
+				reg = <0x502F0000 0x100>;
+				interrupts = <18 19>;
+				clocks = <&sysclk K210_CLK_TIMER2>,
+					 <&sysclk K210_CLK_APB0>;
+				clock-names = "timer", "pclk";
+				resets = <&sysrst K210_RST_TIMER2>;
+				status = "disabled";
+			};
+		};
+
+		apb1: bus@50400000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB1>;
+
+			wdt0: watchdog@50400000 {
+				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
+				reg = <0x50400000 0x100>;
+				interrupts = <21>;
+				clocks = <&sysclk K210_CLK_WDT0>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT0>;
+				status = "disabled";
+			};
+
+			wdt1: watchdog@50410000 {
+				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
+				reg = <0x50410000 0x100>;
+				interrupts = <22>;
+				clocks = <&sysclk K210_CLK_WDT1>,
+					 <&sysclk K210_CLK_APB1>;
+				clock-names = "tclk", "pclk";
+				resets = <&sysrst K210_RST_WDT1>;
+				status = "disabled";
+			};
+
+			otp0: nvmem@50420000 {
+				#address-cells = <1>;
+				#size-cells = <1>;
+				compatible = "kendryte,k210-otp";
+				reg = <0x50420000 0x100>,
+				      <0x88000000 0x20000>;
+				reg-names = "reg", "mem";
+				clocks = <&sysclk K210_CLK_ROM>;
+				resets = <&sysrst K210_RST_ROM>;
+				read-only;
+				status = "disabled";
+
+				/* Bootloader */
+				firmware@00000 {
+					reg = <0x00000 0xC200>;
+				};
+
+				/*
+				 * config string as described in RISC-V
+				 * privileged spec 1.9
+				 */
+				config-1-9@1c000 {
+					reg = <0x1C000 0x1000>;
+				};
+
+				/*
+				 * Device tree containing only registers,
+				 * interrupts, and cpus
+				 */
+				fdt@1d000 {
+					reg = <0x1D000 0x2000>;
+				};
+
+				/* CPU/ROM credits */
+				credits@1f000 {
+					reg = <0x1F000 0x1000>;
+				};
+			};
+
+			dvp0: camera@50430000 {
+				compatible = "kendryte,k210-dvp";
+				reg = <0x50430000 0x100>;
+				interrupts = <24>;
+				clocks = <&sysclk K210_CLK_DVP>;
+				resets = <&sysrst K210_RST_DVP>;
+				kendryte,sysctl = <&sysctl>;
+				kendryte,misc-offset = <K210_SYSCTL_MISC>;
+				status = "disabled";
+			};
+
+			sysctl: syscon@50440000 {
+				compatible = "kendryte,k210-sysctl",
+					     "syscon", "simple-mfd";
+				reg = <0x50440000 0x100>;
+				reg-io-width = <4>;
+				clocks = <&sysclk K210_CLK_APB1>;
+				clock-names = "pclk";
+
+				sysclk: clock-controller {
+					#clock-cells = <1>;
+					compatible = "kendryte,k210-clk";
+					clocks = <&in0>;
+				};
+
+				sysrst: reset-controller {
+					compatible = "kendryte,k210-rst",
+						     "syscon-reset";
+					#reset-cells = <1>;
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_PERI_RESET>;
+					mask = <0x27FFFFFF>;
+					assert-high = <1>;
+				};
+
+				reboot {
+					compatible = "syscon-reboot";
+					regmap = <&sysctl>;
+					offset = <K210_SYSCTL_SOFT_RESET>;
+					mask = <1>;
+					value = <1>;
+				};
+			};
+
+			aes0: aes@50450000 {
+				compatible = "kendryte,k210-aes";
+				reg = <0x50450000 0x100>;
+				clocks = <&sysclk K210_CLK_AES>;
+				resets = <&sysrst K210_RST_AES>;
+				status = "disabled";
+			};
+
+			rtc: rtc@50460000 {
+				compatible = "kendryte,k210-rtc";
+				reg = <0x50460000 0x100>;
+				clocks = <&in0>;
+				resets = <&sysrst K210_RST_RTC>;
+				interrupts = <20>;
+				status = "disabled";
+			};
+		};
+
+		apb2: bus@52000000 {
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "kendryte,k210-apb", "simple-pm-bus";
+			ranges;
+			clocks = <&sysclk K210_CLK_APB2>;
+
+			spi0: spi@52000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x52000000 0x100>;
+				interrupts = <1>;
+				clocks = <&sysclk K210_CLK_SPI0>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI0>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi1: spi@53000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-spi",
+					     "snps,dw-apb-ssi-4.01",
+					     "snps,dw-apb-ssi";
+				reg = <0x53000000 0x100>;
+				interrupts = <2>;
+				clocks = <&sysclk K210_CLK_SPI1>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI1>;
+				reset-names = "spi";
+				spi-max-frequency = <25000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
+
+			spi3: spi@54000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "canaan,kendryte-k210-ssi",
+					     "snps,dwc-ssi-1.01a";
+				reg = <0x54000000 0x200>;
+				interrupts = <4>;
+				clocks = <&sysclk K210_CLK_SPI3>,
+					 <&sysclk K210_CLK_APB2>;
+				clock-names = "ssi_clk", "pclk";
+				resets = <&sysrst K210_RST_SPI3>;
+				reset-names = "spi";
+				/* Could possibly go up to 200 MHz */
+				spi-max-frequency = <100000000>;
+				num-cs = <4>;
+				reg-io-width = <4>;
+				status = "disabled";
+			};
 		};
 	};
 };
diff --git a/arch/riscv/boot/dts/kendryte/k210_generic.dts b/arch/riscv/boot/dts/kendryte/k210_generic.dts
new file mode 100644
index 000000000000..f336f60dc15d
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_generic.dts
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte K210 generic";
+	compatible = "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 27/32] riscv: Add SiPeed MAIX BiT board device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX BiT and MAIX BiTm boards. This
device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++++++++++++++++
 1 file changed, 226 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
new file mode 100644
index 000000000000..fc814f7c1173
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX BiT";
+	compatible = "sipeed,maix-bitm", "sipeed,maix-bit",
+		     "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 27/32] riscv: Add SiPeed MAIX BiT board device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX BiT and MAIX BiTm boards. This
device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++++++++++++++++
 1 file changed, 226 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
new file mode 100644
index 000000000000..fc814f7c1173
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
@@ -0,0 +1,226 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX BiT";
+	compatible = "sipeed,maix-bitm", "sipeed,maix-bit",
+		     "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 28/32] riscv: Add SiPeed MAIX DOCK board device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX DOCK m1 and m1w boards. This
device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../boot/dts/kendryte/k210_maix_dock.dts      | 229 ++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_dock.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts b/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
new file mode 100644
index 000000000000..2ae8413b1e4c
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX Dock";
+	compatible = "sipeed,maix-dock-m1wm", "sipeed,maix-dock-m1",
+		     "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		/*
+		 * Note: the board specification document green on gpio #4,
+		 * red on gpio #5 and blue on gpio #6. However, the board
+		 * is actually wired differently as defined here.
+		 */
+		blue {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		green {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(9, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 28/32] riscv: Add SiPeed MAIX DOCK board device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX DOCK m1 and m1w boards. This
device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../boot/dts/kendryte/k210_maix_dock.dts      | 229 ++++++++++++++++++
 1 file changed, 229 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_dock.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts b/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
new file mode 100644
index 000000000000..2ae8413b1e4c
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_dock.dts
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX Dock";
+	compatible = "sipeed,maix-dock-m1wm", "sipeed,maix-dock-m1",
+		     "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		/*
+		 * Note: the board specification document green on gpio #4,
+		 * red on gpio #5 and blue on gpio #6. However, the board
+		 * is actually wired differently as defined here.
+		 */
+		blue {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		green {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(9, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 29/32] riscv: Add SiPeed MAIX GO board device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX GO board. This device tree
enables buttons, LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/boot/dts/kendryte/k210_maix_go.dts | 237 ++++++++++++++++++
 1 file changed, 237 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_go.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_go.dts b/arch/riscv/boot/dts/kendryte/k210_maix_go.dts
new file mode 100644
index 000000000000..8254d93a5e82
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_go.dts
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX GO";
+	compatible = "sipeed,maix-go", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		up {
+			label = "UP";
+			linux,code = <BTN_1>;
+			gpios = <&gpio1_0 7 GPIO_ACTIVE_LOW>;
+		};
+
+		press {
+			label = "PRESS";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		down {
+			label = "DOWN";
+			linux,code = <BTN_2>;
+			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 29/32] riscv: Add SiPeed MAIX GO board device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIX GO board. This device tree
enables buttons, LEDs, gpio, i2c and spi/mmc SD card devices.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/boot/dts/kendryte/k210_maix_go.dts | 237 ++++++++++++++++++
 1 file changed, 237 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_go.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_go.dts b/arch/riscv/boot/dts/kendryte/k210_maix_go.dts
new file mode 100644
index 000000000000..8254d93a5e82
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maix_go.dts
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIX GO";
+	compatible = "sipeed,maix-go", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		green {
+			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
+		};
+
+		red {
+			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
+		};
+
+		blue {
+			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		up {
+			label = "UP";
+			linux,code = <BTN_1>;
+			gpios = <&gpio1_0 7 GPIO_ACTIVE_LOW>;
+		};
+
+		press {
+			label = "PRESS";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+
+		down {
+			label = "DOWN";
+			linux,code = <BTN_2>;
+			gpios = <&gpio0 1 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
+			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
+			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
+			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
+			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
+			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
+			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
+			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
+			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
+			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 30/32] riscv: Add SiPeed MAIXDUINO board device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIXDUINO board. This device tree
enables LEDs and spi/mmc SD card device. Additionally, gpios and i2c
are also enabled and mapped to the board header pins as indicated on
the board itself.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++++++++++++++++
 1 file changed, 203 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maixduino.dts b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
new file mode 100644
index 000000000000..78a37cf9df97
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIXDUINO";
+	compatible = "sipeed,maixduino", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	status = "okay";
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,  /* BOOT */
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS2)>,  /* Header "2" */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS3)>,  /* Header "3" */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS4)>,  /* Header "4" */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS5)>,  /* Header "5" */
+			 <K210_FPIOA(32, K210_PCF_GPIOHS6)>,  /* Header "6" */
+			 <K210_FPIOA(15, K210_PCF_GPIOHS7)>,  /* Header "7" */
+			 <K210_FPIOA(14, K210_PCF_GPIOHS8)>,  /* Header "8" */
+			 <K210_FPIOA(13, K210_PCF_GPIOHS9)>,  /* Header "9" */
+			 <K210_FPIOA(12, K210_PCF_GPIOHS10)>, /* Header "10" */
+			 <K210_FPIOA(11, K210_PCF_GPIOHS11)>, /* Header "11" */
+			 <K210_FPIOA(10, K210_PCF_GPIOHS12)>, /* Header "12" */
+			 <K210_FPIOA(3,  K210_PCF_GPIOHS13)>, /* Header "13" */
+			 <K210_FPIOA(25, K210_PCF_GPIOHS14)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>, /* Header "scl" */
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;  /* Header "sda" */
+	};
+
+	fpioa_i2s1: i2s1 {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S1_WS)>,
+			 <K210_FPIOA(34, K210_PCF_I2S1_IN_D0)>,
+			 <K210_FPIOA(35, K210_PCF_I2S1_SCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 30/32] riscv: Add SiPeed MAIXDUINO board device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the SiPeed MAIXDUINO board. This device tree
enables LEDs and spi/mmc SD card device. Additionally, gpios and i2c
are also enabled and mapped to the board header pins as indicated on
the board itself.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++++++++++++++++
 1 file changed, 203 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_maixduino.dts b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
new file mode 100644
index 000000000000..78a37cf9df97
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
@@ -0,0 +1,203 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "SiPeed MAIXDUINO";
+	compatible = "sipeed,maixduino", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		boot {
+			label = "BOOT";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	status = "okay";
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
+	};
+
+	fpioa_gpio: gpio {
+		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
+			 <K210_FPIOA(9, K210_PCF_GPIO1)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,  /* BOOT */
+			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
+			 <K210_FPIOA(21, K210_PCF_GPIOHS2)>,  /* Header "2" */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS3)>,  /* Header "3" */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS4)>,  /* Header "4" */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS5)>,  /* Header "5" */
+			 <K210_FPIOA(32, K210_PCF_GPIOHS6)>,  /* Header "6" */
+			 <K210_FPIOA(15, K210_PCF_GPIOHS7)>,  /* Header "7" */
+			 <K210_FPIOA(14, K210_PCF_GPIOHS8)>,  /* Header "8" */
+			 <K210_FPIOA(13, K210_PCF_GPIOHS9)>,  /* Header "9" */
+			 <K210_FPIOA(12, K210_PCF_GPIOHS10)>, /* Header "10" */
+			 <K210_FPIOA(11, K210_PCF_GPIOHS11)>, /* Header "11" */
+			 <K210_FPIOA(10, K210_PCF_GPIOHS12)>, /* Header "12" */
+			 <K210_FPIOA(3,  K210_PCF_GPIOHS13)>, /* Header "13" */
+			 <K210_FPIOA(25, K210_PCF_GPIOHS14)>;
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
+			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2c1: i2c1 {
+		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>, /* Header "scl" */
+			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;  /* Header "sda" */
+	};
+
+	fpioa_i2s1: i2s1 {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S1_WS)>,
+			 <K210_FPIOA(34, K210_PCF_I2S1_IN_D0)>,
+			 <K210_FPIOA(35, K210_PCF_I2S1_SCLK)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
+			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
+			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
+			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio1 {
+	pinctrl-0 = <&fpioa_gpio>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&i2c1 {
+	pinctrl-0 = <&fpioa_i2c1>;
+	pinctrl-names = "default";
+	clock-frequency = <400000>;
+	status = "okay";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "sitronix,st7789v";
+		reg = <0>;
+		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+		dc-gpios = <&gpio0 22 0>;
+		spi-max-frequency = <15000000>;
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
+
+&spi3 {
+	spi-flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <50000000>;
+		m25p,fast-read;
+		broken-flash-reset;
+	};
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 31/32] riscv: Add Kendryte KD233 board device tree
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the Kendryte KD233 board (K210 test board).
This device tree enables LEDs, some gpios and spi/mmc SD card device.
The WS2812B RGB LED and the 10 position rotary dip switch present on the
board are left undefined.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/boot/dts/kendryte/k210_kd233.dts | 177 ++++++++++++++++++++
 1 file changed, 177 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_kd233.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_kd233.dts b/arch/riscv/boot/dts/kendryte/k210_kd233.dts
new file mode 100644
index 000000000000..b4e721a31000
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_kd233.dts
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte KD233";
+	compatible = "kendryte,kd233", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led1 {
+			gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		key0 {
+			label = "KEY0";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(6, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(7, K210_PCF_SPI0_SCLK)>, /* wr */
+			 <K210_FPIOA(8, K210_PCF_GPIOHS21)>;  /* dc */
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(9, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(11, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(12, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(13, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(14, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(15, K210_PCF_DVP_PCLK)>,
+			 <K210_FPIOA(17, K210_PCF_DVP_HSYNC)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(20, K210_PCF_GPIOHS4)>, /* Rot. dip sw line 8 */
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>, /* Rot. dip sw line 4 */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>, /* Rot. dip sw line 2 */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>, /* Rot. dip sw line 1 */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(26, K210_PCF_GPIOHS10)>;
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(29, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(30, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(31, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(32, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S0_IN_D0)>,
+			 <K210_FPIOA(34, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(35, K210_PCF_I2S0_SCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "ilitek,ili9341";
+		reg = <0>;
+		dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 31/32] riscv: Add Kendryte KD233 board device tree
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Add a device tree for the Kendryte KD233 board (K210 test board).
This device tree enables LEDs, some gpios and spi/mmc SD card device.
The WS2812B RGB LED and the 10 position rotary dip switch present on the
board are left undefined.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/boot/dts/kendryte/k210_kd233.dts | 177 ++++++++++++++++++++
 1 file changed, 177 insertions(+)
 create mode 100644 arch/riscv/boot/dts/kendryte/k210_kd233.dts

diff --git a/arch/riscv/boot/dts/kendryte/k210_kd233.dts b/arch/riscv/boot/dts/kendryte/k210_kd233.dts
new file mode 100644
index 000000000000..b4e721a31000
--- /dev/null
+++ b/arch/riscv/boot/dts/kendryte/k210_kd233.dts
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+/dts-v1/;
+
+#include "k210.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+	model = "Kendryte KD233";
+	compatible = "kendryte,kd233", "kendryte,k210";
+
+	chosen {
+		bootargs = "earlycon console=ttySIF0";
+		stdout-path = "serial0:115200n8";
+	};
+
+	gpio-leds {
+		compatible = "gpio-leds";
+
+		led0 {
+			gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
+		};
+
+		led1 {
+			gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		key0 {
+			label = "KEY0";
+			linux,code = <BTN_0>;
+			gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	sound {
+		compatible = "simple-audio-card";
+		simple-audio-card,format = "i2s";
+		status = "disabled";
+
+		simple-audio-card,cpu {
+			sound-dai = <&i2s0 0>;
+		};
+
+		simple-audio-card,codec {
+			sound-dai = <&mic>;
+		};
+	};
+
+	mic: mic {
+		#sound-dai-cells = <0>;
+		compatible = "memsensing,msm261s4030h0";
+		status = "disabled";
+	};
+};
+
+&fpioa {
+	pinctrl-0 = <&fpioa_jtag>;
+	pinctrl-names = "default";
+	status = "okay";
+
+	fpioa_jtag: jtag {
+		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
+			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
+			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
+			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
+	};
+
+	fpioa_uarths: uarths {
+		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
+			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
+	};
+
+	fpioa_spi0: spi0 {
+		pinmux = <K210_FPIOA(6, K210_PCF_GPIOHS20)>,  /* cs */
+			 <K210_FPIOA(7, K210_PCF_SPI0_SCLK)>, /* wr */
+			 <K210_FPIOA(8, K210_PCF_GPIOHS21)>;  /* dc */
+	};
+
+	fpioa_dvp: dvp {
+		pinmux = <K210_FPIOA(9, K210_PCF_SCCB_SCLK)>,
+			 <K210_FPIOA(10, K210_PCF_SCCB_SDA)>,
+			 <K210_FPIOA(11, K210_PCF_DVP_RST)>,
+			 <K210_FPIOA(12, K210_PCF_DVP_VSYNC)>,
+			 <K210_FPIOA(13, K210_PCF_DVP_PWDN)>,
+			 <K210_FPIOA(14, K210_PCF_DVP_XCLK)>,
+			 <K210_FPIOA(15, K210_PCF_DVP_PCLK)>,
+			 <K210_FPIOA(17, K210_PCF_DVP_HSYNC)>;
+	};
+
+	fpioa_gpiohs: gpiohs {
+		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
+			 <K210_FPIOA(20, K210_PCF_GPIOHS4)>, /* Rot. dip sw line 8 */
+			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>, /* Rot. dip sw line 4 */
+			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>, /* Rot. dip sw line 2 */
+			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>, /* Rot. dip sw line 1 */
+			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
+			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
+			 <K210_FPIOA(26, K210_PCF_GPIOHS10)>;
+	};
+
+	fpioa_spi1: spi1 {
+		pinmux = <K210_FPIOA(29, K210_PCF_SPI1_SCLK)>,
+			 <K210_FPIOA(30, K210_PCF_SPI1_D0)>,
+			 <K210_FPIOA(31, K210_PCF_SPI1_D1)>,
+			 <K210_FPIOA(32, K210_PCF_SPI1_SS0)>; /* cs */
+	};
+
+	fpioa_i2s0: i2s0 {
+		pinmux = <K210_FPIOA(33, K210_PCF_I2S0_IN_D0)>,
+			 <K210_FPIOA(34, K210_PCF_I2S0_WS)>,
+			 <K210_FPIOA(35, K210_PCF_I2S0_SCLK)>;
+	};
+};
+
+&uarths0 {
+	pinctrl-0 = <&fpioa_uarths>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&gpio0 {
+	pinctrl-0 = <&fpioa_gpiohs>;
+	pinctrl-names = "default";
+	status = "okay";
+};
+
+&i2s0 {
+	#sound-dai-cells = <1>;
+	pinctrl-0 = <&fpioa_i2s0>;
+	pinctrl-names = "default";
+};
+
+&dvp0 {
+	pinctrl-0 = <&fpioa_dvp>;
+	pinctrl-names = "default";
+};
+
+&spi0 {
+	pinctrl-0 = <&fpioa_spi0>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	cs-gpios = <&gpio0 20 0>;
+
+	panel@0 {
+		compatible = "ilitek,ili9341";
+		reg = <0>;
+		dc-gpios = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+		spi-max-frequency = <15000000>;
+		status = "disabled";
+	};
+};
+
+&spi1 {
+	pinctrl-0 = <&fpioa_spi1>;
+	pinctrl-names = "default";
+	num-cs = <1>;
+	polling;
+	status = "okay";
+
+	slot@0 {
+		compatible = "mmc-spi-slot";
+		reg = <0>;
+		voltage-ranges = <3300 3300>;
+		spi-max-frequency = <4000000>;
+		broken-cd;
+	};
+};
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 32/32] riscv: Update Kendryte K210 defconfig
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-07  8:14   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update the k210 nommu default configuration nommu_k210_defconfig to
include device drivers for reset, reboot, I2C, gpio, LEDs and SD card
support. The boot options are modified to mount the file system on the
first partition of the SD card as the root file system.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/configs/nommu_k210_defconfig | 45 +++++++++++++++++++------
 1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig
index cd1df62b13c7..dda0f437de21 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -1,13 +1,6 @@
 # CONFIG_CPU_ISOLATION is not set
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_FORCE=y
-# CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
-# CONFIG_RD_XZ is not set
-# CONFIG_RD_LZO is not set
-# CONFIG_RD_LZ4 is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSFS_SYSCALL is not set
 # CONFIG_FHANDLE is not set
@@ -25,22 +18,26 @@ CONFIG_EMBEDDED=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLOB=y
-# CONFIG_SLAB_MERGE_DEFAULT is not set
 # CONFIG_MMU is not set
 CONFIG_SOC_KENDRYTE=y
 CONFIG_MAXPHYSMEM_2GB=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_CMDLINE="earlycon console=ttySIF0"
+CONFIG_CMDLINE="earlycon console=ttySIF0 rootdelay=2 root=/dev/mmcblk0p1 rw"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_JUMP_LABEL=y
-# CONFIG_BLOCK is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_STACKPROTECTOR_STRONG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
 CONFIG_BINFMT_FLAT=y
 # CONFIG_COREDUMP is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_BLK_DEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
@@ -48,16 +45,42 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_LDISC_AUTOLOAD is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_DEVMEM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+# CONFIG_SPI_MEM is not set
+CONFIG_SPI_DESIGNWARE=y
+CONFIG_SPI_DW_MMIO=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GPIO_CDEV_V1 is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
 # CONFIG_HWMON is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_PWRSEQ_EMMC is not set
+# CONFIG_PWRSEQ_SIMPLE is not set
+CONFIG_MMC_SPI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_USER=y
 # CONFIG_VIRTIO_MENU is not set
+# CONFIG_VHOST_MENU is not set
+# CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_LSM="[]"
 CONFIG_PRINTK_TIME=y
+# CONFIG_SYMBOLIC_ERRNAME is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MISC is not set
 CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 297+ messages in thread

* [PATCH 32/32] riscv: Update Kendryte K210 defconfig
@ 2020-11-07  8:14   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07  8:14 UTC (permalink / raw)
  To: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel
  Cc: Sean Anderson

Update the k210 nommu default configuration nommu_k210_defconfig to
include device drivers for reset, reboot, I2C, gpio, LEDs and SD card
support. The boot options are modified to mount the file system on the
first partition of the SD card as the root file system.

Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
---
 arch/riscv/configs/nommu_k210_defconfig | 45 +++++++++++++++++++------
 1 file changed, 34 insertions(+), 11 deletions(-)

diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig
index cd1df62b13c7..dda0f437de21 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -1,13 +1,6 @@
 # CONFIG_CPU_ISOLATION is not set
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=14
 CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_FORCE=y
-# CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
-# CONFIG_RD_XZ is not set
-# CONFIG_RD_LZO is not set
-# CONFIG_RD_LZ4 is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSFS_SYSCALL is not set
 # CONFIG_FHANDLE is not set
@@ -25,22 +18,26 @@ CONFIG_EMBEDDED=y
 # CONFIG_VM_EVENT_COUNTERS is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLOB=y
-# CONFIG_SLAB_MERGE_DEFAULT is not set
 # CONFIG_MMU is not set
 CONFIG_SOC_KENDRYTE=y
 CONFIG_MAXPHYSMEM_2GB=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
-CONFIG_CMDLINE="earlycon console=ttySIF0"
+CONFIG_CMDLINE="earlycon console=ttySIF0 rootdelay=2 root=/dev/mmcblk0p1 rw"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_JUMP_LABEL=y
-# CONFIG_BLOCK is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_STACKPROTECTOR_STRONG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
 CONFIG_BINFMT_FLAT=y
 # CONFIG_COREDUMP is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FW_LOADER is not set
 # CONFIG_ALLOW_DEV_COREDUMP is not set
+# CONFIG_BLK_DEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
@@ -48,16 +45,42 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_LDISC_AUTOLOAD is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_DEVMEM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_DESIGNWARE_PLATFORM=y
+CONFIG_SPI=y
+# CONFIG_SPI_MEM is not set
+CONFIG_SPI_DESIGNWARE=y
+CONFIG_SPI_DW_MMIO=y
+CONFIG_GPIO_SYSFS=y
+# CONFIG_GPIO_CDEV_V1 is not set
+CONFIG_GPIO_DWAPB=y
+CONFIG_GPIO_SIFIVE=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
 # CONFIG_HWMON is not set
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+# CONFIG_PWRSEQ_EMMC is not set
+# CONFIG_PWRSEQ_SIMPLE is not set
+CONFIG_MMC_SPI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_USER=y
 # CONFIG_VIRTIO_MENU is not set
+# CONFIG_VHOST_MENU is not set
+# CONFIG_FILE_LOCKING is not set
 # CONFIG_DNOTIFY is not set
 # CONFIG_INOTIFY_USER is not set
 # CONFIG_MISC_FILESYSTEMS is not set
 CONFIG_LSM="[]"
 CONFIG_PRINTK_TIME=y
+# CONFIG_SYMBOLIC_ERRNAME is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_MISC is not set
 CONFIG_PANIC_ON_OOPS=y
 # CONFIG_SCHED_DEBUG is not set
-- 
2.28.0


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-07 13:28     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:28 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> 
> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> | other stuff | spi_frf  |  dfs_32  |
> 
> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> 
> Th main difference of this layout with the 16-bits version is the data
> frame format field which resides in bits 16..20 instead of bits 3..0.
> 
> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
> platform signal that this layout is in use. Modify
> dw_spi_update_config() to test this capability flag to set the data
> frame format field at the correct register location.
> 
> Suggested-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 8 ++++++--
>  drivers/spi/spi-dw.h      | 9 +++++++++
>  2 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 2e50cc0a9291..841c85247f01 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>  	u32 speed_hz;
>  	u16 clk_div;
>  
> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
> -	cr0 |= (cfg->dfs - 1);
> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1);
> +	else
> +		/* CTRLR0[20: 16] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
>  
>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>  		/* CTRLR0[ 9:8] Transfer Mode */
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index faf40cb66498..48a11a51a407 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -9,6 +9,7 @@
>  #include <linux/io.h>
>  #include <linux/scatterlist.h>
>  #include <linux/spi/spi-mem.h>
> +#include <linux/bitfield.h>
>  
>  /* Register offsets */
>  #define DW_SPI_CTRLR0			0x00
> @@ -72,6 +73,13 @@
>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>  
> +/*
> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
> + * Based on DW_apb_ssi Databook v4.02a.
> + */
> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
> +
>  /*
>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>   * 0: SSI is slave
> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
> +#define DW_SPI_CAP_DFS_32		BIT(3)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-07 13:28     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:28 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> 
> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> | other stuff | spi_frf  |  dfs_32  |
> 
> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> 
> Th main difference of this layout with the 16-bits version is the data
> frame format field which resides in bits 16..20 instead of bits 3..0.
> 
> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
> platform signal that this layout is in use. Modify
> dw_spi_update_config() to test this capability flag to set the data
> frame format field at the correct register location.
> 
> Suggested-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 8 ++++++--
>  drivers/spi/spi-dw.h      | 9 +++++++++
>  2 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 2e50cc0a9291..841c85247f01 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>  	u32 speed_hz;
>  	u16 clk_div;
>  
> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
> -	cr0 |= (cfg->dfs - 1);
> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1);
> +	else
> +		/* CTRLR0[20: 16] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
>  
>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>  		/* CTRLR0[ 9:8] Transfer Mode */
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index faf40cb66498..48a11a51a407 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -9,6 +9,7 @@
>  #include <linux/io.h>
>  #include <linux/scatterlist.h>
>  #include <linux/spi/spi-mem.h>
> +#include <linux/bitfield.h>
>  
>  /* Register offsets */
>  #define DW_SPI_CTRLR0			0x00
> @@ -72,6 +73,13 @@
>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>  
> +/*
> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
> + * Based on DW_apb_ssi Databook v4.02a.
> + */
> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
> +
>  /*
>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>   * 0: SSI is slave
> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
> +#define DW_SPI_CAP_DFS_32		BIT(3)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-07 13:30     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:30 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> Fix for the Synopsis DesignWare SPI mmio driver taken from the work
> by Sean Anderson for the U-Boot project. Sean comments:
> 
> The resting state of MOSI is high when nothing is driving it. If we
> drive it low while recieving, it looks like we are transmitting 0x00
> instead of transmitting nothing. This can confuse slaves (like SD cards)
> which allow new commands to be sent over MOSI while they are returning
> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> a byte can look like a start bit and a transmission bit to an SD card.
> This will cause the card to become out-of-sync with the SPI device, as
> it thinks the device has already started transmitting two bytes of a new
> command. The mmc-spi driver will not detect the R1 response from the SD
> card, since it is sent too early, and offset by two bits. This patch
> fixes transfer errors when using SD cards with dw spi.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 841c85247f01..c2ef1d8d46d5 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -137,7 +137,7 @@ static inline u32 rx_max(struct dw_spi *dws)
>  static void dw_writer(struct dw_spi *dws)
>  {
>  	u32 max = tx_max(dws);
> -	u16 txw = 0;
> +	u16 txw = 0xffff;
>  
>  	while (max--) {
>  		if (dws->tx) {
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-07 13:30     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:30 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> Fix for the Synopsis DesignWare SPI mmio driver taken from the work
> by Sean Anderson for the U-Boot project. Sean comments:
> 
> The resting state of MOSI is high when nothing is driving it. If we
> drive it low while recieving, it looks like we are transmitting 0x00
> instead of transmitting nothing. This can confuse slaves (like SD cards)
> which allow new commands to be sent over MOSI while they are returning
> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> a byte can look like a start bit and a transmission bit to an SD card.
> This will cause the card to become out-of-sync with the SPI device, as
> it thinks the device has already started transmitting two bytes of a new
> command. The mmc-spi driver will not detect the R1 response from the SD
> card, since it is sent too early, and offset by two bits. This patch
> fixes transfer errors when using SD cards with dw spi.
> 
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 841c85247f01..c2ef1d8d46d5 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -137,7 +137,7 @@ static inline u32 rx_max(struct dw_spi *dws)
>  static void dw_writer(struct dw_spi *dws)
>  {
>  	u32 max = tx_max(dws);
> -	u16 txw = 0;
> +	u16 txw = 0xffff;
>  
>  	while (max--) {
>  		if (dws->tx) {
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-07 13:31     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:31 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> ctrlr0 register format. This SoC is also quite slow and gets significant
> SD card performance improvements from using no-delay polled transfers.
> Add the dw_spi_k210_init() function tied to the
> "canaan,kendryte-k210-spi" compatible string to set the
> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> for this SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index 3f1bc384cb45..a00def6c5b39 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int dw_spi_k210_init(struct platform_device *pdev,
> +			    struct dw_spi_mmio *dwsmmio)
> +{
> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;

Can't you do runtime detection of DFS_32 in probe?

--Sean

> +
> +	return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>  	int (*init_func)(struct platform_device *pdev,
> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>  	{ /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> 


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-07 13:31     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:31 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:13 AM, Damien Le Moal wrote:
> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> ctrlr0 register format. This SoC is also quite slow and gets significant
> SD card performance improvements from using no-delay polled transfers.
> Add the dw_spi_k210_init() function tied to the
> "canaan,kendryte-k210-spi" compatible string to set the
> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> for this SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index 3f1bc384cb45..a00def6c5b39 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int dw_spi_k210_init(struct platform_device *pdev,
> +			    struct dw_spi_mmio *dwsmmio)
> +{
> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;

Can't you do runtime detection of DFS_32 in probe?

--Sean

> +
> +	return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>  	int (*init_func)(struct platform_device *pdev,
> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>  	{ /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 14/32] dt-bindings: Define all Kendryte K210 clock IDs
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:33     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:33 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Define unique arbitrary IDs for all 44 clocks available on the Kendryte
> K210 RISC-V SoC in the header file include/dt-bindings/clock/k210-clk.h.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/clock/k210-clk.h | 61 +++++++++++++++++++++++-----
>  1 file changed, 50 insertions(+), 11 deletions(-)
> 
> diff --git a/include/dt-bindings/clock/k210-clk.h b/include/dt-bindings/clock/k210-clk.h
> index 5a2fd64d1a49..8d7ab2f0737c 100644
> --- a/include/dt-bindings/clock/k210-clk.h
> +++ b/include/dt-bindings/clock/k210-clk.h
> @@ -3,18 +3,57 @@
>   * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
>   * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>   */
> -#ifndef K210_CLK_H
> -#define K210_CLK_H
> +#ifndef CLOCK_K210_CLK_H
> +#define CLOCK_K210_CLK_H
>  
>  /*
> - * Arbitrary identifiers for clocks.
> - * The structure is: in0 -> pll0 -> aclk -> cpu
> - *
> - * Since we use the hardware defaults for now, set all these to the same clock.
> + * Kendryte K210 SoC clock identifiers (arbitrary values).
>   */
> -#define K210_CLK_PLL0   0
> -#define K210_CLK_PLL1   0
> -#define K210_CLK_ACLK   0
> -#define K210_CLK_CPU    0
> +#define K210_CLK_IN0	0
> +#define K210_CLK_PLL0	1
> +#define K210_CLK_PLL1	2
> +#define K210_CLK_PLL2	3
> +#define K210_CLK_ACLK	4
> +#define K210_CLK_CPU	5
> +#define K210_CLK_CLINT	6
> +#define K210_CLK_DMA	7
> +#define K210_CLK_FFT	8
> +#define K210_CLK_SRAM0	9
> +#define K210_CLK_SRAM1	10
> +#define K210_CLK_ROM	11
> +#define K210_CLK_DVP	12
> +#define K210_CLK_APB0	13
> +#define K210_CLK_APB1	14
> +#define K210_CLK_APB2	15
> +#define K210_CLK_AI	16
> +#define K210_CLK_I2S0	17
> +#define K210_CLK_I2S1	18
> +#define K210_CLK_I2S2	19
> +#define K210_CLK_I2S0_M	20
> +#define K210_CLK_I2S1_M	21
> +#define K210_CLK_I2S2_M	22
> +#define K210_CLK_WDT0	23
> +#define K210_CLK_WDT1	24
> +#define K210_CLK_SPI0	25
> +#define K210_CLK_SPI1	26
> +#define K210_CLK_SPI2	27
> +#define K210_CLK_I2C0	28
> +#define K210_CLK_I2C1	29
> +#define K210_CLK_I2C2	30
> +#define K210_CLK_SPI3	31
> +#define K210_CLK_TIMER0	32
> +#define K210_CLK_TIMER1	33
> +#define K210_CLK_TIMER2	34
> +#define K210_CLK_GPIO	35
> +#define K210_CLK_UART1	36
> +#define K210_CLK_UART2	37
> +#define K210_CLK_UART3	38
> +#define K210_CLK_FPIOA	39
> +#define K210_CLK_SHA	40
> +#define K210_CLK_AES	41
> +#define K210_CLK_OTP	42
> +#define K210_CLK_RTC	43
>  
> -#endif /* K210_CLK_H */
> +#define K210_NUM_CLKS	44
> +
> +#endif /* CLOCK_K210_CLK_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 14/32] dt-bindings: Define all Kendryte K210 clock IDs
@ 2020-11-07 13:33     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:33 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Define unique arbitrary IDs for all 44 clocks available on the Kendryte
> K210 RISC-V SoC in the header file include/dt-bindings/clock/k210-clk.h.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/clock/k210-clk.h | 61 +++++++++++++++++++++++-----
>  1 file changed, 50 insertions(+), 11 deletions(-)
> 
> diff --git a/include/dt-bindings/clock/k210-clk.h b/include/dt-bindings/clock/k210-clk.h
> index 5a2fd64d1a49..8d7ab2f0737c 100644
> --- a/include/dt-bindings/clock/k210-clk.h
> +++ b/include/dt-bindings/clock/k210-clk.h
> @@ -3,18 +3,57 @@
>   * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
>   * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>   */
> -#ifndef K210_CLK_H
> -#define K210_CLK_H
> +#ifndef CLOCK_K210_CLK_H
> +#define CLOCK_K210_CLK_H
>  
>  /*
> - * Arbitrary identifiers for clocks.
> - * The structure is: in0 -> pll0 -> aclk -> cpu
> - *
> - * Since we use the hardware defaults for now, set all these to the same clock.
> + * Kendryte K210 SoC clock identifiers (arbitrary values).
>   */
> -#define K210_CLK_PLL0   0
> -#define K210_CLK_PLL1   0
> -#define K210_CLK_ACLK   0
> -#define K210_CLK_CPU    0
> +#define K210_CLK_IN0	0
> +#define K210_CLK_PLL0	1
> +#define K210_CLK_PLL1	2
> +#define K210_CLK_PLL2	3
> +#define K210_CLK_ACLK	4
> +#define K210_CLK_CPU	5
> +#define K210_CLK_CLINT	6
> +#define K210_CLK_DMA	7
> +#define K210_CLK_FFT	8
> +#define K210_CLK_SRAM0	9
> +#define K210_CLK_SRAM1	10
> +#define K210_CLK_ROM	11
> +#define K210_CLK_DVP	12
> +#define K210_CLK_APB0	13
> +#define K210_CLK_APB1	14
> +#define K210_CLK_APB2	15
> +#define K210_CLK_AI	16
> +#define K210_CLK_I2S0	17
> +#define K210_CLK_I2S1	18
> +#define K210_CLK_I2S2	19
> +#define K210_CLK_I2S0_M	20
> +#define K210_CLK_I2S1_M	21
> +#define K210_CLK_I2S2_M	22
> +#define K210_CLK_WDT0	23
> +#define K210_CLK_WDT1	24
> +#define K210_CLK_SPI0	25
> +#define K210_CLK_SPI1	26
> +#define K210_CLK_SPI2	27
> +#define K210_CLK_I2C0	28
> +#define K210_CLK_I2C1	29
> +#define K210_CLK_I2C2	30
> +#define K210_CLK_SPI3	31
> +#define K210_CLK_TIMER0	32
> +#define K210_CLK_TIMER1	33
> +#define K210_CLK_TIMER2	34
> +#define K210_CLK_GPIO	35
> +#define K210_CLK_UART1	36
> +#define K210_CLK_UART2	37
> +#define K210_CLK_UART3	38
> +#define K210_CLK_FPIOA	39
> +#define K210_CLK_SHA	40
> +#define K210_CLK_AES	41
> +#define K210_CLK_OTP	42
> +#define K210_CLK_RTC	43
>  
> -#endif /* K210_CLK_H */
> +#define K210_NUM_CLKS	44
> +
> +#endif /* CLOCK_K210_CLK_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:34     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:34 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> define the offset of all registers of the K210 system controller.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
> 
> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
> new file mode 100644
> index 000000000000..5cc386d3c9ca
> --- /dev/null
> +++ b/include/dt-bindings/mfd/k210-sysctl.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef MFD_K210_SYSCTL_H
> +#define MFD_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller registers offsets.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
> +
> +#endif /* MFD_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
@ 2020-11-07 13:34     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:34 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> define the offset of all registers of the K210 system controller.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
> 
> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
> new file mode 100644
> index 000000000000..5cc386d3c9ca
> --- /dev/null
> +++ b/include/dt-bindings/mfd/k210-sysctl.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef MFD_K210_SYSCTL_H
> +#define MFD_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller registers offsets.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
> +
> +#endif /* MFD_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 16/32] dt-bindings: Define Kendryte K210 pin functions
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:38     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:38 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file
> include/dt-bindings/pinctrl/k210_pinctrl.h to define all possible 255
> functions that can be assigned to any of the 48 programmable pins of the
> SoC. Macros allowing a device tree to define a pinmux mapping are also
> introduced.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/pinctrl/k210-pinctrl.h | 277 +++++++++++++++++++++
>  1 file changed, 277 insertions(+)
>  create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h
> 
> diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h
> new file mode 100644
> index 000000000000..0b797a4a245e
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/k210-pinctrl.h
> @@ -0,0 +1,277 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef PINCTRL_K210_SYSCTL_H
> +#define PINCTRL_K210_SYSCTL_H
> +
> +/*
> + * Full list of FPIOA functions from
> + * kendryte-standalone-sdk/lib/drivers/include/fpioa.h
> + */
> +#define K210_PCF_MASK		GENMASK(7, 0)
> +#define K210_PCF_JTAG_TCLK	0   /* JTAG Test Clock */
> +#define K210_PCF_JTAG_TDI	1   /* JTAG Test Data In */
> +#define K210_PCF_JTAG_TMS	2   /* JTAG Test Mode Select */
> +#define K210_PCF_JTAG_TDO	3   /* JTAG Test Data Out */
> +#define K210_PCF_SPI0_D0	4   /* SPI0 Data 0 */
> +#define K210_PCF_SPI0_D1	5   /* SPI0 Data 1 */
> +#define K210_PCF_SPI0_D2	6   /* SPI0 Data 2 */
> +#define K210_PCF_SPI0_D3	7   /* SPI0 Data 3 */
> +#define K210_PCF_SPI0_D4	8   /* SPI0 Data 4 */
> +#define K210_PCF_SPI0_D5	9   /* SPI0 Data 5 */
> +#define K210_PCF_SPI0_D6	10  /* SPI0 Data 6 */
> +#define K210_PCF_SPI0_D7	11  /* SPI0 Data 7 */
> +#define K210_PCF_SPI0_SS0	12  /* SPI0 Chip Select 0 */
> +#define K210_PCF_SPI0_SS1	13  /* SPI0 Chip Select 1 */
> +#define K210_PCF_SPI0_SS2	14  /* SPI0 Chip Select 2 */
> +#define K210_PCF_SPI0_SS3	15  /* SPI0 Chip Select 3 */
> +#define K210_PCF_SPI0_ARB	16  /* SPI0 Arbitration */
> +#define K210_PCF_SPI0_SCLK	17  /* SPI0 Serial Clock */
> +#define K210_PCF_UARTHS_RX	18  /* UART High speed Receiver */
> +#define K210_PCF_UARTHS_TX	19  /* UART High speed Transmitter */
> +#define K210_PCF_RESV6		20  /* Reserved function */
> +#define K210_PCF_RESV7		21  /* Reserved function */
> +#define K210_PCF_CLK_SPI1	22  /* Clock SPI1 */
> +#define K210_PCF_CLK_I2C1	23  /* Clock I2C1 */
> +#define K210_PCF_GPIOHS0	24  /* GPIO High speed 0 */
> +#define K210_PCF_GPIOHS1	25  /* GPIO High speed 1 */
> +#define K210_PCF_GPIOHS2	26  /* GPIO High speed 2 */
> +#define K210_PCF_GPIOHS3	27  /* GPIO High speed 3 */
> +#define K210_PCF_GPIOHS4	28  /* GPIO High speed 4 */
> +#define K210_PCF_GPIOHS5	29  /* GPIO High speed 5 */
> +#define K210_PCF_GPIOHS6	30  /* GPIO High speed 6 */
> +#define K210_PCF_GPIOHS7	31  /* GPIO High speed 7 */
> +#define K210_PCF_GPIOHS8	32  /* GPIO High speed 8 */
> +#define K210_PCF_GPIOHS9	33  /* GPIO High speed 9 */
> +#define K210_PCF_GPIOHS10	34  /* GPIO High speed 10 */
> +#define K210_PCF_GPIOHS11	35  /* GPIO High speed 11 */
> +#define K210_PCF_GPIOHS12	36  /* GPIO High speed 12 */
> +#define K210_PCF_GPIOHS13	37  /* GPIO High speed 13 */
> +#define K210_PCF_GPIOHS14	38  /* GPIO High speed 14 */
> +#define K210_PCF_GPIOHS15	39  /* GPIO High speed 15 */
> +#define K210_PCF_GPIOHS16	40  /* GPIO High speed 16 */
> +#define K210_PCF_GPIOHS17	41  /* GPIO High speed 17 */
> +#define K210_PCF_GPIOHS18	42  /* GPIO High speed 18 */
> +#define K210_PCF_GPIOHS19	43  /* GPIO High speed 19 */
> +#define K210_PCF_GPIOHS20	44  /* GPIO High speed 20 */
> +#define K210_PCF_GPIOHS21	45  /* GPIO High speed 21 */
> +#define K210_PCF_GPIOHS22	46  /* GPIO High speed 22 */
> +#define K210_PCF_GPIOHS23	47  /* GPIO High speed 23 */
> +#define K210_PCF_GPIOHS24	48  /* GPIO High speed 24 */
> +#define K210_PCF_GPIOHS25	49  /* GPIO High speed 25 */
> +#define K210_PCF_GPIOHS26	50  /* GPIO High speed 26 */
> +#define K210_PCF_GPIOHS27	51  /* GPIO High speed 27 */
> +#define K210_PCF_GPIOHS28	52  /* GPIO High speed 28 */
> +#define K210_PCF_GPIOHS29	53  /* GPIO High speed 29 */
> +#define K210_PCF_GPIOHS30	54  /* GPIO High speed 30 */
> +#define K210_PCF_GPIOHS31	55  /* GPIO High speed 31 */
> +#define K210_PCF_GPIO0		56  /* GPIO pin 0 */
> +#define K210_PCF_GPIO1		57  /* GPIO pin 1 */
> +#define K210_PCF_GPIO2		58  /* GPIO pin 2 */
> +#define K210_PCF_GPIO3		59  /* GPIO pin 3 */
> +#define K210_PCF_GPIO4		60  /* GPIO pin 4 */
> +#define K210_PCF_GPIO5		61  /* GPIO pin 5 */
> +#define K210_PCF_GPIO6		62  /* GPIO pin 6 */
> +#define K210_PCF_GPIO7		63  /* GPIO pin 7 */
> +#define K210_PCF_UART1_RX	64  /* UART1 Receiver */
> +#define K210_PCF_UART1_TX	65  /* UART1 Transmitter */
> +#define K210_PCF_UART2_RX	66  /* UART2 Receiver */
> +#define K210_PCF_UART2_TX	67  /* UART2 Transmitter */
> +#define K210_PCF_UART3_RX	68  /* UART3 Receiver */
> +#define K210_PCF_UART3_TX	69  /* UART3 Transmitter */
> +#define K210_PCF_SPI1_D0	70  /* SPI1 Data 0 */
> +#define K210_PCF_SPI1_D1	71  /* SPI1 Data 1 */
> +#define K210_PCF_SPI1_D2	72  /* SPI1 Data 2 */
> +#define K210_PCF_SPI1_D3	73  /* SPI1 Data 3 */
> +#define K210_PCF_SPI1_D4	74  /* SPI1 Data 4 */
> +#define K210_PCF_SPI1_D5	75  /* SPI1 Data 5 */
> +#define K210_PCF_SPI1_D6	76  /* SPI1 Data 6 */
> +#define K210_PCF_SPI1_D7	77  /* SPI1 Data 7 */
> +#define K210_PCF_SPI1_SS0	78  /* SPI1 Chip Select 0 */
> +#define K210_PCF_SPI1_SS1	79  /* SPI1 Chip Select 1 */
> +#define K210_PCF_SPI1_SS2	80  /* SPI1 Chip Select 2 */
> +#define K210_PCF_SPI1_SS3	81  /* SPI1 Chip Select 3 */
> +#define K210_PCF_SPI1_ARB	82  /* SPI1 Arbitration */
> +#define K210_PCF_SPI1_SCLK	83  /* SPI1 Serial Clock */
> +#define K210_PCF_SPI2_D0	84  /* SPI2 Data 0 */
> +#define K210_PCF_SPI2_SS	85  /* SPI2 Select */
> +#define K210_PCF_SPI2_SCLK	86  /* SPI2 Serial Clock */
> +#define K210_PCF_I2S0_MCLK	87  /* I2S0 Master Clock */
> +#define K210_PCF_I2S0_SCLK	88  /* I2S0 Serial Clock(BCLK) */
> +#define K210_PCF_I2S0_WS	89  /* I2S0 Word Select(LRCLK) */
> +#define K210_PCF_I2S0_IN_D0	90  /* I2S0 Serial Data Input 0 */
> +#define K210_PCF_I2S0_IN_D1	91  /* I2S0 Serial Data Input 1 */
> +#define K210_PCF_I2S0_IN_D2	92  /* I2S0 Serial Data Input 2 */
> +#define K210_PCF_I2S0_IN_D3	93  /* I2S0 Serial Data Input 3 */
> +#define K210_PCF_I2S0_OUT_D0	94  /* I2S0 Serial Data Output 0 */
> +#define K210_PCF_I2S0_OUT_D1	95  /* I2S0 Serial Data Output 1 */
> +#define K210_PCF_I2S0_OUT_D2	96  /* I2S0 Serial Data Output 2 */
> +#define K210_PCF_I2S0_OUT_D3	97  /* I2S0 Serial Data Output 3 */
> +#define K210_PCF_I2S1_MCLK	98  /* I2S1 Master Clock */
> +#define K210_PCF_I2S1_SCLK	99  /* I2S1 Serial Clock(BCLK) */
> +#define K210_PCF_I2S1_WS	100 /* I2S1 Word Select(LRCLK) */
> +#define K210_PCF_I2S1_IN_D0	101 /* I2S1 Serial Data Input 0 */
> +#define K210_PCF_I2S1_IN_D1	102 /* I2S1 Serial Data Input 1 */
> +#define K210_PCF_I2S1_IN_D2	103 /* I2S1 Serial Data Input 2 */
> +#define K210_PCF_I2S1_IN_D3	104 /* I2S1 Serial Data Input 3 */
> +#define K210_PCF_I2S1_OUT_D0	105 /* I2S1 Serial Data Output 0 */
> +#define K210_PCF_I2S1_OUT_D1	106 /* I2S1 Serial Data Output 1 */
> +#define K210_PCF_I2S1_OUT_D2	107 /* I2S1 Serial Data Output 2 */
> +#define K210_PCF_I2S1_OUT_D3	108 /* I2S1 Serial Data Output 3 */
> +#define K210_PCF_I2S2_MCLK	109 /* I2S2 Master Clock */
> +#define K210_PCF_I2S2_SCLK	110 /* I2S2 Serial Clock(BCLK) */
> +#define K210_PCF_I2S2_WS	111 /* I2S2 Word Select(LRCLK) */
> +#define K210_PCF_I2S2_IN_D0	112 /* I2S2 Serial Data Input 0 */
> +#define K210_PCF_I2S2_IN_D1	113 /* I2S2 Serial Data Input 1 */
> +#define K210_PCF_I2S2_IN_D2	114 /* I2S2 Serial Data Input 2 */
> +#define K210_PCF_I2S2_IN_D3	115 /* I2S2 Serial Data Input 3 */
> +#define K210_PCF_I2S2_OUT_D0	116 /* I2S2 Serial Data Output 0 */
> +#define K210_PCF_I2S2_OUT_D1	117 /* I2S2 Serial Data Output 1 */
> +#define K210_PCF_I2S2_OUT_D2	118 /* I2S2 Serial Data Output 2 */
> +#define K210_PCF_I2S2_OUT_D3	119 /* I2S2 Serial Data Output 3 */
> +#define K210_PCF_RESV0		120 /* Reserved function */
> +#define K210_PCF_RESV1		121 /* Reserved function */
> +#define K210_PCF_RESV2		122 /* Reserved function */
> +#define K210_PCF_RESV3		123 /* Reserved function */
> +#define K210_PCF_RESV4		124 /* Reserved function */
> +#define K210_PCF_RESV5		125 /* Reserved function */
> +#define K210_PCF_I2C0_SCLK	126 /* I2C0 Serial Clock */
> +#define K210_PCF_I2C0_SDA	127 /* I2C0 Serial Data */
> +#define K210_PCF_I2C1_SCLK	128 /* I2C1 Serial Clock */
> +#define K210_PCF_I2C1_SDA	129 /* I2C1 Serial Data */
> +#define K210_PCF_I2C2_SCLK	130 /* I2C2 Serial Clock */
> +#define K210_PCF_I2C2_SDA	131 /* I2C2 Serial Data */
> +#define K210_PCF_DVP_XCLK	132 /* DVP System Clock */
> +#define K210_PCF_DVP_RST	133 /* DVP System Reset */
> +#define K210_PCF_DVP_PWDN	134 /* DVP Power Down Mode */
> +#define K210_PCF_DVP_VSYNC	135 /* DVP Vertical Sync */
> +#define K210_PCF_DVP_HSYNC	136 /* DVP Horizontal Sync */
> +#define K210_PCF_DVP_PCLK	137 /* Pixel Clock */
> +#define K210_PCF_DVP_D0		138 /* Data Bit 0 */
> +#define K210_PCF_DVP_D1		139 /* Data Bit 1 */
> +#define K210_PCF_DVP_D2		140 /* Data Bit 2 */
> +#define K210_PCF_DVP_D3		141 /* Data Bit 3 */
> +#define K210_PCF_DVP_D4		142 /* Data Bit 4 */
> +#define K210_PCF_DVP_D5		143 /* Data Bit 5 */
> +#define K210_PCF_DVP_D6		144 /* Data Bit 6 */
> +#define K210_PCF_DVP_D7		145 /* Data Bit 7 */
> +#define K210_PCF_SCCB_SCLK	146 /* Serial Camera Control Bus Clock */
> +#define K210_PCF_SCCB_SDA	147 /* Serial Camera Control Bus Data */
> +#define K210_PCF_UART1_CTS	148 /* UART1 Clear To Send */
> +#define K210_PCF_UART1_DSR	149 /* UART1 Data Set Ready */
> +#define K210_PCF_UART1_DCD	150 /* UART1 Data Carrier Detect */
> +#define K210_PCF_UART1_RI	151 /* UART1 Ring Indicator */
> +#define K210_PCF_UART1_SIR_IN	152 /* UART1 Serial Infrared Input */
> +#define K210_PCF_UART1_DTR	153 /* UART1 Data Terminal Ready */
> +#define K210_PCF_UART1_RTS	154 /* UART1 Request To Send */
> +#define K210_PCF_UART1_OUT2	155 /* UART1 User-designated Output 2 */
> +#define K210_PCF_UART1_OUT1	156 /* UART1 User-designated Output 1 */
> +#define K210_PCF_UART1_SIR_OUT	157 /* UART1 Serial Infrared Output */
> +#define K210_PCF_UART1_BAUD	158 /* UART1 Transmit Clock Output */
> +#define K210_PCF_UART1_RE	159 /* UART1 Receiver Output Enable */
> +#define K210_PCF_UART1_DE	160 /* UART1 Driver Output Enable */
> +#define K210_PCF_UART1_RS485_EN	161 /* UART1 RS485 Enable */
> +#define K210_PCF_UART2_CTS	162 /* UART2 Clear To Send */
> +#define K210_PCF_UART2_DSR	163 /* UART2 Data Set Ready */
> +#define K210_PCF_UART2_DCD	164 /* UART2 Data Carrier Detect */
> +#define K210_PCF_UART2_RI	165 /* UART2 Ring Indicator */
> +#define K210_PCF_UART2_SIR_IN	166 /* UART2 Serial Infrared Input */
> +#define K210_PCF_UART2_DTR	167 /* UART2 Data Terminal Ready */
> +#define K210_PCF_UART2_RTS	168 /* UART2 Request To Send */
> +#define K210_PCF_UART2_OUT2	169 /* UART2 User-designated Output 2 */
> +#define K210_PCF_UART2_OUT1	170 /* UART2 User-designated Output 1 */
> +#define K210_PCF_UART2_SIR_OUT	171 /* UART2 Serial Infrared Output */
> +#define K210_PCF_UART2_BAUD	172 /* UART2 Transmit Clock Output */
> +#define K210_PCF_UART2_RE	173 /* UART2 Receiver Output Enable */
> +#define K210_PCF_UART2_DE	174 /* UART2 Driver Output Enable */
> +#define K210_PCF_UART2_RS485_EN	175 /* UART2 RS485 Enable */
> +#define K210_PCF_UART3_CTS	176 /* UART3 Clear To Send */
> +#define K210_PCF_UART3_DSR	177 /* UART3 Data Set Ready */
> +#define K210_PCF_UART3_DCD	178 /* UART3 Data Carrier Detect */
> +#define K210_PCF_UART3_RI	179 /* UART3 Ring Indicator */
> +#define K210_PCF_UART3_SIR_IN	180 /* UART3 Serial Infrared Input */
> +#define K210_PCF_UART3_DTR	181 /* UART3 Data Terminal Ready */
> +#define K210_PCF_UART3_RTS	182 /* UART3 Request To Send */
> +#define K210_PCF_UART3_OUT2	183 /* UART3 User-designated Output 2 */
> +#define K210_PCF_UART3_OUT1	184 /* UART3 User-designated Output 1 */
> +#define K210_PCF_UART3_SIR_OUT	185 /* UART3 Serial Infrared Output */
> +#define K210_PCF_UART3_BAUD	186 /* UART3 Transmit Clock Output */
> +#define K210_PCF_UART3_RE	187 /* UART3 Receiver Output Enable */
> +#define K210_PCF_UART3_DE	188 /* UART3 Driver Output Enable */
> +#define K210_PCF_UART3_RS485_EN	189 /* UART3 RS485 Enable */
> +#define K210_PCF_TIMER0_TOGGLE1	190 /* TIMER0 Toggle Output 1 */
> +#define K210_PCF_TIMER0_TOGGLE2	191 /* TIMER0 Toggle Output 2 */
> +#define K210_PCF_TIMER0_TOGGLE3	192 /* TIMER0 Toggle Output 3 */
> +#define K210_PCF_TIMER0_TOGGLE4	193 /* TIMER0 Toggle Output 4 */
> +#define K210_PCF_TIMER1_TOGGLE1	194 /* TIMER1 Toggle Output 1 */
> +#define K210_PCF_TIMER1_TOGGLE2	195 /* TIMER1 Toggle Output 2 */
> +#define K210_PCF_TIMER1_TOGGLE3	196 /* TIMER1 Toggle Output 3 */
> +#define K210_PCF_TIMER1_TOGGLE4	197 /* TIMER1 Toggle Output 4 */
> +#define K210_PCF_TIMER2_TOGGLE1	198 /* TIMER2 Toggle Output 1 */
> +#define K210_PCF_TIMER2_TOGGLE2	199 /* TIMER2 Toggle Output 2 */
> +#define K210_PCF_TIMER2_TOGGLE3	200 /* TIMER2 Toggle Output 3 */
> +#define K210_PCF_TIMER2_TOGGLE4	201 /* TIMER2 Toggle Output 4 */
> +#define K210_PCF_CLK_SPI2	202 /* Clock SPI2 */
> +#define K210_PCF_CLK_I2C2	203 /* Clock I2C2 */
> +#define K210_PCF_INTERNAL0	204 /* Internal function signal 0 */
> +#define K210_PCF_INTERNAL1	205 /* Internal function signal 1 */
> +#define K210_PCF_INTERNAL2	206 /* Internal function signal 2 */
> +#define K210_PCF_INTERNAL3	207 /* Internal function signal 3 */
> +#define K210_PCF_INTERNAL4	208 /* Internal function signal 4 */
> +#define K210_PCF_INTERNAL5	209 /* Internal function signal 5 */
> +#define K210_PCF_INTERNAL6	210 /* Internal function signal 6 */
> +#define K210_PCF_INTERNAL7	211 /* Internal function signal 7 */
> +#define K210_PCF_INTERNAL8	212 /* Internal function signal 8 */
> +#define K210_PCF_INTERNAL9	213 /* Internal function signal 9 */
> +#define K210_PCF_INTERNAL10	214 /* Internal function signal 10 */
> +#define K210_PCF_INTERNAL11	215 /* Internal function signal 11 */
> +#define K210_PCF_INTERNAL12	216 /* Internal function signal 12 */
> +#define K210_PCF_INTERNAL13	217 /* Internal function signal 13 */
> +#define K210_PCF_INTERNAL14	218 /* Internal function signal 14 */
> +#define K210_PCF_INTERNAL15	219 /* Internal function signal 15 */
> +#define K210_PCF_INTERNAL16	220 /* Internal function signal 16 */
> +#define K210_PCF_INTERNAL17	221 /* Internal function signal 17 */
> +#define K210_PCF_CONSTANT	222 /* Constant function */
> +#define K210_PCF_INTERNAL18	223 /* Internal function signal 18 */
> +#define K210_PCF_DEBUG0		224 /* Debug function 0 */
> +#define K210_PCF_DEBUG1		225 /* Debug function 1 */
> +#define K210_PCF_DEBUG2		226 /* Debug function 2 */
> +#define K210_PCF_DEBUG3		227 /* Debug function 3 */
> +#define K210_PCF_DEBUG4		228 /* Debug function 4 */
> +#define K210_PCF_DEBUG5		229 /* Debug function 5 */
> +#define K210_PCF_DEBUG6		230 /* Debug function 6 */
> +#define K210_PCF_DEBUG7		231 /* Debug function 7 */
> +#define K210_PCF_DEBUG8		232 /* Debug function 8 */
> +#define K210_PCF_DEBUG9		233 /* Debug function 9 */
> +#define K210_PCF_DEBUG10	234 /* Debug function 10 */
> +#define K210_PCF_DEBUG11	235 /* Debug function 11 */
> +#define K210_PCF_DEBUG12	236 /* Debug function 12 */
> +#define K210_PCF_DEBUG13	237 /* Debug function 13 */
> +#define K210_PCF_DEBUG14	238 /* Debug function 14 */
> +#define K210_PCF_DEBUG15	239 /* Debug function 15 */
> +#define K210_PCF_DEBUG16	240 /* Debug function 16 */
> +#define K210_PCF_DEBUG17	241 /* Debug function 17 */
> +#define K210_PCF_DEBUG18	242 /* Debug function 18 */
> +#define K210_PCF_DEBUG19	243 /* Debug function 19 */
> +#define K210_PCF_DEBUG20	244 /* Debug function 20 */
> +#define K210_PCF_DEBUG21	245 /* Debug function 21 */
> +#define K210_PCF_DEBUG22	246 /* Debug function 22 */
> +#define K210_PCF_DEBUG23	247 /* Debug function 23 */
> +#define K210_PCF_DEBUG24	248 /* Debug function 24 */
> +#define K210_PCF_DEBUG25	249 /* Debug function 25 */
> +#define K210_PCF_DEBUG26	250 /* Debug function 26 */
> +#define K210_PCF_DEBUG27	251 /* Debug function 27 */
> +#define K210_PCF_DEBUG28	252 /* Debug function 28 */
> +#define K210_PCF_DEBUG29	253 /* Debug function 29 */
> +#define K210_PCF_DEBUG30	254 /* Debug function 30 */
> +#define K210_PCF_DEBUG31	255 /* Debug function 31 */
> +
> +#define K210_FPIOA(pin, func)		(((pin) << 16) | (func))
> +#define K210_FPIOA_DO(pin, func)	(((pin) << 16) | (1 << 8) | (func))

The _DO version of this macro is effectively a no-op on Linux due to how
we set up pins (e.g. see k210_pinctrl_dt_subnode_to_map in patch 20).
I'm not particularly concerned (since this functionality is only
useful for level shifters), but perhaps a comment is warranted.

> +
> +#define K210_PC_POWER_3V3	0
> +#define K210_PC_POWER_1V8	1
> +
> +#endif /* PINCTRL_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 16/32] dt-bindings: Define Kendryte K210 pin functions
@ 2020-11-07 13:38     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:38 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file
> include/dt-bindings/pinctrl/k210_pinctrl.h to define all possible 255
> functions that can be assigned to any of the 48 programmable pins of the
> SoC. Macros allowing a device tree to define a pinmux mapping are also
> introduced.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/pinctrl/k210-pinctrl.h | 277 +++++++++++++++++++++
>  1 file changed, 277 insertions(+)
>  create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h
> 
> diff --git a/include/dt-bindings/pinctrl/k210-pinctrl.h b/include/dt-bindings/pinctrl/k210-pinctrl.h
> new file mode 100644
> index 000000000000..0b797a4a245e
> --- /dev/null
> +++ b/include/dt-bindings/pinctrl/k210-pinctrl.h
> @@ -0,0 +1,277 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef PINCTRL_K210_SYSCTL_H
> +#define PINCTRL_K210_SYSCTL_H
> +
> +/*
> + * Full list of FPIOA functions from
> + * kendryte-standalone-sdk/lib/drivers/include/fpioa.h
> + */
> +#define K210_PCF_MASK		GENMASK(7, 0)
> +#define K210_PCF_JTAG_TCLK	0   /* JTAG Test Clock */
> +#define K210_PCF_JTAG_TDI	1   /* JTAG Test Data In */
> +#define K210_PCF_JTAG_TMS	2   /* JTAG Test Mode Select */
> +#define K210_PCF_JTAG_TDO	3   /* JTAG Test Data Out */
> +#define K210_PCF_SPI0_D0	4   /* SPI0 Data 0 */
> +#define K210_PCF_SPI0_D1	5   /* SPI0 Data 1 */
> +#define K210_PCF_SPI0_D2	6   /* SPI0 Data 2 */
> +#define K210_PCF_SPI0_D3	7   /* SPI0 Data 3 */
> +#define K210_PCF_SPI0_D4	8   /* SPI0 Data 4 */
> +#define K210_PCF_SPI0_D5	9   /* SPI0 Data 5 */
> +#define K210_PCF_SPI0_D6	10  /* SPI0 Data 6 */
> +#define K210_PCF_SPI0_D7	11  /* SPI0 Data 7 */
> +#define K210_PCF_SPI0_SS0	12  /* SPI0 Chip Select 0 */
> +#define K210_PCF_SPI0_SS1	13  /* SPI0 Chip Select 1 */
> +#define K210_PCF_SPI0_SS2	14  /* SPI0 Chip Select 2 */
> +#define K210_PCF_SPI0_SS3	15  /* SPI0 Chip Select 3 */
> +#define K210_PCF_SPI0_ARB	16  /* SPI0 Arbitration */
> +#define K210_PCF_SPI0_SCLK	17  /* SPI0 Serial Clock */
> +#define K210_PCF_UARTHS_RX	18  /* UART High speed Receiver */
> +#define K210_PCF_UARTHS_TX	19  /* UART High speed Transmitter */
> +#define K210_PCF_RESV6		20  /* Reserved function */
> +#define K210_PCF_RESV7		21  /* Reserved function */
> +#define K210_PCF_CLK_SPI1	22  /* Clock SPI1 */
> +#define K210_PCF_CLK_I2C1	23  /* Clock I2C1 */
> +#define K210_PCF_GPIOHS0	24  /* GPIO High speed 0 */
> +#define K210_PCF_GPIOHS1	25  /* GPIO High speed 1 */
> +#define K210_PCF_GPIOHS2	26  /* GPIO High speed 2 */
> +#define K210_PCF_GPIOHS3	27  /* GPIO High speed 3 */
> +#define K210_PCF_GPIOHS4	28  /* GPIO High speed 4 */
> +#define K210_PCF_GPIOHS5	29  /* GPIO High speed 5 */
> +#define K210_PCF_GPIOHS6	30  /* GPIO High speed 6 */
> +#define K210_PCF_GPIOHS7	31  /* GPIO High speed 7 */
> +#define K210_PCF_GPIOHS8	32  /* GPIO High speed 8 */
> +#define K210_PCF_GPIOHS9	33  /* GPIO High speed 9 */
> +#define K210_PCF_GPIOHS10	34  /* GPIO High speed 10 */
> +#define K210_PCF_GPIOHS11	35  /* GPIO High speed 11 */
> +#define K210_PCF_GPIOHS12	36  /* GPIO High speed 12 */
> +#define K210_PCF_GPIOHS13	37  /* GPIO High speed 13 */
> +#define K210_PCF_GPIOHS14	38  /* GPIO High speed 14 */
> +#define K210_PCF_GPIOHS15	39  /* GPIO High speed 15 */
> +#define K210_PCF_GPIOHS16	40  /* GPIO High speed 16 */
> +#define K210_PCF_GPIOHS17	41  /* GPIO High speed 17 */
> +#define K210_PCF_GPIOHS18	42  /* GPIO High speed 18 */
> +#define K210_PCF_GPIOHS19	43  /* GPIO High speed 19 */
> +#define K210_PCF_GPIOHS20	44  /* GPIO High speed 20 */
> +#define K210_PCF_GPIOHS21	45  /* GPIO High speed 21 */
> +#define K210_PCF_GPIOHS22	46  /* GPIO High speed 22 */
> +#define K210_PCF_GPIOHS23	47  /* GPIO High speed 23 */
> +#define K210_PCF_GPIOHS24	48  /* GPIO High speed 24 */
> +#define K210_PCF_GPIOHS25	49  /* GPIO High speed 25 */
> +#define K210_PCF_GPIOHS26	50  /* GPIO High speed 26 */
> +#define K210_PCF_GPIOHS27	51  /* GPIO High speed 27 */
> +#define K210_PCF_GPIOHS28	52  /* GPIO High speed 28 */
> +#define K210_PCF_GPIOHS29	53  /* GPIO High speed 29 */
> +#define K210_PCF_GPIOHS30	54  /* GPIO High speed 30 */
> +#define K210_PCF_GPIOHS31	55  /* GPIO High speed 31 */
> +#define K210_PCF_GPIO0		56  /* GPIO pin 0 */
> +#define K210_PCF_GPIO1		57  /* GPIO pin 1 */
> +#define K210_PCF_GPIO2		58  /* GPIO pin 2 */
> +#define K210_PCF_GPIO3		59  /* GPIO pin 3 */
> +#define K210_PCF_GPIO4		60  /* GPIO pin 4 */
> +#define K210_PCF_GPIO5		61  /* GPIO pin 5 */
> +#define K210_PCF_GPIO6		62  /* GPIO pin 6 */
> +#define K210_PCF_GPIO7		63  /* GPIO pin 7 */
> +#define K210_PCF_UART1_RX	64  /* UART1 Receiver */
> +#define K210_PCF_UART1_TX	65  /* UART1 Transmitter */
> +#define K210_PCF_UART2_RX	66  /* UART2 Receiver */
> +#define K210_PCF_UART2_TX	67  /* UART2 Transmitter */
> +#define K210_PCF_UART3_RX	68  /* UART3 Receiver */
> +#define K210_PCF_UART3_TX	69  /* UART3 Transmitter */
> +#define K210_PCF_SPI1_D0	70  /* SPI1 Data 0 */
> +#define K210_PCF_SPI1_D1	71  /* SPI1 Data 1 */
> +#define K210_PCF_SPI1_D2	72  /* SPI1 Data 2 */
> +#define K210_PCF_SPI1_D3	73  /* SPI1 Data 3 */
> +#define K210_PCF_SPI1_D4	74  /* SPI1 Data 4 */
> +#define K210_PCF_SPI1_D5	75  /* SPI1 Data 5 */
> +#define K210_PCF_SPI1_D6	76  /* SPI1 Data 6 */
> +#define K210_PCF_SPI1_D7	77  /* SPI1 Data 7 */
> +#define K210_PCF_SPI1_SS0	78  /* SPI1 Chip Select 0 */
> +#define K210_PCF_SPI1_SS1	79  /* SPI1 Chip Select 1 */
> +#define K210_PCF_SPI1_SS2	80  /* SPI1 Chip Select 2 */
> +#define K210_PCF_SPI1_SS3	81  /* SPI1 Chip Select 3 */
> +#define K210_PCF_SPI1_ARB	82  /* SPI1 Arbitration */
> +#define K210_PCF_SPI1_SCLK	83  /* SPI1 Serial Clock */
> +#define K210_PCF_SPI2_D0	84  /* SPI2 Data 0 */
> +#define K210_PCF_SPI2_SS	85  /* SPI2 Select */
> +#define K210_PCF_SPI2_SCLK	86  /* SPI2 Serial Clock */
> +#define K210_PCF_I2S0_MCLK	87  /* I2S0 Master Clock */
> +#define K210_PCF_I2S0_SCLK	88  /* I2S0 Serial Clock(BCLK) */
> +#define K210_PCF_I2S0_WS	89  /* I2S0 Word Select(LRCLK) */
> +#define K210_PCF_I2S0_IN_D0	90  /* I2S0 Serial Data Input 0 */
> +#define K210_PCF_I2S0_IN_D1	91  /* I2S0 Serial Data Input 1 */
> +#define K210_PCF_I2S0_IN_D2	92  /* I2S0 Serial Data Input 2 */
> +#define K210_PCF_I2S0_IN_D3	93  /* I2S0 Serial Data Input 3 */
> +#define K210_PCF_I2S0_OUT_D0	94  /* I2S0 Serial Data Output 0 */
> +#define K210_PCF_I2S0_OUT_D1	95  /* I2S0 Serial Data Output 1 */
> +#define K210_PCF_I2S0_OUT_D2	96  /* I2S0 Serial Data Output 2 */
> +#define K210_PCF_I2S0_OUT_D3	97  /* I2S0 Serial Data Output 3 */
> +#define K210_PCF_I2S1_MCLK	98  /* I2S1 Master Clock */
> +#define K210_PCF_I2S1_SCLK	99  /* I2S1 Serial Clock(BCLK) */
> +#define K210_PCF_I2S1_WS	100 /* I2S1 Word Select(LRCLK) */
> +#define K210_PCF_I2S1_IN_D0	101 /* I2S1 Serial Data Input 0 */
> +#define K210_PCF_I2S1_IN_D1	102 /* I2S1 Serial Data Input 1 */
> +#define K210_PCF_I2S1_IN_D2	103 /* I2S1 Serial Data Input 2 */
> +#define K210_PCF_I2S1_IN_D3	104 /* I2S1 Serial Data Input 3 */
> +#define K210_PCF_I2S1_OUT_D0	105 /* I2S1 Serial Data Output 0 */
> +#define K210_PCF_I2S1_OUT_D1	106 /* I2S1 Serial Data Output 1 */
> +#define K210_PCF_I2S1_OUT_D2	107 /* I2S1 Serial Data Output 2 */
> +#define K210_PCF_I2S1_OUT_D3	108 /* I2S1 Serial Data Output 3 */
> +#define K210_PCF_I2S2_MCLK	109 /* I2S2 Master Clock */
> +#define K210_PCF_I2S2_SCLK	110 /* I2S2 Serial Clock(BCLK) */
> +#define K210_PCF_I2S2_WS	111 /* I2S2 Word Select(LRCLK) */
> +#define K210_PCF_I2S2_IN_D0	112 /* I2S2 Serial Data Input 0 */
> +#define K210_PCF_I2S2_IN_D1	113 /* I2S2 Serial Data Input 1 */
> +#define K210_PCF_I2S2_IN_D2	114 /* I2S2 Serial Data Input 2 */
> +#define K210_PCF_I2S2_IN_D3	115 /* I2S2 Serial Data Input 3 */
> +#define K210_PCF_I2S2_OUT_D0	116 /* I2S2 Serial Data Output 0 */
> +#define K210_PCF_I2S2_OUT_D1	117 /* I2S2 Serial Data Output 1 */
> +#define K210_PCF_I2S2_OUT_D2	118 /* I2S2 Serial Data Output 2 */
> +#define K210_PCF_I2S2_OUT_D3	119 /* I2S2 Serial Data Output 3 */
> +#define K210_PCF_RESV0		120 /* Reserved function */
> +#define K210_PCF_RESV1		121 /* Reserved function */
> +#define K210_PCF_RESV2		122 /* Reserved function */
> +#define K210_PCF_RESV3		123 /* Reserved function */
> +#define K210_PCF_RESV4		124 /* Reserved function */
> +#define K210_PCF_RESV5		125 /* Reserved function */
> +#define K210_PCF_I2C0_SCLK	126 /* I2C0 Serial Clock */
> +#define K210_PCF_I2C0_SDA	127 /* I2C0 Serial Data */
> +#define K210_PCF_I2C1_SCLK	128 /* I2C1 Serial Clock */
> +#define K210_PCF_I2C1_SDA	129 /* I2C1 Serial Data */
> +#define K210_PCF_I2C2_SCLK	130 /* I2C2 Serial Clock */
> +#define K210_PCF_I2C2_SDA	131 /* I2C2 Serial Data */
> +#define K210_PCF_DVP_XCLK	132 /* DVP System Clock */
> +#define K210_PCF_DVP_RST	133 /* DVP System Reset */
> +#define K210_PCF_DVP_PWDN	134 /* DVP Power Down Mode */
> +#define K210_PCF_DVP_VSYNC	135 /* DVP Vertical Sync */
> +#define K210_PCF_DVP_HSYNC	136 /* DVP Horizontal Sync */
> +#define K210_PCF_DVP_PCLK	137 /* Pixel Clock */
> +#define K210_PCF_DVP_D0		138 /* Data Bit 0 */
> +#define K210_PCF_DVP_D1		139 /* Data Bit 1 */
> +#define K210_PCF_DVP_D2		140 /* Data Bit 2 */
> +#define K210_PCF_DVP_D3		141 /* Data Bit 3 */
> +#define K210_PCF_DVP_D4		142 /* Data Bit 4 */
> +#define K210_PCF_DVP_D5		143 /* Data Bit 5 */
> +#define K210_PCF_DVP_D6		144 /* Data Bit 6 */
> +#define K210_PCF_DVP_D7		145 /* Data Bit 7 */
> +#define K210_PCF_SCCB_SCLK	146 /* Serial Camera Control Bus Clock */
> +#define K210_PCF_SCCB_SDA	147 /* Serial Camera Control Bus Data */
> +#define K210_PCF_UART1_CTS	148 /* UART1 Clear To Send */
> +#define K210_PCF_UART1_DSR	149 /* UART1 Data Set Ready */
> +#define K210_PCF_UART1_DCD	150 /* UART1 Data Carrier Detect */
> +#define K210_PCF_UART1_RI	151 /* UART1 Ring Indicator */
> +#define K210_PCF_UART1_SIR_IN	152 /* UART1 Serial Infrared Input */
> +#define K210_PCF_UART1_DTR	153 /* UART1 Data Terminal Ready */
> +#define K210_PCF_UART1_RTS	154 /* UART1 Request To Send */
> +#define K210_PCF_UART1_OUT2	155 /* UART1 User-designated Output 2 */
> +#define K210_PCF_UART1_OUT1	156 /* UART1 User-designated Output 1 */
> +#define K210_PCF_UART1_SIR_OUT	157 /* UART1 Serial Infrared Output */
> +#define K210_PCF_UART1_BAUD	158 /* UART1 Transmit Clock Output */
> +#define K210_PCF_UART1_RE	159 /* UART1 Receiver Output Enable */
> +#define K210_PCF_UART1_DE	160 /* UART1 Driver Output Enable */
> +#define K210_PCF_UART1_RS485_EN	161 /* UART1 RS485 Enable */
> +#define K210_PCF_UART2_CTS	162 /* UART2 Clear To Send */
> +#define K210_PCF_UART2_DSR	163 /* UART2 Data Set Ready */
> +#define K210_PCF_UART2_DCD	164 /* UART2 Data Carrier Detect */
> +#define K210_PCF_UART2_RI	165 /* UART2 Ring Indicator */
> +#define K210_PCF_UART2_SIR_IN	166 /* UART2 Serial Infrared Input */
> +#define K210_PCF_UART2_DTR	167 /* UART2 Data Terminal Ready */
> +#define K210_PCF_UART2_RTS	168 /* UART2 Request To Send */
> +#define K210_PCF_UART2_OUT2	169 /* UART2 User-designated Output 2 */
> +#define K210_PCF_UART2_OUT1	170 /* UART2 User-designated Output 1 */
> +#define K210_PCF_UART2_SIR_OUT	171 /* UART2 Serial Infrared Output */
> +#define K210_PCF_UART2_BAUD	172 /* UART2 Transmit Clock Output */
> +#define K210_PCF_UART2_RE	173 /* UART2 Receiver Output Enable */
> +#define K210_PCF_UART2_DE	174 /* UART2 Driver Output Enable */
> +#define K210_PCF_UART2_RS485_EN	175 /* UART2 RS485 Enable */
> +#define K210_PCF_UART3_CTS	176 /* UART3 Clear To Send */
> +#define K210_PCF_UART3_DSR	177 /* UART3 Data Set Ready */
> +#define K210_PCF_UART3_DCD	178 /* UART3 Data Carrier Detect */
> +#define K210_PCF_UART3_RI	179 /* UART3 Ring Indicator */
> +#define K210_PCF_UART3_SIR_IN	180 /* UART3 Serial Infrared Input */
> +#define K210_PCF_UART3_DTR	181 /* UART3 Data Terminal Ready */
> +#define K210_PCF_UART3_RTS	182 /* UART3 Request To Send */
> +#define K210_PCF_UART3_OUT2	183 /* UART3 User-designated Output 2 */
> +#define K210_PCF_UART3_OUT1	184 /* UART3 User-designated Output 1 */
> +#define K210_PCF_UART3_SIR_OUT	185 /* UART3 Serial Infrared Output */
> +#define K210_PCF_UART3_BAUD	186 /* UART3 Transmit Clock Output */
> +#define K210_PCF_UART3_RE	187 /* UART3 Receiver Output Enable */
> +#define K210_PCF_UART3_DE	188 /* UART3 Driver Output Enable */
> +#define K210_PCF_UART3_RS485_EN	189 /* UART3 RS485 Enable */
> +#define K210_PCF_TIMER0_TOGGLE1	190 /* TIMER0 Toggle Output 1 */
> +#define K210_PCF_TIMER0_TOGGLE2	191 /* TIMER0 Toggle Output 2 */
> +#define K210_PCF_TIMER0_TOGGLE3	192 /* TIMER0 Toggle Output 3 */
> +#define K210_PCF_TIMER0_TOGGLE4	193 /* TIMER0 Toggle Output 4 */
> +#define K210_PCF_TIMER1_TOGGLE1	194 /* TIMER1 Toggle Output 1 */
> +#define K210_PCF_TIMER1_TOGGLE2	195 /* TIMER1 Toggle Output 2 */
> +#define K210_PCF_TIMER1_TOGGLE3	196 /* TIMER1 Toggle Output 3 */
> +#define K210_PCF_TIMER1_TOGGLE4	197 /* TIMER1 Toggle Output 4 */
> +#define K210_PCF_TIMER2_TOGGLE1	198 /* TIMER2 Toggle Output 1 */
> +#define K210_PCF_TIMER2_TOGGLE2	199 /* TIMER2 Toggle Output 2 */
> +#define K210_PCF_TIMER2_TOGGLE3	200 /* TIMER2 Toggle Output 3 */
> +#define K210_PCF_TIMER2_TOGGLE4	201 /* TIMER2 Toggle Output 4 */
> +#define K210_PCF_CLK_SPI2	202 /* Clock SPI2 */
> +#define K210_PCF_CLK_I2C2	203 /* Clock I2C2 */
> +#define K210_PCF_INTERNAL0	204 /* Internal function signal 0 */
> +#define K210_PCF_INTERNAL1	205 /* Internal function signal 1 */
> +#define K210_PCF_INTERNAL2	206 /* Internal function signal 2 */
> +#define K210_PCF_INTERNAL3	207 /* Internal function signal 3 */
> +#define K210_PCF_INTERNAL4	208 /* Internal function signal 4 */
> +#define K210_PCF_INTERNAL5	209 /* Internal function signal 5 */
> +#define K210_PCF_INTERNAL6	210 /* Internal function signal 6 */
> +#define K210_PCF_INTERNAL7	211 /* Internal function signal 7 */
> +#define K210_PCF_INTERNAL8	212 /* Internal function signal 8 */
> +#define K210_PCF_INTERNAL9	213 /* Internal function signal 9 */
> +#define K210_PCF_INTERNAL10	214 /* Internal function signal 10 */
> +#define K210_PCF_INTERNAL11	215 /* Internal function signal 11 */
> +#define K210_PCF_INTERNAL12	216 /* Internal function signal 12 */
> +#define K210_PCF_INTERNAL13	217 /* Internal function signal 13 */
> +#define K210_PCF_INTERNAL14	218 /* Internal function signal 14 */
> +#define K210_PCF_INTERNAL15	219 /* Internal function signal 15 */
> +#define K210_PCF_INTERNAL16	220 /* Internal function signal 16 */
> +#define K210_PCF_INTERNAL17	221 /* Internal function signal 17 */
> +#define K210_PCF_CONSTANT	222 /* Constant function */
> +#define K210_PCF_INTERNAL18	223 /* Internal function signal 18 */
> +#define K210_PCF_DEBUG0		224 /* Debug function 0 */
> +#define K210_PCF_DEBUG1		225 /* Debug function 1 */
> +#define K210_PCF_DEBUG2		226 /* Debug function 2 */
> +#define K210_PCF_DEBUG3		227 /* Debug function 3 */
> +#define K210_PCF_DEBUG4		228 /* Debug function 4 */
> +#define K210_PCF_DEBUG5		229 /* Debug function 5 */
> +#define K210_PCF_DEBUG6		230 /* Debug function 6 */
> +#define K210_PCF_DEBUG7		231 /* Debug function 7 */
> +#define K210_PCF_DEBUG8		232 /* Debug function 8 */
> +#define K210_PCF_DEBUG9		233 /* Debug function 9 */
> +#define K210_PCF_DEBUG10	234 /* Debug function 10 */
> +#define K210_PCF_DEBUG11	235 /* Debug function 11 */
> +#define K210_PCF_DEBUG12	236 /* Debug function 12 */
> +#define K210_PCF_DEBUG13	237 /* Debug function 13 */
> +#define K210_PCF_DEBUG14	238 /* Debug function 14 */
> +#define K210_PCF_DEBUG15	239 /* Debug function 15 */
> +#define K210_PCF_DEBUG16	240 /* Debug function 16 */
> +#define K210_PCF_DEBUG17	241 /* Debug function 17 */
> +#define K210_PCF_DEBUG18	242 /* Debug function 18 */
> +#define K210_PCF_DEBUG19	243 /* Debug function 19 */
> +#define K210_PCF_DEBUG20	244 /* Debug function 20 */
> +#define K210_PCF_DEBUG21	245 /* Debug function 21 */
> +#define K210_PCF_DEBUG22	246 /* Debug function 22 */
> +#define K210_PCF_DEBUG23	247 /* Debug function 23 */
> +#define K210_PCF_DEBUG24	248 /* Debug function 24 */
> +#define K210_PCF_DEBUG25	249 /* Debug function 25 */
> +#define K210_PCF_DEBUG26	250 /* Debug function 26 */
> +#define K210_PCF_DEBUG27	251 /* Debug function 27 */
> +#define K210_PCF_DEBUG28	252 /* Debug function 28 */
> +#define K210_PCF_DEBUG29	253 /* Debug function 29 */
> +#define K210_PCF_DEBUG30	254 /* Debug function 30 */
> +#define K210_PCF_DEBUG31	255 /* Debug function 31 */
> +
> +#define K210_FPIOA(pin, func)		(((pin) << 16) | (func))
> +#define K210_FPIOA_DO(pin, func)	(((pin) << 16) | (1 << 8) | (func))

The _DO version of this macro is effectively a no-op on Linux due to how
we set up pins (e.g. see k210_pinctrl_dt_subnode_to_map in patch 20).
I'm not particularly concerned (since this functionality is only
useful for level shifters), but perhaps a comment is warranted.

> +
> +#define K210_PC_POWER_3V3	0
> +#define K210_PC_POWER_1V8	1
> +
> +#endif /* PINCTRL_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 17/32] dt-bindings: Define Kendryte K210 reset signals
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:38     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:38 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/reset/k210_sysctl.h
> to define IDs for all 30 reset signals available on the Kendryte K210
> RISC-V SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/reset/k210-rst.h | 42 ++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>  create mode 100644 include/dt-bindings/reset/k210-rst.h
> 
> diff --git a/include/dt-bindings/reset/k210-rst.h b/include/dt-bindings/reset/k210-rst.h
> new file mode 100644
> index 000000000000..883c1aed50e8
> --- /dev/null
> +++ b/include/dt-bindings/reset/k210-rst.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef RESET_K210_SYSCTL_H
> +#define RESET_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller K210_SYSCTL_SOFT_RESET register bits.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_RST_ROM	0
> +#define K210_RST_DMA	1
> +#define K210_RST_AI	2
> +#define K210_RST_DVP	3
> +#define K210_RST_FFT	4
> +#define K210_RST_GPIO	5
> +#define K210_RST_SPI0	6
> +#define K210_RST_SPI1	7
> +#define K210_RST_SPI2	8
> +#define K210_RST_SPI3	9
> +#define K210_RST_I2S0	10
> +#define K210_RST_I2S1	11
> +#define K210_RST_I2S2	12
> +#define K210_RST_I2C0	13
> +#define K210_RST_I2C1	14
> +#define K210_RST_I2C2	15
> +#define K210_RST_UART1	16
> +#define K210_RST_UART2	17
> +#define K210_RST_UART3	18
> +#define K210_RST_AES	19
> +#define K210_RST_FPIOA	20
> +#define K210_RST_TIMER0	21
> +#define K210_RST_TIMER1	22
> +#define K210_RST_TIMER2	23
> +#define K210_RST_WDT0	24
> +#define K210_RST_WDT1	25
> +#define K210_RST_SHA	26
> +#define K210_RST_RTC	29
> +
> +#endif /* RESET_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 17/32] dt-bindings: Define Kendryte K210 reset signals
@ 2020-11-07 13:38     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:38 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/reset/k210_sysctl.h
> to define IDs for all 30 reset signals available on the Kendryte K210
> RISC-V SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/reset/k210-rst.h | 42 ++++++++++++++++++++++++++++
>  1 file changed, 42 insertions(+)
>  create mode 100644 include/dt-bindings/reset/k210-rst.h
> 
> diff --git a/include/dt-bindings/reset/k210-rst.h b/include/dt-bindings/reset/k210-rst.h
> new file mode 100644
> index 000000000000..883c1aed50e8
> --- /dev/null
> +++ b/include/dt-bindings/reset/k210-rst.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef RESET_K210_SYSCTL_H
> +#define RESET_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller K210_SYSCTL_SOFT_RESET register bits.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_RST_ROM	0
> +#define K210_RST_DMA	1
> +#define K210_RST_AI	2
> +#define K210_RST_DVP	3
> +#define K210_RST_FFT	4
> +#define K210_RST_GPIO	5
> +#define K210_RST_SPI0	6
> +#define K210_RST_SPI1	7
> +#define K210_RST_SPI2	8
> +#define K210_RST_SPI3	9
> +#define K210_RST_I2S0	10
> +#define K210_RST_I2S1	11
> +#define K210_RST_I2S2	12
> +#define K210_RST_I2C0	13
> +#define K210_RST_I2C1	14
> +#define K210_RST_I2C2	15
> +#define K210_RST_UART1	16
> +#define K210_RST_UART2	17
> +#define K210_RST_UART3	18
> +#define K210_RST_AES	19
> +#define K210_RST_FPIOA	20
> +#define K210_RST_TIMER0	21
> +#define K210_RST_TIMER1	22
> +#define K210_RST_TIMER2	23
> +#define K210_RST_WDT0	24
> +#define K210_RST_WDT1	25
> +#define K210_RST_SHA	26
> +#define K210_RST_RTC	29
> +
> +#endif /* RESET_K210_SYSCTL_H */
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07 13:31     ` Sean Anderson
@ 2020-11-07 13:42       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07 13:42 UTC (permalink / raw)
  To: Sean Anderson, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 2020/11/07 22:31, Sean Anderson wrote:
> On 11/7/20 3:13 AM, Damien Le Moal wrote:
>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>> ctrlr0 register format. This SoC is also quite slow and gets significant
>> SD card performance improvements from using no-delay polled transfers.
>> Add the dw_spi_k210_init() function tied to the
>> "canaan,kendryte-k210-spi" compatible string to set the
>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>> for this SoC.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>> index 3f1bc384cb45..a00def6c5b39 100644
>> --- a/drivers/spi/spi-dw-mmio.c
>> +++ b/drivers/spi/spi-dw-mmio.c
>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>  	return 0;
>>  }
>>  
>> +static int dw_spi_k210_init(struct platform_device *pdev,
>> +			    struct dw_spi_mmio *dwsmmio)
>> +{
>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> 
> Can't you do runtime detection of DFS_32 in probe?

I think it is possible, but it was much easier this way given that it seems that
only the K210 uses the DFS_32.

> 
> --Sean
> 
>> +
>> +	return 0;
>> +}
>> +
>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>  {
>>  	int (*init_func)(struct platform_device *pdev,
>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>  	{ /* end of table */}
>>  };
>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>>
> 
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-07 13:42       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-07 13:42 UTC (permalink / raw)
  To: Sean Anderson, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 2020/11/07 22:31, Sean Anderson wrote:
> On 11/7/20 3:13 AM, Damien Le Moal wrote:
>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>> ctrlr0 register format. This SoC is also quite slow and gets significant
>> SD card performance improvements from using no-delay polled transfers.
>> Add the dw_spi_k210_init() function tied to the
>> "canaan,kendryte-k210-spi" compatible string to set the
>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>> for this SoC.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>> index 3f1bc384cb45..a00def6c5b39 100644
>> --- a/drivers/spi/spi-dw-mmio.c
>> +++ b/drivers/spi/spi-dw-mmio.c
>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>  	return 0;
>>  }
>>  
>> +static int dw_spi_k210_init(struct platform_device *pdev,
>> +			    struct dw_spi_mmio *dwsmmio)
>> +{
>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> 
> Can't you do runtime detection of DFS_32 in probe?

I think it is possible, but it was much easier this way given that it seems that
only the K210 uses the DFS_32.

> 
> --Sean
> 
>> +
>> +	return 0;
>> +}
>> +
>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>  {
>>  	int (*init_func)(struct platform_device *pdev,
>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>  	{ /* end of table */}
>>  };
>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>>
> 
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:48     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:48 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a clock provider driver for the Kendryte K210 RISC-V SoC. This new
> driver with compatible string "kendryte,k210-clk", implements the full
> clock structure of the K210 SoC. Since it is required for the correct
> operation of the SoC, this driver is automatically selected for
> compilation when the SOC_KENDRYTE option is selected.
> 
> With this change, the k210-sysctl driver is turned into a simple
> platform driver which enables its power bus clock and triggers
> populating its child nodes. The sysctl soc driver retains the SOC early
> initialization code, but the implementation now relies on the new
> function k210_clk_early_init() provided by the new clk-k210 driver.
> This function declaration is done using the new header file
> include/soc/kendryte/k210-sysctl.h.
> 
> The clock structure implemented and many of the coding ideas for the
> driver come from the work by Sean Anderson on the Kendryte K210 support
> for the U-Boot project.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs            |   1 +
>  drivers/clk/Kconfig                |   9 +
>  drivers/clk/Makefile               |   1 +
>  drivers/clk/clk-k210.c             | 962 +++++++++++++++++++++++++++++
>  drivers/soc/kendryte/k210-sysctl.c | 241 ++------
>  include/soc/kendryte/k210-sysctl.h |  11 +
>  6 files changed, 1025 insertions(+), 200 deletions(-)
>  create mode 100644 drivers/clk/clk-k210.c
>  create mode 100644 include/soc/kendryte/k210-sysctl.h
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 97ef393d0ed0..a4c851ffc6b0 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -30,6 +30,7 @@ config SOC_KENDRYTE
>  	select SERIAL_SIFIVE_CONSOLE if TTY
>  	select SIFIVE_PLIC
>  	select SOC_K210
> +	select CLK_K210
>  	help
>  	  This enables support for Kendryte K210 SoC platform hardware.
>  
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c715d4681a0b..07a30a7b90b1 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -359,6 +359,15 @@ config COMMON_CLK_FIXED_MMIO
>  	help
>  	  Support for Memory Mapped IO Fixed clocks
>  
> +config CLK_K210
> +	bool "Clock driver for the Kendryte K210 SoC"
> +	depends on RISCV && SOC_KENDRYTE
> +	depends on COMMON_CLK && OF
> +	help
> +	  Support for the Kendryte K210 RISC-V SoC clocks. This option
> +	  is automatically selected when the SOC_KENDRYTE option is selected
> +	  in the "SOC selection" menu.
> +
>  source "drivers/clk/actions/Kconfig"
>  source "drivers/clk/analogbits/Kconfig"
>  source "drivers/clk/baikal-t1/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index da8fcf147eb1..ccac89e0fdfe 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
>  obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
>  obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
>  obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
> +obj-$(CONFIG_CLK_K210)			+= clk-k210.o
>  
>  # please keep this section sorted lexicographically by directory path name
>  obj-y					+= actions/
> diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
> new file mode 100644
> index 000000000000..7be5a8cdfef6
> --- /dev/null
> +++ b/drivers/clk/clk-k210.c
> @@ -0,0 +1,962 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2019 Western Digital Corporation or its affiliates.
> + */
> +#define pr_fmt(fmt)     "k210-clk: " fmt
> +
> +#include <soc/kendryte/k210-sysctl.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <asm/soc.h>
> +
> +#include <dt-bindings/clock/k210-clk.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +
> +/*
> + * in0: fixed-rate 26MHz oscillator base clock.
> + */
> +#define K210_IN0_RATE		26000000UL
> +
> +/*
> + * Clocks parameters.
> + */
> +struct k210_clk_cfg {
> +	u8 gate_reg;
> +	u8 gate_bit;
> +	u8 div_reg;
> +	u8 div_shift;
> +	u8 div_width;
> +	u8 div_type;
> +	u8 mux_reg;
> +	u8 mux_bit;
> +};
> +
> +enum k210_clk_div_type {
> +	DIV_NONE,
> +	DIV_ONE_BASED,
> +	DIV_DOUBLE_ONE_BASED,
> +	DIV_POWER_OF_TWO,
> +};
> +
> +#define GATE(_reg, _bit)	\
> +	.gate_reg = (_reg),	\
> +	.gate_bit = (_bit)
> +#define DIV(_reg, _shift, _width, _type)	\
> +	.div_reg = (_reg),			\
> +	.div_shift = (_shift),			\
> +	.div_width = (_width),			\
> +	.div_type = (_type)
> +#define MUX(_reg, _bit)		\
> +	.mux_reg = (_reg),	\
> +	.mux_bit = (_bit)
> +
> +static struct k210_clk_cfg k210_clks[K210_NUM_CLKS] = {
> +
> +	/* Gated clocks, no mux, no divider */
> +	[K210_CLK_CPU] = { GATE(K210_SYSCTL_EN_CENT, 0) },
> +	[K210_CLK_DMA] = { GATE(K210_SYSCTL_EN_PERI, 1) },
> +	[K210_CLK_FFT] = { GATE(K210_SYSCTL_EN_PERI, 4) },
> +	[K210_CLK_GPIO] = { GATE(K210_SYSCTL_EN_PERI, 5) },
> +	[K210_CLK_UART1] = { GATE(K210_SYSCTL_EN_PERI, 16) },
> +	[K210_CLK_UART2] = { GATE(K210_SYSCTL_EN_PERI, 17) },
> +	[K210_CLK_UART3] = { GATE(K210_SYSCTL_EN_PERI, 18) },
> +	[K210_CLK_FPIOA] = { GATE(K210_SYSCTL_EN_PERI, 20) },
> +	[K210_CLK_SHA] = { GATE(K210_SYSCTL_EN_PERI, 26) },
> +	[K210_CLK_AES] = { GATE(K210_SYSCTL_EN_PERI, 19) },
> +	[K210_CLK_OTP] = { GATE(K210_SYSCTL_EN_PERI, 27) },
> +	[K210_CLK_RTC] = { GATE(K210_SYSCTL_EN_PERI, 29) },
> +
> +	/* Gated divider clocks */
> +	[K210_CLK_SRAM0] = {
> +		GATE(K210_SYSCTL_EN_CENT, 1),
> +		DIV(K210_SYSCTL_THR0, 0, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_SRAM1] = {
> +		GATE(K210_SYSCTL_EN_CENT, 2),
> +		DIV(K210_SYSCTL_THR0, 4, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_ROM] = {
> +		GATE(K210_SYSCTL_EN_PERI, 0),
> +		DIV(K210_SYSCTL_THR0, 16, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_DVP] = {
> +		GATE(K210_SYSCTL_EN_PERI, 3),
> +		DIV(K210_SYSCTL_THR0, 12, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB0] = {
> +		GATE(K210_SYSCTL_EN_CENT, 3),
> +		DIV(K210_SYSCTL_SEL0, 3, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB1] = {
> +		GATE(K210_SYSCTL_EN_CENT, 4),
> +		DIV(K210_SYSCTL_SEL0, 6, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB2] = {
> +		GATE(K210_SYSCTL_EN_CENT, 5),
> +		DIV(K210_SYSCTL_SEL0, 9, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_AI] = {
> +		GATE(K210_SYSCTL_EN_PERI, 2),
> +		DIV(K210_SYSCTL_THR0, 8, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_SPI0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 6),
> +		DIV(K210_SYSCTL_THR1, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_SPI1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 7),
> +		DIV(K210_SYSCTL_THR1, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_SPI2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 8),
> +		DIV(K210_SYSCTL_THR1, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 13),
> +		DIV(K210_SYSCTL_THR5, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 14),
> +		DIV(K210_SYSCTL_THR5, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 15),
> +		DIV(K210_SYSCTL_THR5, 24, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_WDT0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 24),
> +		DIV(K210_SYSCTL_THR6, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_WDT1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 25),
> +		DIV(K210_SYSCTL_THR6, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 10),
> +		DIV(K210_SYSCTL_THR3, 0, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 11),
> +		DIV(K210_SYSCTL_THR3, 16, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 12),
> +		DIV(K210_SYSCTL_THR4, 0, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +
> +	/* Divider clocks, no gate, no mux */
> +	[K210_CLK_I2S0_M] = {
> +		DIV(K210_SYSCTL_THR4, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S1_M] = {
> +		DIV(K210_SYSCTL_THR4, 24, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S2_M] = {
> +		DIV(K210_SYSCTL_THR4, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +
> +	/* Muxed gated divider clocks */
> +	[K210_CLK_SPI3] = {
> +		GATE(K210_SYSCTL_EN_PERI, 9),
> +		DIV(K210_SYSCTL_THR1, 24, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 12)
> +	},
> +	[K210_CLK_TIMER0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 21),
> +		DIV(K210_SYSCTL_THR2,  0, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 13)
> +	},
> +	[K210_CLK_TIMER1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 22),
> +		DIV(K210_SYSCTL_THR2, 8, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 14)
> +	},
> +	[K210_CLK_TIMER2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 23),
> +		DIV(K210_SYSCTL_THR2, 16, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 15)
> +	},
> +};
> +
> +/*
> + * PLL control register bits.
> + */
> +#define K210_PLL_CLKR		GENMASK(3, 0)
> +#define K210_PLL_CLKF		GENMASK(9, 4)
> +#define K210_PLL_CLKOD		GENMASK(13, 10)
> +#define K210_PLL_BWADJ		GENMASK(19, 14)
> +#define K210_PLL_RESET		(1 << 20)
> +#define K210_PLL_PWRD		(1 << 21)
> +#define K210_PLL_INTFB		(1 << 22)
> +#define K210_PLL_BYPASS		(1 << 23)
> +#define K210_PLL_TEST		(1 << 24)
> +#define K210_PLL_EN		(1 << 25)
> +#define K210_PLL_SEL		GENMASK(27, 26) /* PLL2 only */
> +
> +/*
> + * PLL lock register bits.
> + */
> +#define K210_PLL_LOCK		0
> +#define K210_PLL_CLEAR_SLIP	2
> +#define K210_PLL_TEST_OUT	3
> +
> +/*
> + * Clock selector register bits.
> + */
> +#define K210_ACLK_SEL		BIT(0)
> +#define K210_ACLK_DIV		GENMASK(2, 1)
> +
> +/*
> + * PLLs.
> + */
> +enum k210_pll_id {
> +	K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM
> +};
> +
> +struct k210_pll {
> +enum k210_pll_id id;
> +	/* PLL setup register */
> +	void __iomem *reg;
> +
> +	/* Common lock register */
> +	void __iomem *lock;
> +
> +	/* Offset and width of lock bits */
> +	u8 lock_shift;
> +	u8 lock_width;
> +
> +	struct clk_hw hw;
> +};
> +#define to_k210_pll(hw)	container_of(hw, struct k210_pll, hw)
> +
> +struct k210_pll_cfg {
> +	/* PLL setup register offset */
> +	u32 reg;
> +
> +	/* Offset and width fo the lock bits */
> +	u8 lock_shift;
> +	u8 lock_width;
> +
> +	/* PLL setup initial factors */
> +	u32 r, f, od, bwadj;
> +};
> +
> +/*
> + * PLL factors:
> + * By default, PLL0 runs at 780 MHz and PLL1 at 299 MHz.
> + * The first 2 sram banks depend on ACLK/CPU clock which is by default
> + * PLL0 rate divided by 2. Set PLL1 to 390 MHz so that the third sram
> + * bank has the same clock.
> + */
> +static struct k210_pll_cfg k210_plls_cfg[] = {
> +	{ K210_SYSCTL_PLL0,  0, 2, 0, 59, 1, 59 }, /* 780 MHz */
> +	{ K210_SYSCTL_PLL1,  8, 1, 0, 59, 3, 59 }, /* 390 MHz */
> +	{ K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */
> +};
> +
> +/*
> + * Clocks data.
> + */
> +struct k210_clk {
> +	void __iomem			*regs;
> +	spinlock_t			clk_lock;
> +	struct k210_pll			plls[K210_PLL_NUM];
> +	struct clk_hw			aclk;
> +	struct clk_hw			clks[K210_NUM_CLKS];
> +	struct clk_hw_onecell_data	*clk_data;
> +};
> +
> +static struct k210_clk *kcl;
> +
> +/*
> + * Set ACLK parent selector: 0 for IN0, 1 for PLL0.
> + */
> +static void k210_aclk_set_selector(u8 sel)
> +{
> +	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
> +
> +	if (sel)
> +		reg |= K210_ACLK_SEL;
> +	else
> +		reg &= K210_ACLK_SEL;
> +	writel(reg, kcl->regs + K210_SYSCTL_SEL0);
> +}
> +
> +static void k210_init_pll(struct k210_pll *pll, enum k210_pll_id id,
> +			  void __iomem *base)
> +{
> +	pll->id = id;
> +	pll->lock = base + K210_SYSCTL_PLL_LOCK;
> +	pll->reg = base + k210_plls_cfg[id].reg;
> +	pll->lock_shift = k210_plls_cfg[id].lock_shift;
> +	pll->lock_width = k210_plls_cfg[id].lock_width;
> +}
> +
> +static void k210_pll_wait_for_lock(struct k210_pll *pll)
> +{
> +	u32 reg, mask = GENMASK(pll->lock_width - 1, 0) << pll->lock_shift;
> +
> +	while (true) {
> +		reg = readl(pll->lock);
> +		if ((reg & mask) == mask)
> +			break;
> +
> +		reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP);
> +		writel(reg, pll->lock);
> +	}
> +}
> +
> +static bool k210_pll_hw_is_enabled(struct k210_pll *pll)
> +{
> +	u32 reg = readl(pll->reg);
> +	u32 mask = K210_PLL_PWRD | K210_PLL_EN;
> +
> +	if (reg & K210_PLL_RESET)
> +		return false;
> +
> +	return (reg & mask) == mask;
> +}
> +
> +static void k210_pll_enable_hw(struct k210_pll *pll)
> +{
> +	struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id];
> +	unsigned long flags;
> +	u32 reg;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +
> +	if (k210_pll_hw_is_enabled(pll))
> +		goto unlock;
> +
> +	if (pll->id == K210_PLL0) {
> +		/* Re-parent aclk to IN0 to keep the CPUs running */
> +		k210_aclk_set_selector(0);
> +	}
> +
> +	/* Set factors */
> +	reg = readl(pll->reg);
> +	reg &= ~GENMASK(19, 0);
> +	reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r);
> +	reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f);
> +	reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od);
> +	reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj);
> +	reg |= K210_PLL_PWRD;
> +	writel(reg, pll->reg);
> +
> +	/* Ensure reset is low before asserting it */
> +	reg &= ~K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +	reg |= K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +	nop();
> +	nop();
> +	reg &= ~K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +
> +	k210_pll_wait_for_lock(pll);
> +
> +	reg &= ~K210_PLL_BYPASS;
> +	reg |= K210_PLL_EN;
> +	writel(reg, pll->reg);
> +
> +	if (pll->id == K210_PLL0) {
> +		/* Re-parent aclk back to PLL0 */
> +		k210_aclk_set_selector(1);
> +	}
> +unlock:
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static void k210_pll_disable_hw(struct k210_pll *pll)
> +{
> +	unsigned long flags;
> +	u32 reg;
> +
> +	/*
> +	 * Bypassing before powering off is important so child clocks don't stop
> +	 * working. This is especially important for pll0, the indirect parent
> +	 * of the cpu clock.
> +	 */

Did you get the bypass bit to work? I'm still having to bypass via
re-parenting ACLK in U-boot. Perhaps it is only necessary if you change
the rate as well?

> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(pll->reg);
> +	reg |= K210_PLL_BYPASS;
> +	writel(reg, pll->reg);
> +
> +	reg &= ~K210_PLL_PWRD;
> +	reg &= ~K210_PLL_EN;
> +	writel(reg, pll->reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static int k210_pll_enable(struct clk_hw *hw)
> +{
> +	k210_pll_enable_hw(to_k210_pll(hw));
> +
> +	return 0;
> +}
> +
> +static void k210_pll_disable(struct clk_hw *hw)
> +{
> +	k210_pll_disable_hw(to_k210_pll(hw));
> +}
> +
> +static int k210_pll_is_enabled(struct clk_hw *hw)
> +{
> +	return k210_pll_hw_is_enabled(to_k210_pll(hw));
> +}
> +
> +static int k210_pll_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	unsigned long flags;
> +	int ret = 0;
> +	u32 reg;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +
> +	switch (pll->id) {
> +	case K210_PLL0:
> +	case K210_PLL1:
> +		if (WARN_ON(index != 0))
> +			ret = -EINVAL;
> +		break;
> +	case K210_PLL2:
> +		if (WARN_ON(index > 2)) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +		reg = readl(pll->reg);
> +		reg &= ~K210_PLL_SEL;
> +		reg |= FIELD_PREP(K210_PLL_SEL, index);
> +		writel(reg, pll->reg);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return ret;
> +}
> +
> +static u8 k210_pll_get_parent(struct clk_hw *hw)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	u32 reg;
> +
> +	switch (pll->id) {
> +	case K210_PLL0:
> +	case K210_PLL1:
> +		return 0;
> +	case K210_PLL2:
> +		reg = readl(pll->reg);
> +		return FIELD_GET(K210_PLL_SEL, reg);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static unsigned long k210_pll_get_rate(struct clk_hw *hw,
> +				       unsigned long parent_rate)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	u32 reg = readl(pll->reg);
> +	u32 r, f, od;
> +
> +	if (reg & K210_PLL_BYPASS)
> +		return parent_rate;
> +
> +	if (!(reg & K210_PLL_PWRD))
> +		return 0;
> +
> +	r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
> +	f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
> +	od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
> +
> +	return (u64)parent_rate * f / (r * od);
> +}
> +
> +static const struct clk_ops k210_pll_ops = {
> +	.enable		= k210_pll_enable,
> +	.disable	= k210_pll_disable,
> +	.is_enabled	= k210_pll_is_enabled,
> +	.set_parent	= k210_pll_set_parent,
> +	.get_parent	= k210_pll_get_parent,
> +	.recalc_rate	= k210_pll_get_rate,
> +};
> +
> +static const char *pll_parents[] = { NULL, "pll0", "pll1" };
> +
> +static struct clk_hw *k210_register_pll(enum k210_pll_id id, const char *name,
> +				const char **parent_names, int num_parents,
> +				unsigned long flags)
> +{
> +	struct k210_pll *pll = &kcl->plls[id];
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = name;
> +	init.parent_names = parent_names;
> +	init.num_parents = num_parents;
> +	init.flags = flags;
> +	init.ops = &k210_pll_ops;
> +	pll->hw.init = &init;
> +
> +	ret = clk_hw_register(NULL, &pll->hw);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &pll->hw;
> +}
> +
> +static int k210_aclk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	if (WARN_ON(index > 1))
> +		return -EINVAL;
> +
> +	k210_aclk_set_selector(index);
> +
> +	return 0;
> +}
> +
> +static u8 k210_aclk_get_parent(struct clk_hw *hw)
> +{
> +	u32 sel = readl(kcl->regs + K210_SYSCTL_SEL0);
> +
> +	return (sel & K210_ACLK_SEL) ? 1 : 0;
> +}
> +
> +static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
> +					unsigned long parent_rate)
> +{
> +	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
> +	unsigned int shift;
> +
> +	if (!(reg & 0x1))
> +		return parent_rate;
> +
> +	shift = FIELD_GET(K210_ACLK_DIV, reg);
> +
> +	return parent_rate / (2UL << shift);
> +}
> +
> +static const struct clk_ops k210_aclk_ops = {
> +	.set_parent	= k210_aclk_set_parent,
> +	.get_parent	= k210_aclk_get_parent,
> +	.recalc_rate	= k210_aclk_get_rate,
> +};
> +
> +static const char *aclk_parents[] = { NULL, "pll0" };
> +
> +static struct clk_hw *k210_register_aclk(void)
> +{
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = "aclk";
> +	init.parent_names = aclk_parents;
> +	init.num_parents = 2;
> +	init.flags = 0;
> +	init.ops = &k210_aclk_ops;
> +	kcl->aclk.init = &init;
> +
> +	ret = clk_hw_register(NULL, &kcl->aclk);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &kcl->aclk;
> +}
> +
> +#define to_k210_clk_id(hw)	((unsigned int)((hw) - &kcl->clks[0]))
> +#define to_k210_clk_cfg(hw)	(&k210_clks[to_k210_clk_id(hw)])
> +
> +static u32 k210_clk_get_div_val(struct k210_clk_cfg *kclk)
> +{
> +	u32 reg = readl(kcl->regs + kclk->div_reg);
> +
> +	return (reg >> kclk->div_shift) & GENMASK(kclk->div_width - 1, 0);
> +}
> +
> +static unsigned long k210_clk_divider(struct k210_clk_cfg *kclk,
> +				      u32 div_val)
> +{
> +	switch (kclk->div_type) {
> +	case DIV_ONE_BASED:
> +		return div_val + 1;
> +	case DIV_DOUBLE_ONE_BASED:
> +		return (div_val + 1) * 2;
> +	case DIV_POWER_OF_TWO:
> +		return 2UL << div_val;
> +	case DIV_NONE:
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int k210_clk_enable(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->gate_reg)
> +		return 0;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->gate_reg);
> +	reg |= BIT(kclk->gate_bit);
> +	writel(reg, kcl->regs + kclk->gate_reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return 0;
> +}
> +
> +static void k210_clk_disable(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->gate_reg)
> +		return;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->gate_reg);
> +	reg &= ~BIT(kclk->gate_bit);
> +	writel(reg, kcl->regs + kclk->gate_reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static int k210_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +
> +	if (!kclk->gate_reg)
> +		return 1;
> +
> +	return readl(kcl->regs + kclk->gate_reg) & BIT(kclk->gate_bit);
> +}
> +
> +static int k210_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->mux_reg) {
> +		if (WARN_ON(index != 0))
> +			return -EINVAL;
> +		return 0;
> +	}
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->mux_reg);
> +	if (index)
> +		reg |= BIT(kclk->mux_bit);
> +	else
> +		reg &= ~BIT(kclk->mux_bit);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return 0;
> +}
> +
> +static u8 k210_clk_get_parent(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg, idx;
> +
> +	if (!kclk->mux_reg)
> +		return 0;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->mux_reg);
> +	idx = (reg & BIT(kclk->mux_bit)) ? 1 : 0;
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return idx;
> +}
> +
> +static unsigned long k210_clk_get_rate(struct clk_hw *hw,
> +				       unsigned long parent_rate)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long divider;
> +
> +	if (!kclk->div_reg)
> +		return parent_rate;
> +
> +	divider = k210_clk_divider(kclk, k210_clk_get_div_val(kclk));
> +	if (WARN_ON(!divider))
> +		return 0;
> +
> +	return parent_rate / divider;
> +}
> +
> +static const struct clk_ops k210_clk_ops = {
> +	.enable		= k210_clk_enable,
> +	.is_enabled	= k210_clk_is_enabled,
> +	.disable	= k210_clk_disable,
> +	.set_parent	= k210_clk_set_parent,
> +	.get_parent	= k210_clk_get_parent,
> +	.recalc_rate	= k210_clk_get_rate,
> +};
> +
> +static const char *mux_parents[] = { NULL, "pll0" };
> +
> +static struct clk_hw *k210_register_clk(int id, const char *name,
> +					const char *parent, unsigned long flags)
> +{
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = name;
> +	if (parent) {
> +		init.parent_names = &parent;
> +		init.num_parents = 1;
> +	} else {
> +		init.parent_names = mux_parents;
> +		init.num_parents = 2;
> +	}
> +	init.flags = flags;
> +	init.ops = &k210_clk_ops;
> +	kcl->clks[id].init = &init;
> +
> +	ret = clk_hw_register(NULL, &kcl->clks[id]);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &kcl->clks[id];
> +}
> +
> +static void __init k210_clk_init(struct device_node *np)
> +{
> +	struct device_node *sysctl_np;
> +	struct clk *in0_clk;
> +	const char *in0;
> +	struct clk_hw **hws;
> +	int i, ret;
> +
> +	pr_info("%pOFP\n", np);
> +
> +	kcl = kzalloc(sizeof(*kcl), GFP_KERNEL);
> +	if (!kcl)
> +		return;
> +
> +	sysctl_np = of_find_compatible_node(NULL, NULL, "kendryte,k210-sysctl");
> +	if (!sysctl_np)
> +		goto err;
> +
> +	kcl->regs = of_iomap(sysctl_np, 0);
> +	if (!kcl->regs)
> +		goto err;
> +
> +	kcl->clk_data = kzalloc(struct_size(kcl->clk_data, hws, K210_NUM_CLKS),
> +				GFP_KERNEL);
> +	if (!kcl->clk_data)
> +		goto err;
> +
> +	for (i = 0; i < K210_PLL_NUM; i++)
> +		k210_init_pll(&kcl->plls[i], i, kcl->regs);
> +	spin_lock_init(&kcl->clk_lock);
> +	kcl->clk_data->num = K210_NUM_CLKS;
> +	hws = kcl->clk_data->hws;
> +	for (i = 1; i < K210_NUM_CLKS; i++)
> +		hws[i] = ERR_PTR(-EPROBE_DEFER);
> +
> +	/*
> +	 * in0 is the system base fixed-rate 26MHz oscillator which
> +	 * should already be defined by the device tree. If it is not,
> +	 * create it here.
> +	 */
> +	in0_clk = of_clk_get(np, 0);
> +	if (IS_ERR(in0_clk)) {
> +		pr_warn("%pOFP: in0 oscillator not found\n", np);
> +		hws[K210_CLK_IN0] =
> +			clk_hw_register_fixed_rate(NULL, "in0", NULL,
> +						   0, K210_IN0_RATE);
> +	} else {
> +		hws[K210_CLK_IN0] = __clk_get_hw(in0_clk);
> +	}
> +	if (IS_ERR(hws[K210_CLK_IN0])) {
> +		pr_err("%pOFP: failed to get base oscillator\n", np);
> +		goto err;
> +	}
> +
> +	in0 = clk_hw_get_name(hws[K210_CLK_IN0]);
> +	aclk_parents[0] = in0;
> +	pll_parents[0] = in0;
> +	mux_parents[0] = in0;
> +
> +	pr_info("%pOFP: fixed-rate %lu MHz %s base clock\n",
> +		np, clk_hw_get_rate(hws[K210_CLK_IN0]) / 1000000, in0);
> +
> +	/* PLLs */
> +	hws[K210_CLK_PLL0] =
> +		k210_register_pll(K210_PLL0, "pll0", pll_parents, 1, 0);
> +	hws[K210_CLK_PLL1] =
> +		k210_register_pll(K210_PLL1, "pll1", pll_parents, 1, 0);
> +	hws[K210_CLK_PLL2] =
> +		k210_register_pll(K210_PLL2, "pll2", pll_parents, 3, 0);
> +
> +	/* aclk: muxed of in0 and pll0_d, no gate */
> +	hws[K210_CLK_ACLK] = k210_register_aclk();
> +
> +	/*
> +	 * Clocks with aclk as source: the CPU clock is obviously critical.
> +	 * So is the CLINT clock as the scheduler clocksource.
> +	 */
> +	hws[K210_CLK_CPU] =
> +		k210_register_clk(K210_CLK_CPU, "cpu", "aclk", CLK_IS_CRITICAL);
> +	hws[K210_CLK_CLINT] =
> +		clk_hw_register_fixed_factor(NULL, "clint", "aclk",
> +					     CLK_IS_CRITICAL, 1, 50);
> +	hws[K210_CLK_DMA] =
> +		k210_register_clk(K210_CLK_DMA, "dma", "aclk", 0);
> +	hws[K210_CLK_FFT] =
> +		k210_register_clk(K210_CLK_FFT, "fft", "aclk", 0);
> +	hws[K210_CLK_ROM] =
> +		k210_register_clk(K210_CLK_ROM, "rom", "aclk", 0);
> +	hws[K210_CLK_DVP] =
> +		k210_register_clk(K210_CLK_DVP, "dvp", "aclk", 0);
> +	hws[K210_CLK_APB0] =
> +		k210_register_clk(K210_CLK_APB0, "apb0", "aclk", 0);
> +	hws[K210_CLK_APB1] =
> +		k210_register_clk(K210_CLK_APB1, "apb1", "aclk", 0);
> +	hws[K210_CLK_APB2] =
> +		k210_register_clk(K210_CLK_APB2, "apb2", "aclk", 0);
> +
> +	/*
> +	 * There is no sram driver taking a ref on the sram banks clocks.
> +	 * So make them critical so they are not disabled due to being unused
> +	 * as seen by the clock infrastructure.
> +	 */
> +	hws[K210_CLK_SRAM0] =
> +		k210_register_clk(K210_CLK_SRAM0,
> +				  "sram0", "aclk", CLK_IS_CRITICAL);
> +	hws[K210_CLK_SRAM1] =
> +		k210_register_clk(K210_CLK_SRAM1,
> +				  "sram1", "aclk", CLK_IS_CRITICAL);
> +
> +	/* Clocks with PLL0 as source */
> +	hws[K210_CLK_SPI0] =
> +		k210_register_clk(K210_CLK_SPI0, "spi0", "pll0", 0);
> +	hws[K210_CLK_SPI1] =
> +		 k210_register_clk(K210_CLK_SPI1, "spi1", "pll0", 0);
> +	hws[K210_CLK_SPI2] =
> +		 k210_register_clk(K210_CLK_SPI2, "spi2", "pll0", 0);
> +	hws[K210_CLK_I2C0] =
> +		 k210_register_clk(K210_CLK_I2C0, "i2c0", "pll0", 0);
> +	hws[K210_CLK_I2C1] =
> +		 k210_register_clk(K210_CLK_I2C1, "i2c1", "pll0", 0);
> +	hws[K210_CLK_I2C2] =
> +		 k210_register_clk(K210_CLK_I2C2, "i2c2", "pll0", 0);
> +
> +	/*
> +	 * Clocks with PLL1 as source: there is only the AI clock for the
> +	 * (unused) KPU device. As this clock also drives the aisram bank
> +	 * which is used as general memory, make it critical.
> +	 */
> +	 hws[K210_CLK_AI] =
> +		 k210_register_clk(K210_CLK_AI, "ai", "pll1", CLK_IS_CRITICAL);
> +
> +	/* Clocks with PLL2 as source */
> +	hws[K210_CLK_I2S0] =
> +		 k210_register_clk(K210_CLK_I2S0, "i2s0", "pll2", 0);
> +	hws[K210_CLK_I2S1] =
> +		 k210_register_clk(K210_CLK_I2S1, "i2s1", "pll2", 0);
> +	hws[K210_CLK_I2S2] =
> +		k210_register_clk(K210_CLK_I2S2, "i2s2", "pll2", 0);
> +	hws[K210_CLK_I2S0_M] =
> +		k210_register_clk(K210_CLK_I2S0_M, "i2s0_m", "pll2", 0);
> +	hws[K210_CLK_I2S1_M] =
> +		k210_register_clk(K210_CLK_I2S1_M, "i2s1_m", "pll2", 0);
> +	hws[K210_CLK_I2S2_M] =
> +		k210_register_clk(K210_CLK_I2S2_M, "i2s2_m", "pll2", 0);
> +
> +	/* Clocks with IN0 as source */
> +	hws[K210_CLK_WDT0] =
> +		k210_register_clk(K210_CLK_WDT0, "wdt0", in0, 0);
> +	hws[K210_CLK_WDT1] =
> +		 k210_register_clk(K210_CLK_WDT1, "wdt1", in0, 0);
> +	hws[K210_CLK_RTC] =
> +		 k210_register_clk(K210_CLK_RTC, "rtc", in0, 0);
> +
> +	/* Clocks with APB0 as source */
> +	hws[K210_CLK_GPIO] =
> +		k210_register_clk(K210_CLK_GPIO, "gpio", "apb0", 0);
> +	hws[K210_CLK_UART1] =
> +		k210_register_clk(K210_CLK_UART1, "uart1", "apb0", 0);
> +	hws[K210_CLK_UART2] =
> +		k210_register_clk(K210_CLK_UART2, "uart2", "apb0", 0);
> +	hws[K210_CLK_UART3] =
> +		k210_register_clk(K210_CLK_UART3, "uart3", "apb0", 0);
> +	hws[K210_CLK_FPIOA] =
> +		k210_register_clk(K210_CLK_FPIOA, "fpioa", "apb0", 0);
> +	hws[K210_CLK_SHA] =
> +		k210_register_clk(K210_CLK_SHA, "sha", "apb0", 0);
> +
> +	/* Clocks with APB1 as source */
> +	hws[K210_CLK_AES] =
> +		 k210_register_clk(K210_CLK_AES, "aes", "apb1", 0);
> +	hws[K210_CLK_OTP] =
> +		 k210_register_clk(K210_CLK_OTP, "otp", "apb1", 0);
> +
> +	/* Muxed clocks with in0/pll0 as source */
> +	hws[K210_CLK_SPI3] =
> +		k210_register_clk(K210_CLK_SPI3, "spi3", NULL, 0);
> +	hws[K210_CLK_TIMER0] =
> +		k210_register_clk(K210_CLK_TIMER0, "timer0", NULL, 0);
> +	hws[K210_CLK_TIMER1] =
> +		k210_register_clk(K210_CLK_TIMER1, "timer1", NULL, 0);
> +	hws[K210_CLK_TIMER2] =
> +		k210_register_clk(K210_CLK_TIMER2, "timer2", NULL, 0);
> +
> +	for (i = 0; i < K210_NUM_CLKS; i++) {
> +		if (IS_ERR(hws[i])) {
> +			pr_err("%pOFP: register clock %d failed %ld\n",
> +			       np, i, PTR_ERR(hws[i]));
> +			goto err;
> +		}
> +	}
> +
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, kcl->clk_data);
> +	if (ret)
> +		pr_err("%pOFP: add clock provider failed %d\n", np, ret);
> +
> +	return;
> +err:
> +	pr_err("%pOFP: clock initialization failed\n", np);
> +	iounmap(kcl->regs);
> +	kfree(kcl->clk_data);
> +	kfree(kcl);
> +	kcl = NULL;
> +}
> +
> +CLK_OF_DECLARE_DRIVER(k210_clk, "kendryte,k210-clk", k210_clk_init);
> +
> +/*
> + * Enable PLL1 to be able to use the AI SRAM.
> + */
> +void k210_clk_early_init(void __iomem *regs)
> +{
> +	struct k210_pll pll1;
> +
> +	/* Make sure aclk selector is set to PLL0 */
> +	k210_aclk_set_selector(1);
> +
> +	/* Startup PLL1 to enable the aisram bank for general memory use */
> +	k210_init_pll(&pll1, K210_PLL1, regs);
> +	k210_pll_enable_hw(&pll1);
> +}
> diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
> index 4608fbca20e1..336f4b119bdd 100644
> --- a/drivers/soc/kendryte/k210-sysctl.c
> +++ b/drivers/soc/kendryte/k210-sysctl.c
> @@ -3,201 +3,41 @@
>   * Copyright (c) 2019 Christoph Hellwig.
>   * Copyright (c) 2019 Western Digital Corporation or its affiliates.
>   */
> -#include <linux/types.h>
>  #include <linux/io.h>
> -#include <linux/of.h>
>  #include <linux/platform_device.h>
> -#include <linux/clk-provider.h>
> -#include <linux/clkdev.h>
> -#include <linux/bitfield.h>
> +#include <linux/of_platform.h>
> +#include <linux/clk.h>
>  #include <asm/soc.h>
>  
> -#define K210_SYSCTL_CLK0_FREQ		26000000UL
> +#include <soc/kendryte/k210-sysctl.h>
>  
> -/* Registers base address */
> -#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
> -
> -/* Registers */
> -#define K210_SYSCTL_PLL0		0x08
> -#define K210_SYSCTL_PLL1		0x0c
> -/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
> -#define   PLL_RESET		(1 << 20)
> -#define   PLL_PWR		(1 << 21)
> -#define   PLL_INTFB		(1 << 22)
> -#define   PLL_BYPASS		(1 << 23)
> -#define   PLL_TEST		(1 << 24)
> -#define   PLL_OUT_EN		(1 << 25)
> -#define   PLL_TEST_EN		(1 << 26)
> -#define K210_SYSCTL_PLL_LOCK		0x18
> -#define   PLL0_LOCK1		(1 << 0)
> -#define   PLL0_LOCK2		(1 << 1)
> -#define   PLL0_SLIP_CLEAR	(1 << 2)
> -#define   PLL0_TEST_CLK_OUT	(1 << 3)
> -#define   PLL1_LOCK1		(1 << 8)
> -#define   PLL1_LOCK2		(1 << 9)
> -#define   PLL1_SLIP_CLEAR	(1 << 10)
> -#define   PLL1_TEST_CLK_OUT	(1 << 11)
> -#define   PLL2_LOCK1		(1 << 16)
> -#define   PLL2_LOCK2		(1 << 16)
> -#define   PLL2_SLIP_CLEAR	(1 << 18)
> -#define   PLL2_TEST_CLK_OUT	(1 << 19)
> -#define K210_SYSCTL_CLKSEL0	0x20
> -#define   CLKSEL_ACLK		(1 << 0)
> -#define K210_SYSCTL_CLKEN_CENT		0x28
> -#define   CLKEN_CPU		(1 << 0)
> -#define   CLKEN_SRAM0		(1 << 1)
> -#define   CLKEN_SRAM1		(1 << 2)
> -#define   CLKEN_APB0		(1 << 3)
> -#define   CLKEN_APB1		(1 << 4)
> -#define   CLKEN_APB2		(1 << 5)
> -#define K210_SYSCTL_CLKEN_PERI		0x2c
> -#define   CLKEN_ROM		(1 << 0)
> -#define   CLKEN_DMA		(1 << 1)
> -#define   CLKEN_AI		(1 << 2)
> -#define   CLKEN_DVP		(1 << 3)
> -#define   CLKEN_FFT		(1 << 4)
> -#define   CLKEN_GPIO		(1 << 5)
> -#define   CLKEN_SPI0		(1 << 6)
> -#define   CLKEN_SPI1		(1 << 7)
> -#define   CLKEN_SPI2		(1 << 8)
> -#define   CLKEN_SPI3		(1 << 9)
> -#define   CLKEN_I2S0		(1 << 10)
> -#define   CLKEN_I2S1		(1 << 11)
> -#define   CLKEN_I2S2		(1 << 12)
> -#define   CLKEN_I2C0		(1 << 13)
> -#define   CLKEN_I2C1		(1 << 14)
> -#define   CLKEN_I2C2		(1 << 15)
> -#define   CLKEN_UART1		(1 << 16)
> -#define   CLKEN_UART2		(1 << 17)
> -#define   CLKEN_UART3		(1 << 18)
> -#define   CLKEN_AES		(1 << 19)
> -#define   CLKEN_FPIO		(1 << 20)
> -#define   CLKEN_TIMER0		(1 << 21)
> -#define   CLKEN_TIMER1		(1 << 22)
> -#define   CLKEN_TIMER2		(1 << 23)
> -#define   CLKEN_WDT0		(1 << 24)
> -#define   CLKEN_WDT1		(1 << 25)
> -#define   CLKEN_SHA		(1 << 26)
> -#define   CLKEN_OTP		(1 << 27)
> -#define   CLKEN_RTC		(1 << 29)
> -
> -struct k210_sysctl {
> -	void __iomem		*regs;
> -	struct clk_hw		hw;
> -};
> -
> -static void k210_set_bits(u32 val, void __iomem *reg)
> -{
> -	writel(readl(reg) | val, reg);
> -}
> -
> -static void k210_clear_bits(u32 val, void __iomem *reg)
> -{
> -	writel(readl(reg) & ~val, reg);
> -}
> -
> -static void k210_pll1_enable(void __iomem *regs)
> +static int __init k210_sysctl_probe(struct platform_device *pdev)
>  {
> -	u32 val;
> +	struct device *dev = &pdev->dev;
> +	struct clk *pclk;
> +	int ret;
>  
> -	val = readl(regs + K210_SYSCTL_PLL1);
> -	val &= ~GENMASK(19, 0);				/* clkr1 = 0 */
> -	val |= FIELD_PREP(GENMASK(9, 4), 0x3B);		/* clkf1 = 59 */
> -	val |= FIELD_PREP(GENMASK(13, 10), 0x3);	/* clkod1 = 3 */
> -	val |= FIELD_PREP(GENMASK(19, 14), 0x3B);	/* bwadj1 = 59 */
> -	writel(val, regs + K210_SYSCTL_PLL1);
> +	dev_info(dev, "K210 system controller\n");
>  
> -	k210_clear_bits(PLL_BYPASS, regs + K210_SYSCTL_PLL1);
> -	k210_set_bits(PLL_PWR, regs + K210_SYSCTL_PLL1);
> -
> -	/*
> -	 * Reset the pll. The magic NOPs come from the Kendryte reference SDK.
> -	 */
> -	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -	k210_set_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -	nop();
> -	nop();
> -	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -
> -	for (;;) {
> -		val = readl(regs + K210_SYSCTL_PLL_LOCK);
> -		if (val & PLL1_LOCK2)
> -			break;
> -		writel(val | PLL1_SLIP_CLEAR, regs + K210_SYSCTL_PLL_LOCK);
> +	/* Get power bus clock */
> +	pclk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(pclk)) {
> +		dev_err(dev, "Get bus clock failed\n");
> +		return PTR_ERR(pclk);
>  	}
>  
> -	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL1);
> -}
> -
> -static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw,
> -		unsigned long parent_rate)
> -{
> -	struct k210_sysctl *s = container_of(hw, struct k210_sysctl, hw);
> -	u32 clksel0, pll0;
> -	u64 pll0_freq, clkr0, clkf0, clkod0;
> -
> -	/*
> -	 * If the clock selector is not set, use the base frequency.
> -	 * Otherwise, use PLL0 frequency with a frequency divisor.
> -	 */
> -	clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0);
> -	if (!(clksel0 & CLKSEL_ACLK))
> -		return K210_SYSCTL_CLK0_FREQ;
> -
> -	/*
> -	 * Get PLL0 frequency:
> -	 * freq = base frequency * clkf0 / (clkr0 * clkod0)
> -	 */
> -	pll0 = readl(s->regs + K210_SYSCTL_PLL0);
> -	clkr0 = 1 + FIELD_GET(GENMASK(3, 0), pll0);
> -	clkf0 = 1 + FIELD_GET(GENMASK(9, 4), pll0);
> -	clkod0 = 1 + FIELD_GET(GENMASK(13, 10), pll0);
> -	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
> -
> -	/* Get the frequency divisor from the clock selector */
> -	return pll0_freq / (2ULL << FIELD_GET(0x00000006, clksel0));
> -}
> -
> -static const struct clk_ops k210_sysctl_clk_ops = {
> -	.recalc_rate	= k210_sysctl_clk_recalc_rate,
> -};
> -
> -static const struct clk_init_data k210_clk_init_data = {
> -	.name		= "k210-sysctl-pll1",
> -	.ops		= &k210_sysctl_clk_ops,
> -};
> -
> -static int k210_sysctl_probe(struct platform_device *pdev)
> -{
> -	struct k210_sysctl *s;
> -	int error;
> -
> -	pr_info("Kendryte K210 SoC sysctl\n");
> -
> -	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
> -	if (!s)
> -		return -ENOMEM;
> -
> -	s->regs = devm_ioremap_resource(&pdev->dev,
> -			platform_get_resource(pdev, IORESOURCE_MEM, 0));
> -	if (IS_ERR(s->regs))
> -		return PTR_ERR(s->regs);
> -
> -	s->hw.init = &k210_clk_init_data;
> -	error = devm_clk_hw_register(&pdev->dev, &s->hw);
> -	if (error) {
> -		dev_err(&pdev->dev, "failed to register clk");
> -		return error;
> +	ret = clk_prepare_enable(pclk);
> +	if (ret) {
> +		dev_err(dev, "Enable bus clock failed\n");
> +		return ret;
>  	}
>  
> -	error = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
> -					    &s->hw);
> -	if (error) {
> -		dev_err(&pdev->dev, "adding clk provider failed\n");
> -		return error;
> -	}
> +	/* Populate children */
> +	ret = devm_of_platform_populate(dev);
> +	if (ret)
> +		dev_err(dev, "Populate platform failed %d\n", ret);
>  
> -	return 0;
> +	return ret;
>  }
>  
>  static const struct of_device_id k210_sysctl_of_match[] = {
> @@ -213,11 +53,22 @@ static struct platform_driver k210_sysctl_driver = {
>  	.probe			= k210_sysctl_probe,
>  };
>  
> +/*
> + * Most devices on the K210 SoC depend on the early initialization of sysctl
> + * fpioa and reset child nodes. So initialize this driver early as part of
> + * the post core initialization.
> + */
>  static int __init k210_sysctl_init(void)
>  {
>  	return platform_driver_register(&k210_sysctl_driver);
>  }
> -core_initcall(k210_sysctl_init);
> +postcore_initcall(k210_sysctl_init);
> +
> +/*
> + * System controller registers base address and size.
> + */
> +#define K210_SYSCTL_BASE_ADDR	0x50440000ULL
> +#define K210_SYSCTL_BASE_SIZE	0x1000
>  
>  /*
>   * This needs to be called very early during initialization, given that
> @@ -225,24 +76,14 @@ core_initcall(k210_sysctl_init);
>   */
>  static void __init k210_soc_early_init(const void *fdt)
>  {
> -	void __iomem *regs;
> -
> -	regs = ioremap(K210_SYSCTL_SYSCTL_BASE_ADDR, 0x1000);
> -	if (!regs)
> -		panic("K210 sysctl ioremap");
> -
> -	/* Enable PLL1 to make the KPU SRAM useable */
> -	k210_pll1_enable(regs);
> -
> -	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0);
> +	void __iomem *sysctl_base;
>  
> -	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
> -		      regs + K210_SYSCTL_CLKEN_CENT);
> -	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
> -		      regs + K210_SYSCTL_CLKEN_PERI);
> +	sysctl_base = ioremap(K210_SYSCTL_BASE_ADDR, K210_SYSCTL_BASE_SIZE);
> +	if (!sysctl_base)
> +		panic("k210-sysctl: ioremap failed");
>  
> -	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0);
> +	k210_clk_early_init(sysctl_base);
>  
> -	iounmap(regs);
> +	iounmap(sysctl_base);
>  }
> -SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
> +SOC_EARLY_INIT_DECLARE(k210_soc, "kendryte,k210", k210_soc_early_init);
> diff --git a/include/soc/kendryte/k210-sysctl.h b/include/soc/kendryte/k210-sysctl.h
> new file mode 100644
> index 000000000000..73e38a8fc31d
> --- /dev/null
> +++ b/include/soc/kendryte/k210-sysctl.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef K210_SYSCTL_H
> +#define K210_SYSCTL_H
> +
> +void k210_clk_early_init(void __iomem *regs);
> +
> +#endif
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
@ 2020-11-07 13:48     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:48 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a clock provider driver for the Kendryte K210 RISC-V SoC. This new
> driver with compatible string "kendryte,k210-clk", implements the full
> clock structure of the K210 SoC. Since it is required for the correct
> operation of the SoC, this driver is automatically selected for
> compilation when the SOC_KENDRYTE option is selected.
> 
> With this change, the k210-sysctl driver is turned into a simple
> platform driver which enables its power bus clock and triggers
> populating its child nodes. The sysctl soc driver retains the SOC early
> initialization code, but the implementation now relies on the new
> function k210_clk_early_init() provided by the new clk-k210 driver.
> This function declaration is done using the new header file
> include/soc/kendryte/k210-sysctl.h.
> 
> The clock structure implemented and many of the coding ideas for the
> driver come from the work by Sean Anderson on the Kendryte K210 support
> for the U-Boot project.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs            |   1 +
>  drivers/clk/Kconfig                |   9 +
>  drivers/clk/Makefile               |   1 +
>  drivers/clk/clk-k210.c             | 962 +++++++++++++++++++++++++++++
>  drivers/soc/kendryte/k210-sysctl.c | 241 ++------
>  include/soc/kendryte/k210-sysctl.h |  11 +
>  6 files changed, 1025 insertions(+), 200 deletions(-)
>  create mode 100644 drivers/clk/clk-k210.c
>  create mode 100644 include/soc/kendryte/k210-sysctl.h
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 97ef393d0ed0..a4c851ffc6b0 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -30,6 +30,7 @@ config SOC_KENDRYTE
>  	select SERIAL_SIFIVE_CONSOLE if TTY
>  	select SIFIVE_PLIC
>  	select SOC_K210
> +	select CLK_K210
>  	help
>  	  This enables support for Kendryte K210 SoC platform hardware.
>  
> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
> index c715d4681a0b..07a30a7b90b1 100644
> --- a/drivers/clk/Kconfig
> +++ b/drivers/clk/Kconfig
> @@ -359,6 +359,15 @@ config COMMON_CLK_FIXED_MMIO
>  	help
>  	  Support for Memory Mapped IO Fixed clocks
>  
> +config CLK_K210
> +	bool "Clock driver for the Kendryte K210 SoC"
> +	depends on RISCV && SOC_KENDRYTE
> +	depends on COMMON_CLK && OF
> +	help
> +	  Support for the Kendryte K210 RISC-V SoC clocks. This option
> +	  is automatically selected when the SOC_KENDRYTE option is selected
> +	  in the "SOC selection" menu.
> +
>  source "drivers/clk/actions/Kconfig"
>  source "drivers/clk/analogbits/Kconfig"
>  source "drivers/clk/baikal-t1/Kconfig"
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index da8fcf147eb1..ccac89e0fdfe 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_ARCH_VT8500)		+= clk-vt8500.o
>  obj-$(CONFIG_COMMON_CLK_VC5)		+= clk-versaclock5.o
>  obj-$(CONFIG_COMMON_CLK_WM831X)		+= clk-wm831x.o
>  obj-$(CONFIG_COMMON_CLK_XGENE)		+= clk-xgene.o
> +obj-$(CONFIG_CLK_K210)			+= clk-k210.o
>  
>  # please keep this section sorted lexicographically by directory path name
>  obj-y					+= actions/
> diff --git a/drivers/clk/clk-k210.c b/drivers/clk/clk-k210.c
> new file mode 100644
> index 000000000000..7be5a8cdfef6
> --- /dev/null
> +++ b/drivers/clk/clk-k210.c
> @@ -0,0 +1,962 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2019 Western Digital Corporation or its affiliates.
> + */
> +#define pr_fmt(fmt)     "k210-clk: " fmt
> +
> +#include <soc/kendryte/k210-sysctl.h>
> +#include <linux/io.h>
> +#include <linux/spinlock.h>
> +#include <linux/platform_device.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/clkdev.h>
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <asm/soc.h>
> +
> +#include <dt-bindings/clock/k210-clk.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +
> +/*
> + * in0: fixed-rate 26MHz oscillator base clock.
> + */
> +#define K210_IN0_RATE		26000000UL
> +
> +/*
> + * Clocks parameters.
> + */
> +struct k210_clk_cfg {
> +	u8 gate_reg;
> +	u8 gate_bit;
> +	u8 div_reg;
> +	u8 div_shift;
> +	u8 div_width;
> +	u8 div_type;
> +	u8 mux_reg;
> +	u8 mux_bit;
> +};
> +
> +enum k210_clk_div_type {
> +	DIV_NONE,
> +	DIV_ONE_BASED,
> +	DIV_DOUBLE_ONE_BASED,
> +	DIV_POWER_OF_TWO,
> +};
> +
> +#define GATE(_reg, _bit)	\
> +	.gate_reg = (_reg),	\
> +	.gate_bit = (_bit)
> +#define DIV(_reg, _shift, _width, _type)	\
> +	.div_reg = (_reg),			\
> +	.div_shift = (_shift),			\
> +	.div_width = (_width),			\
> +	.div_type = (_type)
> +#define MUX(_reg, _bit)		\
> +	.mux_reg = (_reg),	\
> +	.mux_bit = (_bit)
> +
> +static struct k210_clk_cfg k210_clks[K210_NUM_CLKS] = {
> +
> +	/* Gated clocks, no mux, no divider */
> +	[K210_CLK_CPU] = { GATE(K210_SYSCTL_EN_CENT, 0) },
> +	[K210_CLK_DMA] = { GATE(K210_SYSCTL_EN_PERI, 1) },
> +	[K210_CLK_FFT] = { GATE(K210_SYSCTL_EN_PERI, 4) },
> +	[K210_CLK_GPIO] = { GATE(K210_SYSCTL_EN_PERI, 5) },
> +	[K210_CLK_UART1] = { GATE(K210_SYSCTL_EN_PERI, 16) },
> +	[K210_CLK_UART2] = { GATE(K210_SYSCTL_EN_PERI, 17) },
> +	[K210_CLK_UART3] = { GATE(K210_SYSCTL_EN_PERI, 18) },
> +	[K210_CLK_FPIOA] = { GATE(K210_SYSCTL_EN_PERI, 20) },
> +	[K210_CLK_SHA] = { GATE(K210_SYSCTL_EN_PERI, 26) },
> +	[K210_CLK_AES] = { GATE(K210_SYSCTL_EN_PERI, 19) },
> +	[K210_CLK_OTP] = { GATE(K210_SYSCTL_EN_PERI, 27) },
> +	[K210_CLK_RTC] = { GATE(K210_SYSCTL_EN_PERI, 29) },
> +
> +	/* Gated divider clocks */
> +	[K210_CLK_SRAM0] = {
> +		GATE(K210_SYSCTL_EN_CENT, 1),
> +		DIV(K210_SYSCTL_THR0, 0, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_SRAM1] = {
> +		GATE(K210_SYSCTL_EN_CENT, 2),
> +		DIV(K210_SYSCTL_THR0, 4, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_ROM] = {
> +		GATE(K210_SYSCTL_EN_PERI, 0),
> +		DIV(K210_SYSCTL_THR0, 16, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_DVP] = {
> +		GATE(K210_SYSCTL_EN_PERI, 3),
> +		DIV(K210_SYSCTL_THR0, 12, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB0] = {
> +		GATE(K210_SYSCTL_EN_CENT, 3),
> +		DIV(K210_SYSCTL_SEL0, 3, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB1] = {
> +		GATE(K210_SYSCTL_EN_CENT, 4),
> +		DIV(K210_SYSCTL_SEL0, 6, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_APB2] = {
> +		GATE(K210_SYSCTL_EN_CENT, 5),
> +		DIV(K210_SYSCTL_SEL0, 9, 3, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_AI] = {
> +		GATE(K210_SYSCTL_EN_PERI, 2),
> +		DIV(K210_SYSCTL_THR0, 8, 4, DIV_ONE_BASED)
> +	},
> +	[K210_CLK_SPI0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 6),
> +		DIV(K210_SYSCTL_THR1, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_SPI1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 7),
> +		DIV(K210_SYSCTL_THR1, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_SPI2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 8),
> +		DIV(K210_SYSCTL_THR1, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 13),
> +		DIV(K210_SYSCTL_THR5, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 14),
> +		DIV(K210_SYSCTL_THR5, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2C2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 15),
> +		DIV(K210_SYSCTL_THR5, 24, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_WDT0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 24),
> +		DIV(K210_SYSCTL_THR6, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_WDT1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 25),
> +		DIV(K210_SYSCTL_THR6, 8, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 10),
> +		DIV(K210_SYSCTL_THR3, 0, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 11),
> +		DIV(K210_SYSCTL_THR3, 16, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 12),
> +		DIV(K210_SYSCTL_THR4, 0, 16, DIV_DOUBLE_ONE_BASED)
> +	},
> +
> +	/* Divider clocks, no gate, no mux */
> +	[K210_CLK_I2S0_M] = {
> +		DIV(K210_SYSCTL_THR4, 16, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S1_M] = {
> +		DIV(K210_SYSCTL_THR4, 24, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +	[K210_CLK_I2S2_M] = {
> +		DIV(K210_SYSCTL_THR4, 0, 8, DIV_DOUBLE_ONE_BASED)
> +	},
> +
> +	/* Muxed gated divider clocks */
> +	[K210_CLK_SPI3] = {
> +		GATE(K210_SYSCTL_EN_PERI, 9),
> +		DIV(K210_SYSCTL_THR1, 24, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 12)
> +	},
> +	[K210_CLK_TIMER0] = {
> +		GATE(K210_SYSCTL_EN_PERI, 21),
> +		DIV(K210_SYSCTL_THR2,  0, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 13)
> +	},
> +	[K210_CLK_TIMER1] = {
> +		GATE(K210_SYSCTL_EN_PERI, 22),
> +		DIV(K210_SYSCTL_THR2, 8, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 14)
> +	},
> +	[K210_CLK_TIMER2] = {
> +		GATE(K210_SYSCTL_EN_PERI, 23),
> +		DIV(K210_SYSCTL_THR2, 16, 8, DIV_DOUBLE_ONE_BASED),
> +		MUX(K210_SYSCTL_SEL0, 15)
> +	},
> +};
> +
> +/*
> + * PLL control register bits.
> + */
> +#define K210_PLL_CLKR		GENMASK(3, 0)
> +#define K210_PLL_CLKF		GENMASK(9, 4)
> +#define K210_PLL_CLKOD		GENMASK(13, 10)
> +#define K210_PLL_BWADJ		GENMASK(19, 14)
> +#define K210_PLL_RESET		(1 << 20)
> +#define K210_PLL_PWRD		(1 << 21)
> +#define K210_PLL_INTFB		(1 << 22)
> +#define K210_PLL_BYPASS		(1 << 23)
> +#define K210_PLL_TEST		(1 << 24)
> +#define K210_PLL_EN		(1 << 25)
> +#define K210_PLL_SEL		GENMASK(27, 26) /* PLL2 only */
> +
> +/*
> + * PLL lock register bits.
> + */
> +#define K210_PLL_LOCK		0
> +#define K210_PLL_CLEAR_SLIP	2
> +#define K210_PLL_TEST_OUT	3
> +
> +/*
> + * Clock selector register bits.
> + */
> +#define K210_ACLK_SEL		BIT(0)
> +#define K210_ACLK_DIV		GENMASK(2, 1)
> +
> +/*
> + * PLLs.
> + */
> +enum k210_pll_id {
> +	K210_PLL0, K210_PLL1, K210_PLL2, K210_PLL_NUM
> +};
> +
> +struct k210_pll {
> +enum k210_pll_id id;
> +	/* PLL setup register */
> +	void __iomem *reg;
> +
> +	/* Common lock register */
> +	void __iomem *lock;
> +
> +	/* Offset and width of lock bits */
> +	u8 lock_shift;
> +	u8 lock_width;
> +
> +	struct clk_hw hw;
> +};
> +#define to_k210_pll(hw)	container_of(hw, struct k210_pll, hw)
> +
> +struct k210_pll_cfg {
> +	/* PLL setup register offset */
> +	u32 reg;
> +
> +	/* Offset and width fo the lock bits */
> +	u8 lock_shift;
> +	u8 lock_width;
> +
> +	/* PLL setup initial factors */
> +	u32 r, f, od, bwadj;
> +};
> +
> +/*
> + * PLL factors:
> + * By default, PLL0 runs at 780 MHz and PLL1 at 299 MHz.
> + * The first 2 sram banks depend on ACLK/CPU clock which is by default
> + * PLL0 rate divided by 2. Set PLL1 to 390 MHz so that the third sram
> + * bank has the same clock.
> + */
> +static struct k210_pll_cfg k210_plls_cfg[] = {
> +	{ K210_SYSCTL_PLL0,  0, 2, 0, 59, 1, 59 }, /* 780 MHz */
> +	{ K210_SYSCTL_PLL1,  8, 1, 0, 59, 3, 59 }, /* 390 MHz */
> +	{ K210_SYSCTL_PLL2, 16, 1, 0, 22, 1, 22 }, /* 299 MHz */
> +};
> +
> +/*
> + * Clocks data.
> + */
> +struct k210_clk {
> +	void __iomem			*regs;
> +	spinlock_t			clk_lock;
> +	struct k210_pll			plls[K210_PLL_NUM];
> +	struct clk_hw			aclk;
> +	struct clk_hw			clks[K210_NUM_CLKS];
> +	struct clk_hw_onecell_data	*clk_data;
> +};
> +
> +static struct k210_clk *kcl;
> +
> +/*
> + * Set ACLK parent selector: 0 for IN0, 1 for PLL0.
> + */
> +static void k210_aclk_set_selector(u8 sel)
> +{
> +	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
> +
> +	if (sel)
> +		reg |= K210_ACLK_SEL;
> +	else
> +		reg &= K210_ACLK_SEL;
> +	writel(reg, kcl->regs + K210_SYSCTL_SEL0);
> +}
> +
> +static void k210_init_pll(struct k210_pll *pll, enum k210_pll_id id,
> +			  void __iomem *base)
> +{
> +	pll->id = id;
> +	pll->lock = base + K210_SYSCTL_PLL_LOCK;
> +	pll->reg = base + k210_plls_cfg[id].reg;
> +	pll->lock_shift = k210_plls_cfg[id].lock_shift;
> +	pll->lock_width = k210_plls_cfg[id].lock_width;
> +}
> +
> +static void k210_pll_wait_for_lock(struct k210_pll *pll)
> +{
> +	u32 reg, mask = GENMASK(pll->lock_width - 1, 0) << pll->lock_shift;
> +
> +	while (true) {
> +		reg = readl(pll->lock);
> +		if ((reg & mask) == mask)
> +			break;
> +
> +		reg |= BIT(pll->lock_shift + K210_PLL_CLEAR_SLIP);
> +		writel(reg, pll->lock);
> +	}
> +}
> +
> +static bool k210_pll_hw_is_enabled(struct k210_pll *pll)
> +{
> +	u32 reg = readl(pll->reg);
> +	u32 mask = K210_PLL_PWRD | K210_PLL_EN;
> +
> +	if (reg & K210_PLL_RESET)
> +		return false;
> +
> +	return (reg & mask) == mask;
> +}
> +
> +static void k210_pll_enable_hw(struct k210_pll *pll)
> +{
> +	struct k210_pll_cfg *pll_cfg = &k210_plls_cfg[pll->id];
> +	unsigned long flags;
> +	u32 reg;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +
> +	if (k210_pll_hw_is_enabled(pll))
> +		goto unlock;
> +
> +	if (pll->id == K210_PLL0) {
> +		/* Re-parent aclk to IN0 to keep the CPUs running */
> +		k210_aclk_set_selector(0);
> +	}
> +
> +	/* Set factors */
> +	reg = readl(pll->reg);
> +	reg &= ~GENMASK(19, 0);
> +	reg |= FIELD_PREP(K210_PLL_CLKR, pll_cfg->r);
> +	reg |= FIELD_PREP(K210_PLL_CLKF, pll_cfg->f);
> +	reg |= FIELD_PREP(K210_PLL_CLKOD, pll_cfg->od);
> +	reg |= FIELD_PREP(K210_PLL_BWADJ, pll_cfg->bwadj);
> +	reg |= K210_PLL_PWRD;
> +	writel(reg, pll->reg);
> +
> +	/* Ensure reset is low before asserting it */
> +	reg &= ~K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +	reg |= K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +	nop();
> +	nop();
> +	reg &= ~K210_PLL_RESET;
> +	writel(reg, pll->reg);
> +
> +	k210_pll_wait_for_lock(pll);
> +
> +	reg &= ~K210_PLL_BYPASS;
> +	reg |= K210_PLL_EN;
> +	writel(reg, pll->reg);
> +
> +	if (pll->id == K210_PLL0) {
> +		/* Re-parent aclk back to PLL0 */
> +		k210_aclk_set_selector(1);
> +	}
> +unlock:
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static void k210_pll_disable_hw(struct k210_pll *pll)
> +{
> +	unsigned long flags;
> +	u32 reg;
> +
> +	/*
> +	 * Bypassing before powering off is important so child clocks don't stop
> +	 * working. This is especially important for pll0, the indirect parent
> +	 * of the cpu clock.
> +	 */

Did you get the bypass bit to work? I'm still having to bypass via
re-parenting ACLK in U-boot. Perhaps it is only necessary if you change
the rate as well?

> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(pll->reg);
> +	reg |= K210_PLL_BYPASS;
> +	writel(reg, pll->reg);
> +
> +	reg &= ~K210_PLL_PWRD;
> +	reg &= ~K210_PLL_EN;
> +	writel(reg, pll->reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static int k210_pll_enable(struct clk_hw *hw)
> +{
> +	k210_pll_enable_hw(to_k210_pll(hw));
> +
> +	return 0;
> +}
> +
> +static void k210_pll_disable(struct clk_hw *hw)
> +{
> +	k210_pll_disable_hw(to_k210_pll(hw));
> +}
> +
> +static int k210_pll_is_enabled(struct clk_hw *hw)
> +{
> +	return k210_pll_hw_is_enabled(to_k210_pll(hw));
> +}
> +
> +static int k210_pll_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	unsigned long flags;
> +	int ret = 0;
> +	u32 reg;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +
> +	switch (pll->id) {
> +	case K210_PLL0:
> +	case K210_PLL1:
> +		if (WARN_ON(index != 0))
> +			ret = -EINVAL;
> +		break;
> +	case K210_PLL2:
> +		if (WARN_ON(index > 2)) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +		reg = readl(pll->reg);
> +		reg &= ~K210_PLL_SEL;
> +		reg |= FIELD_PREP(K210_PLL_SEL, index);
> +		writel(reg, pll->reg);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return ret;
> +}
> +
> +static u8 k210_pll_get_parent(struct clk_hw *hw)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	u32 reg;
> +
> +	switch (pll->id) {
> +	case K210_PLL0:
> +	case K210_PLL1:
> +		return 0;
> +	case K210_PLL2:
> +		reg = readl(pll->reg);
> +		return FIELD_GET(K210_PLL_SEL, reg);
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static unsigned long k210_pll_get_rate(struct clk_hw *hw,
> +				       unsigned long parent_rate)
> +{
> +	struct k210_pll *pll = to_k210_pll(hw);
> +	u32 reg = readl(pll->reg);
> +	u32 r, f, od;
> +
> +	if (reg & K210_PLL_BYPASS)
> +		return parent_rate;
> +
> +	if (!(reg & K210_PLL_PWRD))
> +		return 0;
> +
> +	r = FIELD_GET(K210_PLL_CLKR, reg) + 1;
> +	f = FIELD_GET(K210_PLL_CLKF, reg) + 1;
> +	od = FIELD_GET(K210_PLL_CLKOD, reg) + 1;
> +
> +	return (u64)parent_rate * f / (r * od);
> +}
> +
> +static const struct clk_ops k210_pll_ops = {
> +	.enable		= k210_pll_enable,
> +	.disable	= k210_pll_disable,
> +	.is_enabled	= k210_pll_is_enabled,
> +	.set_parent	= k210_pll_set_parent,
> +	.get_parent	= k210_pll_get_parent,
> +	.recalc_rate	= k210_pll_get_rate,
> +};
> +
> +static const char *pll_parents[] = { NULL, "pll0", "pll1" };
> +
> +static struct clk_hw *k210_register_pll(enum k210_pll_id id, const char *name,
> +				const char **parent_names, int num_parents,
> +				unsigned long flags)
> +{
> +	struct k210_pll *pll = &kcl->plls[id];
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = name;
> +	init.parent_names = parent_names;
> +	init.num_parents = num_parents;
> +	init.flags = flags;
> +	init.ops = &k210_pll_ops;
> +	pll->hw.init = &init;
> +
> +	ret = clk_hw_register(NULL, &pll->hw);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &pll->hw;
> +}
> +
> +static int k210_aclk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	if (WARN_ON(index > 1))
> +		return -EINVAL;
> +
> +	k210_aclk_set_selector(index);
> +
> +	return 0;
> +}
> +
> +static u8 k210_aclk_get_parent(struct clk_hw *hw)
> +{
> +	u32 sel = readl(kcl->regs + K210_SYSCTL_SEL0);
> +
> +	return (sel & K210_ACLK_SEL) ? 1 : 0;
> +}
> +
> +static unsigned long k210_aclk_get_rate(struct clk_hw *hw,
> +					unsigned long parent_rate)
> +{
> +	u32 reg = readl(kcl->regs + K210_SYSCTL_SEL0);
> +	unsigned int shift;
> +
> +	if (!(reg & 0x1))
> +		return parent_rate;
> +
> +	shift = FIELD_GET(K210_ACLK_DIV, reg);
> +
> +	return parent_rate / (2UL << shift);
> +}
> +
> +static const struct clk_ops k210_aclk_ops = {
> +	.set_parent	= k210_aclk_set_parent,
> +	.get_parent	= k210_aclk_get_parent,
> +	.recalc_rate	= k210_aclk_get_rate,
> +};
> +
> +static const char *aclk_parents[] = { NULL, "pll0" };
> +
> +static struct clk_hw *k210_register_aclk(void)
> +{
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = "aclk";
> +	init.parent_names = aclk_parents;
> +	init.num_parents = 2;
> +	init.flags = 0;
> +	init.ops = &k210_aclk_ops;
> +	kcl->aclk.init = &init;
> +
> +	ret = clk_hw_register(NULL, &kcl->aclk);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &kcl->aclk;
> +}
> +
> +#define to_k210_clk_id(hw)	((unsigned int)((hw) - &kcl->clks[0]))
> +#define to_k210_clk_cfg(hw)	(&k210_clks[to_k210_clk_id(hw)])
> +
> +static u32 k210_clk_get_div_val(struct k210_clk_cfg *kclk)
> +{
> +	u32 reg = readl(kcl->regs + kclk->div_reg);
> +
> +	return (reg >> kclk->div_shift) & GENMASK(kclk->div_width - 1, 0);
> +}
> +
> +static unsigned long k210_clk_divider(struct k210_clk_cfg *kclk,
> +				      u32 div_val)
> +{
> +	switch (kclk->div_type) {
> +	case DIV_ONE_BASED:
> +		return div_val + 1;
> +	case DIV_DOUBLE_ONE_BASED:
> +		return (div_val + 1) * 2;
> +	case DIV_POWER_OF_TWO:
> +		return 2UL << div_val;
> +	case DIV_NONE:
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int k210_clk_enable(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->gate_reg)
> +		return 0;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->gate_reg);
> +	reg |= BIT(kclk->gate_bit);
> +	writel(reg, kcl->regs + kclk->gate_reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return 0;
> +}
> +
> +static void k210_clk_disable(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->gate_reg)
> +		return;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->gate_reg);
> +	reg &= ~BIT(kclk->gate_bit);
> +	writel(reg, kcl->regs + kclk->gate_reg);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +}
> +
> +static int k210_clk_is_enabled(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +
> +	if (!kclk->gate_reg)
> +		return 1;
> +
> +	return readl(kcl->regs + kclk->gate_reg) & BIT(kclk->gate_bit);
> +}
> +
> +static int k210_clk_set_parent(struct clk_hw *hw, u8 index)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg;
> +
> +	if (!kclk->mux_reg) {
> +		if (WARN_ON(index != 0))
> +			return -EINVAL;
> +		return 0;
> +	}
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->mux_reg);
> +	if (index)
> +		reg |= BIT(kclk->mux_bit);
> +	else
> +		reg &= ~BIT(kclk->mux_bit);
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return 0;
> +}
> +
> +static u8 k210_clk_get_parent(struct clk_hw *hw)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long flags;
> +	u32 reg, idx;
> +
> +	if (!kclk->mux_reg)
> +		return 0;
> +
> +	spin_lock_irqsave(&kcl->clk_lock, flags);
> +	reg = readl(kcl->regs + kclk->mux_reg);
> +	idx = (reg & BIT(kclk->mux_bit)) ? 1 : 0;
> +	spin_unlock_irqrestore(&kcl->clk_lock, flags);
> +
> +	return idx;
> +}
> +
> +static unsigned long k210_clk_get_rate(struct clk_hw *hw,
> +				       unsigned long parent_rate)
> +{
> +	struct k210_clk_cfg *kclk = to_k210_clk_cfg(hw);
> +	unsigned long divider;
> +
> +	if (!kclk->div_reg)
> +		return parent_rate;
> +
> +	divider = k210_clk_divider(kclk, k210_clk_get_div_val(kclk));
> +	if (WARN_ON(!divider))
> +		return 0;
> +
> +	return parent_rate / divider;
> +}
> +
> +static const struct clk_ops k210_clk_ops = {
> +	.enable		= k210_clk_enable,
> +	.is_enabled	= k210_clk_is_enabled,
> +	.disable	= k210_clk_disable,
> +	.set_parent	= k210_clk_set_parent,
> +	.get_parent	= k210_clk_get_parent,
> +	.recalc_rate	= k210_clk_get_rate,
> +};
> +
> +static const char *mux_parents[] = { NULL, "pll0" };
> +
> +static struct clk_hw *k210_register_clk(int id, const char *name,
> +					const char *parent, unsigned long flags)
> +{
> +	struct clk_init_data init = {};
> +	int ret;
> +
> +	init.name = name;
> +	if (parent) {
> +		init.parent_names = &parent;
> +		init.num_parents = 1;
> +	} else {
> +		init.parent_names = mux_parents;
> +		init.num_parents = 2;
> +	}
> +	init.flags = flags;
> +	init.ops = &k210_clk_ops;
> +	kcl->clks[id].init = &init;
> +
> +	ret = clk_hw_register(NULL, &kcl->clks[id]);
> +	if (ret)
> +		return ERR_PTR(ret);
> +
> +	return &kcl->clks[id];
> +}
> +
> +static void __init k210_clk_init(struct device_node *np)
> +{
> +	struct device_node *sysctl_np;
> +	struct clk *in0_clk;
> +	const char *in0;
> +	struct clk_hw **hws;
> +	int i, ret;
> +
> +	pr_info("%pOFP\n", np);
> +
> +	kcl = kzalloc(sizeof(*kcl), GFP_KERNEL);
> +	if (!kcl)
> +		return;
> +
> +	sysctl_np = of_find_compatible_node(NULL, NULL, "kendryte,k210-sysctl");
> +	if (!sysctl_np)
> +		goto err;
> +
> +	kcl->regs = of_iomap(sysctl_np, 0);
> +	if (!kcl->regs)
> +		goto err;
> +
> +	kcl->clk_data = kzalloc(struct_size(kcl->clk_data, hws, K210_NUM_CLKS),
> +				GFP_KERNEL);
> +	if (!kcl->clk_data)
> +		goto err;
> +
> +	for (i = 0; i < K210_PLL_NUM; i++)
> +		k210_init_pll(&kcl->plls[i], i, kcl->regs);
> +	spin_lock_init(&kcl->clk_lock);
> +	kcl->clk_data->num = K210_NUM_CLKS;
> +	hws = kcl->clk_data->hws;
> +	for (i = 1; i < K210_NUM_CLKS; i++)
> +		hws[i] = ERR_PTR(-EPROBE_DEFER);
> +
> +	/*
> +	 * in0 is the system base fixed-rate 26MHz oscillator which
> +	 * should already be defined by the device tree. If it is not,
> +	 * create it here.
> +	 */
> +	in0_clk = of_clk_get(np, 0);
> +	if (IS_ERR(in0_clk)) {
> +		pr_warn("%pOFP: in0 oscillator not found\n", np);
> +		hws[K210_CLK_IN0] =
> +			clk_hw_register_fixed_rate(NULL, "in0", NULL,
> +						   0, K210_IN0_RATE);
> +	} else {
> +		hws[K210_CLK_IN0] = __clk_get_hw(in0_clk);
> +	}
> +	if (IS_ERR(hws[K210_CLK_IN0])) {
> +		pr_err("%pOFP: failed to get base oscillator\n", np);
> +		goto err;
> +	}
> +
> +	in0 = clk_hw_get_name(hws[K210_CLK_IN0]);
> +	aclk_parents[0] = in0;
> +	pll_parents[0] = in0;
> +	mux_parents[0] = in0;
> +
> +	pr_info("%pOFP: fixed-rate %lu MHz %s base clock\n",
> +		np, clk_hw_get_rate(hws[K210_CLK_IN0]) / 1000000, in0);
> +
> +	/* PLLs */
> +	hws[K210_CLK_PLL0] =
> +		k210_register_pll(K210_PLL0, "pll0", pll_parents, 1, 0);
> +	hws[K210_CLK_PLL1] =
> +		k210_register_pll(K210_PLL1, "pll1", pll_parents, 1, 0);
> +	hws[K210_CLK_PLL2] =
> +		k210_register_pll(K210_PLL2, "pll2", pll_parents, 3, 0);
> +
> +	/* aclk: muxed of in0 and pll0_d, no gate */
> +	hws[K210_CLK_ACLK] = k210_register_aclk();
> +
> +	/*
> +	 * Clocks with aclk as source: the CPU clock is obviously critical.
> +	 * So is the CLINT clock as the scheduler clocksource.
> +	 */
> +	hws[K210_CLK_CPU] =
> +		k210_register_clk(K210_CLK_CPU, "cpu", "aclk", CLK_IS_CRITICAL);
> +	hws[K210_CLK_CLINT] =
> +		clk_hw_register_fixed_factor(NULL, "clint", "aclk",
> +					     CLK_IS_CRITICAL, 1, 50);
> +	hws[K210_CLK_DMA] =
> +		k210_register_clk(K210_CLK_DMA, "dma", "aclk", 0);
> +	hws[K210_CLK_FFT] =
> +		k210_register_clk(K210_CLK_FFT, "fft", "aclk", 0);
> +	hws[K210_CLK_ROM] =
> +		k210_register_clk(K210_CLK_ROM, "rom", "aclk", 0);
> +	hws[K210_CLK_DVP] =
> +		k210_register_clk(K210_CLK_DVP, "dvp", "aclk", 0);
> +	hws[K210_CLK_APB0] =
> +		k210_register_clk(K210_CLK_APB0, "apb0", "aclk", 0);
> +	hws[K210_CLK_APB1] =
> +		k210_register_clk(K210_CLK_APB1, "apb1", "aclk", 0);
> +	hws[K210_CLK_APB2] =
> +		k210_register_clk(K210_CLK_APB2, "apb2", "aclk", 0);
> +
> +	/*
> +	 * There is no sram driver taking a ref on the sram banks clocks.
> +	 * So make them critical so they are not disabled due to being unused
> +	 * as seen by the clock infrastructure.
> +	 */
> +	hws[K210_CLK_SRAM0] =
> +		k210_register_clk(K210_CLK_SRAM0,
> +				  "sram0", "aclk", CLK_IS_CRITICAL);
> +	hws[K210_CLK_SRAM1] =
> +		k210_register_clk(K210_CLK_SRAM1,
> +				  "sram1", "aclk", CLK_IS_CRITICAL);
> +
> +	/* Clocks with PLL0 as source */
> +	hws[K210_CLK_SPI0] =
> +		k210_register_clk(K210_CLK_SPI0, "spi0", "pll0", 0);
> +	hws[K210_CLK_SPI1] =
> +		 k210_register_clk(K210_CLK_SPI1, "spi1", "pll0", 0);
> +	hws[K210_CLK_SPI2] =
> +		 k210_register_clk(K210_CLK_SPI2, "spi2", "pll0", 0);
> +	hws[K210_CLK_I2C0] =
> +		 k210_register_clk(K210_CLK_I2C0, "i2c0", "pll0", 0);
> +	hws[K210_CLK_I2C1] =
> +		 k210_register_clk(K210_CLK_I2C1, "i2c1", "pll0", 0);
> +	hws[K210_CLK_I2C2] =
> +		 k210_register_clk(K210_CLK_I2C2, "i2c2", "pll0", 0);
> +
> +	/*
> +	 * Clocks with PLL1 as source: there is only the AI clock for the
> +	 * (unused) KPU device. As this clock also drives the aisram bank
> +	 * which is used as general memory, make it critical.
> +	 */
> +	 hws[K210_CLK_AI] =
> +		 k210_register_clk(K210_CLK_AI, "ai", "pll1", CLK_IS_CRITICAL);
> +
> +	/* Clocks with PLL2 as source */
> +	hws[K210_CLK_I2S0] =
> +		 k210_register_clk(K210_CLK_I2S0, "i2s0", "pll2", 0);
> +	hws[K210_CLK_I2S1] =
> +		 k210_register_clk(K210_CLK_I2S1, "i2s1", "pll2", 0);
> +	hws[K210_CLK_I2S2] =
> +		k210_register_clk(K210_CLK_I2S2, "i2s2", "pll2", 0);
> +	hws[K210_CLK_I2S0_M] =
> +		k210_register_clk(K210_CLK_I2S0_M, "i2s0_m", "pll2", 0);
> +	hws[K210_CLK_I2S1_M] =
> +		k210_register_clk(K210_CLK_I2S1_M, "i2s1_m", "pll2", 0);
> +	hws[K210_CLK_I2S2_M] =
> +		k210_register_clk(K210_CLK_I2S2_M, "i2s2_m", "pll2", 0);
> +
> +	/* Clocks with IN0 as source */
> +	hws[K210_CLK_WDT0] =
> +		k210_register_clk(K210_CLK_WDT0, "wdt0", in0, 0);
> +	hws[K210_CLK_WDT1] =
> +		 k210_register_clk(K210_CLK_WDT1, "wdt1", in0, 0);
> +	hws[K210_CLK_RTC] =
> +		 k210_register_clk(K210_CLK_RTC, "rtc", in0, 0);
> +
> +	/* Clocks with APB0 as source */
> +	hws[K210_CLK_GPIO] =
> +		k210_register_clk(K210_CLK_GPIO, "gpio", "apb0", 0);
> +	hws[K210_CLK_UART1] =
> +		k210_register_clk(K210_CLK_UART1, "uart1", "apb0", 0);
> +	hws[K210_CLK_UART2] =
> +		k210_register_clk(K210_CLK_UART2, "uart2", "apb0", 0);
> +	hws[K210_CLK_UART3] =
> +		k210_register_clk(K210_CLK_UART3, "uart3", "apb0", 0);
> +	hws[K210_CLK_FPIOA] =
> +		k210_register_clk(K210_CLK_FPIOA, "fpioa", "apb0", 0);
> +	hws[K210_CLK_SHA] =
> +		k210_register_clk(K210_CLK_SHA, "sha", "apb0", 0);
> +
> +	/* Clocks with APB1 as source */
> +	hws[K210_CLK_AES] =
> +		 k210_register_clk(K210_CLK_AES, "aes", "apb1", 0);
> +	hws[K210_CLK_OTP] =
> +		 k210_register_clk(K210_CLK_OTP, "otp", "apb1", 0);
> +
> +	/* Muxed clocks with in0/pll0 as source */
> +	hws[K210_CLK_SPI3] =
> +		k210_register_clk(K210_CLK_SPI3, "spi3", NULL, 0);
> +	hws[K210_CLK_TIMER0] =
> +		k210_register_clk(K210_CLK_TIMER0, "timer0", NULL, 0);
> +	hws[K210_CLK_TIMER1] =
> +		k210_register_clk(K210_CLK_TIMER1, "timer1", NULL, 0);
> +	hws[K210_CLK_TIMER2] =
> +		k210_register_clk(K210_CLK_TIMER2, "timer2", NULL, 0);
> +
> +	for (i = 0; i < K210_NUM_CLKS; i++) {
> +		if (IS_ERR(hws[i])) {
> +			pr_err("%pOFP: register clock %d failed %ld\n",
> +			       np, i, PTR_ERR(hws[i]));
> +			goto err;
> +		}
> +	}
> +
> +	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, kcl->clk_data);
> +	if (ret)
> +		pr_err("%pOFP: add clock provider failed %d\n", np, ret);
> +
> +	return;
> +err:
> +	pr_err("%pOFP: clock initialization failed\n", np);
> +	iounmap(kcl->regs);
> +	kfree(kcl->clk_data);
> +	kfree(kcl);
> +	kcl = NULL;
> +}
> +
> +CLK_OF_DECLARE_DRIVER(k210_clk, "kendryte,k210-clk", k210_clk_init);
> +
> +/*
> + * Enable PLL1 to be able to use the AI SRAM.
> + */
> +void k210_clk_early_init(void __iomem *regs)
> +{
> +	struct k210_pll pll1;
> +
> +	/* Make sure aclk selector is set to PLL0 */
> +	k210_aclk_set_selector(1);
> +
> +	/* Startup PLL1 to enable the aisram bank for general memory use */
> +	k210_init_pll(&pll1, K210_PLL1, regs);
> +	k210_pll_enable_hw(&pll1);
> +}
> diff --git a/drivers/soc/kendryte/k210-sysctl.c b/drivers/soc/kendryte/k210-sysctl.c
> index 4608fbca20e1..336f4b119bdd 100644
> --- a/drivers/soc/kendryte/k210-sysctl.c
> +++ b/drivers/soc/kendryte/k210-sysctl.c
> @@ -3,201 +3,41 @@
>   * Copyright (c) 2019 Christoph Hellwig.
>   * Copyright (c) 2019 Western Digital Corporation or its affiliates.
>   */
> -#include <linux/types.h>
>  #include <linux/io.h>
> -#include <linux/of.h>
>  #include <linux/platform_device.h>
> -#include <linux/clk-provider.h>
> -#include <linux/clkdev.h>
> -#include <linux/bitfield.h>
> +#include <linux/of_platform.h>
> +#include <linux/clk.h>
>  #include <asm/soc.h>
>  
> -#define K210_SYSCTL_CLK0_FREQ		26000000UL
> +#include <soc/kendryte/k210-sysctl.h>
>  
> -/* Registers base address */
> -#define K210_SYSCTL_SYSCTL_BASE_ADDR	0x50440000ULL
> -
> -/* Registers */
> -#define K210_SYSCTL_PLL0		0x08
> -#define K210_SYSCTL_PLL1		0x0c
> -/* clkr: 4bits, clkf1: 6bits, clkod: 4bits, bwadj: 4bits */
> -#define   PLL_RESET		(1 << 20)
> -#define   PLL_PWR		(1 << 21)
> -#define   PLL_INTFB		(1 << 22)
> -#define   PLL_BYPASS		(1 << 23)
> -#define   PLL_TEST		(1 << 24)
> -#define   PLL_OUT_EN		(1 << 25)
> -#define   PLL_TEST_EN		(1 << 26)
> -#define K210_SYSCTL_PLL_LOCK		0x18
> -#define   PLL0_LOCK1		(1 << 0)
> -#define   PLL0_LOCK2		(1 << 1)
> -#define   PLL0_SLIP_CLEAR	(1 << 2)
> -#define   PLL0_TEST_CLK_OUT	(1 << 3)
> -#define   PLL1_LOCK1		(1 << 8)
> -#define   PLL1_LOCK2		(1 << 9)
> -#define   PLL1_SLIP_CLEAR	(1 << 10)
> -#define   PLL1_TEST_CLK_OUT	(1 << 11)
> -#define   PLL2_LOCK1		(1 << 16)
> -#define   PLL2_LOCK2		(1 << 16)
> -#define   PLL2_SLIP_CLEAR	(1 << 18)
> -#define   PLL2_TEST_CLK_OUT	(1 << 19)
> -#define K210_SYSCTL_CLKSEL0	0x20
> -#define   CLKSEL_ACLK		(1 << 0)
> -#define K210_SYSCTL_CLKEN_CENT		0x28
> -#define   CLKEN_CPU		(1 << 0)
> -#define   CLKEN_SRAM0		(1 << 1)
> -#define   CLKEN_SRAM1		(1 << 2)
> -#define   CLKEN_APB0		(1 << 3)
> -#define   CLKEN_APB1		(1 << 4)
> -#define   CLKEN_APB2		(1 << 5)
> -#define K210_SYSCTL_CLKEN_PERI		0x2c
> -#define   CLKEN_ROM		(1 << 0)
> -#define   CLKEN_DMA		(1 << 1)
> -#define   CLKEN_AI		(1 << 2)
> -#define   CLKEN_DVP		(1 << 3)
> -#define   CLKEN_FFT		(1 << 4)
> -#define   CLKEN_GPIO		(1 << 5)
> -#define   CLKEN_SPI0		(1 << 6)
> -#define   CLKEN_SPI1		(1 << 7)
> -#define   CLKEN_SPI2		(1 << 8)
> -#define   CLKEN_SPI3		(1 << 9)
> -#define   CLKEN_I2S0		(1 << 10)
> -#define   CLKEN_I2S1		(1 << 11)
> -#define   CLKEN_I2S2		(1 << 12)
> -#define   CLKEN_I2C0		(1 << 13)
> -#define   CLKEN_I2C1		(1 << 14)
> -#define   CLKEN_I2C2		(1 << 15)
> -#define   CLKEN_UART1		(1 << 16)
> -#define   CLKEN_UART2		(1 << 17)
> -#define   CLKEN_UART3		(1 << 18)
> -#define   CLKEN_AES		(1 << 19)
> -#define   CLKEN_FPIO		(1 << 20)
> -#define   CLKEN_TIMER0		(1 << 21)
> -#define   CLKEN_TIMER1		(1 << 22)
> -#define   CLKEN_TIMER2		(1 << 23)
> -#define   CLKEN_WDT0		(1 << 24)
> -#define   CLKEN_WDT1		(1 << 25)
> -#define   CLKEN_SHA		(1 << 26)
> -#define   CLKEN_OTP		(1 << 27)
> -#define   CLKEN_RTC		(1 << 29)
> -
> -struct k210_sysctl {
> -	void __iomem		*regs;
> -	struct clk_hw		hw;
> -};
> -
> -static void k210_set_bits(u32 val, void __iomem *reg)
> -{
> -	writel(readl(reg) | val, reg);
> -}
> -
> -static void k210_clear_bits(u32 val, void __iomem *reg)
> -{
> -	writel(readl(reg) & ~val, reg);
> -}
> -
> -static void k210_pll1_enable(void __iomem *regs)
> +static int __init k210_sysctl_probe(struct platform_device *pdev)
>  {
> -	u32 val;
> +	struct device *dev = &pdev->dev;
> +	struct clk *pclk;
> +	int ret;
>  
> -	val = readl(regs + K210_SYSCTL_PLL1);
> -	val &= ~GENMASK(19, 0);				/* clkr1 = 0 */
> -	val |= FIELD_PREP(GENMASK(9, 4), 0x3B);		/* clkf1 = 59 */
> -	val |= FIELD_PREP(GENMASK(13, 10), 0x3);	/* clkod1 = 3 */
> -	val |= FIELD_PREP(GENMASK(19, 14), 0x3B);	/* bwadj1 = 59 */
> -	writel(val, regs + K210_SYSCTL_PLL1);
> +	dev_info(dev, "K210 system controller\n");
>  
> -	k210_clear_bits(PLL_BYPASS, regs + K210_SYSCTL_PLL1);
> -	k210_set_bits(PLL_PWR, regs + K210_SYSCTL_PLL1);
> -
> -	/*
> -	 * Reset the pll. The magic NOPs come from the Kendryte reference SDK.
> -	 */
> -	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -	k210_set_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -	nop();
> -	nop();
> -	k210_clear_bits(PLL_RESET, regs + K210_SYSCTL_PLL1);
> -
> -	for (;;) {
> -		val = readl(regs + K210_SYSCTL_PLL_LOCK);
> -		if (val & PLL1_LOCK2)
> -			break;
> -		writel(val | PLL1_SLIP_CLEAR, regs + K210_SYSCTL_PLL_LOCK);
> +	/* Get power bus clock */
> +	pclk = devm_clk_get(dev, NULL);
> +	if (IS_ERR(pclk)) {
> +		dev_err(dev, "Get bus clock failed\n");
> +		return PTR_ERR(pclk);
>  	}
>  
> -	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL1);
> -}
> -
> -static unsigned long k210_sysctl_clk_recalc_rate(struct clk_hw *hw,
> -		unsigned long parent_rate)
> -{
> -	struct k210_sysctl *s = container_of(hw, struct k210_sysctl, hw);
> -	u32 clksel0, pll0;
> -	u64 pll0_freq, clkr0, clkf0, clkod0;
> -
> -	/*
> -	 * If the clock selector is not set, use the base frequency.
> -	 * Otherwise, use PLL0 frequency with a frequency divisor.
> -	 */
> -	clksel0 = readl(s->regs + K210_SYSCTL_CLKSEL0);
> -	if (!(clksel0 & CLKSEL_ACLK))
> -		return K210_SYSCTL_CLK0_FREQ;
> -
> -	/*
> -	 * Get PLL0 frequency:
> -	 * freq = base frequency * clkf0 / (clkr0 * clkod0)
> -	 */
> -	pll0 = readl(s->regs + K210_SYSCTL_PLL0);
> -	clkr0 = 1 + FIELD_GET(GENMASK(3, 0), pll0);
> -	clkf0 = 1 + FIELD_GET(GENMASK(9, 4), pll0);
> -	clkod0 = 1 + FIELD_GET(GENMASK(13, 10), pll0);
> -	pll0_freq = clkf0 * K210_SYSCTL_CLK0_FREQ / (clkr0 * clkod0);
> -
> -	/* Get the frequency divisor from the clock selector */
> -	return pll0_freq / (2ULL << FIELD_GET(0x00000006, clksel0));
> -}
> -
> -static const struct clk_ops k210_sysctl_clk_ops = {
> -	.recalc_rate	= k210_sysctl_clk_recalc_rate,
> -};
> -
> -static const struct clk_init_data k210_clk_init_data = {
> -	.name		= "k210-sysctl-pll1",
> -	.ops		= &k210_sysctl_clk_ops,
> -};
> -
> -static int k210_sysctl_probe(struct platform_device *pdev)
> -{
> -	struct k210_sysctl *s;
> -	int error;
> -
> -	pr_info("Kendryte K210 SoC sysctl\n");
> -
> -	s = devm_kzalloc(&pdev->dev, sizeof(*s), GFP_KERNEL);
> -	if (!s)
> -		return -ENOMEM;
> -
> -	s->regs = devm_ioremap_resource(&pdev->dev,
> -			platform_get_resource(pdev, IORESOURCE_MEM, 0));
> -	if (IS_ERR(s->regs))
> -		return PTR_ERR(s->regs);
> -
> -	s->hw.init = &k210_clk_init_data;
> -	error = devm_clk_hw_register(&pdev->dev, &s->hw);
> -	if (error) {
> -		dev_err(&pdev->dev, "failed to register clk");
> -		return error;
> +	ret = clk_prepare_enable(pclk);
> +	if (ret) {
> +		dev_err(dev, "Enable bus clock failed\n");
> +		return ret;
>  	}
>  
> -	error = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
> -					    &s->hw);
> -	if (error) {
> -		dev_err(&pdev->dev, "adding clk provider failed\n");
> -		return error;
> -	}
> +	/* Populate children */
> +	ret = devm_of_platform_populate(dev);
> +	if (ret)
> +		dev_err(dev, "Populate platform failed %d\n", ret);
>  
> -	return 0;
> +	return ret;
>  }
>  
>  static const struct of_device_id k210_sysctl_of_match[] = {
> @@ -213,11 +53,22 @@ static struct platform_driver k210_sysctl_driver = {
>  	.probe			= k210_sysctl_probe,
>  };
>  
> +/*
> + * Most devices on the K210 SoC depend on the early initialization of sysctl
> + * fpioa and reset child nodes. So initialize this driver early as part of
> + * the post core initialization.
> + */
>  static int __init k210_sysctl_init(void)
>  {
>  	return platform_driver_register(&k210_sysctl_driver);
>  }
> -core_initcall(k210_sysctl_init);
> +postcore_initcall(k210_sysctl_init);
> +
> +/*
> + * System controller registers base address and size.
> + */
> +#define K210_SYSCTL_BASE_ADDR	0x50440000ULL
> +#define K210_SYSCTL_BASE_SIZE	0x1000
>  
>  /*
>   * This needs to be called very early during initialization, given that
> @@ -225,24 +76,14 @@ core_initcall(k210_sysctl_init);
>   */
>  static void __init k210_soc_early_init(const void *fdt)
>  {
> -	void __iomem *regs;
> -
> -	regs = ioremap(K210_SYSCTL_SYSCTL_BASE_ADDR, 0x1000);
> -	if (!regs)
> -		panic("K210 sysctl ioremap");
> -
> -	/* Enable PLL1 to make the KPU SRAM useable */
> -	k210_pll1_enable(regs);
> -
> -	k210_set_bits(PLL_OUT_EN, regs + K210_SYSCTL_PLL0);
> +	void __iomem *sysctl_base;
>  
> -	k210_set_bits(CLKEN_CPU | CLKEN_SRAM0 | CLKEN_SRAM1,
> -		      regs + K210_SYSCTL_CLKEN_CENT);
> -	k210_set_bits(CLKEN_ROM | CLKEN_TIMER0 | CLKEN_RTC,
> -		      regs + K210_SYSCTL_CLKEN_PERI);
> +	sysctl_base = ioremap(K210_SYSCTL_BASE_ADDR, K210_SYSCTL_BASE_SIZE);
> +	if (!sysctl_base)
> +		panic("k210-sysctl: ioremap failed");
>  
> -	k210_set_bits(CLKSEL_ACLK, regs + K210_SYSCTL_CLKSEL0);
> +	k210_clk_early_init(sysctl_base);
>  
> -	iounmap(regs);
> +	iounmap(sysctl_base);
>  }
> -SOC_EARLY_INIT_DECLARE(generic_k210, "kendryte,k210", k210_soc_early_init);
> +SOC_EARLY_INIT_DECLARE(k210_soc, "kendryte,k210", k210_soc_early_init);
> diff --git a/include/soc/kendryte/k210-sysctl.h b/include/soc/kendryte/k210-sysctl.h
> new file mode 100644
> index 000000000000..73e38a8fc31d
> --- /dev/null
> +++ b/include/soc/kendryte/k210-sysctl.h
> @@ -0,0 +1,11 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef K210_SYSCTL_H
> +#define K210_SYSCTL_H
> +
> +void k210_clk_early_init(void __iomem *regs);
> +
> +#endif
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07 13:42       ` Damien Le Moal
@ 2020-11-07 13:52         ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:52 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 8:42 AM, Damien Le Moal wrote:
> On 2020/11/07 22:31, Sean Anderson wrote:
>> On 11/7/20 3:13 AM, Damien Le Moal wrote:
>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>> SD card performance improvements from using no-delay polled transfers.
>>> Add the dw_spi_k210_init() function tied to the
>>> "canaan,kendryte-k210-spi" compatible string to set the
>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>> for this SoC.
>>>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> ---
>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>  1 file changed, 9 insertions(+)
>>>
>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>> index 3f1bc384cb45..a00def6c5b39 100644
>>> --- a/drivers/spi/spi-dw-mmio.c
>>> +++ b/drivers/spi/spi-dw-mmio.c
>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>  	return 0;
>>>  }
>>>  
>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>> +			    struct dw_spi_mmio *dwsmmio)
>>> +{
>>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>
>> Can't you do runtime detection of DFS_32 in probe?
> 
> I think it is possible, but it was much easier this way given that it seems that
> only the K210 uses the DFS_32.

I think if it is detectable at runtime it should be, instead of relying
on compatible strings. That way causes less future grief to anyone
porting a device possibly using DFS_32.

 --Sean

>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>  {
>>>  	int (*init_func)(struct platform_device *pdev,
>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>  	{ /* end of table */}
>>>  };
>>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>>>
>>
>>
> 
> 


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-07 13:52         ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:52 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 8:42 AM, Damien Le Moal wrote:
> On 2020/11/07 22:31, Sean Anderson wrote:
>> On 11/7/20 3:13 AM, Damien Le Moal wrote:
>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>> SD card performance improvements from using no-delay polled transfers.
>>> Add the dw_spi_k210_init() function tied to the
>>> "canaan,kendryte-k210-spi" compatible string to set the
>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>> for this SoC.
>>>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> ---
>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>  1 file changed, 9 insertions(+)
>>>
>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>> index 3f1bc384cb45..a00def6c5b39 100644
>>> --- a/drivers/spi/spi-dw-mmio.c
>>> +++ b/drivers/spi/spi-dw-mmio.c
>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>  	return 0;
>>>  }
>>>  
>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>> +			    struct dw_spi_mmio *dwsmmio)
>>> +{
>>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>
>> Can't you do runtime detection of DFS_32 in probe?
> 
> I think it is possible, but it was much easier this way given that it seems that
> only the K210 uses the DFS_32.

I think if it is detectable at runtime it should be, instead of relying
on compatible strings. That way causes less future grief to anyone
porting a device possibly using DFS_32.

 --Sean

>>> +
>>> +	return 0;
>>> +}
>>> +
>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>  {
>>>  	int (*init_func)(struct platform_device *pdev,
>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>  	{ /* end of table */}
>>>  };
>>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>>>
>>
>>
> 
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 19/32] riscv: Add Kendryte K210 SoC reset controller
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 13:58     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:58 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel


On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a reset controller driver for the Kendryte K210 SoC. This driver
> relies on its syscon compatible parent node for its register mapping.
> Automatically select this driver for compilation when the SOC_KENDRYTE
> option is selected.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs    |   3 +
>  drivers/reset/Kconfig      |   9 ++
>  drivers/reset/Makefile     |   1 +
>  drivers/reset/reset-k210.c | 186 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 199 insertions(+)
>  create mode 100644 drivers/reset/reset-k210.c
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index a4c851ffc6b0..4d8e66d0556a 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -31,6 +31,9 @@ config SOC_KENDRYTE
>  	select SIFIVE_PLIC
>  	select SOC_K210
>  	select CLK_K210
> +	select ARCH_HAS_RESET_CONTROLLER
> +	select RESET_CONTROLLER
> +	select RESET_K210
>  	help
>  	  This enables support for Kendryte K210 SoC platform hardware.
>  
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 07d162b179fc..c943051b5fc8 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -245,6 +245,15 @@ config RESET_ZYNQ
>  	help
>  	  This enables the reset controller driver for Xilinx Zynq SoCs.
>  
> +config RESET_K210
> +	bool "Reset controller driver for Kendryte K210 SoC"
> +	depends on RISCV && SOC_KENDRYTE
> +	depends on OF && MFD_SYSCON
> +	help
> +	  Support for the Kendryte K210 RISC-V SoC reset controller. If
> +          Say Y if you want to control reset signals provided by this
> +	  controller.
> +
>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
>  source "drivers/reset/tegra/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 16947610cc3b..1730a31e6871 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -33,4 +33,5 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>  obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>  obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
> +obj-$(CONFIG_RESET_K210) += reset-k210.o
>  
> diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c
> new file mode 100644
> index 000000000000..b6401aef2923
> --- /dev/null
> +++ b/drivers/reset/reset-k210.c
> @@ -0,0 +1,186 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dt-bindings/reset/k210-rst.h>
> +
> +struct k210_rst {
> +	struct regmap *map;
> +	u32 offset;
> +	u32 mask;
> +	u32 assert_high;
> +	struct reset_controller_dev rcdev;
> +};
> +
> +static inline struct k210_rst *
> +to_k210_rst(struct reset_controller_dev *rcdev)
> +{
> +	return container_of(rcdev, struct k210_rst, rcdev);
> +}
> +
> +static inline int k210_rst_assert(struct reset_controller_dev *rcdev,
> +				  unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 bit = BIT(id);
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid assert id %lu\n", id);
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(rcdev->dev, "assert %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	regmap_update_bits(ksr->map, ksr->offset, bit,
> +			   ksr->assert_high ? bit : 0);
> +
> +	return 0;
> +}
> +
> +static inline int k210_rst_deassert(struct reset_controller_dev *rcdev,
> +				    unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 bit = BIT(id);
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid deassert id %lu\n", id);
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(rcdev->dev, "deassert %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	regmap_update_bits(ksr->map, ksr->offset, bit,
> +			   ksr->assert_high ? 0 : bit);
> +
> +	return 0;
> +}
> +
> +static int k210_rst_reset(struct reset_controller_dev *rcdev,
> +			  unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	int ret;
> +
> +	dev_dbg(rcdev->dev, "reset %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	ret = k210_rst_assert(rcdev, id);
> +	if (ret == 0) {
> +		udelay(10);
> +		ret = k210_rst_deassert(rcdev, id);
> +	}
> +
> +	return ret;
> +}
> +
> +static int k210_rst_status(struct reset_controller_dev *rcdev,
> +			   unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 reg, bit = BIT(id);
> +	int ret;
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid reset %lx\n", id);
> +		return -EINVAL;
> +	}
> +
> +	ret = regmap_read(ksr->map, ksr->offset, &reg);
> +	if (ret)
> +		return ret;
> +
> +	if (ksr->assert_high)
> +		return ret & bit;
> +
> +	return !(ret & bit);
> +}
> +
> +static const struct reset_control_ops k210_rst_ops = {
> +	.assert		= k210_rst_assert,
> +	.deassert	= k210_rst_deassert,
> +	.reset		= k210_rst_reset,
> +	.status		= k210_rst_status,
> +};
> +
> +static int __init k210_rst_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct k210_rst *ksr;
> +	int ret, nr_resets;
> +
> +	dev_info(dev, "K210 reset controller\n");
> +
> +	ksr = devm_kzalloc(dev, sizeof(*ksr), GFP_KERNEL);
> +	if (!ksr)
> +		return -ENOMEM;
> +
> +	ksr->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
> +	if (IS_ERR(ksr->map)) {
> +		ksr->map = syscon_node_to_regmap(dev->parent->of_node);
> +		if (IS_ERR(ksr->map)) {
> +			dev_err(dev, "get register map failed\n");
> +			return PTR_ERR(ksr->map);
> +		}
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "offset", &ksr->offset);
> +	ret = of_property_read_u32(dev->of_node, "assert-high",
> +				   &ksr->assert_high);
> +	if (ret) {
> +		dev_err(dev, "unable to read 'offset' and 'assert-high'\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "mask", &ksr->mask);
> +	if (ret) {
> +		/* Use default mask */
> +		ksr->mask = 0x27FFFFFF;
> +	}
> +	nr_resets = fls(ksr->mask);
> +	if (!nr_resets) {
> +		dev_err(dev, "Invalid mask 0x%08x\n", ksr->mask);
> +		return -EINVAL;
> +	}
> +
> +	ksr->rcdev.owner = THIS_MODULE;
> +	ksr->rcdev.dev = dev;
> +	ksr->rcdev.of_node = dev->of_node;
> +	ksr->rcdev.nr_resets = nr_resets;
> +	ksr->rcdev.ops = &k210_rst_ops;
> +
> +	return devm_reset_controller_register(dev, &ksr->rcdev);
> +}
> +
> +static const struct of_device_id k210_rst_dt_ids[] = {
> +	{ .compatible = "kendryte,k210-rst" },
> +};
> +
> +static struct platform_driver k210_rst_driver = {
> +	.probe	= k210_rst_probe,
> +	.driver = {
> +		.name		= "k210-rst",
> +		.of_match_table	= k210_rst_dt_ids,
> +	},
> +};
> +
> +/*
> + * Most devices on the K210 SoC need reset as part of their initialization.
> + * So initialize this driver early as part of the post core initialization.
> + */
> +static int __init k210_rst_init(void)
> +{
> +	return platform_driver_register(&k210_rst_driver);
> +}
> +postcore_initcall(k210_rst_init);
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 19/32] riscv: Add Kendryte K210 SoC reset controller
@ 2020-11-07 13:58     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 13:58 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel


On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a reset controller driver for the Kendryte K210 SoC. This driver
> relies on its syscon compatible parent node for its register mapping.
> Automatically select this driver for compilation when the SOC_KENDRYTE
> option is selected.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs    |   3 +
>  drivers/reset/Kconfig      |   9 ++
>  drivers/reset/Makefile     |   1 +
>  drivers/reset/reset-k210.c | 186 +++++++++++++++++++++++++++++++++++++
>  4 files changed, 199 insertions(+)
>  create mode 100644 drivers/reset/reset-k210.c
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index a4c851ffc6b0..4d8e66d0556a 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -31,6 +31,9 @@ config SOC_KENDRYTE
>  	select SIFIVE_PLIC
>  	select SOC_K210
>  	select CLK_K210
> +	select ARCH_HAS_RESET_CONTROLLER
> +	select RESET_CONTROLLER
> +	select RESET_K210
>  	help
>  	  This enables support for Kendryte K210 SoC platform hardware.
>  
> diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
> index 07d162b179fc..c943051b5fc8 100644
> --- a/drivers/reset/Kconfig
> +++ b/drivers/reset/Kconfig
> @@ -245,6 +245,15 @@ config RESET_ZYNQ
>  	help
>  	  This enables the reset controller driver for Xilinx Zynq SoCs.
>  
> +config RESET_K210
> +	bool "Reset controller driver for Kendryte K210 SoC"
> +	depends on RISCV && SOC_KENDRYTE
> +	depends on OF && MFD_SYSCON
> +	help
> +	  Support for the Kendryte K210 RISC-V SoC reset controller. If
> +          Say Y if you want to control reset signals provided by this
> +	  controller.
> +
>  source "drivers/reset/sti/Kconfig"
>  source "drivers/reset/hisilicon/Kconfig"
>  source "drivers/reset/tegra/Kconfig"
> diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
> index 16947610cc3b..1730a31e6871 100644
> --- a/drivers/reset/Makefile
> +++ b/drivers/reset/Makefile
> @@ -33,4 +33,5 @@ obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
>  obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
>  obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
>  obj-$(CONFIG_ARCH_ZYNQMP) += reset-zynqmp.o
> +obj-$(CONFIG_RESET_K210) += reset-k210.o
>  
> diff --git a/drivers/reset/reset-k210.c b/drivers/reset/reset-k210.c
> new file mode 100644
> index 000000000000..b6401aef2923
> --- /dev/null
> +++ b/drivers/reset/reset-k210.c
> @@ -0,0 +1,186 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/platform_device.h>
> +#include <linux/reset-controller.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dt-bindings/reset/k210-rst.h>
> +
> +struct k210_rst {
> +	struct regmap *map;
> +	u32 offset;
> +	u32 mask;
> +	u32 assert_high;
> +	struct reset_controller_dev rcdev;
> +};
> +
> +static inline struct k210_rst *
> +to_k210_rst(struct reset_controller_dev *rcdev)
> +{
> +	return container_of(rcdev, struct k210_rst, rcdev);
> +}
> +
> +static inline int k210_rst_assert(struct reset_controller_dev *rcdev,
> +				  unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 bit = BIT(id);
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid assert id %lu\n", id);
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(rcdev->dev, "assert %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	regmap_update_bits(ksr->map, ksr->offset, bit,
> +			   ksr->assert_high ? bit : 0);
> +
> +	return 0;
> +}
> +
> +static inline int k210_rst_deassert(struct reset_controller_dev *rcdev,
> +				    unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 bit = BIT(id);
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid deassert id %lu\n", id);
> +		return -EINVAL;
> +	}
> +
> +	dev_dbg(rcdev->dev, "deassert %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	regmap_update_bits(ksr->map, ksr->offset, bit,
> +			   ksr->assert_high ? 0 : bit);
> +
> +	return 0;
> +}
> +
> +static int k210_rst_reset(struct reset_controller_dev *rcdev,
> +			  unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	int ret;
> +
> +	dev_dbg(rcdev->dev, "reset %s %lu\n",
> +		ksr->assert_high ? "high" : "low", id);
> +
> +	ret = k210_rst_assert(rcdev, id);
> +	if (ret == 0) {
> +		udelay(10);
> +		ret = k210_rst_deassert(rcdev, id);
> +	}
> +
> +	return ret;
> +}
> +
> +static int k210_rst_status(struct reset_controller_dev *rcdev,
> +			   unsigned long id)
> +{
> +	struct k210_rst *ksr = to_k210_rst(rcdev);
> +	u32 reg, bit = BIT(id);
> +	int ret;
> +
> +	if (!(bit & ksr->mask)) {
> +		dev_err(rcdev->dev, "Invalid reset %lx\n", id);
> +		return -EINVAL;
> +	}
> +
> +	ret = regmap_read(ksr->map, ksr->offset, &reg);
> +	if (ret)
> +		return ret;
> +
> +	if (ksr->assert_high)
> +		return ret & bit;
> +
> +	return !(ret & bit);
> +}
> +
> +static const struct reset_control_ops k210_rst_ops = {
> +	.assert		= k210_rst_assert,
> +	.deassert	= k210_rst_deassert,
> +	.reset		= k210_rst_reset,
> +	.status		= k210_rst_status,
> +};
> +
> +static int __init k210_rst_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct k210_rst *ksr;
> +	int ret, nr_resets;
> +
> +	dev_info(dev, "K210 reset controller\n");
> +
> +	ksr = devm_kzalloc(dev, sizeof(*ksr), GFP_KERNEL);
> +	if (!ksr)
> +		return -ENOMEM;
> +
> +	ksr->map = syscon_regmap_lookup_by_phandle(dev->of_node, "regmap");
> +	if (IS_ERR(ksr->map)) {
> +		ksr->map = syscon_node_to_regmap(dev->parent->of_node);
> +		if (IS_ERR(ksr->map)) {
> +			dev_err(dev, "get register map failed\n");
> +			return PTR_ERR(ksr->map);
> +		}
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "offset", &ksr->offset);
> +	ret = of_property_read_u32(dev->of_node, "assert-high",
> +				   &ksr->assert_high);
> +	if (ret) {
> +		dev_err(dev, "unable to read 'offset' and 'assert-high'\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = of_property_read_u32(dev->of_node, "mask", &ksr->mask);
> +	if (ret) {
> +		/* Use default mask */
> +		ksr->mask = 0x27FFFFFF;
> +	}
> +	nr_resets = fls(ksr->mask);
> +	if (!nr_resets) {
> +		dev_err(dev, "Invalid mask 0x%08x\n", ksr->mask);
> +		return -EINVAL;
> +	}
> +
> +	ksr->rcdev.owner = THIS_MODULE;
> +	ksr->rcdev.dev = dev;
> +	ksr->rcdev.of_node = dev->of_node;
> +	ksr->rcdev.nr_resets = nr_resets;
> +	ksr->rcdev.ops = &k210_rst_ops;
> +
> +	return devm_reset_controller_register(dev, &ksr->rcdev);
> +}
> +
> +static const struct of_device_id k210_rst_dt_ids[] = {
> +	{ .compatible = "kendryte,k210-rst" },
> +};
> +
> +static struct platform_driver k210_rst_driver = {
> +	.probe	= k210_rst_probe,
> +	.driver = {
> +		.name		= "k210-rst",
> +		.of_match_table	= k210_rst_dt_ids,
> +	},
> +};
> +
> +/*
> + * Most devices on the K210 SoC need reset as part of their initialization.
> + * So initialize this driver early as part of the post core initialization.
> + */
> +static int __init k210_rst_init(void)
> +{
> +	return platform_driver_register(&k210_rst_driver);
> +}
> +postcore_initcall(k210_rst_init);
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:03     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:03 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel


On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index 2735be1a8470..f53d4d8e7f2a 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -179,6 +179,8 @@ patternProperties:
>      description: CALAO Systems SAS
>    "^calxeda,.*":
>      description: Calxeda
> +  "^canaan,.*":
> +    description: Canaan, Inc.
>    "^caninos,.*":
>      description: Caninos Loucos Program
>    "^capella,.*":
> @@ -537,6 +539,8 @@ patternProperties:
>      description: Ka-Ro electronics GmbH
>    "^keithkoep,.*":
>      description: Keith & Koep GmbH
> +  "^kendryte,.*":
> +    description: Canaan, Inc.
>    "^keymile,.*":
>      description: Keymile GmbH
>    "^khadas,.*":
> 

So AFAIK Canaan is the company, and Kendryte is the brand. However, I
was unaware of this when I did my initial porting work. So all the
compatible strings like "kendryte,k210-foo" should really be
"canaan,kendryte-k210-foo". These _should_ all get fixed in the device
tree, but no one has done it yet.

--Sean

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
@ 2020-11-07 14:03     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:03 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel


On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index 2735be1a8470..f53d4d8e7f2a 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -179,6 +179,8 @@ patternProperties:
>      description: CALAO Systems SAS
>    "^calxeda,.*":
>      description: Calxeda
> +  "^canaan,.*":
> +    description: Canaan, Inc.
>    "^caninos,.*":
>      description: Caninos Loucos Program
>    "^capella,.*":
> @@ -537,6 +539,8 @@ patternProperties:
>      description: Ka-Ro electronics GmbH
>    "^keithkoep,.*":
>      description: Keith & Koep GmbH
> +  "^kendryte,.*":
> +    description: Canaan, Inc.
>    "^keymile,.*":
>      description: Keymile GmbH
>    "^khadas,.*":
> 

So AFAIK Canaan is the company, and Kendryte is the brand. However, I
was unaware of this when I did my initial porting work. So all the
compatible strings like "kendryte,k210-foo" should really be
"canaan,kendryte-k210-foo". These _should_ all get fixed in the device
tree, but no one has done it yet.

--Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:05     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:05 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC system
> controller driver in
> Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
>  1 file changed, 65 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> new file mode 100644
> index 000000000000..8c002d2078f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> @@ -0,0 +1,65 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/kendryte,k210-sysctl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 System Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 system controller driver which provides a register map for
> +  clocks and peripherals within the SoC.
> +
> +  See also:
> +  - dt-bindings/mfd/kendryte,k210-sysctl.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-sysctl
> +        - const: syscon
> +        - const: simple-mfd
> +
> +  clocks:
> +    minItems: 1
> +    maxItems: 1
> +    items:
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 1
> +    items:
> +      - const: pclk
> +
> +  reg:
> +    items:
> +      - description: system controller register space base address and size
> +
> +  reg-io-width:
> +    const: 4
> +
> +required:
> +  - compatible
> +  - clocks
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      reg-io-width = <4>;
> +      /* ... */
> +    };
> +
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
@ 2020-11-07 14:05     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:05 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC system
> controller driver in
> Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
>  1 file changed, 65 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> 
> diff --git a/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> new file mode 100644
> index 000000000000..8c002d2078f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> @@ -0,0 +1,65 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mfd/kendryte,k210-sysctl.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 System Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 system controller driver which provides a register map for
> +  clocks and peripherals within the SoC.
> +
> +  See also:
> +  - dt-bindings/mfd/kendryte,k210-sysctl.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-sysctl
> +        - const: syscon
> +        - const: simple-mfd
> +
> +  clocks:
> +    minItems: 1
> +    maxItems: 1
> +    items:
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 1
> +    items:
> +      - const: pclk
> +
> +  reg:
> +    items:
> +      - description: system controller register space base address and size
> +
> +  reg-io-width:
> +    const: 4
> +
> +required:
> +  - compatible
> +  - clocks
> +  - reg
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      reg-io-width = <4>;
> +      /* ... */
> +    };
> +
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:05     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:05 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC clock driver
> in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> 
> diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> new file mode 100644
> index 000000000000..02f5f8a86bc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Clock Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 clock controller driver which support the system controller
> +  subsystem supplied clocks for the various controllers and peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/clock/k210-clk.h
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-clk
> +
> +  clocks:
> +    maxItems: 1
> +    description: System fixed rate oscillator clock
> +
> +  '#clock-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - '#clock-cells'
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/k210-clk.h>
> +
> +    clocks {
> +      in0: oscillator {
> +        compatible = "fixed-clock";
> +        #clock-cells = <0>;
> +        clock-frequency = <26000000>;
> +      };
> +    };
> +
> +    soc {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      /* ... */
> +
> +      sysctl: system-controller@50440000 {
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        compatible = "kendryte,k210-sysctl",
> +                     "syscon", "simple-mfd";
> +        reg = <0x50440000 0x1000>;
> +        /* ... */
> +        sysclk: clock-controller {
> +          #clock-cells = <1>;
> +          compatible = "kendryte,k210-clk";
> +          clocks = <&in0>;
> +        };
> +        /* ... */
> +      };
> +    };
> +
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
@ 2020-11-07 14:05     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:05 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC clock driver
> in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> 
> diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> new file mode 100644
> index 000000000000..02f5f8a86bc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Clock Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 clock controller driver which support the system controller
> +  subsystem supplied clocks for the various controllers and peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/clock/k210-clk.h
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-clk
> +
> +  clocks:
> +    maxItems: 1
> +    description: System fixed rate oscillator clock
> +
> +  '#clock-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - '#clock-cells'
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/k210-clk.h>
> +
> +    clocks {
> +      in0: oscillator {
> +        compatible = "fixed-clock";
> +        #clock-cells = <0>;
> +        clock-frequency = <26000000>;
> +      };
> +    };
> +
> +    soc {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      /* ... */
> +
> +      sysctl: system-controller@50440000 {
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        compatible = "kendryte,k210-sysctl",
> +                     "syscon", "simple-mfd";
> +        reg = <0x50440000 0x1000>;
> +        /* ... */
> +        sysclk: clock-controller {
> +          #clock-cells = <1>;
> +          compatible = "kendryte,k210-clk";
> +          clocks = <&in0>;
> +        };
> +        /* ... */
> +      };
> +    };
> +
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:06     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:06 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> new file mode 100644
> index 000000000000..8730add88ee0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description:
> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> +  is performed on a per-pin basis.
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-fpioa
> +
> +  reg:
> +    description: FPIOA controller register space base address and size
> +
> +  clocks:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - description: Controller reference clock source
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - const: ref
> +      - const: pclk
> +
> +  resets:
> +    maxItems: 1
> +
> +  kendryte,sysctl:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      phandle to the system controller node
> +
> +  kendryte,power-offset:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Offset of the power domain control register of the system controller.
> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> +      dt-bindings/mfd/k210-sysctl.h.
> +
> +patternProperties:
> +  '^.*$':
> +    if:
> +      type: object
> +    then:
> +      patternProperties:
> +        "^pinmux$":
> +          $ref: /schemas/pinctrl/pincfg-node.yaml
> +          description:
> +            An array of IO pins alternate functions. The values for each
> +            IO pin is a combination of an IO pin number (0 to 47) with the
> +            desired function for the IO pin. Functions are defined as macros in
> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
> +            is provided to facilitate the combination of IO pin numbers and
> +            functions.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - kendryte,sysctl
> +  - kendryte,power-offset
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/clock/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-sysctl.h>
> +
> +    fpioa: pinmux@502B0000 {
> +      compatible = "kendryte,k210-fpioa";
> +      reg = <0x502B0000 0x100>;
> +      clocks = <&sysclk K210_CLK_FPIOA>;
> +      resets = <&sysrst K210_RST_FPIOA>;
> +      kendryte,sysctl = <&sysctl>;
> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +      pinctrl-0 = <&fpioa_jtag>;
> +      pinctrl-names = "default";
> +
> +      fpioa_jtag: jtag {
> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +      };
> +    };
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-07 14:06     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:06 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> new file mode 100644
> index 000000000000..8730add88ee0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description:
> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> +  is performed on a per-pin basis.
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-fpioa
> +
> +  reg:
> +    description: FPIOA controller register space base address and size
> +
> +  clocks:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - description: Controller reference clock source
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - const: ref
> +      - const: pclk
> +
> +  resets:
> +    maxItems: 1
> +
> +  kendryte,sysctl:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      phandle to the system controller node
> +
> +  kendryte,power-offset:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Offset of the power domain control register of the system controller.
> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> +      dt-bindings/mfd/k210-sysctl.h.
> +
> +patternProperties:
> +  '^.*$':
> +    if:
> +      type: object
> +    then:
> +      patternProperties:
> +        "^pinmux$":
> +          $ref: /schemas/pinctrl/pincfg-node.yaml
> +          description:
> +            An array of IO pins alternate functions. The values for each
> +            IO pin is a combination of an IO pin number (0 to 47) with the
> +            desired function for the IO pin. Functions are defined as macros in
> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
> +            is provided to facilitate the combination of IO pin numbers and
> +            functions.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - kendryte,sysctl
> +  - kendryte,power-offset
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/clock/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-sysctl.h>
> +
> +    fpioa: pinmux@502B0000 {
> +      compatible = "kendryte,k210-fpioa";
> +      reg = <0x502B0000 0x100>;
> +      clocks = <&sysclk K210_CLK_FPIOA>;
> +      resets = <&sysrst K210_RST_FPIOA>;
> +      kendryte,sysctl = <&sysctl>;
> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +      pinctrl-0 = <&fpioa_jtag>;
> +      pinctrl-names = "default";
> +
> +      fpioa_jtag: jtag {
> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +      };
> +    };
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:07     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:07 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> new file mode 100644
> index 000000000000..bdd0bf37bdfb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 reset controller driver which support the system controller
> +  subsystem supplied reset registers for the various peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/reset/k210-rst.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-rst
> +        - const: syscon-reset
> +
> +  regmap:
> +    maxItems: 1
> +    description: phandle of the system controller (sysctl) node
> +
> +  offset:
> +    maxItems: 1
> +    description: peripheral reset register offset in the system controller
> +      controller register map
> +
> +  mask:
> +    maxItems: 1
> +    description: bit-mask indicating valid reset bits in the reset register
> +
> +  assert-high:
> +    maxItems: 1
> +    description: bit value to write when asserting a reset
> +
> +  '#reset-cells':
> +    const: 1
> +
> +required:
> +  - '#reset-cells'
> +  - compatible
> +  - regmap
> +  - offset
> +  - mask
> +  - assert-high
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-rst.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      /* ... */
> +      sysrst: reset-controller {
> +        compatible = "kendryte,k210-rst",
> +                      "syscon-reset";
> +        #reset-cells = <1>;
> +        regmap = <&sysctl>;
> +        offset = <K210_SYSCTL_PERI_RESET>;
> +        mask = <0x27FFFFFF>;
> +        assert-high = <1>;
> +      };
> +    };
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
@ 2020-11-07 14:07     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:07 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> new file mode 100644
> index 000000000000..bdd0bf37bdfb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 reset controller driver which support the system controller
> +  subsystem supplied reset registers for the various peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/reset/k210-rst.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-rst
> +        - const: syscon-reset
> +
> +  regmap:
> +    maxItems: 1
> +    description: phandle of the system controller (sysctl) node
> +
> +  offset:
> +    maxItems: 1
> +    description: peripheral reset register offset in the system controller
> +      controller register map
> +
> +  mask:
> +    maxItems: 1
> +    description: bit-mask indicating valid reset bits in the reset register
> +
> +  assert-high:
> +    maxItems: 1
> +    description: bit value to write when asserting a reset
> +
> +  '#reset-cells':
> +    const: 1
> +
> +required:
> +  - '#reset-cells'
> +  - compatible
> +  - regmap
> +  - offset
> +  - mask
> +  - assert-high
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-rst.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      /* ... */
> +      sysrst: reset-controller {
> +        compatible = "kendryte,k210-rst",
> +                      "syscon-reset";
> +        #reset-cells = <1>;
> +        regmap = <&sysctl>;
> +        offset = <K210_SYSCTL_PERI_RESET>;
> +        mask = <0x27FFFFFF>;
> +        assert-high = <1>;
> +      };
> +    };
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 26/32] riscv: Update Kendryte K210 device tree
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:08     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:08 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Update the Kendryte K210 base device tree k210.dtsi to define all
> peripherals of the SoC, their clocks and reset lines. The device tree
> file k210.dts is renamed to k210_generic.dts and becomes the default
> dwivalue selection of the SOC_KENDRYTE_K210_DTB_BUILTIN_SOURCE
> configuration option. No device beside the serial console is defined by
> this device tree. This makes it suitable for all known K210 boards using
> a builtin initramfs.
> 
> Most updates to the k210.dtsi file come from Sean Anderson's work on
> U-Boot support for the Kendryte K210.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs                       |   2 +-
>  arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
>  arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++++++++++-
>  arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 ++
>  4 files changed, 583 insertions(+), 52 deletions(-)
>  delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 56ba82a64e18..9230af7fb763 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -59,7 +59,7 @@ config SOC_KENDRYTE_K210_DTB_SOURCE
>  	string "Source file for the Kendryte K210 builtin DTB"
>  	depends on SOC_KENDRYTE
>  	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
> -	default "k210"
> +	default "k210_generic"
>  	help
>  	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
>  	  for the DTS file that will be used to produce the DTB linked into the
> diff --git a/arch/riscv/boot/dts/kendryte/k210.dts b/arch/riscv/boot/dts/kendryte/k210.dts
> deleted file mode 100644
> index 0d1f28fce6b2..000000000000
> --- a/arch/riscv/boot/dts/kendryte/k210.dts
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0+
> -/*
> - * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> - */
> -
> -/dts-v1/;
> -
> -#include "k210.dtsi"
> -
> -/ {
> -	model = "Kendryte K210 generic";
> -	compatible = "kendryte,k210";
> -
> -	chosen {
> -		bootargs = "earlycon console=ttySIF0";
> -		stdout-path = "serial0";
> -	};
> -};
> -
> -&uarths0 {
> -	status = "okay";
> -};
> -
> diff --git a/arch/riscv/boot/dts/kendryte/k210.dtsi b/arch/riscv/boot/dts/kendryte/k210.dtsi
> index d2d0ff645632..b8706fe78b21 100644
> --- a/arch/riscv/boot/dts/kendryte/k210.dtsi
> +++ b/arch/riscv/boot/dts/kendryte/k210.dtsi
> @@ -1,9 +1,12 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> - * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
>   * Copyright (C) 2020 Western Digital Corporation or its affiliates.
>   */
>  #include <dt-bindings/clock/k210-clk.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dt-bindings/pinctrl/k210-pinctrl.h>
> +#include <dt-bindings/reset/k210-rst.h>
>  
>  / {
>  	/*
> @@ -15,7 +18,26 @@ / {
>  	compatible = "kendryte,k210";
>  
>  	aliases {
> +		cpu0 = &cpu0;
> +		cpu1 = &cpu1;
> +		dma0 = &dmac0;
> +		gpio0 = &gpio0;
> +		gpio1 = &gpio1_0;
> +		i2c0 = &i2c0;
> +		i2c1 = &i2c1;
> +		i2c2 = &i2c2;
> +		pinctrl0 = &fpioa;
>  		serial0 = &uarths0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +		serial3 = &uart3;
> +		spi0 = &spi0;
> +		spi1 = &spi1;
> +		spi2 = &spi2;
> +		spi3 = &spi3;
> +		timer0 = &timer0;
> +		timer1 = &timer1;
> +		timer2 = &timer2;
>  	};
>  
>  	/*
> @@ -30,16 +52,15 @@ cpus {
>  		timebase-frequency = <7800000>;
>  		cpu0: cpu@0 {
>  			device_type = "cpu";
> -			reg = <0>;
>  			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
> -			riscv,isa = "rv64imafdc";
> +			reg = <0>;
> +			riscv,isa = "rv64imafdgc";
>  			mmu-type = "none";
> -			i-cache-size = <0x8000>;
>  			i-cache-block-size = <64>;
> -			d-cache-size = <0x8000>;
> +			i-cache-size = <0x8000>;
>  			d-cache-block-size = <64>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> -			clock-frequency = <390000000>;
> +			d-cache-size = <0x8000>;
> +			clocks = <&sysclk K210_CLK_CPU>;
>  			cpu0_intc: interrupt-controller {
>  				#interrupt-cells = <1>;
>  				interrupt-controller;
> @@ -48,16 +69,15 @@ cpu0_intc: interrupt-controller {
>  		};
>  		cpu1: cpu@1 {
>  			device_type = "cpu";
> -			reg = <1>;
>  			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
> -			riscv,isa = "rv64imafdc";
> +			reg = <1>;
> +			riscv,isa = "rv64imafdgc";
>  			mmu-type = "none";
> -			i-cache-size = <0x8000>;
>  			i-cache-block-size = <64>;
> -			d-cache-size = <0x8000>;
> +			i-cache-size = <0x8000>;
>  			d-cache-block-size = <64>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> -			clock-frequency = <390000000>;
> +			d-cache-size = <0x8000>;
> +			clocks = <&sysclk K210_CLK_CPU>;
>  			cpu1_intc: interrupt-controller {
>  				#interrupt-cells = <1>;
>  				interrupt-controller;
> @@ -68,14 +88,19 @@ cpu1_intc: interrupt-controller {
>  
>  	sram: memory@80000000 {
>  		device_type = "memory";
> +		compatible = "kendryte,k210-sram";
>  		reg = <0x80000000 0x400000>,
>  		      <0x80400000 0x200000>,
>  		      <0x80600000 0x200000>;
>  		reg-names = "sram0", "sram1", "aisram";
> +		clocks = <&sysclk K210_CLK_SRAM0>,
> +			 <&sysclk K210_CLK_SRAM1>,
> +			 <&sysclk K210_CLK_AI>;
> +		clock-names = "sram0", "sram1", "aisram";
>  	};
>  
>  	clocks {
> -		in0: oscillator {
> +		in0: osc {
>  			compatible = "fixed-clock";
>  			#clock-cells = <0>;
>  			clock-frequency = <26000000>;
> @@ -89,28 +114,34 @@ soc {
>  		ranges;
>  		interrupt-parent = <&plic0>;
>  
> -		sysctl: sysctl@50440000 {
> -			compatible = "kendryte,k210-sysctl", "simple-mfd";
> -			reg = <0x50440000 0x1000>;
> -			#clock-cells = <1>;
> +		debug0: debug@0 {
> +			compatible = "kendryte,k210-debug", "riscv,debug";
> +			reg = <0x0 0x1000>;
> +			status = "disabled";
> +		};
> +
> +		rom0: nvmem@1000 {
> +			reg = <0x1000 0x1000>;
> +			read-only;
> +			status = "disabled";
>  		};
>  
>  		clint0: clint@2000000 {
>  			#interrupt-cells = <1>;
> -			compatible = "riscv,clint0";
> +			compatible = "kendryte,k210-clint", "riscv,clint0";
>  			reg = <0x2000000 0xC000>;
> -			interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
> -						&cpu1_intc 3 &cpu1_intc 7>;
> -			clocks = <&sysctl K210_CLK_ACLK>;
> +			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
> +					      <&cpu1_intc 3>, <&cpu1_intc 7>;
> +			clocks = <&sysclk K210_CLK_CLINT>;
>  		};
>  
> -		plic0: interrupt-controller@c000000 {
> +		plic0: interrupt-controller@C000000 {
>  			#interrupt-cells = <1>;
> -			interrupt-controller;
> -			compatible = "kendryte,k210-plic0", "riscv,plic0";
> +			compatible = "kendryte,k210-plic", "riscv,plic0";
>  			reg = <0xC000000 0x4000000>;
> -			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 0xffffffff>,
> -					      <&cpu1_intc 11>, <&cpu1_intc 0xffffffff>;
> +			interrupt-controller;
> +			interrupts-extended = <&cpu0_intc 11>,
> +					      <&cpu1_intc 11>;
>  			riscv,ndev = <65>;
>  			riscv,max-priority = <7>;
>  		};
> @@ -119,7 +150,484 @@ uarths0: serial@38000000 {
>  			compatible = "kendryte,k210-uarths", "sifive,uart0";
>  			reg = <0x38000000 0x1000>;
>  			interrupts = <33>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> +			clocks = <&sysclk K210_CLK_CPU>;
> +			status = "disabled";
> +		};
> +
> +		gpio0: gpio-controller@38001000 {
> +			#interrupt-cells = <2>;
> +			#gpio-cells = <2>;
> +			compatible = "kendryte,k210-gpiohs", "sifive,gpio0";
> +			reg = <0x38001000 0x1000>;
> +			interrupt-controller;
> +			interrupts = <34 35 36 37 38 39 40 41
> +				      42 43 44 45 46 47 48 49
> +				      50 51 52 53 54 55 56 57
> +				      58 59 60 61 62 63 64 65>;
> +			gpio-controller;
> +			ngpios = <32>;
> +			status = "disabled";
> +		};
> +
> +		kpu0: kpu@40800000 {
> +			compatible = "kendryte,k210-kpu";
> +			reg = <0x40800000 0xc00000>;
> +			interrupts = <25>;
> +			clocks = <&sysclk K210_CLK_AI>;
> +			status = "disabled";
> +		};
> +
> +		fft0: fft@42000000 {
> +			compatible = "kendryte,k210-fft";
> +			reg = <0x42000000 0x400000>;
> +			interrupts = <26>;
> +			clocks = <&sysclk K210_CLK_FFT>;
> +			resets = <&sysrst K210_RST_FFT>;
> +			status = "disabled";
> +		};
> +
> +		dmac0: dma-controller@50000000 {
> +			compatible = "kendryte,k210-dmac", "snps,axi-dma-1.01a";
> +			reg = <0x50000000 0x1000>;
> +			interrupts = <27 28 29 30 31 32>;
> +			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
> +			clock-names = "core-clk", "cfgr-clk";
> +			resets = <&sysrst K210_RST_DMA>;
> +			dma-channels = <6>;
> +			snps,dma-masters = <2>;
> +			snps,priority = <0 1 2 3 4 5>;
> +			snps,data-width = <5>;
> +			snps,block-size = <0x200000 0x200000 0x200000
> +					   0x200000 0x200000 0x200000>;
> +			snps,axi-max-burst-len = <256>;
> +			status = "disabled";
> +		};
> +
> +		apb0: bus@50200000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB0>;
> +
> +			gpio1: gpio-controller@50200000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "kendryte,k210-gpio",
> +					     "snps,dw-apb-gpio";
> +				reg = <0x50200000 0x80>;
> +				clocks = <&sysclk K210_CLK_APB0>,
> +					 <&sysclk K210_CLK_GPIO>;
> +				clock-names = "bus", "db";
> +				resets = <&sysrst K210_RST_GPIO>;
> +				status = "disabled";
> +
> +				gpio1_0: gpio1@0 {
> +					#gpio-cells = <2>;
> +					#interrupt-cells = <2>;
> +					compatible = "snps,dw-apb-gpio-port";
> +					reg = <0>;
> +					interrupt-controller;
> +					interrupts = <23>;
> +					gpio-controller;
> +					snps,nr-gpios = <8>;
> +				};
> +			};
> +
> +			uart1: serial@50210000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50210000 0x100>;
> +				interrupts = <11>;
> +				clocks = <&sysclk K210_CLK_UART1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART1>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			uart2: serial@50220000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50220000 0x100>;
> +				interrupts = <12>;
> +				clocks = <&sysclk K210_CLK_UART2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART2>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			uart3: serial@50230000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50230000 0x100>;
> +				interrupts = <13>;
> +				clocks = <&sysclk K210_CLK_UART3>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART3>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			spi2: spi@50240000 {
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				spi-slave;
> +				reg = <0x50240000 0x100>;
> +				interrupts = <3>;
> +				clocks = <&sysclk K210_CLK_SPI2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI2>;
> +				spi-max-frequency = <25000000>;
> +				status = "disabled";
> +			};
> +
> +			i2s0: i2s@50250000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50250000 0x200>;
> +				interrupts = <5>;
> +				clocks = <&sysclk K210_CLK_I2S0>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S0>;
> +				status = "disabled";
> +			};
> +
> +			apu0: sound@520250200 {
> +				compatible = "kendryte,k210-apu";
> +				reg = <0x50250200 0x200>;
> +				status = "disabled";
> +			};
> +
> +			i2s1: i2s@50260000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50260000 0x200>;
> +				interrupts = <6>;
> +				clocks = <&sysclk K210_CLK_I2S1>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S1>;
> +				status = "disabled";
> +			};
> +
> +			i2s2: i2s@50270000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50270000 0x200>;
> +				interrupts = <7>;
> +				clocks = <&sysclk K210_CLK_I2S2>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S2>;
> +				status = "disabled";
> +			};
> +
> +			i2c0: i2c@50280000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x50280000 0x100>;
> +				interrupts = <8>;
> +				clocks = <&sysclk K210_CLK_I2C0>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C0>;
> +				status = "disabled";
> +			};
> +
> +			i2c1: i2c@50290000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x50290000 0x100>;
> +				interrupts = <9>;
> +				clocks = <&sysclk K210_CLK_I2C1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C1>;
> +				status = "disabled";
> +			};
> +
> +			i2c2: i2c@502A0000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x502A0000 0x100>;
> +				interrupts = <10>;
> +				clocks = <&sysclk K210_CLK_I2C2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C2>;
> +				status = "disabled";
> +			};
> +
> +			fpioa: pinmux@502B0000 {
> +				compatible = "kendryte,k210-fpioa";
> +				reg = <0x502B0000 0x100>;
> +				clocks = <&sysclk K210_CLK_FPIOA>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_FPIOA>;
> +				kendryte,sysctl = <&sysctl>;
> +				kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +				status = "disabled";
> +			};
> +
> +			sha256: sha256@502C0000 {
> +				compatible = "kendryte,k210-sha256";
> +				reg = <0x502C0000 0x100>;
> +				clocks = <&sysclk K210_CLK_SHA>;
> +				resets = <&sysrst K210_RST_SHA>;
> +				status = "disabled";
> +			};
> +
> +			timer0: timer@502D0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502D0000 0x100>;
> +				interrupts = <14 15>;
> +				clocks = <&sysclk K210_CLK_TIMER0>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER0>;
> +				status = "disabled";
> +			};
> +
> +			timer1: timer@502E0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502E0000 0x100>;
> +				interrupts = <16 17>;
> +				clocks = <&sysclk K210_CLK_TIMER1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER1>;
> +				status = "disabled";
> +			};
> +
> +			timer2: timer@502F0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502F0000 0x100>;
> +				interrupts = <18 19>;
> +				clocks = <&sysclk K210_CLK_TIMER2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER2>;
> +				status = "disabled";
> +			};
> +		};
> +
> +		apb1: bus@50400000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB1>;
> +
> +			wdt0: watchdog@50400000 {
> +				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
> +				reg = <0x50400000 0x100>;
> +				interrupts = <21>;
> +				clocks = <&sysclk K210_CLK_WDT0>,
> +					 <&sysclk K210_CLK_APB1>;
> +				clock-names = "tclk", "pclk";
> +				resets = <&sysrst K210_RST_WDT0>;
> +				status = "disabled";
> +			};
> +
> +			wdt1: watchdog@50410000 {
> +				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
> +				reg = <0x50410000 0x100>;
> +				interrupts = <22>;
> +				clocks = <&sysclk K210_CLK_WDT1>,
> +					 <&sysclk K210_CLK_APB1>;
> +				clock-names = "tclk", "pclk";
> +				resets = <&sysrst K210_RST_WDT1>;
> +				status = "disabled";
> +			};
> +
> +			otp0: nvmem@50420000 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				compatible = "kendryte,k210-otp";
> +				reg = <0x50420000 0x100>,
> +				      <0x88000000 0x20000>;
> +				reg-names = "reg", "mem";
> +				clocks = <&sysclk K210_CLK_ROM>;
> +				resets = <&sysrst K210_RST_ROM>;
> +				read-only;
> +				status = "disabled";
> +
> +				/* Bootloader */
> +				firmware@00000 {
> +					reg = <0x00000 0xC200>;
> +				};
> +
> +				/*
> +				 * config string as described in RISC-V
> +				 * privileged spec 1.9
> +				 */
> +				config-1-9@1c000 {
> +					reg = <0x1C000 0x1000>;
> +				};
> +
> +				/*
> +				 * Device tree containing only registers,
> +				 * interrupts, and cpus
> +				 */
> +				fdt@1d000 {
> +					reg = <0x1D000 0x2000>;
> +				};
> +
> +				/* CPU/ROM credits */
> +				credits@1f000 {
> +					reg = <0x1F000 0x1000>;
> +				};
> +			};
> +
> +			dvp0: camera@50430000 {
> +				compatible = "kendryte,k210-dvp";
> +				reg = <0x50430000 0x100>;
> +				interrupts = <24>;
> +				clocks = <&sysclk K210_CLK_DVP>;
> +				resets = <&sysrst K210_RST_DVP>;
> +				kendryte,sysctl = <&sysctl>;
> +				kendryte,misc-offset = <K210_SYSCTL_MISC>;
> +				status = "disabled";
> +			};
> +
> +			sysctl: syscon@50440000 {
> +				compatible = "kendryte,k210-sysctl",
> +					     "syscon", "simple-mfd";
> +				reg = <0x50440000 0x100>;
> +				reg-io-width = <4>;
> +				clocks = <&sysclk K210_CLK_APB1>;
> +				clock-names = "pclk";
> +
> +				sysclk: clock-controller {
> +					#clock-cells = <1>;
> +					compatible = "kendryte,k210-clk";
> +					clocks = <&in0>;
> +				};
> +
> +				sysrst: reset-controller {
> +					compatible = "kendryte,k210-rst",
> +						     "syscon-reset";
> +					#reset-cells = <1>;
> +					regmap = <&sysctl>;
> +					offset = <K210_SYSCTL_PERI_RESET>;
> +					mask = <0x27FFFFFF>;
> +					assert-high = <1>;
> +				};
> +
> +				reboot {
> +					compatible = "syscon-reboot";
> +					regmap = <&sysctl>;
> +					offset = <K210_SYSCTL_SOFT_RESET>;
> +					mask = <1>;
> +					value = <1>;
> +				};
> +			};
> +
> +			aes0: aes@50450000 {
> +				compatible = "kendryte,k210-aes";
> +				reg = <0x50450000 0x100>;
> +				clocks = <&sysclk K210_CLK_AES>;
> +				resets = <&sysrst K210_RST_AES>;
> +				status = "disabled";
> +			};
> +
> +			rtc: rtc@50460000 {
> +				compatible = "kendryte,k210-rtc";
> +				reg = <0x50460000 0x100>;
> +				clocks = <&in0>;
> +				resets = <&sysrst K210_RST_RTC>;
> +				interrupts = <20>;
> +				status = "disabled";
> +			};
> +		};
> +
> +		apb2: bus@52000000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB2>;
> +
> +			spi0: spi@52000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				reg = <0x52000000 0x100>;
> +				interrupts = <1>;
> +				clocks = <&sysclk K210_CLK_SPI0>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI0>;
> +				reset-names = "spi";
> +				spi-max-frequency = <25000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
> +
> +			spi1: spi@53000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				reg = <0x53000000 0x100>;
> +				interrupts = <2>;
> +				clocks = <&sysclk K210_CLK_SPI1>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI1>;
> +				reset-names = "spi";
> +				spi-max-frequency = <25000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
> +
> +			spi3: spi@54000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-ssi",
> +					     "snps,dwc-ssi-1.01a";
> +				reg = <0x54000000 0x200>;
> +				interrupts = <4>;
> +				clocks = <&sysclk K210_CLK_SPI3>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI3>;
> +				reset-names = "spi";
> +				/* Could possibly go up to 200 MHz */
> +				spi-max-frequency = <100000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
>  		};
>  	};
>  };
> diff --git a/arch/riscv/boot/dts/kendryte/k210_generic.dts b/arch/riscv/boot/dts/kendryte/k210_generic.dts
> new file mode 100644
> index 000000000000..f336f60dc15d
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_generic.dts
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "Kendryte K210 generic";
> +	compatible = "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +};
> +
> +&fpioa {
> +	pinctrl-0 = <&fpioa_jtag>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +
> +	fpioa_jtag: jtag {
> +		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +	};
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 26/32] riscv: Update Kendryte K210 device tree
@ 2020-11-07 14:08     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:08 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Update the Kendryte K210 base device tree k210.dtsi to define all
> peripherals of the SoC, their clocks and reset lines. The device tree
> file k210.dts is renamed to k210_generic.dts and becomes the default
> dwivalue selection of the SOC_KENDRYTE_K210_DTB_BUILTIN_SOURCE
> configuration option. No device beside the serial console is defined by
> this device tree. This makes it suitable for all known K210 boards using
> a builtin initramfs.
> 
> Most updates to the k210.dtsi file come from Sean Anderson's work on
> U-Boot support for the Kendryte K210.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/Kconfig.socs                       |   2 +-
>  arch/riscv/boot/dts/kendryte/k210.dts         |  23 -
>  arch/riscv/boot/dts/kendryte/k210.dtsi        | 564 +++++++++++++++++-
>  arch/riscv/boot/dts/kendryte/k210_generic.dts |  46 ++
>  4 files changed, 583 insertions(+), 52 deletions(-)
>  delete mode 100644 arch/riscv/boot/dts/kendryte/k210.dts
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_generic.dts
> 
> diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
> index 56ba82a64e18..9230af7fb763 100644
> --- a/arch/riscv/Kconfig.socs
> +++ b/arch/riscv/Kconfig.socs
> @@ -59,7 +59,7 @@ config SOC_KENDRYTE_K210_DTB_SOURCE
>  	string "Source file for the Kendryte K210 builtin DTB"
>  	depends on SOC_KENDRYTE
>  	depends on SOC_KENDRYTE_K210_DTB_BUILTIN
> -	default "k210"
> +	default "k210_generic"
>  	help
>  	  Base name (without suffix, relative to arch/riscv/boot/dts/kendryte)
>  	  for the DTS file that will be used to produce the DTB linked into the
> diff --git a/arch/riscv/boot/dts/kendryte/k210.dts b/arch/riscv/boot/dts/kendryte/k210.dts
> deleted file mode 100644
> index 0d1f28fce6b2..000000000000
> --- a/arch/riscv/boot/dts/kendryte/k210.dts
> +++ /dev/null
> @@ -1,23 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0+
> -/*
> - * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> - */
> -
> -/dts-v1/;
> -
> -#include "k210.dtsi"
> -
> -/ {
> -	model = "Kendryte K210 generic";
> -	compatible = "kendryte,k210";
> -
> -	chosen {
> -		bootargs = "earlycon console=ttySIF0";
> -		stdout-path = "serial0";
> -	};
> -};
> -
> -&uarths0 {
> -	status = "okay";
> -};
> -
> diff --git a/arch/riscv/boot/dts/kendryte/k210.dtsi b/arch/riscv/boot/dts/kendryte/k210.dtsi
> index d2d0ff645632..b8706fe78b21 100644
> --- a/arch/riscv/boot/dts/kendryte/k210.dtsi
> +++ b/arch/riscv/boot/dts/kendryte/k210.dtsi
> @@ -1,9 +1,12 @@
>  // SPDX-License-Identifier: GPL-2.0+
>  /*
> - * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
>   * Copyright (C) 2020 Western Digital Corporation or its affiliates.
>   */
>  #include <dt-bindings/clock/k210-clk.h>
> +#include <dt-bindings/mfd/k210-sysctl.h>
> +#include <dt-bindings/pinctrl/k210-pinctrl.h>
> +#include <dt-bindings/reset/k210-rst.h>
>  
>  / {
>  	/*
> @@ -15,7 +18,26 @@ / {
>  	compatible = "kendryte,k210";
>  
>  	aliases {
> +		cpu0 = &cpu0;
> +		cpu1 = &cpu1;
> +		dma0 = &dmac0;
> +		gpio0 = &gpio0;
> +		gpio1 = &gpio1_0;
> +		i2c0 = &i2c0;
> +		i2c1 = &i2c1;
> +		i2c2 = &i2c2;
> +		pinctrl0 = &fpioa;
>  		serial0 = &uarths0;
> +		serial1 = &uart1;
> +		serial2 = &uart2;
> +		serial3 = &uart3;
> +		spi0 = &spi0;
> +		spi1 = &spi1;
> +		spi2 = &spi2;
> +		spi3 = &spi3;
> +		timer0 = &timer0;
> +		timer1 = &timer1;
> +		timer2 = &timer2;
>  	};
>  
>  	/*
> @@ -30,16 +52,15 @@ cpus {
>  		timebase-frequency = <7800000>;
>  		cpu0: cpu@0 {
>  			device_type = "cpu";
> -			reg = <0>;
>  			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
> -			riscv,isa = "rv64imafdc";
> +			reg = <0>;
> +			riscv,isa = "rv64imafdgc";
>  			mmu-type = "none";
> -			i-cache-size = <0x8000>;
>  			i-cache-block-size = <64>;
> -			d-cache-size = <0x8000>;
> +			i-cache-size = <0x8000>;
>  			d-cache-block-size = <64>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> -			clock-frequency = <390000000>;
> +			d-cache-size = <0x8000>;
> +			clocks = <&sysclk K210_CLK_CPU>;
>  			cpu0_intc: interrupt-controller {
>  				#interrupt-cells = <1>;
>  				interrupt-controller;
> @@ -48,16 +69,15 @@ cpu0_intc: interrupt-controller {
>  		};
>  		cpu1: cpu@1 {
>  			device_type = "cpu";
> -			reg = <1>;
>  			compatible = "kendryte,k210", "sifive,rocket0", "riscv";
> -			riscv,isa = "rv64imafdc";
> +			reg = <1>;
> +			riscv,isa = "rv64imafdgc";
>  			mmu-type = "none";
> -			i-cache-size = <0x8000>;
>  			i-cache-block-size = <64>;
> -			d-cache-size = <0x8000>;
> +			i-cache-size = <0x8000>;
>  			d-cache-block-size = <64>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> -			clock-frequency = <390000000>;
> +			d-cache-size = <0x8000>;
> +			clocks = <&sysclk K210_CLK_CPU>;
>  			cpu1_intc: interrupt-controller {
>  				#interrupt-cells = <1>;
>  				interrupt-controller;
> @@ -68,14 +88,19 @@ cpu1_intc: interrupt-controller {
>  
>  	sram: memory@80000000 {
>  		device_type = "memory";
> +		compatible = "kendryte,k210-sram";
>  		reg = <0x80000000 0x400000>,
>  		      <0x80400000 0x200000>,
>  		      <0x80600000 0x200000>;
>  		reg-names = "sram0", "sram1", "aisram";
> +		clocks = <&sysclk K210_CLK_SRAM0>,
> +			 <&sysclk K210_CLK_SRAM1>,
> +			 <&sysclk K210_CLK_AI>;
> +		clock-names = "sram0", "sram1", "aisram";
>  	};
>  
>  	clocks {
> -		in0: oscillator {
> +		in0: osc {
>  			compatible = "fixed-clock";
>  			#clock-cells = <0>;
>  			clock-frequency = <26000000>;
> @@ -89,28 +114,34 @@ soc {
>  		ranges;
>  		interrupt-parent = <&plic0>;
>  
> -		sysctl: sysctl@50440000 {
> -			compatible = "kendryte,k210-sysctl", "simple-mfd";
> -			reg = <0x50440000 0x1000>;
> -			#clock-cells = <1>;
> +		debug0: debug@0 {
> +			compatible = "kendryte,k210-debug", "riscv,debug";
> +			reg = <0x0 0x1000>;
> +			status = "disabled";
> +		};
> +
> +		rom0: nvmem@1000 {
> +			reg = <0x1000 0x1000>;
> +			read-only;
> +			status = "disabled";
>  		};
>  
>  		clint0: clint@2000000 {
>  			#interrupt-cells = <1>;
> -			compatible = "riscv,clint0";
> +			compatible = "kendryte,k210-clint", "riscv,clint0";
>  			reg = <0x2000000 0xC000>;
> -			interrupts-extended =  <&cpu0_intc 3 &cpu0_intc 7
> -						&cpu1_intc 3 &cpu1_intc 7>;
> -			clocks = <&sysctl K210_CLK_ACLK>;
> +			interrupts-extended = <&cpu0_intc 3>, <&cpu0_intc 7>,
> +					      <&cpu1_intc 3>, <&cpu1_intc 7>;
> +			clocks = <&sysclk K210_CLK_CLINT>;
>  		};
>  
> -		plic0: interrupt-controller@c000000 {
> +		plic0: interrupt-controller@C000000 {
>  			#interrupt-cells = <1>;
> -			interrupt-controller;
> -			compatible = "kendryte,k210-plic0", "riscv,plic0";
> +			compatible = "kendryte,k210-plic", "riscv,plic0";
>  			reg = <0xC000000 0x4000000>;
> -			interrupts-extended = <&cpu0_intc 11>, <&cpu0_intc 0xffffffff>,
> -					      <&cpu1_intc 11>, <&cpu1_intc 0xffffffff>;
> +			interrupt-controller;
> +			interrupts-extended = <&cpu0_intc 11>,
> +					      <&cpu1_intc 11>;
>  			riscv,ndev = <65>;
>  			riscv,max-priority = <7>;
>  		};
> @@ -119,7 +150,484 @@ uarths0: serial@38000000 {
>  			compatible = "kendryte,k210-uarths", "sifive,uart0";
>  			reg = <0x38000000 0x1000>;
>  			interrupts = <33>;
> -			clocks = <&sysctl K210_CLK_CPU>;
> +			clocks = <&sysclk K210_CLK_CPU>;
> +			status = "disabled";
> +		};
> +
> +		gpio0: gpio-controller@38001000 {
> +			#interrupt-cells = <2>;
> +			#gpio-cells = <2>;
> +			compatible = "kendryte,k210-gpiohs", "sifive,gpio0";
> +			reg = <0x38001000 0x1000>;
> +			interrupt-controller;
> +			interrupts = <34 35 36 37 38 39 40 41
> +				      42 43 44 45 46 47 48 49
> +				      50 51 52 53 54 55 56 57
> +				      58 59 60 61 62 63 64 65>;
> +			gpio-controller;
> +			ngpios = <32>;
> +			status = "disabled";
> +		};
> +
> +		kpu0: kpu@40800000 {
> +			compatible = "kendryte,k210-kpu";
> +			reg = <0x40800000 0xc00000>;
> +			interrupts = <25>;
> +			clocks = <&sysclk K210_CLK_AI>;
> +			status = "disabled";
> +		};
> +
> +		fft0: fft@42000000 {
> +			compatible = "kendryte,k210-fft";
> +			reg = <0x42000000 0x400000>;
> +			interrupts = <26>;
> +			clocks = <&sysclk K210_CLK_FFT>;
> +			resets = <&sysrst K210_RST_FFT>;
> +			status = "disabled";
> +		};
> +
> +		dmac0: dma-controller@50000000 {
> +			compatible = "kendryte,k210-dmac", "snps,axi-dma-1.01a";
> +			reg = <0x50000000 0x1000>;
> +			interrupts = <27 28 29 30 31 32>;
> +			clocks = <&sysclk K210_CLK_DMA>, <&sysclk K210_CLK_DMA>;
> +			clock-names = "core-clk", "cfgr-clk";
> +			resets = <&sysrst K210_RST_DMA>;
> +			dma-channels = <6>;
> +			snps,dma-masters = <2>;
> +			snps,priority = <0 1 2 3 4 5>;
> +			snps,data-width = <5>;
> +			snps,block-size = <0x200000 0x200000 0x200000
> +					   0x200000 0x200000 0x200000>;
> +			snps,axi-max-burst-len = <256>;
> +			status = "disabled";
> +		};
> +
> +		apb0: bus@50200000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB0>;
> +
> +			gpio1: gpio-controller@50200000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "kendryte,k210-gpio",
> +					     "snps,dw-apb-gpio";
> +				reg = <0x50200000 0x80>;
> +				clocks = <&sysclk K210_CLK_APB0>,
> +					 <&sysclk K210_CLK_GPIO>;
> +				clock-names = "bus", "db";
> +				resets = <&sysrst K210_RST_GPIO>;
> +				status = "disabled";
> +
> +				gpio1_0: gpio1@0 {
> +					#gpio-cells = <2>;
> +					#interrupt-cells = <2>;
> +					compatible = "snps,dw-apb-gpio-port";
> +					reg = <0>;
> +					interrupt-controller;
> +					interrupts = <23>;
> +					gpio-controller;
> +					snps,nr-gpios = <8>;
> +				};
> +			};
> +
> +			uart1: serial@50210000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50210000 0x100>;
> +				interrupts = <11>;
> +				clocks = <&sysclk K210_CLK_UART1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART1>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			uart2: serial@50220000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50220000 0x100>;
> +				interrupts = <12>;
> +				clocks = <&sysclk K210_CLK_UART2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART2>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			uart3: serial@50230000 {
> +				compatible = "kendryte,k210-uart",
> +					     "snps,dw-apb-uart";
> +				reg = <0x50230000 0x100>;
> +				interrupts = <13>;
> +				clocks = <&sysclk K210_CLK_UART3>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "baudclk", "apb_pclk";
> +				resets = <&sysrst K210_RST_UART3>;
> +				reg-io-width = <4>;
> +				reg-shift = <2>;
> +				dcd-override;
> +				dsr-override;
> +				cts-override;
> +				ri-override;
> +				status = "disabled";
> +			};
> +
> +			spi2: spi@50240000 {
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				spi-slave;
> +				reg = <0x50240000 0x100>;
> +				interrupts = <3>;
> +				clocks = <&sysclk K210_CLK_SPI2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI2>;
> +				spi-max-frequency = <25000000>;
> +				status = "disabled";
> +			};
> +
> +			i2s0: i2s@50250000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50250000 0x200>;
> +				interrupts = <5>;
> +				clocks = <&sysclk K210_CLK_I2S0>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S0>;
> +				status = "disabled";
> +			};
> +
> +			apu0: sound@520250200 {
> +				compatible = "kendryte,k210-apu";
> +				reg = <0x50250200 0x200>;
> +				status = "disabled";
> +			};
> +
> +			i2s1: i2s@50260000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50260000 0x200>;
> +				interrupts = <6>;
> +				clocks = <&sysclk K210_CLK_I2S1>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S1>;
> +				status = "disabled";
> +			};
> +
> +			i2s2: i2s@50270000 {
> +				compatible = "kendryte,k210-i2s",
> +					     "snps,designware-i2s";
> +				reg = <0x50270000 0x200>;
> +				interrupts = <7>;
> +				clocks = <&sysclk K210_CLK_I2S2>;
> +				clock-names = "i2sclk";
> +				resets = <&sysrst K210_RST_I2S2>;
> +				status = "disabled";
> +			};
> +
> +			i2c0: i2c@50280000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x50280000 0x100>;
> +				interrupts = <8>;
> +				clocks = <&sysclk K210_CLK_I2C0>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C0>;
> +				status = "disabled";
> +			};
> +
> +			i2c1: i2c@50290000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x50290000 0x100>;
> +				interrupts = <9>;
> +				clocks = <&sysclk K210_CLK_I2C1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C1>;
> +				status = "disabled";
> +			};
> +
> +			i2c2: i2c@502A0000 {
> +				compatible = "kendryte,k210-i2c",
> +					     "snps,designware-i2c";
> +				reg = <0x502A0000 0x100>;
> +				interrupts = <10>;
> +				clocks = <&sysclk K210_CLK_I2C2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_I2C2>;
> +				status = "disabled";
> +			};
> +
> +			fpioa: pinmux@502B0000 {
> +				compatible = "kendryte,k210-fpioa";
> +				reg = <0x502B0000 0x100>;
> +				clocks = <&sysclk K210_CLK_FPIOA>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "ref", "pclk";
> +				resets = <&sysrst K210_RST_FPIOA>;
> +				kendryte,sysctl = <&sysctl>;
> +				kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +				status = "disabled";
> +			};
> +
> +			sha256: sha256@502C0000 {
> +				compatible = "kendryte,k210-sha256";
> +				reg = <0x502C0000 0x100>;
> +				clocks = <&sysclk K210_CLK_SHA>;
> +				resets = <&sysrst K210_RST_SHA>;
> +				status = "disabled";
> +			};
> +
> +			timer0: timer@502D0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502D0000 0x100>;
> +				interrupts = <14 15>;
> +				clocks = <&sysclk K210_CLK_TIMER0>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER0>;
> +				status = "disabled";
> +			};
> +
> +			timer1: timer@502E0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502E0000 0x100>;
> +				interrupts = <16 17>;
> +				clocks = <&sysclk K210_CLK_TIMER1>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER1>;
> +				status = "disabled";
> +			};
> +
> +			timer2: timer@502F0000 {
> +				compatible = "kendryte,k210-timer",
> +					     "snps,dw-apb-timer";
> +				reg = <0x502F0000 0x100>;
> +				interrupts = <18 19>;
> +				clocks = <&sysclk K210_CLK_TIMER2>,
> +					 <&sysclk K210_CLK_APB0>;
> +				clock-names = "timer", "pclk";
> +				resets = <&sysrst K210_RST_TIMER2>;
> +				status = "disabled";
> +			};
> +		};
> +
> +		apb1: bus@50400000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB1>;
> +
> +			wdt0: watchdog@50400000 {
> +				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
> +				reg = <0x50400000 0x100>;
> +				interrupts = <21>;
> +				clocks = <&sysclk K210_CLK_WDT0>,
> +					 <&sysclk K210_CLK_APB1>;
> +				clock-names = "tclk", "pclk";
> +				resets = <&sysrst K210_RST_WDT0>;
> +				status = "disabled";
> +			};
> +
> +			wdt1: watchdog@50410000 {
> +				compatible = "kendryte,k210-wdt", "snps,dw-wdt";
> +				reg = <0x50410000 0x100>;
> +				interrupts = <22>;
> +				clocks = <&sysclk K210_CLK_WDT1>,
> +					 <&sysclk K210_CLK_APB1>;
> +				clock-names = "tclk", "pclk";
> +				resets = <&sysrst K210_RST_WDT1>;
> +				status = "disabled";
> +			};
> +
> +			otp0: nvmem@50420000 {
> +				#address-cells = <1>;
> +				#size-cells = <1>;
> +				compatible = "kendryte,k210-otp";
> +				reg = <0x50420000 0x100>,
> +				      <0x88000000 0x20000>;
> +				reg-names = "reg", "mem";
> +				clocks = <&sysclk K210_CLK_ROM>;
> +				resets = <&sysrst K210_RST_ROM>;
> +				read-only;
> +				status = "disabled";
> +
> +				/* Bootloader */
> +				firmware@00000 {
> +					reg = <0x00000 0xC200>;
> +				};
> +
> +				/*
> +				 * config string as described in RISC-V
> +				 * privileged spec 1.9
> +				 */
> +				config-1-9@1c000 {
> +					reg = <0x1C000 0x1000>;
> +				};
> +
> +				/*
> +				 * Device tree containing only registers,
> +				 * interrupts, and cpus
> +				 */
> +				fdt@1d000 {
> +					reg = <0x1D000 0x2000>;
> +				};
> +
> +				/* CPU/ROM credits */
> +				credits@1f000 {
> +					reg = <0x1F000 0x1000>;
> +				};
> +			};
> +
> +			dvp0: camera@50430000 {
> +				compatible = "kendryte,k210-dvp";
> +				reg = <0x50430000 0x100>;
> +				interrupts = <24>;
> +				clocks = <&sysclk K210_CLK_DVP>;
> +				resets = <&sysrst K210_RST_DVP>;
> +				kendryte,sysctl = <&sysctl>;
> +				kendryte,misc-offset = <K210_SYSCTL_MISC>;
> +				status = "disabled";
> +			};
> +
> +			sysctl: syscon@50440000 {
> +				compatible = "kendryte,k210-sysctl",
> +					     "syscon", "simple-mfd";
> +				reg = <0x50440000 0x100>;
> +				reg-io-width = <4>;
> +				clocks = <&sysclk K210_CLK_APB1>;
> +				clock-names = "pclk";
> +
> +				sysclk: clock-controller {
> +					#clock-cells = <1>;
> +					compatible = "kendryte,k210-clk";
> +					clocks = <&in0>;
> +				};
> +
> +				sysrst: reset-controller {
> +					compatible = "kendryte,k210-rst",
> +						     "syscon-reset";
> +					#reset-cells = <1>;
> +					regmap = <&sysctl>;
> +					offset = <K210_SYSCTL_PERI_RESET>;
> +					mask = <0x27FFFFFF>;
> +					assert-high = <1>;
> +				};
> +
> +				reboot {
> +					compatible = "syscon-reboot";
> +					regmap = <&sysctl>;
> +					offset = <K210_SYSCTL_SOFT_RESET>;
> +					mask = <1>;
> +					value = <1>;
> +				};
> +			};
> +
> +			aes0: aes@50450000 {
> +				compatible = "kendryte,k210-aes";
> +				reg = <0x50450000 0x100>;
> +				clocks = <&sysclk K210_CLK_AES>;
> +				resets = <&sysrst K210_RST_AES>;
> +				status = "disabled";
> +			};
> +
> +			rtc: rtc@50460000 {
> +				compatible = "kendryte,k210-rtc";
> +				reg = <0x50460000 0x100>;
> +				clocks = <&in0>;
> +				resets = <&sysrst K210_RST_RTC>;
> +				interrupts = <20>;
> +				status = "disabled";
> +			};
> +		};
> +
> +		apb2: bus@52000000 {
> +			#address-cells = <1>;
> +			#size-cells = <1>;
> +			compatible = "kendryte,k210-apb", "simple-pm-bus";
> +			ranges;
> +			clocks = <&sysclk K210_CLK_APB2>;
> +
> +			spi0: spi@52000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				reg = <0x52000000 0x100>;
> +				interrupts = <1>;
> +				clocks = <&sysclk K210_CLK_SPI0>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI0>;
> +				reset-names = "spi";
> +				spi-max-frequency = <25000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
> +
> +			spi1: spi@53000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-spi",
> +					     "snps,dw-apb-ssi-4.01",
> +					     "snps,dw-apb-ssi";
> +				reg = <0x53000000 0x100>;
> +				interrupts = <2>;
> +				clocks = <&sysclk K210_CLK_SPI1>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI1>;
> +				reset-names = "spi";
> +				spi-max-frequency = <25000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
> +
> +			spi3: spi@54000000 {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +				compatible = "canaan,kendryte-k210-ssi",
> +					     "snps,dwc-ssi-1.01a";
> +				reg = <0x54000000 0x200>;
> +				interrupts = <4>;
> +				clocks = <&sysclk K210_CLK_SPI3>,
> +					 <&sysclk K210_CLK_APB2>;
> +				clock-names = "ssi_clk", "pclk";
> +				resets = <&sysrst K210_RST_SPI3>;
> +				reset-names = "spi";
> +				/* Could possibly go up to 200 MHz */
> +				spi-max-frequency = <100000000>;
> +				num-cs = <4>;
> +				reg-io-width = <4>;
> +				status = "disabled";
> +			};
>  		};
>  	};
>  };
> diff --git a/arch/riscv/boot/dts/kendryte/k210_generic.dts b/arch/riscv/boot/dts/kendryte/k210_generic.dts
> new file mode 100644
> index 000000000000..f336f60dc15d
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_generic.dts
> @@ -0,0 +1,46 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "Kendryte K210 generic";
> +	compatible = "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +};
> +
> +&fpioa {
> +	pinctrl-0 = <&fpioa_jtag>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +
> +	fpioa_jtag: jtag {
> +		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +	};
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 27/32] riscv: Add SiPeed MAIX BiT board device tree
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:13     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:13 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a device tree for the SiPeed MAIX BiT and MAIX BiTm boards. This
> device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++++++++++++++++
>  1 file changed, 226 insertions(+)
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> 
> diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> new file mode 100644
> index 000000000000..fc814f7c1173
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> @@ -0,0 +1,226 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "SiPeed MAIX BiT";
> +	compatible = "sipeed,maix-bitm", "sipeed,maix-bit",
> +		     "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +
> +		green {
> +			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		red {
> +			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		blue {
> +			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		boot {
> +			label = "BOOT";
> +			linux,code = <BTN_0>;
> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	sound {
> +		compatible = "simple-audio-card";
> +		simple-audio-card,format = "i2s";
> +		status = "disabled";
> +
> +		simple-audio-card,cpu {
> +			sound-dai = <&i2s0 0>;
> +		};
> +
> +		simple-audio-card,codec {
> +			sound-dai = <&mic>;
> +		};
> +	};
> +
> +	mic: mic {
> +		#sound-dai-cells = <0>;
> +		compatible = "memsensing,msm261s4030h0";
> +		status = "disabled";
> +	};
> +};
> +
> +&fpioa {
> +	pinctrl-0 = <&fpioa_jtag>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +
> +	fpioa_jtag: jtag {
> +		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +	};
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
> +	};
> +
> +	fpioa_gpio: gpio {
> +		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
> +			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
> +			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
> +			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
> +			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
> +			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
> +			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
> +			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
> +	};
> +
> +	fpioa_gpiohs: gpiohs {
> +		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
> +			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
> +			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
> +			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
> +			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
> +			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
> +			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
> +			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
> +			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
> +			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
> +			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
> +	};
> +
> +	fpioa_i2s0: i2s0 {
> +		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
> +			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
> +			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
> +	};
> +
> +	fpioa_dvp: dvp {
> +		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
> +			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
> +			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
> +			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
> +			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
> +			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
> +			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
> +			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
> +	};
> +
> +	fpioa_spi0: spi0 {
> +		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
> +			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
> +			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
> +			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
> +	};
> +
> +	fpioa_spi1: spi1 {
> +		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
> +			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
> +			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
> +			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
> +	};
> +
> +	fpioa_i2c1: i2c1 {
> +		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
> +			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio0 {
> +	pinctrl-0 = <&fpioa_gpiohs>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio1 {
> +	pinctrl-0 = <&fpioa_gpio>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&i2s0 {
> +	#sound-dai-cells = <1>;
> +	pinctrl-0 = <&fpioa_i2s0>;
> +	pinctrl-names = "default";
> +};
> +
> +&i2c1 {
> +	pinctrl-0 = <&fpioa_i2c1>;
> +	pinctrl-names = "default";
> +	clock-frequency = <400000>;
> +	status = "okay";
> +};
> +
> +&dvp0 {
> +	pinctrl-0 = <&fpioa_dvp>;
> +	pinctrl-names = "default";
> +};
> +
> +&spi0 {
> +	pinctrl-0 = <&fpioa_spi0>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	cs-gpios = <&gpio0 20 0>;
> +
> +	panel@0 {
> +		compatible = "sitronix,st7789v";
> +		reg = <0>;
> +		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
> +		dc-gpios = <&gpio0 22 0>;
> +		spi-max-frequency = <15000000>;
> +		status = "disabled";
> +	};
> +};
> +
> +&spi1 {
> +	pinctrl-0 = <&fpioa_spi1>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	polling;
> +	status = "okay";
> +
> +	slot@0 {
> +		compatible = "mmc-spi-slot";
> +		reg = <0>;
> +		voltage-ranges = <3300 3300>;
> +		spi-max-frequency = <4000000>;
> +		broken-cd;
> +	};
> +};
> +
> +&spi3 {
> +	spi-flash@0 {
> +		compatible = "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <50000000>;
> +		m25p,fast-read;
> +		broken-flash-reset;
> +	};
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 27/32] riscv: Add SiPeed MAIX BiT board device tree
@ 2020-11-07 14:13     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:13 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a device tree for the SiPeed MAIX BiT and MAIX BiTm boards. This
> device tree enables LEDs, gpio, i2c and spi/mmc SD card devices.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../riscv/boot/dts/kendryte/k210_maix_bit.dts | 226 ++++++++++++++++++
>  1 file changed, 226 insertions(+)
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> 
> diff --git a/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> new file mode 100644
> index 000000000000..fc814f7c1173
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_maix_bit.dts
> @@ -0,0 +1,226 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "SiPeed MAIX BiT";
> +	compatible = "sipeed,maix-bitm", "sipeed,maix-bit",
> +		     "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	gpio-leds {
> +		compatible = "gpio-leds";
> +
> +		green {
> +			gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		red {
> +			gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>;
> +		};
> +
> +		blue {
> +			gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		boot {
> +			label = "BOOT";
> +			linux,code = <BTN_0>;
> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	sound {
> +		compatible = "simple-audio-card";
> +		simple-audio-card,format = "i2s";
> +		status = "disabled";
> +
> +		simple-audio-card,cpu {
> +			sound-dai = <&i2s0 0>;
> +		};
> +
> +		simple-audio-card,codec {
> +			sound-dai = <&mic>;
> +		};
> +	};
> +
> +	mic: mic {
> +		#sound-dai-cells = <0>;
> +		compatible = "memsensing,msm261s4030h0";
> +		status = "disabled";
> +	};
> +};
> +
> +&fpioa {
> +	pinctrl-0 = <&fpioa_jtag>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +
> +	fpioa_jtag: jtag {
> +		pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +			 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +			 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +			 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +	};
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>,
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>;
> +	};
> +
> +	fpioa_gpio: gpio {
> +		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
> +			 <K210_FPIOA(9, K210_PCF_GPIO1)>,
> +			 <K210_FPIOA(10, K210_PCF_GPIO2)>,
> +			 <K210_FPIOA(11, K210_PCF_GPIO3)>,
> +			 <K210_FPIOA(12, K210_PCF_GPIO4)>,
> +			 <K210_FPIOA(13, K210_PCF_GPIO5)>,
> +			 <K210_FPIOA(14, K210_PCF_GPIO6)>,
> +			 <K210_FPIOA(15, K210_PCF_GPIO7)>;
> +	};
> +
> +	fpioa_gpiohs: gpiohs {
> +		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,
> +			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
> +			 <K210_FPIOA(21, K210_PCF_GPIOHS5)>,
> +			 <K210_FPIOA(22, K210_PCF_GPIOHS6)>,
> +			 <K210_FPIOA(23, K210_PCF_GPIOHS7)>,
> +			 <K210_FPIOA(24, K210_PCF_GPIOHS8)>,
> +			 <K210_FPIOA(25, K210_PCF_GPIOHS9)>,
> +			 <K210_FPIOA(32, K210_PCF_GPIOHS16)>,
> +			 <K210_FPIOA(33, K210_PCF_GPIOHS17)>,
> +			 <K210_FPIOA(34, K210_PCF_GPIOHS18)>,
> +			 <K210_FPIOA(35, K210_PCF_GPIOHS19)>;
> +	};
> +
> +	fpioa_i2s0: i2s0 {
> +		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
> +			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
> +			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
> +	};
> +
> +	fpioa_dvp: dvp {
> +		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
> +			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
> +			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
> +			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
> +			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
> +			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
> +			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
> +			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
> +	};
> +
> +	fpioa_spi0: spi0 {
> +		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
> +			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
> +			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
> +			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
> +	};
> +
> +	fpioa_spi1: spi1 {
> +		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
> +			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
> +			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
> +			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
> +	};
> +
> +	fpioa_i2c1: i2c1 {
> +		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>,
> +			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio0 {
> +	pinctrl-0 = <&fpioa_gpiohs>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio1 {
> +	pinctrl-0 = <&fpioa_gpio>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&i2s0 {
> +	#sound-dai-cells = <1>;
> +	pinctrl-0 = <&fpioa_i2s0>;
> +	pinctrl-names = "default";
> +};
> +
> +&i2c1 {
> +	pinctrl-0 = <&fpioa_i2c1>;
> +	pinctrl-names = "default";
> +	clock-frequency = <400000>;
> +	status = "okay";
> +};
> +
> +&dvp0 {
> +	pinctrl-0 = <&fpioa_dvp>;
> +	pinctrl-names = "default";
> +};
> +
> +&spi0 {
> +	pinctrl-0 = <&fpioa_spi0>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	cs-gpios = <&gpio0 20 0>;
> +
> +	panel@0 {
> +		compatible = "sitronix,st7789v";
> +		reg = <0>;
> +		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
> +		dc-gpios = <&gpio0 22 0>;
> +		spi-max-frequency = <15000000>;
> +		status = "disabled";
> +	};
> +};
> +
> +&spi1 {
> +	pinctrl-0 = <&fpioa_spi1>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	polling;
> +	status = "okay";
> +
> +	slot@0 {
> +		compatible = "mmc-spi-slot";
> +		reg = <0>;
> +		voltage-ranges = <3300 3300>;
> +		spi-max-frequency = <4000000>;
> +		broken-cd;
> +	};
> +};
> +
> +&spi3 {
> +	spi-flash@0 {
> +		compatible = "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <50000000>;
> +		m25p,fast-read;
> +		broken-flash-reset;
> +	};
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 30/32] riscv: Add SiPeed MAIXDUINO board device tree
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-07 14:14     ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:14 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a device tree for the SiPeed MAIXDUINO board. This device tree
> enables LEDs and spi/mmc SD card device. Additionally, gpios and i2c
> are also enabled and mapped to the board header pins as indicated on
> the board itself.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++++++++++++++++
>  1 file changed, 203 insertions(+)
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> 
> diff --git a/arch/riscv/boot/dts/kendryte/k210_maixduino.dts b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> new file mode 100644
> index 000000000000..78a37cf9df97
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> @@ -0,0 +1,203 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "SiPeed MAIXDUINO";
> +	compatible = "sipeed,maixduino", "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		boot {
> +			label = "BOOT";
> +			linux,code = <BTN_0>;
> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	sound {
> +		compatible = "simple-audio-card";
> +		simple-audio-card,format = "i2s";
> +		status = "disabled";
> +
> +		simple-audio-card,cpu {
> +			sound-dai = <&i2s0 0>;
> +		};
> +
> +		simple-audio-card,codec {
> +			sound-dai = <&mic>;
> +		};
> +	};
> +
> +	mic: mic {
> +		#sound-dai-cells = <0>;
> +		compatible = "memsensing,msm261s4030h0";
> +		status = "disabled";
> +	};
> +};
> +
> +&fpioa {
> +	status = "okay";
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
> +	};
> +
> +	fpioa_gpio: gpio {
> +		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
> +			 <K210_FPIOA(9, K210_PCF_GPIO1)>;
> +	};
> +
> +	fpioa_gpiohs: gpiohs {
> +		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,  /* BOOT */
> +			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
> +			 <K210_FPIOA(21, K210_PCF_GPIOHS2)>,  /* Header "2" */
> +			 <K210_FPIOA(22, K210_PCF_GPIOHS3)>,  /* Header "3" */
> +			 <K210_FPIOA(23, K210_PCF_GPIOHS4)>,  /* Header "4" */
> +			 <K210_FPIOA(24, K210_PCF_GPIOHS5)>,  /* Header "5" */
> +			 <K210_FPIOA(32, K210_PCF_GPIOHS6)>,  /* Header "6" */
> +			 <K210_FPIOA(15, K210_PCF_GPIOHS7)>,  /* Header "7" */
> +			 <K210_FPIOA(14, K210_PCF_GPIOHS8)>,  /* Header "8" */
> +			 <K210_FPIOA(13, K210_PCF_GPIOHS9)>,  /* Header "9" */
> +			 <K210_FPIOA(12, K210_PCF_GPIOHS10)>, /* Header "10" */
> +			 <K210_FPIOA(11, K210_PCF_GPIOHS11)>, /* Header "11" */
> +			 <K210_FPIOA(10, K210_PCF_GPIOHS12)>, /* Header "12" */
> +			 <K210_FPIOA(3,  K210_PCF_GPIOHS13)>, /* Header "13" */
> +			 <K210_FPIOA(25, K210_PCF_GPIOHS14)>;
> +	};
> +
> +	fpioa_i2s0: i2s0 {
> +		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
> +			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
> +			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
> +	};
> +
> +	fpioa_spi1: spi1 {
> +		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
> +			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
> +			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
> +			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
> +	};
> +
> +	fpioa_i2c1: i2c1 {
> +		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>, /* Header "scl" */
> +			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;  /* Header "sda" */
> +	};
> +
> +	fpioa_i2s1: i2s1 {
> +		pinmux = <K210_FPIOA(33, K210_PCF_I2S1_WS)>,
> +			 <K210_FPIOA(34, K210_PCF_I2S1_IN_D0)>,
> +			 <K210_FPIOA(35, K210_PCF_I2S1_SCLK)>;
> +	};
> +
> +	fpioa_spi0: spi0 {
> +		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
> +			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
> +			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
> +			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
> +	};
> +
> +	fpioa_dvp: dvp {
> +		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
> +			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
> +			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
> +			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
> +			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
> +			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
> +			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
> +			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio0 {
> +	pinctrl-0 = <&fpioa_gpiohs>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio1 {
> +	pinctrl-0 = <&fpioa_gpio>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&i2s0 {
> +	#sound-dai-cells = <1>;
> +	pinctrl-0 = <&fpioa_i2s0>;
> +	pinctrl-names = "default";
> +};
> +
> +&i2c1 {
> +	pinctrl-0 = <&fpioa_i2c1>;
> +	pinctrl-names = "default";
> +	clock-frequency = <400000>;
> +	status = "okay";
> +};
> +
> +&dvp0 {
> +	pinctrl-0 = <&fpioa_dvp>;
> +	pinctrl-names = "default";
> +};
> +
> +&spi0 {
> +	pinctrl-0 = <&fpioa_spi0>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	cs-gpios = <&gpio0 20 0>;
> +
> +	panel@0 {
> +		compatible = "sitronix,st7789v";
> +		reg = <0>;
> +		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
> +		dc-gpios = <&gpio0 22 0>;
> +		spi-max-frequency = <15000000>;
> +	};
> +};
> +
> +&spi1 {
> +	pinctrl-0 = <&fpioa_spi1>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	polling;
> +	status = "okay";
> +
> +	slot@0 {
> +		compatible = "mmc-spi-slot";
> +		reg = <0>;
> +		voltage-ranges = <3300 3300>;
> +		spi-max-frequency = <4000000>;
> +		broken-cd;
> +	};
> +};
> +
> +&spi3 {
> +	spi-flash@0 {
> +		compatible = "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <50000000>;
> +		m25p,fast-read;
> +		broken-flash-reset;
> +	};
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 30/32] riscv: Add SiPeed MAIXDUINO board device tree
@ 2020-11-07 14:14     ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-07 14:14 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, linux-gpio,
	Philipp Zabel

On 11/7/20 3:14 AM, Damien Le Moal wrote:
> Add a device tree for the SiPeed MAIXDUINO board. This device tree
> enables LEDs and spi/mmc SD card device. Additionally, gpios and i2c
> are also enabled and mapped to the board header pins as indicated on
> the board itself.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../boot/dts/kendryte/k210_maixduino.dts      | 203 ++++++++++++++++++
>  1 file changed, 203 insertions(+)
>  create mode 100644 arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> 
> diff --git a/arch/riscv/boot/dts/kendryte/k210_maixduino.dts b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> new file mode 100644
> index 000000000000..78a37cf9df97
> --- /dev/null
> +++ b/arch/riscv/boot/dts/kendryte/k210_maixduino.dts
> @@ -0,0 +1,203 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (C) 2019-20 Sean Anderson <seanga2@gmail.com>
> + * Copyright (C) 2020 Western Digital Corporation or its affiliates.
> + */
> +
> +/dts-v1/;
> +
> +#include "k210.dtsi"
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +
> +/ {
> +	model = "SiPeed MAIXDUINO";
> +	compatible = "sipeed,maixduino", "kendryte,k210";
> +
> +	chosen {
> +		bootargs = "earlycon console=ttySIF0";
> +		stdout-path = "serial0:115200n8";
> +	};
> +
> +	gpio-keys {
> +		compatible = "gpio-keys";
> +
> +		boot {
> +			label = "BOOT";
> +			linux,code = <BTN_0>;
> +			gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
> +		};
> +	};
> +
> +	sound {
> +		compatible = "simple-audio-card";
> +		simple-audio-card,format = "i2s";
> +		status = "disabled";
> +
> +		simple-audio-card,cpu {
> +			sound-dai = <&i2s0 0>;
> +		};
> +
> +		simple-audio-card,codec {
> +			sound-dai = <&mic>;
> +		};
> +	};
> +
> +	mic: mic {
> +		#sound-dai-cells = <0>;
> +		compatible = "memsensing,msm261s4030h0";
> +		status = "disabled";
> +	};
> +};
> +
> +&fpioa {
> +	status = "okay";
> +
> +	fpioa_uarths: uarths {
> +		pinmux = <K210_FPIOA(4, K210_PCF_UARTHS_RX)>, /* Header "0" */
> +			 <K210_FPIOA(5, K210_PCF_UARTHS_TX)>; /* Header "1" */
> +	};
> +
> +	fpioa_gpio: gpio {
> +		pinmux = <K210_FPIOA(8, K210_PCF_GPIO0)>,
> +			 <K210_FPIOA(9, K210_PCF_GPIO1)>;
> +	};
> +
> +	fpioa_gpiohs: gpiohs {
> +		pinmux = <K210_FPIOA(16, K210_PCF_GPIOHS0)>,  /* BOOT */
> +			 <K210_FPIOA(17, K210_PCF_GPIOHS1)>,
> +			 <K210_FPIOA(21, K210_PCF_GPIOHS2)>,  /* Header "2" */
> +			 <K210_FPIOA(22, K210_PCF_GPIOHS3)>,  /* Header "3" */
> +			 <K210_FPIOA(23, K210_PCF_GPIOHS4)>,  /* Header "4" */
> +			 <K210_FPIOA(24, K210_PCF_GPIOHS5)>,  /* Header "5" */
> +			 <K210_FPIOA(32, K210_PCF_GPIOHS6)>,  /* Header "6" */
> +			 <K210_FPIOA(15, K210_PCF_GPIOHS7)>,  /* Header "7" */
> +			 <K210_FPIOA(14, K210_PCF_GPIOHS8)>,  /* Header "8" */
> +			 <K210_FPIOA(13, K210_PCF_GPIOHS9)>,  /* Header "9" */
> +			 <K210_FPIOA(12, K210_PCF_GPIOHS10)>, /* Header "10" */
> +			 <K210_FPIOA(11, K210_PCF_GPIOHS11)>, /* Header "11" */
> +			 <K210_FPIOA(10, K210_PCF_GPIOHS12)>, /* Header "12" */
> +			 <K210_FPIOA(3,  K210_PCF_GPIOHS13)>, /* Header "13" */
> +			 <K210_FPIOA(25, K210_PCF_GPIOHS14)>;
> +	};
> +
> +	fpioa_i2s0: i2s0 {
> +		pinmux = <K210_FPIOA(18, K210_PCF_I2S0_SCLK)>,
> +			 <K210_FPIOA(19, K210_PCF_I2S0_WS)>,
> +			 <K210_FPIOA(20, K210_PCF_I2S0_IN_D0)>;
> +	};
> +
> +	fpioa_spi1: spi1 {
> +		pinmux = <K210_FPIOA(26, K210_PCF_SPI1_D1)>,
> +			 <K210_FPIOA(27, K210_PCF_SPI1_SCLK)>,
> +			 <K210_FPIOA(28, K210_PCF_SPI1_D0)>,
> +			 <K210_FPIOA(29, K210_PCF_SPI1_SS0)>; /* cs */
> +	};
> +
> +	fpioa_i2c1: i2c1 {
> +		pinmux = <K210_FPIOA(30, K210_PCF_I2C1_SCLK)>, /* Header "scl" */
> +			 <K210_FPIOA(31, K210_PCF_I2C1_SDA)>;  /* Header "sda" */
> +	};
> +
> +	fpioa_i2s1: i2s1 {
> +		pinmux = <K210_FPIOA(33, K210_PCF_I2S1_WS)>,
> +			 <K210_FPIOA(34, K210_PCF_I2S1_IN_D0)>,
> +			 <K210_FPIOA(35, K210_PCF_I2S1_SCLK)>;
> +	};
> +
> +	fpioa_spi0: spi0 {
> +		pinmux = <K210_FPIOA(36, K210_PCF_GPIOHS20)>,  /* cs */
> +			 <K210_FPIOA(37, K210_PCF_GPIOHS21)>,  /* rst */
> +			 <K210_FPIOA(38, K210_PCF_GPIOHS22)>,  /* dc */
> +			 <K210_FPIOA(39, K210_PCF_SPI0_SCLK)>; /* wr */
> +	};
> +
> +	fpioa_dvp: dvp {
> +		pinmux = <K210_FPIOA(40, K210_PCF_SCCB_SDA)>,
> +			 <K210_FPIOA(41, K210_PCF_SCCB_SCLK)>,
> +			 <K210_FPIOA(42, K210_PCF_DVP_RST)>,
> +			 <K210_FPIOA(43, K210_PCF_DVP_VSYNC)>,
> +			 <K210_FPIOA(44, K210_PCF_DVP_PWDN)>,
> +			 <K210_FPIOA(45, K210_PCF_DVP_HSYNC)>,
> +			 <K210_FPIOA(46, K210_PCF_DVP_XCLK)>,
> +			 <K210_FPIOA(47, K210_PCF_DVP_PCLK)>;
> +	};
> +};
> +
> +&uarths0 {
> +	pinctrl-0 = <&fpioa_uarths>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio0 {
> +	pinctrl-0 = <&fpioa_gpiohs>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&gpio1 {
> +	pinctrl-0 = <&fpioa_gpio>;
> +	pinctrl-names = "default";
> +	status = "okay";
> +};
> +
> +&i2s0 {
> +	#sound-dai-cells = <1>;
> +	pinctrl-0 = <&fpioa_i2s0>;
> +	pinctrl-names = "default";
> +};
> +
> +&i2c1 {
> +	pinctrl-0 = <&fpioa_i2c1>;
> +	pinctrl-names = "default";
> +	clock-frequency = <400000>;
> +	status = "okay";
> +};
> +
> +&dvp0 {
> +	pinctrl-0 = <&fpioa_dvp>;
> +	pinctrl-names = "default";
> +};
> +
> +&spi0 {
> +	pinctrl-0 = <&fpioa_spi0>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	cs-gpios = <&gpio0 20 0>;
> +
> +	panel@0 {
> +		compatible = "sitronix,st7789v";
> +		reg = <0>;
> +		reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
> +		dc-gpios = <&gpio0 22 0>;
> +		spi-max-frequency = <15000000>;
> +	};
> +};
> +
> +&spi1 {
> +	pinctrl-0 = <&fpioa_spi1>;
> +	pinctrl-names = "default";
> +	num-cs = <1>;
> +	polling;
> +	status = "okay";
> +
> +	slot@0 {
> +		compatible = "mmc-spi-slot";
> +		reg = <0>;
> +		voltage-ranges = <3300 3300>;
> +		spi-max-frequency = <4000000>;
> +		broken-cd;
> +	};
> +};
> +
> +&spi3 {
> +	spi-flash@0 {
> +		compatible = "jedec,spi-nor";
> +		reg = <0>;
> +		spi-max-frequency = <50000000>;
> +		m25p,fast-read;
> +		broken-flash-reset;
> +	};
> +};
> 

Reviewed-by: Sean Anderson <seanga2@gmail.com>

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 00/32] RISC-V Kendryte K210 support improvments
  2020-11-07  8:13 ` Damien Le Moal
@ 2020-11-09 12:51   ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 12:51 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

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

On Sat, Nov 07, 2020 at 05:13:48PM +0900, Damien Le Moal wrote:

> The first patch of this series is a fix of the device tree parsing code.
> Without this fix, a warning is generated when parsing Designware gpio
> controller nodes.

> The following 6 patches are fixes and improvements to the Designware SPI
> driver to enable support for the MMC-spi slot found on all K210 boards.

> Pathes 8 to 13 are various fixes for riscv arch code and riscv
> dependent devices. Of not here is patch 11 which fix system call
> execution in the no MMU case, and patch 13 which simplifies DTB builtin
> handling.

> The following patches 14 to 25 implement and document idevice tree
> mapping of several drivers for the K210 SoC: clock driver, reset
> controller and pin function management (pinctrl).

> Patches 26 to 31 update the existing K210 device tree and device new
> device tree files for several K210 based boards: the MAIX Bit,
> MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
> development board from Kendryte.

Please don't mix unrelated changes into a single series like this -
patch serieses this big are generally something to be avoided at the
best of times since they're a bit overwhelming in people's inboxes and
when unrelated changes are put in a single series it makes dependencies
between patches unclear which can hold things up.  It is better to send
the changes for each subsystem separately, it makes life easier all
round.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 00/32] RISC-V Kendryte K210 support improvments
@ 2020-11-09 12:51   ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 12:51 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 1458 bytes --]

On Sat, Nov 07, 2020 at 05:13:48PM +0900, Damien Le Moal wrote:

> The first patch of this series is a fix of the device tree parsing code.
> Without this fix, a warning is generated when parsing Designware gpio
> controller nodes.

> The following 6 patches are fixes and improvements to the Designware SPI
> driver to enable support for the MMC-spi slot found on all K210 boards.

> Pathes 8 to 13 are various fixes for riscv arch code and riscv
> dependent devices. Of not here is patch 11 which fix system call
> execution in the no MMU case, and patch 13 which simplifies DTB builtin
> handling.

> The following patches 14 to 25 implement and document idevice tree
> mapping of several drivers for the K210 SoC: clock driver, reset
> controller and pin function management (pinctrl).

> Patches 26 to 31 update the existing K210 device tree and device new
> device tree files for several K210 based boards: the MAIX Bit,
> MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
> development board from Kendryte.

Please don't mix unrelated changes into a single series like this -
patch serieses this big are generally something to be avoided at the
best of times since they're a bit overwhelming in people's inboxes and
when unrelated changes are put in a single series it makes dependencies
between patches unclear which can hold things up.  It is better to send
the changes for each subsystem separately, it makes life easier all
round.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 00/32] RISC-V Kendryte K210 support improvments
  2020-11-09 12:51   ` Mark Brown
@ 2020-11-09 12:55     ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 12:55 UTC (permalink / raw)
  To: Mark Brown
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On 2020/11/09 21:51, Mark Brown wrote:
> On Sat, Nov 07, 2020 at 05:13:48PM +0900, Damien Le Moal wrote:
> 
>> The first patch of this series is a fix of the device tree parsing code.
>> Without this fix, a warning is generated when parsing Designware gpio
>> controller nodes.
> 
>> The following 6 patches are fixes and improvements to the Designware SPI
>> driver to enable support for the MMC-spi slot found on all K210 boards.
> 
>> Pathes 8 to 13 are various fixes for riscv arch code and riscv
>> dependent devices. Of not here is patch 11 which fix system call
>> execution in the no MMU case, and patch 13 which simplifies DTB builtin
>> handling.
> 
>> The following patches 14 to 25 implement and document idevice tree
>> mapping of several drivers for the K210 SoC: clock driver, reset
>> controller and pin function management (pinctrl).
> 
>> Patches 26 to 31 update the existing K210 device tree and device new
>> device tree files for several K210 based boards: the MAIX Bit,
>> MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
>> development board from Kendryte.
> 
> Please don't mix unrelated changes into a single series like this -
> patch serieses this big are generally something to be avoided at the
> best of times since they're a bit overwhelming in people's inboxes and
> when unrelated changes are put in a single series it makes dependencies
> between patches unclear which can hold things up.  It is better to send
> the changes for each subsystem separately, it makes life easier all
> round.

I wondered about it and in retrospect, it was a bad idea indeed to send
everything to everyone. My apologies about that.
I need to send a V2 but this time I will split it up by subsystem. Some patches
are related however (e.g. DT changes and documentation), so I will keep these
together.

Thanks !

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 00/32] RISC-V Kendryte K210 support improvments
@ 2020-11-09 12:55     ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 12:55 UTC (permalink / raw)
  To: Mark Brown
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On 2020/11/09 21:51, Mark Brown wrote:
> On Sat, Nov 07, 2020 at 05:13:48PM +0900, Damien Le Moal wrote:
> 
>> The first patch of this series is a fix of the device tree parsing code.
>> Without this fix, a warning is generated when parsing Designware gpio
>> controller nodes.
> 
>> The following 6 patches are fixes and improvements to the Designware SPI
>> driver to enable support for the MMC-spi slot found on all K210 boards.
> 
>> Pathes 8 to 13 are various fixes for riscv arch code and riscv
>> dependent devices. Of not here is patch 11 which fix system call
>> execution in the no MMU case, and patch 13 which simplifies DTB builtin
>> handling.
> 
>> The following patches 14 to 25 implement and document idevice tree
>> mapping of several drivers for the K210 SoC: clock driver, reset
>> controller and pin function management (pinctrl).
> 
>> Patches 26 to 31 update the existing K210 device tree and device new
>> device tree files for several K210 based boards: the MAIX Bit,
>> MAIXSUINO, MAIX Dock and MAIX Go boards from SiPeed and the KD233
>> development board from Kendryte.
> 
> Please don't mix unrelated changes into a single series like this -
> patch serieses this big are generally something to be avoided at the
> best of times since they're a bit overwhelming in people's inboxes and
> when unrelated changes are put in a single series it makes dependencies
> between patches unclear which can hold things up.  It is better to send
> the changes for each subsystem separately, it makes life easier all
> round.

I wondered about it and in retrospect, it was a bad idea indeed to send
everything to everyone. My apologies about that.
I need to send a V2 but this time I will split it up by subsystem. Some patches
are related however (e.g. DT changes and documentation), so I will keep these
together.

Thanks !

-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 13:29     ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 13:29 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

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

On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:

> The resting state of MOSI is high when nothing is driving it. If we
> drive it low while recieving, it looks like we are transmitting 0x00
> instead of transmitting nothing. This can confuse slaves (like SD cards)
> which allow new commands to be sent over MOSI while they are returning
> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> a byte can look like a start bit and a transmission bit to an SD card.

If client devices are interpreting the transmitted data then I would
expect the drivers for that hardware to be ensuring that whatever we
transmit matches what the device is expecting.  We shouldn't be putting
a hack in a particular controller driver to paper over things, that will
mean that the device will break when used with other controllers and if
different devices have different requirements then obviously we can't
satisfy them.  There is not meaningfully a general specification for SPI
which says what happens when signals are idle, it's all specific to the
client device.

In this case it also looks like the controller hardware requires
transmit data and therefore should be setting SPI_MUST_TX and just
removing the in driver default anyway, though that will have no effect
one way or anther on the issue you're seeing.

Please also try to avoid the use of master/slave terminology where
reasonable, controller and device tend to work for SPI (though MOSI/MISO
are going to be harder to shift).

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 13:29     ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 13:29 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 1511 bytes --]

On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:

> The resting state of MOSI is high when nothing is driving it. If we
> drive it low while recieving, it looks like we are transmitting 0x00
> instead of transmitting nothing. This can confuse slaves (like SD cards)
> which allow new commands to be sent over MOSI while they are returning
> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> a byte can look like a start bit and a transmission bit to an SD card.

If client devices are interpreting the transmitted data then I would
expect the drivers for that hardware to be ensuring that whatever we
transmit matches what the device is expecting.  We shouldn't be putting
a hack in a particular controller driver to paper over things, that will
mean that the device will break when used with other controllers and if
different devices have different requirements then obviously we can't
satisfy them.  There is not meaningfully a general specification for SPI
which says what happens when signals are idle, it's all specific to the
client device.

In this case it also looks like the controller hardware requires
transmit data and therefore should be setting SPI_MUST_TX and just
removing the in driver default anyway, though that will have no effect
one way or anther on the issue you're seeing.

Please also try to avoid the use of master/slave terminology where
reasonable, controller and device tend to work for SPI (though MOSI/MISO
are going to be harder to shift).

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 13:29     ` Mark Brown
@ 2020-11-09 13:47       ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 13:47 UTC (permalink / raw)
  To: Mark Brown, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 8:29 AM, Mark Brown wrote:
> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> 
>> The resting state of MOSI is high when nothing is driving it. If we
>> drive it low while recieving, it looks like we are transmitting 0x00
>> instead of transmitting nothing. This can confuse slaves (like SD cards)
>> which allow new commands to be sent over MOSI while they are returning
>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
>> a byte can look like a start bit and a transmission bit to an SD card.
> 
> If client devices are interpreting the transmitted data then I would
> expect the drivers for that hardware to be ensuring that whatever we
> transmit matches what the device is expecting.  We shouldn't be putting
> a hack in a particular controller driver to paper over things, that will
> mean that the device will break when used with other controllers and if
> different devices have different requirements then obviously we can't
> satisfy them.  There is not meaningfully a general specification for SPI
> which says what happens when signals are idle, it's all specific to the
> client device.
>
> In this case it also looks like the controller hardware requires
> transmit data and therefore should be setting SPI_MUST_TX and just
> removing the in driver default anyway, though that will have no effect
> one way or anther on the issue you're seeing.

There is a recieve-only mode, but it is not used by this driver. Perhaps
it should be.

> Please also try to avoid the use of master/slave terminology where
> reasonable, controller and device tend to work for SPI (though MOSI/MISO
> are going to be harder to shift).

Here I use it to draw distinction between the SPI master and the SPI
slave, which are both devices in different contexts. 

--Sean

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 13:47       ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 13:47 UTC (permalink / raw)
  To: Mark Brown, Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Frank Rowand, linux-clk

On 11/9/20 8:29 AM, Mark Brown wrote:
> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> 
>> The resting state of MOSI is high when nothing is driving it. If we
>> drive it low while recieving, it looks like we are transmitting 0x00
>> instead of transmitting nothing. This can confuse slaves (like SD cards)
>> which allow new commands to be sent over MOSI while they are returning
>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
>> a byte can look like a start bit and a transmission bit to an SD card.
> 
> If client devices are interpreting the transmitted data then I would
> expect the drivers for that hardware to be ensuring that whatever we
> transmit matches what the device is expecting.  We shouldn't be putting
> a hack in a particular controller driver to paper over things, that will
> mean that the device will break when used with other controllers and if
> different devices have different requirements then obviously we can't
> satisfy them.  There is not meaningfully a general specification for SPI
> which says what happens when signals are idle, it's all specific to the
> client device.
>
> In this case it also looks like the controller hardware requires
> transmit data and therefore should be setting SPI_MUST_TX and just
> removing the in driver default anyway, though that will have no effect
> one way or anther on the issue you're seeing.

There is a recieve-only mode, but it is not used by this driver. Perhaps
it should be.

> Please also try to avoid the use of master/slave terminology where
> reasonable, controller and device tend to work for SPI (though MOSI/MISO
> are going to be harder to shift).

Here I use it to draw distinction between the SPI master and the SPI
slave, which are both devices in different contexts. 

--Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 14:03     ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:03 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

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

On Sat, Nov 07, 2020 at 05:13:53PM +0900, Damien Le Moal wrote:
> On slow systems, i.e. systems with a slow CPU resulting in slow context
> switches, calling spi_delay_exec() when executing polled transfers
> using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
> platforms to opt out of delayed polling by introducing the
> DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
> the execution of spi_delay_exec() in dw_spi_poll_transfer().

This feels like it should be done based on something like a cutoff for
sufficiently small delays rather than with a capability - it's tuning,
not a property of the system.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
@ 2020-11-09 14:03     ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:03 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 632 bytes --]

On Sat, Nov 07, 2020 at 05:13:53PM +0900, Damien Le Moal wrote:
> On slow systems, i.e. systems with a slow CPU resulting in slow context
> switches, calling spi_delay_exec() when executing polled transfers
> using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
> platforms to opt out of delayed polling by introducing the
> DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
> the execution of spi_delay_exec() in dw_spi_poll_transfer().

This feels like it should be done based on something like a cutoff for
sufficiently small delays rather than with a capability - it's tuning,
not a property of the system.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 13:47       ` Sean Anderson
@ 2020-11-09 14:14         ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:14 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> On 11/9/20 8:29 AM, Mark Brown wrote:

> > In this case it also looks like the controller hardware requires
> > transmit data and therefore should be setting SPI_MUST_TX and just
> > removing the in driver default anyway, though that will have no effect
> > one way or anther on the issue you're seeing.

> There is a recieve-only mode, but it is not used by this driver. Perhaps
> it should be.

I'd expect it'd perform better, especially on systems that are
apparently struggling for CPU bandwidth like yours seems to.

> > Please also try to avoid the use of master/slave terminology where
> > reasonable, controller and device tend to work for SPI (though MOSI/MISO
> > are going to be harder to shift).

> Here I use it to draw distinction between the SPI master and the SPI
> slave, which are both devices in different contexts. 

If you find the use of device to refer to the device being controlled
confusing consider also using something like client device instead,
there's a number of ways to do it (there's a list in Documentation IIRC).

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 14:14         ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:14 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Serge Semin, linux-spi, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 1138 bytes --]

On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> On 11/9/20 8:29 AM, Mark Brown wrote:

> > In this case it also looks like the controller hardware requires
> > transmit data and therefore should be setting SPI_MUST_TX and just
> > removing the in driver default anyway, though that will have no effect
> > one way or anther on the issue you're seeing.

> There is a recieve-only mode, but it is not used by this driver. Perhaps
> it should be.

I'd expect it'd perform better, especially on systems that are
apparently struggling for CPU bandwidth like yours seems to.

> > Please also try to avoid the use of master/slave terminology where
> > reasonable, controller and device tend to work for SPI (though MOSI/MISO
> > are going to be harder to shift).

> Here I use it to draw distinction between the SPI master and the SPI
> slave, which are both devices in different contexts. 

If you find the use of device to refer to the device being controlled
confusing consider also using something like client device instead,
there's a number of ways to do it (there's a list in Documentation IIRC).

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07 13:52         ` Sean Anderson
@ 2020-11-09 14:15           ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:15 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Sat, Nov 07, 2020 at 08:52:24AM -0500, Sean Anderson wrote:

> I think if it is detectable at runtime it should be, instead of relying
> on compatible strings. That way causes less future grief to anyone
> porting a device possibly using DFS_32.

Yes, runtime enumeration is generally preferred.  Having the compatible
string is nice in case some quirks are discoverd but for things that
can be enumerated there's less that can go wrong if we do so.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 14:15           ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 14:15 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Serge Semin, linux-spi, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 453 bytes --]

On Sat, Nov 07, 2020 at 08:52:24AM -0500, Sean Anderson wrote:

> I think if it is detectable at runtime it should be, instead of relying
> on compatible strings. That way causes less future grief to anyone
> porting a device possibly using DFS_32.

Yes, runtime enumeration is generally preferred.  Having the compatible
string is nice in case some quirks are discoverd but for things that
can be enumerated there's less that can go wrong if we do so.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 14:25     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 14:25 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

Hello Damien,
Thanks for your patches. My comments are below.

On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> 
> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> | other stuff | spi_frf  |  dfs_32  |
> 
> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> 

> Th main difference of this layout with the 16-bits version is the data
    ^
    |
    e

> frame format field which resides in bits 16..20 instead of bits 3..0.
> 

Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
manual for the 4.0x version of the core, but according to this patch:
https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
it has been ok to use the lowest four bits for DFS setting. Is the commit
message misleading there?

> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
> platform signal that this layout is in use. Modify
> dw_spi_update_config() to test this capability flag to set the data
> frame format field at the correct register location.
> 
> Suggested-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 8 ++++++--
>  drivers/spi/spi-dw.h      | 9 +++++++++
>  2 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 2e50cc0a9291..841c85247f01 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>  	u32 speed_hz;
>  	u16 clk_div;
>  

> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
> -	cr0 |= (cfg->dfs - 1);
> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1);
> +	else
> +		/* CTRLR0[20: 16] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;

If you extend the dfs field from four to five bits, then
controller->bits_per_word_mask field should be properly updated too.

Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
should be fixed for the both of them.

Just for the record. There are very handy macros for setting and getting bit fields
to/from a variable. This is a good place to use them instead of manually
shifting and defining the offsets. The macros are defined in linux/bitfield.h .
Alas this driver hasn't been converted to using them. So I won't insist on using
them here. But I hope someone will fix it sometime in future...

-Sergey

>  
>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>  		/* CTRLR0[ 9:8] Transfer Mode */
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index faf40cb66498..48a11a51a407 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -9,6 +9,7 @@
>  #include <linux/io.h>
>  #include <linux/scatterlist.h>
>  #include <linux/spi/spi-mem.h>
> +#include <linux/bitfield.h>
>  
>  /* Register offsets */
>  #define DW_SPI_CTRLR0			0x00
> @@ -72,6 +73,13 @@
>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>  
> +/*
> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
> + * Based on DW_apb_ssi Databook v4.02a.
> + */
> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
> +
>  /*
>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>   * 0: SSI is slave
> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
> +#define DW_SPI_CAP_DFS_32		BIT(3)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:25     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 14:25 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

Hello Damien,
Thanks for your patches. My comments are below.

On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> 
> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> | other stuff | spi_frf  |  dfs_32  |
> 
> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> 

> Th main difference of this layout with the 16-bits version is the data
    ^
    |
    e

> frame format field which resides in bits 16..20 instead of bits 3..0.
> 

Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
manual for the 4.0x version of the core, but according to this patch:
https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
it has been ok to use the lowest four bits for DFS setting. Is the commit
message misleading there?

> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
> platform signal that this layout is in use. Modify
> dw_spi_update_config() to test this capability flag to set the data
> frame format field at the correct register location.
> 
> Suggested-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 8 ++++++--
>  drivers/spi/spi-dw.h      | 9 +++++++++
>  2 files changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index 2e50cc0a9291..841c85247f01 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>  	u32 speed_hz;
>  	u16 clk_div;
>  

> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
> -	cr0 |= (cfg->dfs - 1);
> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1);
> +	else
> +		/* CTRLR0[20: 16] Data Frame Size */
> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;

If you extend the dfs field from four to five bits, then
controller->bits_per_word_mask field should be properly updated too.

Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
should be fixed for the both of them.

Just for the record. There are very handy macros for setting and getting bit fields
to/from a variable. This is a good place to use them instead of manually
shifting and defining the offsets. The macros are defined in linux/bitfield.h .
Alas this driver hasn't been converted to using them. So I won't insist on using
them here. But I hope someone will fix it sometime in future...

-Sergey

>  
>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>  		/* CTRLR0[ 9:8] Transfer Mode */
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index faf40cb66498..48a11a51a407 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -9,6 +9,7 @@
>  #include <linux/io.h>
>  #include <linux/scatterlist.h>
>  #include <linux/spi/spi-mem.h>
> +#include <linux/bitfield.h>
>  
>  /* Register offsets */
>  #define DW_SPI_CTRLR0			0x00
> @@ -72,6 +73,13 @@
>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>  
> +/*
> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
> + * Based on DW_apb_ssi Databook v4.02a.
> + */
> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
> +
>  /*
>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>   * 0: SSI is slave
> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
> +#define DW_SPI_CAP_DFS_32		BIT(3)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:25     ` Serge Semin
@ 2020-11-09 14:33       ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:33 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 9:25 AM, Serge Semin wrote:
> Hello Damien,
> Thanks for your patches. My comments are below.
> 
> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
>> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
>>
>> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
>> | other stuff | spi_frf  |  dfs_32  |
>>
>> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
>> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
>>
> 
>> Th main difference of this layout with the 16-bits version is the data
>     ^
>     |
>     e
> 
>> frame format field which resides in bits 16..20 instead of bits 3..0.
>>
> 
> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> manual for the 4.0x version of the core, but according to this patch:
> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> it has been ok to use the lowest four bits for DFS setting. Is the commit
> message misleading there?

This commit message is a truncated version of [1]. Importantly, DFS is
valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
(since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
parameter, there exist devices where DFS must be used, and also where
DFS_32 must be used. 

[1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/

--Sean

> 
>> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
>> platform signal that this layout is in use. Modify
>> dw_spi_update_config() to test this capability flag to set the data
>> frame format field at the correct register location.
>>
>> Suggested-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-core.c | 8 ++++++--
>>  drivers/spi/spi-dw.h      | 9 +++++++++
>>  2 files changed, 15 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
>> index 2e50cc0a9291..841c85247f01 100644
>> --- a/drivers/spi/spi-dw-core.c
>> +++ b/drivers/spi/spi-dw-core.c
>> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>>  	u32 speed_hz;
>>  	u16 clk_div;
>>  
> 
>> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
>> -	cr0 |= (cfg->dfs - 1);
>> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
>> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
>> +		cr0 |= (cfg->dfs - 1);
>> +	else
>> +		/* CTRLR0[20: 16] Data Frame Size */
>> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
> 
> If you extend the dfs field from four to five bits, then
> controller->bits_per_word_mask field should be properly updated too.
> 
> Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
> should be fixed for the both of them.
> 
> Just for the record. There are very handy macros for setting and getting bit fields
> to/from a variable. This is a good place to use them instead of manually
> shifting and defining the offsets. The macros are defined in linux/bitfield.h .
> Alas this driver hasn't been converted to using them. So I won't insist on using
> them here. But I hope someone will fix it sometime in future...

I second that request.

> -Sergey
> 
>>  
>>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>>  		/* CTRLR0[ 9:8] Transfer Mode */
>> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
>> index faf40cb66498..48a11a51a407 100644
>> --- a/drivers/spi/spi-dw.h
>> +++ b/drivers/spi/spi-dw.h
>> @@ -9,6 +9,7 @@
>>  #include <linux/io.h>
>>  #include <linux/scatterlist.h>
>>  #include <linux/spi/spi-mem.h>
>> +#include <linux/bitfield.h>
>>  
>>  /* Register offsets */
>>  #define DW_SPI_CTRLR0			0x00
>> @@ -72,6 +73,13 @@
>>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>>  
>> +/*
>> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
>> + * Based on DW_apb_ssi Databook v4.02a.
>> + */
>> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
>> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
>> +
>>  /*
>>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>>   * 0: SSI is slave
>> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>> +#define DW_SPI_CAP_DFS_32		BIT(3)
>>  
>>  /* Slave spi_transfer/spi_mem_op related */
>>  struct dw_spi_cfg {
>> -- 
>> 2.28.0
>>


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:33       ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:33 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Frank Rowand, linux-clk

On 11/9/20 9:25 AM, Serge Semin wrote:
> Hello Damien,
> Thanks for your patches. My comments are below.
> 
> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
>> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
>>
>> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
>> | other stuff | spi_frf  |  dfs_32  |
>>
>> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
>> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
>>
> 
>> Th main difference of this layout with the 16-bits version is the data
>     ^
>     |
>     e
> 
>> frame format field which resides in bits 16..20 instead of bits 3..0.
>>
> 
> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> manual for the 4.0x version of the core, but according to this patch:
> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> it has been ok to use the lowest four bits for DFS setting. Is the commit
> message misleading there?

This commit message is a truncated version of [1]. Importantly, DFS is
valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
(since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
parameter, there exist devices where DFS must be used, and also where
DFS_32 must be used. 

[1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/

--Sean

> 
>> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
>> platform signal that this layout is in use. Modify
>> dw_spi_update_config() to test this capability flag to set the data
>> frame format field at the correct register location.
>>
>> Suggested-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-core.c | 8 ++++++--
>>  drivers/spi/spi-dw.h      | 9 +++++++++
>>  2 files changed, 15 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
>> index 2e50cc0a9291..841c85247f01 100644
>> --- a/drivers/spi/spi-dw-core.c
>> +++ b/drivers/spi/spi-dw-core.c
>> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>>  	u32 speed_hz;
>>  	u16 clk_div;
>>  
> 
>> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
>> -	cr0 |= (cfg->dfs - 1);
>> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
>> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
>> +		cr0 |= (cfg->dfs - 1);
>> +	else
>> +		/* CTRLR0[20: 16] Data Frame Size */
>> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
> 
> If you extend the dfs field from four to five bits, then
> controller->bits_per_word_mask field should be properly updated too.
> 
> Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
> should be fixed for the both of them.
> 
> Just for the record. There are very handy macros for setting and getting bit fields
> to/from a variable. This is a good place to use them instead of manually
> shifting and defining the offsets. The macros are defined in linux/bitfield.h .
> Alas this driver hasn't been converted to using them. So I won't insist on using
> them here. But I hope someone will fix it sometime in future...

I second that request.

> -Sergey
> 
>>  
>>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>>  		/* CTRLR0[ 9:8] Transfer Mode */
>> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
>> index faf40cb66498..48a11a51a407 100644
>> --- a/drivers/spi/spi-dw.h
>> +++ b/drivers/spi/spi-dw.h
>> @@ -9,6 +9,7 @@
>>  #include <linux/io.h>
>>  #include <linux/scatterlist.h>
>>  #include <linux/spi/spi-mem.h>
>> +#include <linux/bitfield.h>
>>  
>>  /* Register offsets */
>>  #define DW_SPI_CTRLR0			0x00
>> @@ -72,6 +73,13 @@
>>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>>  
>> +/*
>> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
>> + * Based on DW_apb_ssi Databook v4.02a.
>> + */
>> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
>> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
>> +
>>  /*
>>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>>   * 0: SSI is slave
>> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>> +#define DW_SPI_CAP_DFS_32		BIT(3)
>>  
>>  /* Slave spi_transfer/spi_mem_op related */
>>  struct dw_spi_cfg {
>> -- 
>> 2.28.0
>>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:33       ` Sean Anderson
@ 2020-11-09 14:35         ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:35 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 9:33 AM, Sean Anderson wrote:
> On 11/9/20 9:25 AM, Serge Semin wrote:
>> Hello Damien,
>> Thanks for your patches. My comments are below.
>>
>> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>>> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
>>> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
>>>
>>> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
>>> | other stuff | spi_frf  |  dfs_32  |
>>>
>>> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
>>> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
>>>
>>
>>> Th main difference of this layout with the 16-bits version is the data
>>     ^
>>     |
>>     e
>>
>>> frame format field which resides in bits 16..20 instead of bits 3..0.
>>>
>>
>> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
>> manual for the 4.0x version of the core, but according to this patch:
>> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
>> it has been ok to use the lowest four bits for DFS setting. Is the commit
>> message misleading there?
> 
> This commit message is a truncated version of [1]. Importantly, DFS is
> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
s/0xF/0x0/

> parameter, there exist devices where DFS must be used, and also where
> DFS_32 must be used. 
> 
> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/
> 
> --Sean
> 
>>
>>> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
>>> platform signal that this layout is in use. Modify
>>> dw_spi_update_config() to test this capability flag to set the data
>>> frame format field at the correct register location.
>>>
>>> Suggested-by: Sean Anderson <seanga2@gmail.com>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> ---
>>>  drivers/spi/spi-dw-core.c | 8 ++++++--
>>>  drivers/spi/spi-dw.h      | 9 +++++++++
>>>  2 files changed, 15 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
>>> index 2e50cc0a9291..841c85247f01 100644
>>> --- a/drivers/spi/spi-dw-core.c
>>> +++ b/drivers/spi/spi-dw-core.c
>>> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>>>  	u32 speed_hz;
>>>  	u16 clk_div;
>>>  
>>
>>> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
>>> -	cr0 |= (cfg->dfs - 1);
>>> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
>>> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
>>> +		cr0 |= (cfg->dfs - 1);
>>> +	else
>>> +		/* CTRLR0[20: 16] Data Frame Size */
>>> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
>>
>> If you extend the dfs field from four to five bits, then
>> controller->bits_per_word_mask field should be properly updated too.
>>
>> Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
>> should be fixed for the both of them.
>>
>> Just for the record. There are very handy macros for setting and getting bit fields
>> to/from a variable. This is a good place to use them instead of manually
>> shifting and defining the offsets. The macros are defined in linux/bitfield.h .
>> Alas this driver hasn't been converted to using them. So I won't insist on using
>> them here. But I hope someone will fix it sometime in future...
> 
> I second that request.
> 
>> -Sergey
>>
>>>  
>>>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>>>  		/* CTRLR0[ 9:8] Transfer Mode */
>>> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
>>> index faf40cb66498..48a11a51a407 100644
>>> --- a/drivers/spi/spi-dw.h
>>> +++ b/drivers/spi/spi-dw.h
>>> @@ -9,6 +9,7 @@
>>>  #include <linux/io.h>
>>>  #include <linux/scatterlist.h>
>>>  #include <linux/spi/spi-mem.h>
>>> +#include <linux/bitfield.h>
>>>  
>>>  /* Register offsets */
>>>  #define DW_SPI_CTRLR0			0x00
>>> @@ -72,6 +73,13 @@
>>>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>>>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>>>  
>>> +/*
>>> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
>>> + * Based on DW_apb_ssi Databook v4.02a.
>>> + */
>>> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
>>> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
>>> +
>>>  /*
>>>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>>>   * 0: SSI is slave
>>> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>>>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>>>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>>>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>>> +#define DW_SPI_CAP_DFS_32		BIT(3)
>>>  
>>>  /* Slave spi_transfer/spi_mem_op related */
>>>  struct dw_spi_cfg {
>>> -- 
>>> 2.28.0
>>>
> 


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:35         ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:35 UTC (permalink / raw)
  To: Serge Semin, Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Frank Rowand, linux-clk

On 11/9/20 9:33 AM, Sean Anderson wrote:
> On 11/9/20 9:25 AM, Serge Semin wrote:
>> Hello Damien,
>> Thanks for your patches. My comments are below.
>>
>> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>>> Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
>>> the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
>>>
>>> |   31 .. 23  | 22 .. 21 | 20 .. 16 |
>>> | other stuff | spi_frf  |  dfs_32  |
>>>
>>> |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
>>> | other stuff |  tmod  |  mode  |  frf   |  dfs   |
>>>
>>
>>> Th main difference of this layout with the 16-bits version is the data
>>     ^
>>     |
>>     e
>>
>>> frame format field which resides in bits 16..20 instead of bits 3..0.
>>>
>>
>> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
>> manual for the 4.0x version of the core, but according to this patch:
>> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
>> it has been ok to use the lowest four bits for DFS setting. Is the commit
>> message misleading there?
> 
> This commit message is a truncated version of [1]. Importantly, DFS is
> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
s/0xF/0x0/

> parameter, there exist devices where DFS must be used, and also where
> DFS_32 must be used. 
> 
> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/
> 
> --Sean
> 
>>
>>> Introduce the DW SPI capability flag DW_SPI_CAP_DFS_32 to let a
>>> platform signal that this layout is in use. Modify
>>> dw_spi_update_config() to test this capability flag to set the data
>>> frame format field at the correct register location.
>>>
>>> Suggested-by: Sean Anderson <seanga2@gmail.com>
>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>> ---
>>>  drivers/spi/spi-dw-core.c | 8 ++++++--
>>>  drivers/spi/spi-dw.h      | 9 +++++++++
>>>  2 files changed, 15 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
>>> index 2e50cc0a9291..841c85247f01 100644
>>> --- a/drivers/spi/spi-dw-core.c
>>> +++ b/drivers/spi/spi-dw-core.c
>>> @@ -311,8 +311,12 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
>>>  	u32 speed_hz;
>>>  	u16 clk_div;
>>>  
>>
>>> -	/* CTRLR0[ 4/3: 0] Data Frame Size */
>>> -	cr0 |= (cfg->dfs - 1);
>>> +	if (!(dws->caps & DW_SPI_CAP_DFS_32))
>>> +		/* CTRLR0[ 4/3: 0] Data Frame Size */
>>> +		cr0 |= (cfg->dfs - 1);
>>> +	else
>>> +		/* CTRLR0[20: 16] Data Frame Size */
>>> +		cr0 |= (cfg->dfs - 1) << DWC_APB_CTRLR0_32_DFS_OFFSET;
>>
>> If you extend the dfs field from four to five bits, then
>> controller->bits_per_word_mask field should be properly updated too.
>>
>> Alas it hasn't been done for the DWC_ssi version of the core. So I suppose it
>> should be fixed for the both of them.
>>
>> Just for the record. There are very handy macros for setting and getting bit fields
>> to/from a variable. This is a good place to use them instead of manually
>> shifting and defining the offsets. The macros are defined in linux/bitfield.h .
>> Alas this driver hasn't been converted to using them. So I won't insist on using
>> them here. But I hope someone will fix it sometime in future...
> 
> I second that request.
> 
>> -Sergey
>>
>>>  
>>>  	if (!(dws->caps & DW_SPI_CAP_DWC_SSI))
>>>  		/* CTRLR0[ 9:8] Transfer Mode */
>>> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
>>> index faf40cb66498..48a11a51a407 100644
>>> --- a/drivers/spi/spi-dw.h
>>> +++ b/drivers/spi/spi-dw.h
>>> @@ -9,6 +9,7 @@
>>>  #include <linux/io.h>
>>>  #include <linux/scatterlist.h>
>>>  #include <linux/spi/spi-mem.h>
>>> +#include <linux/bitfield.h>
>>>  
>>>  /* Register offsets */
>>>  #define DW_SPI_CTRLR0			0x00
>>> @@ -72,6 +73,13 @@
>>>  #define DWC_SSI_CTRLR0_FRF_OFFSET	6
>>>  #define DWC_SSI_CTRLR0_DFS_OFFSET	0
>>>  
>>> +/*
>>> + * Bit fields in CTRLR0 for DWC_apb_ssi v4 32-bits ctrlr0.
>>> + * Based on DW_apb_ssi Databook v4.02a.
>>> + */
>>> +#define DWC_APB_CTRLR0_32_DFS_OFFSET	16
>>> +#define DWC_APB_CTRLR0_32_DFS_MASK	GENMASK(20, 16)
>>> +
>>>  /*
>>>   * For Keem Bay, CTRLR0[31] is used to select controller mode.
>>>   * 0: SSI is slave
>>> @@ -121,6 +129,7 @@ enum dw_ssi_type {
>>>  #define DW_SPI_CAP_CS_OVERRIDE		BIT(0)
>>>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>>>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>>> +#define DW_SPI_CAP_DFS_32		BIT(3)
>>>  
>>>  /* Slave spi_transfer/spi_mem_op related */
>>>  struct dw_spi_cfg {
>>> -- 
>>> 2.28.0
>>>
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:25     ` Serge Semin
@ 2020-11-09 14:36       ` Andy Shevchenko
  -1 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:36 UTC (permalink / raw)
  To: Serge Semin
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel, Sean Anderson

On Mon, Nov 9, 2020 at 4:25 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Damien,
> Thanks for your patches. My comments are below.
>
> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> > Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> > the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> >
> > |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> > | other stuff | spi_frf  |  dfs_32  |
> >
> > |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> > | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> >
>
> > Th main difference of this layout with the 16-bits version is the data
>     ^
>     |
>     e
>
> > frame format field which resides in bits 16..20 instead of bits 3..0.
> >
>
> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> manual for the 4.0x version of the core, but according to this patch:
> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> it has been ok to use the lowest four bits for DFS setting. Is the commit
> message misleading there?

20:16 DFS_32
Data Frame Size in 32-bit transfer size mode. Used to select
the data frame size in 32-bit transfer mode. These bits are
only valid when SSI_MAX_XFER_SIZE is configured to 32.
When the data frame size is programmed to be less than 32
bits, the receive data are automatically right-justified by the
receive logic, with the upper bits of the receive FIFO zero-
padded.

3:0 DFS
Data Frame Size.
This register field is only valid when SSI_MAX_XFER_SIZE
is configured to 16. If SSI_MAX_XFER_SIZE is configured to
32, then writing to this field will not have any effect.

As far as I can tell it's an extension to the existing one (which one
in use depends on the SSI configuration).


The comment you are referring to is about DW_ssi v1.x (vs. DW_apb_ssi v4.x).


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:36       ` Andy Shevchenko
  0 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:36 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk, Linus Walleij

On Mon, Nov 9, 2020 at 4:25 PM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Damien,
> Thanks for your patches. My comments are below.
>
> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> > Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> > the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> >
> > |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> > | other stuff | spi_frf  |  dfs_32  |
> >
> > |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> > | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> >
>
> > Th main difference of this layout with the 16-bits version is the data
>     ^
>     |
>     e
>
> > frame format field which resides in bits 16..20 instead of bits 3..0.
> >
>
> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> manual for the 4.0x version of the core, but according to this patch:
> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> it has been ok to use the lowest four bits for DFS setting. Is the commit
> message misleading there?

20:16 DFS_32
Data Frame Size in 32-bit transfer size mode. Used to select
the data frame size in 32-bit transfer mode. These bits are
only valid when SSI_MAX_XFER_SIZE is configured to 32.
When the data frame size is programmed to be less than 32
bits, the receive data are automatically right-justified by the
receive logic, with the upper bits of the receive FIFO zero-
padded.

3:0 DFS
Data Frame Size.
This register field is only valid when SSI_MAX_XFER_SIZE
is configured to 16. If SSI_MAX_XFER_SIZE is configured to
32, then writing to this field will not have any effect.

As far as I can tell it's an extension to the existing one (which one
in use depends on the SSI configuration).


The comment you are referring to is about DW_ssi v1.x (vs. DW_apb_ssi v4.x).


-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:33       ` Sean Anderson
@ 2020-11-09 14:40         ` Andy Shevchenko
  -1 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:40 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Serge Semin, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 9:25 AM, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:

...

> > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > manual for the 4.0x version of the core, but according to this patch:
> > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > message misleading there?
>
> This commit message is a truncated version of [1].

I don't see how they are related.

> Importantly, DFS is
> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
> parameter, there exist devices where DFS must be used, and also where
> DFS_32 must be used.
>
> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/


-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:40         ` Andy Shevchenko
  0 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:40 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Rob Herring,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk, Linus Walleij

On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 9:25 AM, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:

...

> > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > manual for the 4.0x version of the core, but according to this patch:
> > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > message misleading there?
>
> This commit message is a truncated version of [1].

I don't see how they are related.

> Importantly, DFS is
> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
> parameter, there exist devices where DFS must be used, and also where
> DFS_32 must be used.
>
> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/


-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:40         ` Andy Shevchenko
@ 2020-11-09 14:41           ` Andy Shevchenko
  -1 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:41 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Serge Semin, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
> > On 11/9/20 9:25 AM, Serge Semin wrote:
> > > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>
> ...
>
> > > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > > manual for the 4.0x version of the core, but according to this patch:
> > > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > > message misleading there?
> >
> > This commit message is a truncated version of [1].
>
> I don't see how they are related.

For DW_ssi v1.x DFS is always for transfers up to 32-bit.

> > Importantly, DFS is
> > valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> > (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
> > parameter, there exist devices where DFS must be used, and also where
> > DFS_32 must be used.
> >
> > [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/



-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:41           ` Andy Shevchenko
  0 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 14:41 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Rob Herring,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk, Linus Walleij

On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
> > On 11/9/20 9:25 AM, Serge Semin wrote:
> > > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>
> ...
>
> > > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > > manual for the 4.0x version of the core, but according to this patch:
> > > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > > message misleading there?
> >
> > This commit message is a truncated version of [1].
>
> I don't see how they are related.

For DW_ssi v1.x DFS is always for transfers up to 32-bit.

> > Importantly, DFS is
> > valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
> > (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
> > parameter, there exist devices where DFS must be used, and also where
> > DFS_32 must be used.
> >
> > [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/



-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 14:14         ` Mark Brown
@ 2020-11-09 14:48           ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 14:48 UTC (permalink / raw)
  To: Mark Brown, Sean Anderson, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, linux-spi, Stephen Boyd, linux-clk, Linus Walleij,
	linux-gpio, Philipp Zabel

On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> > On 11/9/20 8:29 AM, Mark Brown wrote:
> 
> > > In this case it also looks like the controller hardware requires
> > > transmit data and therefore should be setting SPI_MUST_TX and just
> > > removing the in driver default anyway, though that will have no effect
> > > one way or anther on the issue you're seeing.
> 

> > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > it should be.
> 
> I'd expect it'd perform better, especially on systems that are
> apparently struggling for CPU bandwidth like yours seems to.

Well, it might seem a good idea to use that mode, but there are multiple problems
you may get in implementing it.

First of all the Receive-only mode is having a limited number bytes to receive
at once. It's just 64KB. So in order to implement it you'd need to split the
bigger transfers up, and feed the DMA engine with smaller chunks one-by-one.

Secondly the Receive-only mode will make the DW SSI controller to constantly receive
the data from the SPI bus and to put it into the Rx FIFO. So your DMA engine will
have to keep up with extracting the data from there on time, otherwise you'll
end up with Rx FIFO overflow error eventually. The problem will be actual for the
DMA engines/system buses, which are slower than the SPI bus speed, second for the
DMA engines with no hardware accelerated LLP traversal support (like on our DWC DMA
controller). The second problem can be also fixed by splitting the transfers up as
it has been already implemented in the spi-dw-dma.c. But the first problem can't be
fixed, but just workarounded by limiting the SPI bus frequency so the DMA engine
would keep up with incoming data traffic.

-Sergey

> 
> > > Please also try to avoid the use of master/slave terminology where
> > > reasonable, controller and device tend to work for SPI (though MOSI/MISO
> > > are going to be harder to shift).
> 
> > Here I use it to draw distinction between the SPI master and the SPI
> > slave, which are both devices in different contexts. 
> 
> If you find the use of device to refer to the device being controlled
> confusing consider also using something like client device instead,
> there's a number of ways to do it (there's a list in Documentation IIRC).



^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 14:48           ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 14:48 UTC (permalink / raw)
  To: Mark Brown, Sean Anderson, Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, linux-spi, linux-gpio,
	Rob Herring, Palmer Dabbelt, Philipp Zabel, linux-riscv,
	Frank Rowand, linux-clk

On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> > On 11/9/20 8:29 AM, Mark Brown wrote:
> 
> > > In this case it also looks like the controller hardware requires
> > > transmit data and therefore should be setting SPI_MUST_TX and just
> > > removing the in driver default anyway, though that will have no effect
> > > one way or anther on the issue you're seeing.
> 

> > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > it should be.
> 
> I'd expect it'd perform better, especially on systems that are
> apparently struggling for CPU bandwidth like yours seems to.

Well, it might seem a good idea to use that mode, but there are multiple problems
you may get in implementing it.

First of all the Receive-only mode is having a limited number bytes to receive
at once. It's just 64KB. So in order to implement it you'd need to split the
bigger transfers up, and feed the DMA engine with smaller chunks one-by-one.

Secondly the Receive-only mode will make the DW SSI controller to constantly receive
the data from the SPI bus and to put it into the Rx FIFO. So your DMA engine will
have to keep up with extracting the data from there on time, otherwise you'll
end up with Rx FIFO overflow error eventually. The problem will be actual for the
DMA engines/system buses, which are slower than the SPI bus speed, second for the
DMA engines with no hardware accelerated LLP traversal support (like on our DWC DMA
controller). The second problem can be also fixed by splitting the transfers up as
it has been already implemented in the spi-dw-dma.c. But the first problem can't be
fixed, but just workarounded by limiting the SPI bus frequency so the DMA engine
would keep up with incoming data traffic.

-Sergey

> 
> > > Please also try to avoid the use of master/slave terminology where
> > > reasonable, controller and device tend to work for SPI (though MOSI/MISO
> > > are going to be harder to shift).
> 
> > Here I use it to draw distinction between the SPI master and the SPI
> > slave, which are both devices in different contexts. 
> 
> If you find the use of device to refer to the device being controlled
> confusing consider also using something like client device instead,
> there's a number of ways to do it (there's a list in Documentation IIRC).



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:41           ` Andy Shevchenko
@ 2020-11-09 14:49             ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:49 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Serge Semin, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On 11/9/20 9:41 AM, Andy Shevchenko wrote:
> On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
>>
>> On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
>>> On 11/9/20 9:25 AM, Serge Semin wrote:
>>>> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>>
>> ...
>>
>>>> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
>>>> manual for the 4.0x version of the core, but according to this patch:
>>>> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
>>>> it has been ok to use the lowest four bits for DFS setting. Is the commit
>>>> message misleading there?
>>>
>>> This commit message is a truncated version of [1].
>>
>> I don't see how they are related.

I think this commit message is specifically taken from v3 of that patch
[2]. However, I had not gotten a chance to have a look at the datasheet
at that point, so it is a bit misleading (e.g. showing dfs for devices
with SSI_MAX_XFER_SIZE=32, even though it is all zeros for those
devices). In any case, the diagram is taken from that patch.

[2] https://patchwork.ozlabs.org/project/uboot/patch/20200914153503.91983-7-seanga2@gmail.com/

> 
> For DW_ssi v1.x DFS is always for transfers up to 32-bit.

Do you mean DWC_ssi?

> 
>>> Importantly, DFS is
>>> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
>>> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
>>> parameter, there exist devices where DFS must be used, and also where
>>> DFS_32 must be used.
>>>
>>> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/
> 
> 
> 


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 14:49             ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 14:49 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Rob Herring,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk, Linus Walleij

On 11/9/20 9:41 AM, Andy Shevchenko wrote:
> On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
>>
>> On Mon, Nov 9, 2020 at 4:34 PM Sean Anderson <seanga2@gmail.com> wrote:
>>> On 11/9/20 9:25 AM, Serge Semin wrote:
>>>> On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
>>
>> ...
>>
>>>> Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
>>>> manual for the 4.0x version of the core, but according to this patch:
>>>> https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
>>>> it has been ok to use the lowest four bits for DFS setting. Is the commit
>>>> message misleading there?
>>>
>>> This commit message is a truncated version of [1].
>>
>> I don't see how they are related.

I think this commit message is specifically taken from v3 of that patch
[2]. However, I had not gotten a chance to have a look at the datasheet
at that point, so it is a bit misleading (e.g. showing dfs for devices
with SSI_MAX_XFER_SIZE=32, even though it is all zeros for those
devices). In any case, the diagram is taken from that patch.

[2] https://patchwork.ozlabs.org/project/uboot/patch/20200914153503.91983-7-seanga2@gmail.com/

> 
> For DW_ssi v1.x DFS is always for transfers up to 32-bit.

Do you mean DWC_ssi?

> 
>>> Importantly, DFS is
>>> valid when SSI_MAX_XFER_SIZE=16. When it =32, then DFS_32 must be used
>>> (since DFS is constant 0xF). Since SSI_MAX_XFER_SIZE is a synthesis
>>> parameter, there exist devices where DFS must be used, and also where
>>> DFS_32 must be used.
>>>
>>> [1] https://patchwork.ozlabs.org/project/uboot/patch/20201016225755.302659-10-seanga2@gmail.com/
> 
> 
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 15:05     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 15:05 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:13:49PM +0900, Damien Le Moal wrote:
> The DesignWare GPIO driver gpio-dwapb ("snps,dw-apb-gpio" or
> "apm,xgene-gpio-v2" compatible string) defines the property
> "snps,nr-gpios" for the user to specify the number of GPIOs available
> on a port. The "-gpios" suffix of this property name ends up being
> interpreted as a cell reference when properties are parsed in
> of_link_to_suppliers(), leading to error messages such as:
> 
> OF: /soc/bus@50200000/gpio-controller@50200000/gpio-port@0: could not
> find phandle
> 
> Fix this by manually defining a parse_gpios() function which ignores
> this property, skipping the search for the supplier and thus avoiding
> the device tree parsing error.

That's why I have introduced the "ngpios" property support and marked the 
"snps,nr-gpios" as deprecated here:
https://lkml.org/lkml/2020/7/22/1298

to encourage the later one from being used in favor of the first one. So I
suggest for you to convert your dts'es (if you have ones) to using the
"ngpios" property anyway.

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/of/property.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 408a7b5f06a9..d16111c0d6da 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
>  
>  static struct device_node *parse_iommu_maps(struct device_node *np,
>  					    const char *prop_name, int index)
> @@ -1319,6 +1318,22 @@ static struct device_node *parse_iommu_maps(struct device_node *np,
>  	return of_parse_phandle(np, prop_name, (index * 4) + 1);
>  }
>  

> +static struct device_node *parse_gpios(struct device_node *np,
> +				       const char *prop_name, int index)
> +{
> +	/*
> +	 * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
           ^
           |
           Quirk?     
> +	 * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +	 * available. As this conflict with "xx-gpios" reference properties,
> +	 * ignore it.
> +	 */
> +	if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +		return NULL;
> +
> +	return parse_suffix_prop_cells(np, prop_name, index,
> +				       "-gpios", "#gpio-cells");
> +}
> +

Personally I'd prefer to convert all the dts-es to using the "ngpios' instead of
the vendor-specific property. That's why I haven't fixed the problem the way you
suggest in the first place, to encourage people to send the patches with such
fixes. Anyway it's up to the OF-subsystem maintainers to decide whether to accept
this quirk.

-Sergey

>  static const struct supplier_bindings of_supplier_bindings[] = {
>  	{ .parse_prop = parse_clocks, },
>  	{ .parse_prop = parse_interconnects, },
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-09 15:05     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 15:05 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:13:49PM +0900, Damien Le Moal wrote:
> The DesignWare GPIO driver gpio-dwapb ("snps,dw-apb-gpio" or
> "apm,xgene-gpio-v2" compatible string) defines the property
> "snps,nr-gpios" for the user to specify the number of GPIOs available
> on a port. The "-gpios" suffix of this property name ends up being
> interpreted as a cell reference when properties are parsed in
> of_link_to_suppliers(), leading to error messages such as:
> 
> OF: /soc/bus@50200000/gpio-controller@50200000/gpio-port@0: could not
> find phandle
> 
> Fix this by manually defining a parse_gpios() function which ignores
> this property, skipping the search for the supplier and thus avoiding
> the device tree parsing error.

That's why I have introduced the "ngpios" property support and marked the 
"snps,nr-gpios" as deprecated here:
https://lkml.org/lkml/2020/7/22/1298

to encourage the later one from being used in favor of the first one. So I
suggest for you to convert your dts'es (if you have ones) to using the
"ngpios" property anyway.

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/of/property.c | 17 ++++++++++++++++-
>  1 file changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 408a7b5f06a9..d16111c0d6da 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
>  
>  static struct device_node *parse_iommu_maps(struct device_node *np,
>  					    const char *prop_name, int index)
> @@ -1319,6 +1318,22 @@ static struct device_node *parse_iommu_maps(struct device_node *np,
>  	return of_parse_phandle(np, prop_name, (index * 4) + 1);
>  }
>  

> +static struct device_node *parse_gpios(struct device_node *np,
> +				       const char *prop_name, int index)
> +{
> +	/*
> +	 * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
           ^
           |
           Quirk?     
> +	 * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +	 * available. As this conflict with "xx-gpios" reference properties,
> +	 * ignore it.
> +	 */
> +	if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +		return NULL;
> +
> +	return parse_suffix_prop_cells(np, prop_name, index,
> +				       "-gpios", "#gpio-cells");
> +}
> +

Personally I'd prefer to convert all the dts-es to using the "ngpios' instead of
the vendor-specific property. That's why I haven't fixed the problem the way you
suggest in the first place, to encourage people to send the patches with such
fixes. Anyway it's up to the OF-subsystem maintainers to decide whether to accept
this quirk.

-Sergey

>  static const struct supplier_bindings of_supplier_bindings[] = {
>  	{ .parse_prop = parse_clocks, },
>  	{ .parse_prop = parse_interconnects, },
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:49             ` Sean Anderson
@ 2020-11-09 15:10               ` Andy Shevchenko
  -1 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 15:10 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Serge Semin, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On Mon, Nov 9, 2020 at 4:49 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 9:41 AM, Andy Shevchenko wrote:
> > On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:
...

> > For DW_ssi v1.x DFS is always for transfers up to 32-bit.
>
> Do you mean DWC_ssi?

One is called DWC_ssi (yes, the newer IP)
The other is DW_apb_ssi (the older one)



--
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 15:10               ` Andy Shevchenko
  0 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 15:10 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Rob Herring,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk, Linus Walleij

On Mon, Nov 9, 2020 at 4:49 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 9:41 AM, Andy Shevchenko wrote:
> > On Mon, Nov 9, 2020 at 4:40 PM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:
...

> > For DW_ssi v1.x DFS is always for transfers up to 32-bit.
>
> Do you mean DWC_ssi?

One is called DWC_ssi (yes, the newer IP)
The other is DW_apb_ssi (the older one)



--
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 15:14     ` Andy Shevchenko
  -1 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 15:14 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel, Sean Anderson

On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")

Sorry, but the above doesn't sound right to me.
It's a generic code and you may imagine how many systems you broke by
this change.

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-09 15:14     ` Andy Shevchenko
  0 siblings, 0 replies; 297+ messages in thread
From: Andy Shevchenko @ 2020-11-09 15:14 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, Serge Semin,
	linux-spi, open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")

Sorry, but the above doesn't sound right to me.
It's a generic code and you may imagine how many systems you broke by
this change.

-- 
With Best Regards,
Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 15:32     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:32 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Mark Brown, Stephen Boyd, Linus Walleij, linux-gpio,
	Frank Rowand, linux-riscv, Palmer Dabbelt, Rob Herring,
	devicetree, Sean Anderson, linux-spi, Serge Semin, Philipp Zabel,
	linux-clk

On Sat, 07 Nov 2020 17:14:10 +0900, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC system
> controller driver in
> Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
>  1 file changed, 65 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml:23:9: [warning] wrong indentation: expected 10 but found 8 (indentation)

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
	/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'anyOf' conditional failed, one must be fixed:
		/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
			'minItems' is not one of ['maxItems']
			'minItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
			'items' is not one of ['maxItems']
			'items' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		'maxItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		1 is less than the minimum of 2
	'minItems' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'maxItems' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'items' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'type' is a required property
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: ignoring, error in schema: properties: clocks
warning: no schema found in file: ./Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml


See https://patchwork.ozlabs.org/patch/1396076

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings
@ 2020-11-09 15:32     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:32 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Rob Herring,
	Sean Anderson, linux-gpio, Mark Brown, Palmer Dabbelt,
	Serge Semin, Philipp Zabel, linux-riscv, linux-spi, Frank Rowand,
	linux-clk

On Sat, 07 Nov 2020 17:14:10 +0900, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC system
> controller driver in
> Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/mfd/kendryte,k210-sysctl.yaml    | 65 +++++++++++++++++++
>  1 file changed, 65 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml:23:9: [warning] wrong indentation: expected 10 but found 8 (indentation)

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
	/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'anyOf' conditional failed, one must be fixed:
		/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
			'minItems' is not one of ['maxItems']
			'minItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: properties:clocks: 'oneOf' conditional failed, one must be fixed:
			'items' is not one of ['maxItems']
			'items' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		'maxItems' is not one of ['description', 'deprecated', 'const', 'enum', 'minimum', 'maximum', 'default', '$ref']
		1 is less than the minimum of 2
	'minItems' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'maxItems' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'items' is not one of ['type', 'description', 'dependencies', 'properties', 'patternProperties', 'additionalProperties', 'unevaluatedProperties', 'deprecated', 'required', 'allOf', 'anyOf', 'oneOf', '$ref']
	'type' is a required property
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml: ignoring, error in schema: properties: clocks
warning: no schema found in file: ./Documentation/devicetree/bindings/mfd/kendryte,k210-sysctl.yaml


See https://patchwork.ozlabs.org/patch/1396076

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 15:32     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:32 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Rob Herring, devicetree, linux-riscv, linux-spi, Stephen Boyd,
	linux-clk, Palmer Dabbelt, Frank Rowand, linux-gpio,
	Philipp Zabel, Serge Semin, Sean Anderson, Mark Brown,
	Linus Walleij

On Sat, 07 Nov 2020 17:14:12 +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clocks:minItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clocks:maxItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clock-names:minItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clock-names:maxItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: ignoring, error in schema: properties: clocks: minItems
warning: no schema found in file: ./Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.example.dts:19:18: fatal error: dt-bindings/pinctrl/k210-pinctrl.h: No such file or directory
   19 |         #include <dt-bindings/pinctrl/k210-pinctrl.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:342: Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1364: dt_binding_check] Error 2


See https://patchwork.ozlabs.org/patch/1396081

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-09 15:32     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:32 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, Serge Semin,
	linux-spi, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Sat, 07 Nov 2020 17:14:12 +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clocks:minItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clocks:maxItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clock-names:minItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: properties:clock-names:maxItems: False schema does not allow 2
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml: ignoring, error in schema: properties: clocks: minItems
warning: no schema found in file: ./Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.example.dts:19:18: fatal error: dt-bindings/pinctrl/k210-pinctrl.h: No such file or directory
   19 |         #include <dt-bindings/pinctrl/k210-pinctrl.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:342: Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1364: dt_binding_check] Error 2


See https://patchwork.ozlabs.org/patch/1396081

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 15:36     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:36 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> new file mode 100644
> index 000000000000..8730add88ee0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description:
> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> +  is performed on a per-pin basis.
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-fpioa
> +
> +  reg:
> +    description: FPIOA controller register space base address and size
> +
> +  clocks:
> +    minItems: 2
> +    maxItems: 2

Can drop these. Implied by 'items' length.

> +    items:
> +      - description: Controller reference clock source
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - const: ref
> +      - const: pclk
> +
> +  resets:
> +    maxItems: 1
> +
> +  kendryte,sysctl:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      phandle to the system controller node
> +
> +  kendryte,power-offset:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Offset of the power domain control register of the system controller.

Sounds like you should be using power-domains binding.

> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> +      dt-bindings/mfd/k210-sysctl.h.
> +
> +patternProperties:
> +  '^.*$':
> +    if:
> +      type: object
> +    then:

This is a hack for existing bindings. Use '-pins$' for the node names.

> +      patternProperties:
> +        "^pinmux$":

Not really a pattern.

> +          $ref: /schemas/pinctrl/pincfg-node.yaml

This is at the wrong level. Goes up 1 level.

> +          description:
> +            An array of IO pins alternate functions. The values for each
> +            IO pin is a combination of an IO pin number (0 to 47) with the
> +            desired function for the IO pin. Functions are defined as macros in
> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
> +            is provided to facilitate the combination of IO pin numbers and
> +            functions.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - kendryte,sysctl
> +  - kendryte,power-offset
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/clock/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-sysctl.h>
> +
> +    fpioa: pinmux@502B0000 {
> +      compatible = "kendryte,k210-fpioa";
> +      reg = <0x502B0000 0x100>;
> +      clocks = <&sysclk K210_CLK_FPIOA>;
> +      resets = <&sysrst K210_RST_FPIOA>;
> +      kendryte,sysctl = <&sysctl>;
> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +      pinctrl-0 = <&fpioa_jtag>;
> +      pinctrl-names = "default";
> +
> +      fpioa_jtag: jtag {
> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +      };
> +    };
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-09 15:36     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:36 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC Fully
> Programmable IO Array (FPIOA) pinctrl driver in
> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>  1 file changed, 106 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> new file mode 100644
> index 000000000000..8730add88ee0
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description:
> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> +  is performed on a per-pin basis.
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-fpioa
> +
> +  reg:
> +    description: FPIOA controller register space base address and size
> +
> +  clocks:
> +    minItems: 2
> +    maxItems: 2

Can drop these. Implied by 'items' length.

> +    items:
> +      - description: Controller reference clock source
> +      - description: APB interface clock source
> +
> +  clock-names:
> +    minItems: 2
> +    maxItems: 2
> +    items:
> +      - const: ref
> +      - const: pclk
> +
> +  resets:
> +    maxItems: 1
> +
> +  kendryte,sysctl:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> +    description: |
> +      phandle to the system controller node
> +
> +  kendryte,power-offset:
> +    minItems: 1
> +    maxItems: 1
> +    $ref: /schemas/types.yaml#/definitions/uint32
> +    description: |
> +      Offset of the power domain control register of the system controller.

Sounds like you should be using power-domains binding.

> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> +      dt-bindings/mfd/k210-sysctl.h.
> +
> +patternProperties:
> +  '^.*$':
> +    if:
> +      type: object
> +    then:

This is a hack for existing bindings. Use '-pins$' for the node names.

> +      patternProperties:
> +        "^pinmux$":

Not really a pattern.

> +          $ref: /schemas/pinctrl/pincfg-node.yaml

This is at the wrong level. Goes up 1 level.

> +          description:
> +            An array of IO pins alternate functions. The values for each
> +            IO pin is a combination of an IO pin number (0 to 47) with the
> +            desired function for the IO pin. Functions are defined as macros in
> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
> +            is provided to facilitate the combination of IO pin numbers and
> +            functions.
> +
> +required:
> +  - compatible
> +  - reg
> +  - clocks
> +  - resets
> +  - kendryte,sysctl
> +  - kendryte,power-offset
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/clock/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-sysctl.h>
> +
> +    fpioa: pinmux@502B0000 {
> +      compatible = "kendryte,k210-fpioa";
> +      reg = <0x502B0000 0x100>;
> +      clocks = <&sysclk K210_CLK_FPIOA>;
> +      resets = <&sysrst K210_RST_FPIOA>;
> +      kendryte,sysctl = <&sysctl>;
> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
> +      pinctrl-0 = <&fpioa_jtag>;
> +      pinctrl-names = "default";
> +
> +      fpioa_jtag: jtag {
> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
> +      };
> +    };
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 15:37     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:37 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Rob Herring, devicetree, Serge Semin, Sean Anderson,
	Linus Walleij, Philipp Zabel, Frank Rowand, Palmer Dabbelt,
	linux-clk, linux-riscv, linux-gpio, Mark Brown, Stephen Boyd,
	linux-spi

On Sat, 07 Nov 2020 17:14:13 +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml:24:9: [warning] wrong indentation: expected 10 but found 8 (indentation)

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/reset/kendryte,k210-rst.example.dts:19:18: fatal error: dt-bindings/mfd/k210-sysctl.h: No such file or directory
   19 |         #include <dt-bindings/mfd/k210-sysctl.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:342: Documentation/devicetree/bindings/reset/kendryte,k210-rst.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1364: dt_binding_check] Error 2


See https://patchwork.ozlabs.org/patch/1396082

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
@ 2020-11-09 15:37     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:37 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Mark Brown, Philipp Zabel, linux-riscv, linux-spi, Frank Rowand,
	linux-clk

On Sat, 07 Nov 2020 17:14:13 +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 


My bot found errors running 'make dt_binding_check' on your patch:

yamllint warnings/errors:
./Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml:24:9: [warning] wrong indentation: expected 10 but found 8 (indentation)

dtschema/dtc warnings/errors:
Documentation/devicetree/bindings/reset/kendryte,k210-rst.example.dts:19:18: fatal error: dt-bindings/mfd/k210-sysctl.h: No such file or directory
   19 |         #include <dt-bindings/mfd/k210-sysctl.h>
      |                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[1]: *** [scripts/Makefile.lib:342: Documentation/devicetree/bindings/reset/kendryte,k210-rst.example.dt.yaml] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1364: dt_binding_check] Error 2


See https://patchwork.ozlabs.org/patch/1396082

The base for the patch is generally the last rc1. Any dependencies
should be noted.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 15:41     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:41 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:14:13PM +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> new file mode 100644
> index 000000000000..bdd0bf37bdfb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 reset controller driver which support the system controller
> +  subsystem supplied reset registers for the various peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/reset/k210-rst.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-rst

> +        - const: syscon-reset

This is not a generic thing.

> +
> +  regmap:
> +    maxItems: 1
> +    description: phandle of the system controller (sysctl) node
> +
> +  offset:
> +    maxItems: 1
> +    description: peripheral reset register offset in the system controller
> +      controller register map
> +
> +  mask:
> +    maxItems: 1
> +    description: bit-mask indicating valid reset bits in the reset register

You don't need this. Just don't use invalid cell values.

> +
> +  assert-high:
> +    maxItems: 1
> +    description: bit value to write when asserting a reset

Should be implied by the compatible string.

> +
> +  '#reset-cells':
> +    const: 1
> +
> +required:
> +  - '#reset-cells'
> +  - compatible
> +  - regmap
> +  - offset
> +  - mask
> +  - assert-high
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-rst.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      /* ... */
> +      sysrst: reset-controller {
> +        compatible = "kendryte,k210-rst",
> +                      "syscon-reset";
> +        #reset-cells = <1>;
> +        regmap = <&sysctl>;

That's just the parent node, you don't need this.

> +        offset = <K210_SYSCTL_PERI_RESET>;

Use 'reg'.

> +        mask = <0x27FFFFFF>;
> +        assert-high = <1>;
> +      };
> +    };
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings
@ 2020-11-09 15:41     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 15:41 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:14:13PM +0900, Damien Le Moal wrote:
> Document the device tree bindings for the Kendryte K210 SoC reset
> controller driver in
> Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/reset/kendryte,k210-rst.yaml     | 78 +++++++++++++++++++
>  1 file changed, 78 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> 
> diff --git a/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> new file mode 100644
> index 000000000000..bdd0bf37bdfb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/reset/kendryte,k210-rst.yaml
> @@ -0,0 +1,78 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/reset/kendryte,k210-rst.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Reset Controller Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 reset controller driver which support the system controller
> +  subsystem supplied reset registers for the various peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/reset/k210-rst.h
> +
> +properties:
> +  compatible:
> +    allOf:
> +      - items:
> +        - const: kendryte,k210-rst

> +        - const: syscon-reset

This is not a generic thing.

> +
> +  regmap:
> +    maxItems: 1
> +    description: phandle of the system controller (sysctl) node
> +
> +  offset:
> +    maxItems: 1
> +    description: peripheral reset register offset in the system controller
> +      controller register map
> +
> +  mask:
> +    maxItems: 1
> +    description: bit-mask indicating valid reset bits in the reset register

You don't need this. Just don't use invalid cell values.

> +
> +  assert-high:
> +    maxItems: 1
> +    description: bit value to write when asserting a reset

Should be implied by the compatible string.

> +
> +  '#reset-cells':
> +    const: 1
> +
> +required:
> +  - '#reset-cells'
> +  - compatible
> +  - regmap
> +  - offset
> +  - mask
> +  - assert-high
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/mfd/k210-sysctl.h>
> +    #include <dt-bindings/reset/k210-rst.h>
> +
> +    sysctl: system-controller@50440000 {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      compatible = "kendryte,k210-sysctl",
> +                   "syscon", "simple-mfd";
> +      reg = <0x50440000 0x1000>;
> +      /* ... */
> +      sysrst: reset-controller {
> +        compatible = "kendryte,k210-rst",
> +                      "syscon-reset";
> +        #reset-cells = <1>;
> +        regmap = <&sysctl>;

That's just the parent node, you don't need this.

> +        offset = <K210_SYSCTL_PERI_RESET>;

Use 'reg'.

> +        mask = <0x27FFFFFF>;
> +        assert-high = <1>;
> +      };
> +    };
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-09 15:36     ` Rob Herring
@ 2020-11-09 15:45       ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 15:45 UTC (permalink / raw)
  To: Rob Herring, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 10:36 AM, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>> Document the device tree bindings for the Kendryte K210 SoC Fully
>> Programmable IO Array (FPIOA) pinctrl driver in
>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>>  1 file changed, 106 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>> new file mode 100644
>> index 000000000000..8730add88ee0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>> @@ -0,0 +1,106 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
>> +
>> +maintainers:
>> +  - Damien Le Moal <damien.lemoal@wdc.com>
>> +
>> +description:
>> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
>> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
>> +  is performed on a per-pin basis.
>> +
>> +properties:
>> +  compatible:
>> +    const: kendryte,k210-fpioa
>> +
>> +  reg:
>> +    description: FPIOA controller register space base address and size
>> +
>> +  clocks:
>> +    minItems: 2
>> +    maxItems: 2
> 
> Can drop these. Implied by 'items' length.
> 
>> +    items:
>> +      - description: Controller reference clock source
>> +      - description: APB interface clock source
>> +
>> +  clock-names:
>> +    minItems: 2
>> +    maxItems: 2
>> +    items:
>> +      - const: ref
>> +      - const: pclk
>> +
>> +  resets:
>> +    maxItems: 1
>> +
>> +  kendryte,sysctl:
>> +    minItems: 1
>> +    maxItems: 1
>> +    $ref: /schemas/types.yaml#/definitions/phandle-array
>> +    description: |
>> +      phandle to the system controller node
>> +
>> +  kendryte,power-offset:
>> +    minItems: 1
>> +    maxItems: 1
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    description: |
>> +      Offset of the power domain control register of the system controller.
> 
> Sounds like you should be using power-domains binding.

This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

--Sean

> 
>> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
>> +      dt-bindings/mfd/k210-sysctl.h.
>> +
>> +patternProperties:
>> +  '^.*$':
>> +    if:
>> +      type: object
>> +    then:
> 
> This is a hack for existing bindings. Use '-pins$' for the node names.
> 
>> +      patternProperties:
>> +        "^pinmux$":
> 
> Not really a pattern.
> 
>> +          $ref: /schemas/pinctrl/pincfg-node.yaml
> 
> This is at the wrong level. Goes up 1 level.
> 
>> +          description:
>> +            An array of IO pins alternate functions. The values for each
>> +            IO pin is a combination of an IO pin number (0 to 47) with the
>> +            desired function for the IO pin. Functions are defined as macros in
>> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
>> +            is provided to facilitate the combination of IO pin numbers and
>> +            functions.
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - clocks
>> +  - resets
>> +  - kendryte,sysctl
>> +  - kendryte,power-offset
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
>> +    #include <dt-bindings/mfd/k210-sysctl.h>
>> +    #include <dt-bindings/clock/k210-sysctl.h>
>> +    #include <dt-bindings/reset/k210-sysctl.h>
>> +
>> +    fpioa: pinmux@502B0000 {
>> +      compatible = "kendryte,k210-fpioa";
>> +      reg = <0x502B0000 0x100>;
>> +      clocks = <&sysclk K210_CLK_FPIOA>;
>> +      resets = <&sysrst K210_RST_FPIOA>;
>> +      kendryte,sysctl = <&sysctl>;
>> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
>> +      pinctrl-0 = <&fpioa_jtag>;
>> +      pinctrl-names = "default";
>> +
>> +      fpioa_jtag: jtag {
>> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
>> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
>> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
>> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
>> +      };
>> +    };
>> -- 
>> 2.28.0
>>


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-09 15:45       ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 15:45 UTC (permalink / raw)
  To: Rob Herring, Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Frank Rowand, linux-clk

On 11/9/20 10:36 AM, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>> Document the device tree bindings for the Kendryte K210 SoC Fully
>> Programmable IO Array (FPIOA) pinctrl driver in
>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>>  1 file changed, 106 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>> new file mode 100644
>> index 000000000000..8730add88ee0
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>> @@ -0,0 +1,106 @@
>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>> +%YAML 1.2
>> +---
>> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>> +
>> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
>> +
>> +maintainers:
>> +  - Damien Le Moal <damien.lemoal@wdc.com>
>> +
>> +description:
>> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
>> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
>> +  is performed on a per-pin basis.
>> +
>> +properties:
>> +  compatible:
>> +    const: kendryte,k210-fpioa
>> +
>> +  reg:
>> +    description: FPIOA controller register space base address and size
>> +
>> +  clocks:
>> +    minItems: 2
>> +    maxItems: 2
> 
> Can drop these. Implied by 'items' length.
> 
>> +    items:
>> +      - description: Controller reference clock source
>> +      - description: APB interface clock source
>> +
>> +  clock-names:
>> +    minItems: 2
>> +    maxItems: 2
>> +    items:
>> +      - const: ref
>> +      - const: pclk
>> +
>> +  resets:
>> +    maxItems: 1
>> +
>> +  kendryte,sysctl:
>> +    minItems: 1
>> +    maxItems: 1
>> +    $ref: /schemas/types.yaml#/definitions/phandle-array
>> +    description: |
>> +      phandle to the system controller node
>> +
>> +  kendryte,power-offset:
>> +    minItems: 1
>> +    maxItems: 1
>> +    $ref: /schemas/types.yaml#/definitions/uint32
>> +    description: |
>> +      Offset of the power domain control register of the system controller.
> 
> Sounds like you should be using power-domains binding.

This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

--Sean

> 
>> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
>> +      dt-bindings/mfd/k210-sysctl.h.
>> +
>> +patternProperties:
>> +  '^.*$':
>> +    if:
>> +      type: object
>> +    then:
> 
> This is a hack for existing bindings. Use '-pins$' for the node names.
> 
>> +      patternProperties:
>> +        "^pinmux$":
> 
> Not really a pattern.
> 
>> +          $ref: /schemas/pinctrl/pincfg-node.yaml
> 
> This is at the wrong level. Goes up 1 level.
> 
>> +          description:
>> +            An array of IO pins alternate functions. The values for each
>> +            IO pin is a combination of an IO pin number (0 to 47) with the
>> +            desired function for the IO pin. Functions are defined as macros in
>> +            dt-bindings/pinctrl/k210-pinctrl.h. The K210_FPIOA(IO pin, function)
>> +            is provided to facilitate the combination of IO pin numbers and
>> +            functions.
>> +
>> +required:
>> +  - compatible
>> +  - reg
>> +  - clocks
>> +  - resets
>> +  - kendryte,sysctl
>> +  - kendryte,power-offset
>> +
>> +additionalProperties: false
>> +
>> +examples:
>> +  - |
>> +    #include <dt-bindings/pinctrl/k210-pinctrl.h>
>> +    #include <dt-bindings/mfd/k210-sysctl.h>
>> +    #include <dt-bindings/clock/k210-sysctl.h>
>> +    #include <dt-bindings/reset/k210-sysctl.h>
>> +
>> +    fpioa: pinmux@502B0000 {
>> +      compatible = "kendryte,k210-fpioa";
>> +      reg = <0x502B0000 0x100>;
>> +      clocks = <&sysclk K210_CLK_FPIOA>;
>> +      resets = <&sysrst K210_RST_FPIOA>;
>> +      kendryte,sysctl = <&sysctl>;
>> +      kendryte,power-offset = <K210_SYSCTL_POWER_SEL>;
>> +      pinctrl-0 = <&fpioa_jtag>;
>> +      pinctrl-names = "default";
>> +
>> +      fpioa_jtag: jtag {
>> +        pinmux = <K210_FPIOA(0, K210_PCF_JTAG_TCLK)>,
>> +                 <K210_FPIOA(1, K210_PCF_JTAG_TDI)>,
>> +                 <K210_FPIOA(2, K210_PCF_JTAG_TMS)>,
>> +                 <K210_FPIOA(3, K210_PCF_JTAG_TDO)>;
>> +      };
>> +    };
>> -- 
>> 2.28.0
>>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 16:04     ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 16:04 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

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

On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:

> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi, using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed). Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:

This isn't something that looks like it should be configured via DT as a
separate property, this is more of a tuning property as far as I can see
- even on the same hardware there might be cases where people prefer to
keep using interrupts but for example allow transfers to stall while
waiting for the interrupt controller giving lower throughput but more
CPU cycles available for other things.

Unfortunately we don't have any information about how much interrupt
latency we should expect which makes this a bit annoying.  I do see that
there's already some existing attempt in the DMA code to tune burst
sizes to avoid FIFO overflows - it looks like the hardware is doing
something unusual and possibly unfortunate here though I've never
looked at it so I'm not sure exactly what is going on there but perhaps
ther's some tuning that can be done in there?  TBH I'm not clear what
the failure mode is where we need software to service interrupts
promptly in the middle of a DMA transfer in the first place, that seems
really strange.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-09 16:04     ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 16:04 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 1705 bytes --]

On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:

> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi, using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed). Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:

This isn't something that looks like it should be configured via DT as a
separate property, this is more of a tuning property as far as I can see
- even on the same hardware there might be cases where people prefer to
keep using interrupts but for example allow transfers to stall while
waiting for the interrupt controller giving lower throughput but more
CPU cycles available for other things.

Unfortunately we don't have any information about how much interrupt
latency we should expect which makes this a bit annoying.  I do see that
there's already some existing attempt in the DMA code to tune burst
sizes to avoid FIFO overflows - it looks like the hardware is doing
something unusual and possibly unfortunate here though I've never
looked at it so I'm not sure exactly what is going on there but perhaps
ther's some tuning that can be done in there?  TBH I'm not clear what
the failure mode is where we need software to service interrupts
promptly in the middle of a DMA transfer in the first place, that seems
really strange.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 14:48           ` Serge Semin
@ 2020-11-09 16:45             ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 16:45 UTC (permalink / raw)
  To: Serge Semin
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Mon, Nov 09, 2020 at 05:48:08PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> > On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:

> > > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > > it should be.

> > I'd expect it'd perform better, especially on systems that are
> > apparently struggling for CPU bandwidth like yours seems to.

> Well, it might seem a good idea to use that mode, but there are multiple problems
> you may get in implementing it.

> First of all the Receive-only mode is having a limited number bytes to receive
> at once. It's just 64KB. So in order to implement it you'd need to split the
> bigger transfers up, and feed the DMA engine with smaller chunks one-by-one.

That at least is handlable, even if it's only by falling back to
transmitting when the data grows over 64K.

> Secondly the Receive-only mode will make the DW SSI controller to constantly receive
> the data from the SPI bus and to put it into the Rx FIFO. So your DMA engine will
> have to keep up with extracting the data from there on time, otherwise you'll
> end up with Rx FIFO overflow error eventually. The problem will be actual for the
> DMA engines/system buses, which are slower than the SPI bus speed, second for the
> DMA engines with no hardware accelerated LLP traversal support (like on our DWC DMA
> controller). The second problem can be also fixed by splitting the transfers up as
> it has been already implemented in the spi-dw-dma.c. But the first problem can't be
> fixed, but just workarounded by limiting the SPI bus frequency so the DMA engine
> would keep up with incoming data traffic.

I'd have expected that a single duplex mode would lessen the pressure on
at least the system bus - that's the main advantage, and might help the
DMA controllers as well depending on why they might be struggling.  From
the comments in the code there's issues on some systems with TX and RX
running at different rates which would go away in single duplex cases if
nothing else.  But yeah, it's not going to just fix everything.

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 16:45             ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 16:45 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 2297 bytes --]

On Mon, Nov 09, 2020 at 05:48:08PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> > On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:

> > > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > > it should be.

> > I'd expect it'd perform better, especially on systems that are
> > apparently struggling for CPU bandwidth like yours seems to.

> Well, it might seem a good idea to use that mode, but there are multiple problems
> you may get in implementing it.

> First of all the Receive-only mode is having a limited number bytes to receive
> at once. It's just 64KB. So in order to implement it you'd need to split the
> bigger transfers up, and feed the DMA engine with smaller chunks one-by-one.

That at least is handlable, even if it's only by falling back to
transmitting when the data grows over 64K.

> Secondly the Receive-only mode will make the DW SSI controller to constantly receive
> the data from the SPI bus and to put it into the Rx FIFO. So your DMA engine will
> have to keep up with extracting the data from there on time, otherwise you'll
> end up with Rx FIFO overflow error eventually. The problem will be actual for the
> DMA engines/system buses, which are slower than the SPI bus speed, second for the
> DMA engines with no hardware accelerated LLP traversal support (like on our DWC DMA
> controller). The second problem can be also fixed by splitting the transfers up as
> it has been already implemented in the spi-dw-dma.c. But the first problem can't be
> fixed, but just workarounded by limiting the SPI bus frequency so the DMA engine
> would keep up with incoming data traffic.

I'd have expected that a single duplex mode would lessen the pressure on
at least the system bus - that's the main advantage, and might help the
DMA controllers as well depending on why they might be struggling.  From
the comments in the code there's issues on some systems with TX and RX
running at different rates which would go away in single duplex cases if
nothing else.  But yeah, it's not going to just fix everything.

Please fix your mail client to word wrap within paragraphs at something
substantially less than 80 columns.  Doing this makes your messages much
easier to read and reply to.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-09 15:14     ` Andy Shevchenko
@ 2020-11-09 17:44       ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 17:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel, Sean Anderson

Hello Andy,

On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
> > @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> >  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> >  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> >  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> > -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> 
> Sorry, but the above doesn't sound right to me.
> It's a generic code and you may imagine how many systems you broke by
> this change.

Damien replaced the macro above with the code below (your removed it from your
message):

+static struct device_node *parse_gpios(struct device_node *np,
+                                      const char *prop_name, int index)
+{
+       /*
+        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
+        * the "snps,nr-gpios" property to indicate the total number of GPIOs
+        * available. As this conflict with "xx-gpios" reference properties,
+        * ignore it.
+        */
+       if (strcmp(prop_name, "snps,nr-gpios") == 0)
+               return NULL;
+
+       return parse_suffix_prop_cells(np, prop_name, index,
+                                      "-gpios", "#gpio-cells");
+}

So AFAICS removing the macro shouldn't cause any problem.

My concern was whether the quirk has been really needed. As I said the
"snps,nr-gpios" property has been marked as deprecated in favor of the standard
"ngpios" one. Due to the problem noted by Damien any deprecated property
utilization will cause the DW APB SSI DT-nodes probe malfunction. That
though implicitly but is supposed to encourage people to provide fixes for
the dts-files with the deprecated property replaced with "ngpios".

On the other hand an encouragement based on breaking the kernel doesn't seem a
good solution. So as I see it either we should accept the solution provided by
Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
DT-node defined. I suggest to hear the OF-subsystem maintainers out what
solution would they prefer.

-Sergey

> 
> -- 
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-09 17:44       ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 17:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk, Linus Walleij

Hello Andy,

On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
> > @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> >  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> >  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> >  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> > -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> 
> Sorry, but the above doesn't sound right to me.
> It's a generic code and you may imagine how many systems you broke by
> this change.

Damien replaced the macro above with the code below (your removed it from your
message):

+static struct device_node *parse_gpios(struct device_node *np,
+                                      const char *prop_name, int index)
+{
+       /*
+        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
+        * the "snps,nr-gpios" property to indicate the total number of GPIOs
+        * available. As this conflict with "xx-gpios" reference properties,
+        * ignore it.
+        */
+       if (strcmp(prop_name, "snps,nr-gpios") == 0)
+               return NULL;
+
+       return parse_suffix_prop_cells(np, prop_name, index,
+                                      "-gpios", "#gpio-cells");
+}

So AFAICS removing the macro shouldn't cause any problem.

My concern was whether the quirk has been really needed. As I said the
"snps,nr-gpios" property has been marked as deprecated in favor of the standard
"ngpios" one. Due to the problem noted by Damien any deprecated property
utilization will cause the DW APB SSI DT-nodes probe malfunction. That
though implicitly but is supposed to encourage people to provide fixes for
the dts-files with the deprecated property replaced with "ngpios".

On the other hand an encouragement based on breaking the kernel doesn't seem a
good solution. So as I see it either we should accept the solution provided by
Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
DT-node defined. I suggest to hear the OF-subsystem maintainers out what
solution would they prefer.

-Sergey

> 
> -- 
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
  2020-11-09 14:36       ` Andy Shevchenko
@ 2020-11-09 17:56         ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 17:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel, Sean Anderson

Hello Andy,

On Mon, Nov 09, 2020 at 04:36:51PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 9, 2020 at 4:25 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > Hello Damien,
> > Thanks for your patches. My comments are below.
> >
> > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> > > Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> > > the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> > >
> > > |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> > > | other stuff | spi_frf  |  dfs_32  |
> > >
> > > |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> > > | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> > >
> >
> > > Th main difference of this layout with the 16-bits version is the data
> >     ^
> >     |
> >     e
> >
> > > frame format field which resides in bits 16..20 instead of bits 3..0.
> > >
> >
> > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > manual for the 4.0x version of the core, but according to this patch:
> > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > message misleading there?
> 

> 20:16 DFS_32
> Data Frame Size in 32-bit transfer size mode. Used to select
> the data frame size in 32-bit transfer mode. These bits are
> only valid when SSI_MAX_XFER_SIZE is configured to 32.
> When the data frame size is programmed to be less than 32
> bits, the receive data are automatically right-justified by the
> receive logic, with the upper bits of the receive FIFO zero-
> padded.
> 
> 3:0 DFS
> Data Frame Size.
> This register field is only valid when SSI_MAX_XFER_SIZE
> is configured to 16. If SSI_MAX_XFER_SIZE is configured to
> 32, then writing to this field will not have any effect.
> 
> As far as I can tell it's an extension to the existing one (which one
> in use depends on the SSI configuration).
> 
> 
> The comment you are referring to is about DW_ssi v1.x (vs. DW_apb_ssi v4.x).

Ok. Thanks for clarifying this. Now I see the way it's working.

-Sergey

> 
> 
> -- 
> With Best Regards,
> Andy Shevchenko

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout
@ 2020-11-09 17:56         ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 17:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Mark Brown, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk, Linus Walleij

Hello Andy,

On Mon, Nov 09, 2020 at 04:36:51PM +0200, Andy Shevchenko wrote:
> On Mon, Nov 9, 2020 at 4:25 PM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > Hello Damien,
> > Thanks for your patches. My comments are below.
> >
> > On Sat, Nov 07, 2020 at 05:13:50PM +0900, Damien Le Moal wrote:
> > > Synopsis DesignWare DW_apb_ssi version 4 defines a 32-bit layout of
> > > the ctrlr0 register for SPI masters. The layout of ctrlr0 is:
> > >
> > > |   31 .. 23  | 22 .. 21 | 20 .. 16 |
> > > | other stuff | spi_frf  |  dfs_32  |
> > >
> > > |   15 .. 10  | 9 .. 8 | 7 .. 6 | 5 .. 4 | 3 .. 0 |
> > > | other stuff |  tmod  |  mode  |  frf   |  dfs   |
> > >
> >
> > > Th main difference of this layout with the 16-bits version is the data
> >     ^
> >     |
> >     e
> >
> > > frame format field which resides in bits 16..20 instead of bits 3..0.
> > >
> >
> > Are you sure they have been moved from [0, 3] to [16, 20]? I don't have the
> > manual for the 4.0x version of the core, but according to this patch:
> > https://patchwork.kernel.org/project/spi-devel-general/patch/1575907443-26377-7-git-send-email-wan.ahmad.zainie.wan.mohamad@intel.com/
> > it has been ok to use the lowest four bits for DFS setting. Is the commit
> > message misleading there?
> 

> 20:16 DFS_32
> Data Frame Size in 32-bit transfer size mode. Used to select
> the data frame size in 32-bit transfer mode. These bits are
> only valid when SSI_MAX_XFER_SIZE is configured to 32.
> When the data frame size is programmed to be less than 32
> bits, the receive data are automatically right-justified by the
> receive logic, with the upper bits of the receive FIFO zero-
> padded.
> 
> 3:0 DFS
> Data Frame Size.
> This register field is only valid when SSI_MAX_XFER_SIZE
> is configured to 16. If SSI_MAX_XFER_SIZE is configured to
> 32, then writing to this field will not have any effect.
> 
> As far as I can tell it's an extension to the existing one (which one
> in use depends on the SSI configuration).
> 
> 
> The comment you are referring to is about DW_ssi v1.x (vs. DW_apb_ssi v4.x).

Ok. Thanks for clarifying this. Now I see the way it's working.

-Sergey

> 
> 
> -- 
> With Best Regards,
> Andy Shevchenko

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-07  8:14   ` Damien Le Moal
  (?)
@ 2020-11-09 18:48     ` kernel test robot
  -1 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-09 18:48 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: kbuild-all

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next linus/master v5.10-rc3 next-20201109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-nommu_k210_defconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
     848 | int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 9115 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-09 18:48     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-09 18:48 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: kbuild-all

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next linus/master v5.10-rc3 next-20201109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-nommu_k210_defconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
     848 | int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 9115 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-09 18:48     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-09 18:48 UTC (permalink / raw)
  To: kbuild-all

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next linus/master v5.10-rc3 next-20201109]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-nommu_k210_defconfig (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
     848 | int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
         |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 9115 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 14:14         ` Mark Brown
@ 2020-11-09 19:19           ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 19:19 UTC (permalink / raw)
  To: Mark Brown
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> > On 11/9/20 8:29 AM, Mark Brown wrote:
> > > On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> > > 

> > >> The resting state of MOSI is high when nothing is driving it. If we
> > >> drive it low while recieving, it looks like we are transmitting 0x00
> > >> instead of transmitting nothing. This can confuse slaves (like SD cards)
> > >> which allow new commands to be sent over MOSI while they are returning
> > >> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> > >> a byte can look like a start bit and a transmission bit to an SD card.

Yeah, that's what we've also experienced on our systems. We've worked
around the problem in exactly the same way as you have. But we haven't
dared to send it out as the solution seemed a bit hackish.

> > > 
> > > If client devices are interpreting the transmitted data then I would
> > > expect the drivers for that hardware to be ensuring that whatever we
> > > transmit matches what the device is expecting.  We shouldn't be putting
> > > a hack in a particular controller driver to paper over things, that will
> > > mean that the device will break when used with other controllers and if
> > > different devices have different requirements then obviously we can't
> > > satisfy them.  There is not meaningfully a general specification for SPI
> > > which says what happens when signals are idle, it's all specific to the
> > > client device.
> > > 
> > > In this case it also looks like the controller hardware requires
> > > transmit data and therefore should be setting SPI_MUST_TX and just
> > > removing the in driver default anyway, though that will have no effect
> > > one way or anther on the issue you're seeing.
> 

> > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > it should be.
> 
> I'd expect it'd perform better, especially on systems that are
> apparently struggling for CPU bandwidth like yours seems to.

CPU-wise. RO-mode won't help in that case. Moreover it will be even
more errors-prone for the systems with small CPU bandwidth. As I said
the Receive-only mode will make the SPI controller automatically
receiving data from the SPI bus and putting it into the Rx FIFO. If
CPU is either busy with something else or too slow in fetching the
data from the Rx FIFO, the FIFO will be eventually overflown with
data, which we need to avoid at all cost.

As I see it the Receive-only mode is only acceptable in the next two
situations:

1) Rx-only DMA. But only if the DMA-engine and system bus are fast
enough to fetch the incoming data on time. (Note for example in our
system some DWC DMA-engine channels don't work well with the DW APB
SSI working with full-speed, so we had to set constraints on the DWC
DMA channels being used in conjunction with the DW APB SSI
controller.)

2) Rx-only with atomic CPU utilization. In order to make sure that the
CPU keeps up with fetching the data from the Rx FIFO, we have to
disable the local CPU IRQs while performing the Rx-only transfers, so
to prevent the Rx FIFO overflow while the CPU is doing something else.
Needless to say that such approach should be utilized only as a last
resort, if we have no choice but to run the Receive-only transfers.
Because locking the CPU for God knows how much time may cause the
system interactivity degradation. For instance, a possible use-case of
that design is when the controller is communicating with the
SPI-devices with native DW APB SSI chip-select attached. BTW You can
also find that design implemented in the kernel 5.10 spi-dw-core.c
driver in context of the SPI-memory operations (with my last patches
merged in). In particular I had to use it to handle the CPU-based
EEPROM-read mode.

So in all other cases for normal CPU-based SPI-transfers when
GPIO-based chip-select is available the safest solution would be to
use a normal Push-Pull mode. In this case we have no risk in getting
the Rx FIFO overflow unless there is a bug in the code, which is
fixable anyway.

Getting back to the patch. In fact I don't really see how the
Receive-only mode will help us with solving the problem noted in the
patch log. As Mark said the problem with the Tx data on Rx-only
transfers should be fixed on the client side. If an subordinate
SPI-device needs a specific value to be received in that case, then
that value should be somehow provided to the SPI-controller anyway.
So the native Rx-only mode of the DW APB SSI controller won't help.
Currently it's possible to be done only by executing a Full-duplex
SPI-transfer with the Tx-buffer being pre-initialized with that
value.

Another possible solution for the problem would be to fix the SPI core
so aside with tx_buf being set to the NULL-pointer, a client driver
would provide a default level or some specific value being put to the
SPI bus on Rx-only transfers. If an SPI-controller is capable of
satisfying the request, then it will accept the transfer. If it's not,
then the SPI core may try to convert the Rx-only transfer into the
Full-duplex transfer with the Tx-buffer being initialized with the
requested level.

-Sergey

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 19:19           ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 19:19 UTC (permalink / raw)
  To: Mark Brown
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk

On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> > On 11/9/20 8:29 AM, Mark Brown wrote:
> > > On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> > > 

> > >> The resting state of MOSI is high when nothing is driving it. If we
> > >> drive it low while recieving, it looks like we are transmitting 0x00
> > >> instead of transmitting nothing. This can confuse slaves (like SD cards)
> > >> which allow new commands to be sent over MOSI while they are returning
> > >> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> > >> a byte can look like a start bit and a transmission bit to an SD card.

Yeah, that's what we've also experienced on our systems. We've worked
around the problem in exactly the same way as you have. But we haven't
dared to send it out as the solution seemed a bit hackish.

> > > 
> > > If client devices are interpreting the transmitted data then I would
> > > expect the drivers for that hardware to be ensuring that whatever we
> > > transmit matches what the device is expecting.  We shouldn't be putting
> > > a hack in a particular controller driver to paper over things, that will
> > > mean that the device will break when used with other controllers and if
> > > different devices have different requirements then obviously we can't
> > > satisfy them.  There is not meaningfully a general specification for SPI
> > > which says what happens when signals are idle, it's all specific to the
> > > client device.
> > > 
> > > In this case it also looks like the controller hardware requires
> > > transmit data and therefore should be setting SPI_MUST_TX and just
> > > removing the in driver default anyway, though that will have no effect
> > > one way or anther on the issue you're seeing.
> 

> > There is a recieve-only mode, but it is not used by this driver. Perhaps
> > it should be.
> 
> I'd expect it'd perform better, especially on systems that are
> apparently struggling for CPU bandwidth like yours seems to.

CPU-wise. RO-mode won't help in that case. Moreover it will be even
more errors-prone for the systems with small CPU bandwidth. As I said
the Receive-only mode will make the SPI controller automatically
receiving data from the SPI bus and putting it into the Rx FIFO. If
CPU is either busy with something else or too slow in fetching the
data from the Rx FIFO, the FIFO will be eventually overflown with
data, which we need to avoid at all cost.

As I see it the Receive-only mode is only acceptable in the next two
situations:

1) Rx-only DMA. But only if the DMA-engine and system bus are fast
enough to fetch the incoming data on time. (Note for example in our
system some DWC DMA-engine channels don't work well with the DW APB
SSI working with full-speed, so we had to set constraints on the DWC
DMA channels being used in conjunction with the DW APB SSI
controller.)

2) Rx-only with atomic CPU utilization. In order to make sure that the
CPU keeps up with fetching the data from the Rx FIFO, we have to
disable the local CPU IRQs while performing the Rx-only transfers, so
to prevent the Rx FIFO overflow while the CPU is doing something else.
Needless to say that such approach should be utilized only as a last
resort, if we have no choice but to run the Receive-only transfers.
Because locking the CPU for God knows how much time may cause the
system interactivity degradation. For instance, a possible use-case of
that design is when the controller is communicating with the
SPI-devices with native DW APB SSI chip-select attached. BTW You can
also find that design implemented in the kernel 5.10 spi-dw-core.c
driver in context of the SPI-memory operations (with my last patches
merged in). In particular I had to use it to handle the CPU-based
EEPROM-read mode.

So in all other cases for normal CPU-based SPI-transfers when
GPIO-based chip-select is available the safest solution would be to
use a normal Push-Pull mode. In this case we have no risk in getting
the Rx FIFO overflow unless there is a bug in the code, which is
fixable anyway.

Getting back to the patch. In fact I don't really see how the
Receive-only mode will help us with solving the problem noted in the
patch log. As Mark said the problem with the Tx data on Rx-only
transfers should be fixed on the client side. If an subordinate
SPI-device needs a specific value to be received in that case, then
that value should be somehow provided to the SPI-controller anyway.
So the native Rx-only mode of the DW APB SSI controller won't help.
Currently it's possible to be done only by executing a Full-duplex
SPI-transfer with the Tx-buffer being pre-initialized with that
value.

Another possible solution for the problem would be to fix the SPI core
so aside with tx_buf being set to the NULL-pointer, a client driver
would provide a default level or some specific value being put to the
SPI bus on Rx-only transfers. If an SPI-controller is capable of
satisfying the request, then it will accept the transfer. If it's not,
then the SPI core may try to convert the Rx-only transfer into the
Full-duplex transfer with the Tx-buffer being initialized with the
requested level.

-Sergey

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 19:19           ` Serge Semin
@ 2020-11-09 19:40             ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 19:40 UTC (permalink / raw)
  To: Serge Semin, Mark Brown
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 2:19 PM, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
>> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
>>> On 11/9/20 8:29 AM, Mark Brown wrote:
>>>> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
>>>>
> 
>>>>> The resting state of MOSI is high when nothing is driving it. If we
>>>>> drive it low while recieving, it looks like we are transmitting 0x00
>>>>> instead of transmitting nothing. This can confuse slaves (like SD cards)
>>>>> which allow new commands to be sent over MOSI while they are returning
>>>>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
>>>>> a byte can look like a start bit and a transmission bit to an SD card.
> 
> Yeah, that's what we've also experienced on our systems. We've worked
> around the problem in exactly the same way as you have. But we haven't
> dared to send it out as the solution seemed a bit hackish.

Well, the way it is now is equally wrong, since it is driving the line
low.

>>>>
>>>> If client devices are interpreting the transmitted data then I would
>>>> expect the drivers for that hardware to be ensuring that whatever we
>>>> transmit matches what the device is expecting.  We shouldn't be putting
>>>> a hack in a particular controller driver to paper over things, that will
>>>> mean that the device will break when used with other controllers and if
>>>> different devices have different requirements then obviously we can't
>>>> satisfy them.  There is not meaningfully a general specification for SPI
>>>> which says what happens when signals are idle, it's all specific to the
>>>> client device.
>>>>
>>>> In this case it also looks like the controller hardware requires
>>>> transmit data and therefore should be setting SPI_MUST_TX and just
>>>> removing the in driver default anyway, though that will have no effect
>>>> one way or anther on the issue you're seeing.
>>
> 
>>> There is a recieve-only mode, but it is not used by this driver. Perhaps
>>> it should be.
>>
>> I'd expect it'd perform better, especially on systems that are
>> apparently struggling for CPU bandwidth like yours seems to.
> 
> CPU-wise. RO-mode won't help in that case. Moreover it will be even
> more errors-prone for the systems with small CPU bandwidth. As I said
> the Receive-only mode will make the SPI controller automatically
> receiving data from the SPI bus and putting it into the Rx FIFO. If
> CPU is either busy with something else or too slow in fetching the
> data from the Rx FIFO, the FIFO will be eventually overflown with
> data, which we need to avoid at all cost.
> 
> As I see it the Receive-only mode is only acceptable in the next two
> situations:
> 
> 1) Rx-only DMA. But only if the DMA-engine and system bus are fast
> enough to fetch the incoming data on time. (Note for example in our
> system some DWC DMA-engine channels don't work well with the DW APB
> SSI working with full-speed, so we had to set constraints on the DWC
> DMA channels being used in conjunction with the DW APB SSI
> controller.)
> 
> 2) Rx-only with atomic CPU utilization. In order to make sure that the
> CPU keeps up with fetching the data from the Rx FIFO, we have to
> disable the local CPU IRQs while performing the Rx-only transfers, so
> to prevent the Rx FIFO overflow while the CPU is doing something else.
> Needless to say that such approach should be utilized only as a last
> resort, if we have no choice but to run the Receive-only transfers.
> Because locking the CPU for God knows how much time may cause the
> system interactivity degradation. For instance, a possible use-case of
> that design is when the controller is communicating with the
> SPI-devices with native DW APB SSI chip-select attached. BTW You can
> also find that design implemented in the kernel 5.10 spi-dw-core.c
> driver in context of the SPI-memory operations (with my last patches
> merged in). In particular I had to use it to handle the CPU-based
> EEPROM-read mode.
> 
> So in all other cases for normal CPU-based SPI-transfers when
> GPIO-based chip-select is available the safest solution would be to
> use a normal Push-Pull mode. In this case we have no risk in getting
> the Rx FIFO overflow unless there is a bug in the code, which is
> fixable anyway.
> 
> Getting back to the patch. In fact I don't really see how the
> Receive-only mode will help us with solving the problem noted in the
> patch log.

Shouldn't it put MOSI into High-Z like when the device is idle? The
issue is mainly that the idle state and RX state are different.

> As Mark said the problem with the Tx data on Rx-only
> transfers should be fixed on the client side. If an subordinate
> SPI-device needs a specific value to be received in that case, then
> that value should be somehow provided to the SPI-controller anyway.
> So the native Rx-only mode of the DW APB SSI controller won't help.
> Currently it's possible to be done only by executing a Full-duplex
> SPI-transfer with the Tx-buffer being pre-initialized with that
> value.
> 
> Another possible solution for the problem would be to fix the SPI core
> so aside with tx_buf being set to the NULL-pointer, a client driver
> would provide a default level or some specific value being put to the
> SPI bus on Rx-only transfers. If an SPI-controller is capable of
> satisfying the request, then it will accept the transfer. If it's not,
> then the SPI core may try to convert the Rx-only transfer into the
> Full-duplex transfer with the Tx-buffer being initialized with the
> requested level.

This is probably the most general solution; is there an existing way to
specify this sort of thing?

--Sean

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 19:40             ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 19:40 UTC (permalink / raw)
  To: Serge Semin, Mark Brown
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	linux-spi, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk

On 11/9/20 2:19 PM, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
>> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
>>> On 11/9/20 8:29 AM, Mark Brown wrote:
>>>> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
>>>>
> 
>>>>> The resting state of MOSI is high when nothing is driving it. If we
>>>>> drive it low while recieving, it looks like we are transmitting 0x00
>>>>> instead of transmitting nothing. This can confuse slaves (like SD cards)
>>>>> which allow new commands to be sent over MOSI while they are returning
>>>>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
>>>>> a byte can look like a start bit and a transmission bit to an SD card.
> 
> Yeah, that's what we've also experienced on our systems. We've worked
> around the problem in exactly the same way as you have. But we haven't
> dared to send it out as the solution seemed a bit hackish.

Well, the way it is now is equally wrong, since it is driving the line
low.

>>>>
>>>> If client devices are interpreting the transmitted data then I would
>>>> expect the drivers for that hardware to be ensuring that whatever we
>>>> transmit matches what the device is expecting.  We shouldn't be putting
>>>> a hack in a particular controller driver to paper over things, that will
>>>> mean that the device will break when used with other controllers and if
>>>> different devices have different requirements then obviously we can't
>>>> satisfy them.  There is not meaningfully a general specification for SPI
>>>> which says what happens when signals are idle, it's all specific to the
>>>> client device.
>>>>
>>>> In this case it also looks like the controller hardware requires
>>>> transmit data and therefore should be setting SPI_MUST_TX and just
>>>> removing the in driver default anyway, though that will have no effect
>>>> one way or anther on the issue you're seeing.
>>
> 
>>> There is a recieve-only mode, but it is not used by this driver. Perhaps
>>> it should be.
>>
>> I'd expect it'd perform better, especially on systems that are
>> apparently struggling for CPU bandwidth like yours seems to.
> 
> CPU-wise. RO-mode won't help in that case. Moreover it will be even
> more errors-prone for the systems with small CPU bandwidth. As I said
> the Receive-only mode will make the SPI controller automatically
> receiving data from the SPI bus and putting it into the Rx FIFO. If
> CPU is either busy with something else or too slow in fetching the
> data from the Rx FIFO, the FIFO will be eventually overflown with
> data, which we need to avoid at all cost.
> 
> As I see it the Receive-only mode is only acceptable in the next two
> situations:
> 
> 1) Rx-only DMA. But only if the DMA-engine and system bus are fast
> enough to fetch the incoming data on time. (Note for example in our
> system some DWC DMA-engine channels don't work well with the DW APB
> SSI working with full-speed, so we had to set constraints on the DWC
> DMA channels being used in conjunction with the DW APB SSI
> controller.)
> 
> 2) Rx-only with atomic CPU utilization. In order to make sure that the
> CPU keeps up with fetching the data from the Rx FIFO, we have to
> disable the local CPU IRQs while performing the Rx-only transfers, so
> to prevent the Rx FIFO overflow while the CPU is doing something else.
> Needless to say that such approach should be utilized only as a last
> resort, if we have no choice but to run the Receive-only transfers.
> Because locking the CPU for God knows how much time may cause the
> system interactivity degradation. For instance, a possible use-case of
> that design is when the controller is communicating with the
> SPI-devices with native DW APB SSI chip-select attached. BTW You can
> also find that design implemented in the kernel 5.10 spi-dw-core.c
> driver in context of the SPI-memory operations (with my last patches
> merged in). In particular I had to use it to handle the CPU-based
> EEPROM-read mode.
> 
> So in all other cases for normal CPU-based SPI-transfers when
> GPIO-based chip-select is available the safest solution would be to
> use a normal Push-Pull mode. In this case we have no risk in getting
> the Rx FIFO overflow unless there is a bug in the code, which is
> fixable anyway.
> 
> Getting back to the patch. In fact I don't really see how the
> Receive-only mode will help us with solving the problem noted in the
> patch log.

Shouldn't it put MOSI into High-Z like when the device is idle? The
issue is mainly that the idle state and RX state are different.

> As Mark said the problem with the Tx data on Rx-only
> transfers should be fixed on the client side. If an subordinate
> SPI-device needs a specific value to be received in that case, then
> that value should be somehow provided to the SPI-controller anyway.
> So the native Rx-only mode of the DW APB SSI controller won't help.
> Currently it's possible to be done only by executing a Full-duplex
> SPI-transfer with the Tx-buffer being pre-initialized with that
> value.
> 
> Another possible solution for the problem would be to fix the SPI core
> so aside with tx_buf being set to the NULL-pointer, a client driver
> would provide a default level or some specific value being put to the
> SPI bus on Rx-only transfers. If an SPI-controller is capable of
> satisfying the request, then it will accept the transfer. If it's not,
> then the SPI core may try to convert the Rx-only transfer into the
> Full-duplex transfer with the Tx-buffer being initialized with the
> requested level.

This is probably the most general solution; is there an existing way to
specify this sort of thing?

--Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 19:59     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 19:59 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi,

> using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and

I can believe in that. But the next part seems questionable:

> can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed).

No matter whether it's an IRQ-based or poll-based transfer, as long as a
client SPI-device is connected with a GPIO-based chip-select (or the
DW APB SSI-controller feature of the automatic chip-select toggling is
fixed), the Rx FIFO should never overrun. It's ensured by the transfer
algorithm design by calculating the rxtx_gap in the dw_writer()
method. If the error still happens then there must be some bug in
the code.

It's also strange to hear that the polling-based transfer helps
to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
causes them. Both of those methods are based on the same dw_writer()
and dw_reader() methods. So basically they both should either work
well or cause the errors at same time.

So to speak could you more through debug your case?

On the other hand the errors (but not the Rx FIFO overflow) might be
caused by the DW APB SSI nasty feature of the native chip-select
automatic assertion/de-assertion. So if your MMC-spi port is handled
by the native DW APB SSI CS lane, then it won't work well for sure.
No matter whether you use the poll- or IRQ-based transfers.

-Sergey


> Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:
> 
> Generic soc.dtsi dts:
> 
> spi0: spi@53000000 {
> 	#address-cells = <1>;
> 	#size-cells = <0>;
> 	compatible = "snps,dw-apb-ssi";
> 	reg = <0x53000000 0x100>;
> 	interrupts = <2>;
> 	...
> }
> 
> Board specific dts:
> 
> ...
> &spi0 {
> 	polling;
> 	status = "okay";
> 
> 	slot@0 {
> 		compatible = "mmc-spi-slot";
> 		reg = <0>;
> 		voltage-ranges = <3300 3300>;
> 		spi-max-frequency = <4000000>;
> 	};
> }
> 
> will result in using polled transfers for the SD card while other boards
> using spi0 for different peripherals can use interrupt based transfers
> without needing to change the generic base soc dts.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index d0cc5bf4fa4e..3f1bc384cb45 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -20,6 +20,7 @@
>  #include <linux/property.h>
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
> +#include <linux/interrupt.h>
>  
>  #include "spi-dw.h"
>  
> @@ -246,9 +247,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
>  
>  	dws->paddr = mem->start;
>  
> -	dws->irq = platform_get_irq(pdev, 0);
> -	if (dws->irq < 0)
> -		return dws->irq; /* -ENXIO */
> +	if (device_property_read_bool(&pdev->dev, "polling")) {
> +		dws->irq = IRQ_NOTCONNECTED;
> +	} else {
> +		dws->irq = platform_get_irq(pdev, 0);
> +		if (dws->irq < 0)
> +			return dws->irq; /* -ENXIO */
> +	}
>  
>  	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
>  	if (IS_ERR(dwsmmio->clk))
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-09 19:59     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 19:59 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> With boards that have slow interrupts context switch, and a fast device
> connected to a spi master, e.g. an SD card through mmc-spi,

> using
> dw_spi_poll_transfer() intead of the regular interrupt based
> dw_spi_transfer_handler() function is more efficient and

I can believe in that. But the next part seems questionable:

> can avoid a lot
> of RX FIFO overflow errors while keeping the device SPI frequency
> reasonnably high (for speed).

No matter whether it's an IRQ-based or poll-based transfer, as long as a
client SPI-device is connected with a GPIO-based chip-select (or the
DW APB SSI-controller feature of the automatic chip-select toggling is
fixed), the Rx FIFO should never overrun. It's ensured by the transfer
algorithm design by calculating the rxtx_gap in the dw_writer()
method. If the error still happens then there must be some bug in
the code.

It's also strange to hear that the polling-based transfer helps
to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
causes them. Both of those methods are based on the same dw_writer()
and dw_reader() methods. So basically they both should either work
well or cause the errors at same time.

So to speak could you more through debug your case?

On the other hand the errors (but not the Rx FIFO overflow) might be
caused by the DW APB SSI nasty feature of the native chip-select
automatic assertion/de-assertion. So if your MMC-spi port is handled
by the native DW APB SSI CS lane, then it won't work well for sure.
No matter whether you use the poll- or IRQ-based transfers.

-Sergey


> Introduce the "polling" device tree
> property to allow requesting polled processing of transfer depending on
> the connected device while keeping the spi master interrupts property
> unschanged. E.g. device trees such as:
> 
> Generic soc.dtsi dts:
> 
> spi0: spi@53000000 {
> 	#address-cells = <1>;
> 	#size-cells = <0>;
> 	compatible = "snps,dw-apb-ssi";
> 	reg = <0x53000000 0x100>;
> 	interrupts = <2>;
> 	...
> }
> 
> Board specific dts:
> 
> ...
> &spi0 {
> 	polling;
> 	status = "okay";
> 
> 	slot@0 {
> 		compatible = "mmc-spi-slot";
> 		reg = <0>;
> 		voltage-ranges = <3300 3300>;
> 		spi-max-frequency = <4000000>;
> 	};
> }
> 
> will result in using polled transfers for the SD card while other boards
> using spi0 for different peripherals can use interrupt based transfers
> without needing to change the generic base soc dts.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index d0cc5bf4fa4e..3f1bc384cb45 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -20,6 +20,7 @@
>  #include <linux/property.h>
>  #include <linux/regmap.h>
>  #include <linux/reset.h>
> +#include <linux/interrupt.h>
>  
>  #include "spi-dw.h"
>  
> @@ -246,9 +247,13 @@ static int dw_spi_mmio_probe(struct platform_device *pdev)
>  
>  	dws->paddr = mem->start;
>  
> -	dws->irq = platform_get_irq(pdev, 0);
> -	if (dws->irq < 0)
> -		return dws->irq; /* -ENXIO */
> +	if (device_property_read_bool(&pdev->dev, "polling")) {
> +		dws->irq = IRQ_NOTCONNECTED;
> +	} else {
> +		dws->irq = platform_get_irq(pdev, 0);
> +		if (dws->irq < 0)
> +			return dws->irq; /* -ENXIO */
> +	}
>  
>  	dwsmmio->clk = devm_clk_get(&pdev->dev, NULL);
>  	if (IS_ERR(dwsmmio->clk))
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 19:40             ` Sean Anderson
@ 2020-11-09 20:17               ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 20:17 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Mark Brown, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

On Mon, Nov 09, 2020 at 02:40:01PM -0500, Sean Anderson wrote:
> On 11/9/20 2:19 PM, Serge Semin wrote:
> > On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> >> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> >>> On 11/9/20 8:29 AM, Mark Brown wrote:
> >>>> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> >>>>
> > 
> >>>>> The resting state of MOSI is high when nothing is driving it. If we
> >>>>> drive it low while recieving, it looks like we are transmitting 0x00
> >>>>> instead of transmitting nothing. This can confuse slaves (like SD cards)
> >>>>> which allow new commands to be sent over MOSI while they are returning
> >>>>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> >>>>> a byte can look like a start bit and a transmission bit to an SD card.
> > 
> > Yeah, that's what we've also experienced on our systems. We've worked
> > around the problem in exactly the same way as you have. But we haven't
> > dared to send it out as the solution seemed a bit hackish.
> 

> Well, the way it is now is equally wrong, since it is driving the line
> low.

Alas a lot of the SPI-controller drivers have got it implemented in the
same way. So, yeah, all of them won't work well with the SPI-based MMC
interfaces, unless either the client driver or the SPI core code are
properly fixed.

> 
> >>>>
> >>>> If client devices are interpreting the transmitted data then I would
> >>>> expect the drivers for that hardware to be ensuring that whatever we
> >>>> transmit matches what the device is expecting.  We shouldn't be putting
> >>>> a hack in a particular controller driver to paper over things, that will
> >>>> mean that the device will break when used with other controllers and if
> >>>> different devices have different requirements then obviously we can't
> >>>> satisfy them.  There is not meaningfully a general specification for SPI
> >>>> which says what happens when signals are idle, it's all specific to the
> >>>> client device.
> >>>>
> >>>> In this case it also looks like the controller hardware requires
> >>>> transmit data and therefore should be setting SPI_MUST_TX and just
> >>>> removing the in driver default anyway, though that will have no effect
> >>>> one way or anther on the issue you're seeing.
> >>
> > 
> >>> There is a recieve-only mode, but it is not used by this driver. Perhaps
> >>> it should be.
> >>
> >> I'd expect it'd perform better, especially on systems that are
> >> apparently struggling for CPU bandwidth like yours seems to.
> > 
> > CPU-wise. RO-mode won't help in that case. Moreover it will be even
> > more errors-prone for the systems with small CPU bandwidth. As I said
> > the Receive-only mode will make the SPI controller automatically
> > receiving data from the SPI bus and putting it into the Rx FIFO. If
> > CPU is either busy with something else or too slow in fetching the
> > data from the Rx FIFO, the FIFO will be eventually overflown with
> > data, which we need to avoid at all cost.
> > 
> > As I see it the Receive-only mode is only acceptable in the next two
> > situations:
> > 
> > 1) Rx-only DMA. But only if the DMA-engine and system bus are fast
> > enough to fetch the incoming data on time. (Note for example in our
> > system some DWC DMA-engine channels don't work well with the DW APB
> > SSI working with full-speed, so we had to set constraints on the DWC
> > DMA channels being used in conjunction with the DW APB SSI
> > controller.)
> > 
> > 2) Rx-only with atomic CPU utilization. In order to make sure that the
> > CPU keeps up with fetching the data from the Rx FIFO, we have to
> > disable the local CPU IRQs while performing the Rx-only transfers, so
> > to prevent the Rx FIFO overflow while the CPU is doing something else.
> > Needless to say that such approach should be utilized only as a last
> > resort, if we have no choice but to run the Receive-only transfers.
> > Because locking the CPU for God knows how much time may cause the
> > system interactivity degradation. For instance, a possible use-case of
> > that design is when the controller is communicating with the
> > SPI-devices with native DW APB SSI chip-select attached. BTW You can
> > also find that design implemented in the kernel 5.10 spi-dw-core.c
> > driver in context of the SPI-memory operations (with my last patches
> > merged in). In particular I had to use it to handle the CPU-based
> > EEPROM-read mode.
> > 
> > So in all other cases for normal CPU-based SPI-transfers when
> > GPIO-based chip-select is available the safest solution would be to
> > use a normal Push-Pull mode. In this case we have no risk in getting
> > the Rx FIFO overflow unless there is a bug in the code, which is
> > fixable anyway.
> > 
> > Getting back to the patch. In fact I don't really see how the
> > Receive-only mode will help us with solving the problem noted in the
> > patch log.
> 

> Shouldn't it put MOSI into High-Z like when the device is idle? The
> issue is mainly that the idle state and RX state are different.

AFAICS the manual doesn't say anything about High-Z, but only: "In
receive-only mode, transmitted data are not valid. After the first
write to the transmit FIFO, the same word is retransmitted for the
duration of the transfer."

I don't know for sure what "word" the authors meant, but it doesn't
sound like Tri-state anyway. So some value will still be put out on
the bus. Most likely it's the word written to the Tx-buffer to
initiate the Rx-only transfer.

> 
> > As Mark said the problem with the Tx data on Rx-only
> > transfers should be fixed on the client side. If an subordinate
> > SPI-device needs a specific value to be received in that case, then
> > that value should be somehow provided to the SPI-controller anyway.
> > So the native Rx-only mode of the DW APB SSI controller won't help.
> > Currently it's possible to be done only by executing a Full-duplex
> > SPI-transfer with the Tx-buffer being pre-initialized with that
> > value.
> > 
> > Another possible solution for the problem would be to fix the SPI core
> > so aside with tx_buf being set to the NULL-pointer, a client driver
> > would provide a default level or some specific value being put to the
> > SPI bus on Rx-only transfers. If an SPI-controller is capable of
> > satisfying the request, then it will accept the transfer. If it's not,
> > then the SPI core may try to convert the Rx-only transfer into the
> > Full-duplex transfer with the Tx-buffer being initialized with the
> > requested level.
> 

> This is probably the most general solution; is there an existing way to
> specify this sort of thing?

Without touching the SPI core code, as Mark said, the problem is
fixable only by converting the client-driver to executing the
Full-duplex SPI-transfers instead of the Rx-only ones. The client
driver will have to allocate a dummy-buffer and pre-initialize it with
the required default value of the MOSI lane.

-Sergey

> 
> --Sean

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 20:17               ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 20:17 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Rob Herring, linux-spi, linux-gpio, Mark Brown, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk

On Mon, Nov 09, 2020 at 02:40:01PM -0500, Sean Anderson wrote:
> On 11/9/20 2:19 PM, Serge Semin wrote:
> > On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> >> On Mon, Nov 09, 2020 at 08:47:10AM -0500, Sean Anderson wrote:
> >>> On 11/9/20 8:29 AM, Mark Brown wrote:
> >>>> On Sat, Nov 07, 2020 at 05:13:51PM +0900, Damien Le Moal wrote:
> >>>>
> > 
> >>>>> The resting state of MOSI is high when nothing is driving it. If we
> >>>>> drive it low while recieving, it looks like we are transmitting 0x00
> >>>>> instead of transmitting nothing. This can confuse slaves (like SD cards)
> >>>>> which allow new commands to be sent over MOSI while they are returning
> >>>>> data over MISO. The return of MOSI from 0 to 1 at the end of recieving
> >>>>> a byte can look like a start bit and a transmission bit to an SD card.
> > 
> > Yeah, that's what we've also experienced on our systems. We've worked
> > around the problem in exactly the same way as you have. But we haven't
> > dared to send it out as the solution seemed a bit hackish.
> 

> Well, the way it is now is equally wrong, since it is driving the line
> low.

Alas a lot of the SPI-controller drivers have got it implemented in the
same way. So, yeah, all of them won't work well with the SPI-based MMC
interfaces, unless either the client driver or the SPI core code are
properly fixed.

> 
> >>>>
> >>>> If client devices are interpreting the transmitted data then I would
> >>>> expect the drivers for that hardware to be ensuring that whatever we
> >>>> transmit matches what the device is expecting.  We shouldn't be putting
> >>>> a hack in a particular controller driver to paper over things, that will
> >>>> mean that the device will break when used with other controllers and if
> >>>> different devices have different requirements then obviously we can't
> >>>> satisfy them.  There is not meaningfully a general specification for SPI
> >>>> which says what happens when signals are idle, it's all specific to the
> >>>> client device.
> >>>>
> >>>> In this case it also looks like the controller hardware requires
> >>>> transmit data and therefore should be setting SPI_MUST_TX and just
> >>>> removing the in driver default anyway, though that will have no effect
> >>>> one way or anther on the issue you're seeing.
> >>
> > 
> >>> There is a recieve-only mode, but it is not used by this driver. Perhaps
> >>> it should be.
> >>
> >> I'd expect it'd perform better, especially on systems that are
> >> apparently struggling for CPU bandwidth like yours seems to.
> > 
> > CPU-wise. RO-mode won't help in that case. Moreover it will be even
> > more errors-prone for the systems with small CPU bandwidth. As I said
> > the Receive-only mode will make the SPI controller automatically
> > receiving data from the SPI bus and putting it into the Rx FIFO. If
> > CPU is either busy with something else or too slow in fetching the
> > data from the Rx FIFO, the FIFO will be eventually overflown with
> > data, which we need to avoid at all cost.
> > 
> > As I see it the Receive-only mode is only acceptable in the next two
> > situations:
> > 
> > 1) Rx-only DMA. But only if the DMA-engine and system bus are fast
> > enough to fetch the incoming data on time. (Note for example in our
> > system some DWC DMA-engine channels don't work well with the DW APB
> > SSI working with full-speed, so we had to set constraints on the DWC
> > DMA channels being used in conjunction with the DW APB SSI
> > controller.)
> > 
> > 2) Rx-only with atomic CPU utilization. In order to make sure that the
> > CPU keeps up with fetching the data from the Rx FIFO, we have to
> > disable the local CPU IRQs while performing the Rx-only transfers, so
> > to prevent the Rx FIFO overflow while the CPU is doing something else.
> > Needless to say that such approach should be utilized only as a last
> > resort, if we have no choice but to run the Receive-only transfers.
> > Because locking the CPU for God knows how much time may cause the
> > system interactivity degradation. For instance, a possible use-case of
> > that design is when the controller is communicating with the
> > SPI-devices with native DW APB SSI chip-select attached. BTW You can
> > also find that design implemented in the kernel 5.10 spi-dw-core.c
> > driver in context of the SPI-memory operations (with my last patches
> > merged in). In particular I had to use it to handle the CPU-based
> > EEPROM-read mode.
> > 
> > So in all other cases for normal CPU-based SPI-transfers when
> > GPIO-based chip-select is available the safest solution would be to
> > use a normal Push-Pull mode. In this case we have no risk in getting
> > the Rx FIFO overflow unless there is a bug in the code, which is
> > fixable anyway.
> > 
> > Getting back to the patch. In fact I don't really see how the
> > Receive-only mode will help us with solving the problem noted in the
> > patch log.
> 

> Shouldn't it put MOSI into High-Z like when the device is idle? The
> issue is mainly that the idle state and RX state are different.

AFAICS the manual doesn't say anything about High-Z, but only: "In
receive-only mode, transmitted data are not valid. After the first
write to the transmit FIFO, the same word is retransmitted for the
duration of the transfer."

I don't know for sure what "word" the authors meant, but it doesn't
sound like Tri-state anyway. So some value will still be put out on
the bus. Most likely it's the word written to the Tx-buffer to
initiate the Rx-only transfer.

> 
> > As Mark said the problem with the Tx data on Rx-only
> > transfers should be fixed on the client side. If an subordinate
> > SPI-device needs a specific value to be received in that case, then
> > that value should be somehow provided to the SPI-controller anyway.
> > So the native Rx-only mode of the DW APB SSI controller won't help.
> > Currently it's possible to be done only by executing a Full-duplex
> > SPI-transfer with the Tx-buffer being pre-initialized with that
> > value.
> > 
> > Another possible solution for the problem would be to fix the SPI core
> > so aside with tx_buf being set to the NULL-pointer, a client driver
> > would provide a default level or some specific value being put to the
> > SPI bus on Rx-only transfers. If an SPI-controller is capable of
> > satisfying the request, then it will accept the transfer. If it's not,
> > then the SPI core may try to convert the Rx-only transfer into the
> > Full-duplex transfer with the Tx-buffer being initialized with the
> > requested level.
> 

> This is probably the most general solution; is there an existing way to
> specify this sort of thing?

Without touching the SPI core code, as Mark said, the problem is
fixable only by converting the client-driver to executing the
Full-duplex SPI-transfers instead of the Rx-only ones. The client
driver will have to allocate a dummy-buffer and pre-initialize it with
the required default value of the MOSI lane.

-Sergey

> 
> --Sean

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 19:19           ` Serge Semin
@ 2020-11-09 20:20             ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 20:20 UTC (permalink / raw)
  To: Serge Semin
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Mon, Nov 09, 2020 at 10:19:09PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:

> > I'd expect it'd perform better, especially on systems that are
> > apparently struggling for CPU bandwidth like yours seems to.

> CPU-wise. RO-mode won't help in that case. Moreover it will be even
> more errors-prone for the systems with small CPU bandwidth. As I said

Right, these are two separate issues - one is that the client device
has requirements on the transmit data at times when the driver isn't
defining what should be transmitted, the other is that the controller
driver is using full duplex mode even for single duplex data.  I just
happened to notice the second issue while reviewing the change - there
shouldn't be any code for setting the dummy transmit pattern in the
driver in the first place.

> 2) Rx-only with atomic CPU utilization. In order to make sure that the
> CPU keeps up with fetching the data from the Rx FIFO, we have to
> disable the local CPU IRQs while performing the Rx-only transfers, so
> to prevent the Rx FIFO overflow while the CPU is doing something else.

...

> So in all other cases for normal CPU-based SPI-transfers when
> GPIO-based chip-select is available the safest solution would be to
> use a normal Push-Pull mode. In this case we have no risk in getting
> the Rx FIFO overflow unless there is a bug in the code, which is
> fixable anyway.

I'm not clear why we would have issues with the FIFO overflowing in PIO
mode, especially with a GPIO chip select - even if we're forced to tell
the controller how big the transfer is if we're using a GPIO chip select
we could just tell it we're doing a series of FIFO sized transfers?

> Another possible solution for the problem would be to fix the SPI core
> so aside with tx_buf being set to the NULL-pointer, a client driver
> would provide a default level or some specific value being put to the
> SPI bus on Rx-only transfers. If an SPI-controller is capable of
> satisfying the request, then it will accept the transfer. If it's not,
> then the SPI core may try to convert the Rx-only transfer into the
> Full-duplex transfer with the Tx-buffer being initialized with the
> requested level.

We do have support in the core for creating dummy data buffers for
controllers that can't do half duplex - that's the SPI_MUST_TX and
matching SPI_MUST_RX that I mentioned in my initial reply.  Currently we
always zero fill transmit buffers, the expected semantic is that if the
client driver isn't supplying data that means the device doesn't care
what gets sent and it's not clear to me that it isn't sensible to just
keep that like I said earlier, I don't know how common it's going to be
to need this since most half duplex transfers generally are half duplex.
The whole point with the SPI_MUST_ flags was to remove the need for
controller drivers to open code handling this, it was adding
complication and supporting configuration of the dummy data feels like
it's adding room for things to go wrong.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 20:20             ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 20:20 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 3032 bytes --]

On Mon, Nov 09, 2020 at 10:19:09PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:

> > I'd expect it'd perform better, especially on systems that are
> > apparently struggling for CPU bandwidth like yours seems to.

> CPU-wise. RO-mode won't help in that case. Moreover it will be even
> more errors-prone for the systems with small CPU bandwidth. As I said

Right, these are two separate issues - one is that the client device
has requirements on the transmit data at times when the driver isn't
defining what should be transmitted, the other is that the controller
driver is using full duplex mode even for single duplex data.  I just
happened to notice the second issue while reviewing the change - there
shouldn't be any code for setting the dummy transmit pattern in the
driver in the first place.

> 2) Rx-only with atomic CPU utilization. In order to make sure that the
> CPU keeps up with fetching the data from the Rx FIFO, we have to
> disable the local CPU IRQs while performing the Rx-only transfers, so
> to prevent the Rx FIFO overflow while the CPU is doing something else.

...

> So in all other cases for normal CPU-based SPI-transfers when
> GPIO-based chip-select is available the safest solution would be to
> use a normal Push-Pull mode. In this case we have no risk in getting
> the Rx FIFO overflow unless there is a bug in the code, which is
> fixable anyway.

I'm not clear why we would have issues with the FIFO overflowing in PIO
mode, especially with a GPIO chip select - even if we're forced to tell
the controller how big the transfer is if we're using a GPIO chip select
we could just tell it we're doing a series of FIFO sized transfers?

> Another possible solution for the problem would be to fix the SPI core
> so aside with tx_buf being set to the NULL-pointer, a client driver
> would provide a default level or some specific value being put to the
> SPI bus on Rx-only transfers. If an SPI-controller is capable of
> satisfying the request, then it will accept the transfer. If it's not,
> then the SPI core may try to convert the Rx-only transfer into the
> Full-duplex transfer with the Tx-buffer being initialized with the
> requested level.

We do have support in the core for creating dummy data buffers for
controllers that can't do half duplex - that's the SPI_MUST_TX and
matching SPI_MUST_RX that I mentioned in my initial reply.  Currently we
always zero fill transmit buffers, the expected semantic is that if the
client driver isn't supplying data that means the device doesn't care
what gets sent and it's not clear to me that it isn't sensible to just
keep that like I said earlier, I don't know how common it's going to be
to need this since most half duplex transfers generally are half duplex.
The whole point with the SPI_MUST_ flags was to remove the need for
controller drivers to open code handling this, it was adding
complication and supporting configuration of the dummy data feels like
it's adding room for things to go wrong.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 20:17               ` Serge Semin
@ 2020-11-09 20:29                 ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 20:29 UTC (permalink / raw)
  To: Serge Semin
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Mon, Nov 09, 2020 at 11:17:44PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:40:01PM -0500, Sean Anderson wrote:
> > On 11/9/20 2:19 PM, Serge Semin wrote:

> > > Getting back to the patch. In fact I don't really see how the
> > > Receive-only mode will help us with solving the problem noted in the
> > > patch log.

> > Shouldn't it put MOSI into High-Z like when the device is idle? The
> > issue is mainly that the idle state and RX state are different.

> AFAICS the manual doesn't say anything about High-Z, but only: "In
> receive-only mode, transmitted data are not valid. After the first
> write to the transmit FIFO, the same word is retransmitted for the
> duration of the transfer."

This is the sort of behaviour I would expect, and I'd expect that going
high Z could potentially cause electrical problems as the line won't be
being driven when it's been designed to be an output from the controller
so it's probably not desirable to do that.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 20:29                 ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-09 20:29 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 969 bytes --]

On Mon, Nov 09, 2020 at 11:17:44PM +0300, Serge Semin wrote:
> On Mon, Nov 09, 2020 at 02:40:01PM -0500, Sean Anderson wrote:
> > On 11/9/20 2:19 PM, Serge Semin wrote:

> > > Getting back to the patch. In fact I don't really see how the
> > > Receive-only mode will help us with solving the problem noted in the
> > > patch log.

> > Shouldn't it put MOSI into High-Z like when the device is idle? The
> > issue is mainly that the idle state and RX state are different.

> AFAICS the manual doesn't say anything about High-Z, but only: "In
> receive-only mode, transmitted data are not valid. After the first
> write to the transmit FIFO, the same word is retransmitted for the
> duration of the transfer."

This is the sort of behaviour I would expect, and I'd expect that going
high Z could potentially cause electrical problems as the line won't be
being driven when it's been designed to be an output from the controller
so it's probably not desirable to do that.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 20:45     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 20:45 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:13:53PM +0900, Damien Le Moal wrote:
> On slow systems, i.e. systems with a slow CPU resulting in slow context
> switches, calling spi_delay_exec() when executing polled transfers
> using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
> platforms to opt out of delayed polling by introducing the
> DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
> the execution of spi_delay_exec() in dw_spi_poll_transfer().

Please, have a more thorough problem review. Rx FIFO shouldn't
overflow even for the CPUs with slow context switch. If it does, then
most likely there is a bug in the code. So it's not a good idea to
work it around by introducing a dts-property in any case.

Just to note in case of our hardware no matter what CPU frequency I
specified (it can be varied from 200MHz to 1500MHz), there have never
been seen the Rx FIFO overflow error even with heavy background tasks
executed. I am really puzzled why some context switch causes the error
in your case...

As I said in another thread, some logical MMC-SPI drivers errors may
happen if the native CS is utilized...

On the other hand, if you have a DMA-engine utilized together with
your controller and the Tx DMA-channel is tuned to work faster than
the Rx DMA-channel, then the Rx FIFO overflow will eventually happen.
So replacing the DMA-based transfers with the poll- or IRQ-based ones
shall indeed solve the problem. But the better solution would be to
balance the DMA-channels priority if your DMA-controller is capable of
doing that.

-Sergey

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 12 ++++++++----
>  drivers/spi/spi-dw.h      |  1 +
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index c2ef1d8d46d5..16a6fd569145 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -385,14 +385,18 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
>  	u16 nbits;
>  	int ret;
>  
> -	delay.unit = SPI_DELAY_UNIT_SCK;
> -	nbits = dws->n_bytes * BITS_PER_BYTE;
> +	if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
> +		delay.unit = SPI_DELAY_UNIT_SCK;
> +		nbits = dws->n_bytes * BITS_PER_BYTE;
> +	}
>  
>  	do {
>  		dw_writer(dws);
>  
> -		delay.value = nbits * (dws->rx_len - dws->tx_len);
> -		spi_delay_exec(&delay, transfer);
> +		if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
> +			delay.value = nbits * (dws->rx_len - dws->tx_len);
> +			spi_delay_exec(&delay, transfer);
> +		}
>  
>  		dw_reader(dws);
>  
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index 48a11a51a407..25f6372b993a 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -130,6 +130,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>  #define DW_SPI_CAP_DFS_32		BIT(3)
> +#define DW_SPI_CAP_POLL_NODELAY		BIT(4)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY
@ 2020-11-09 20:45     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 20:45 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:13:53PM +0900, Damien Le Moal wrote:
> On slow systems, i.e. systems with a slow CPU resulting in slow context
> switches, calling spi_delay_exec() when executing polled transfers
> using dw_spi_poll_transfer() can lead to RX FIFO overflows. Allow
> platforms to opt out of delayed polling by introducing the
> DW_SPI_CAP_POLL_NODELAY DW SPI capability flag to disable
> the execution of spi_delay_exec() in dw_spi_poll_transfer().

Please, have a more thorough problem review. Rx FIFO shouldn't
overflow even for the CPUs with slow context switch. If it does, then
most likely there is a bug in the code. So it's not a good idea to
work it around by introducing a dts-property in any case.

Just to note in case of our hardware no matter what CPU frequency I
specified (it can be varied from 200MHz to 1500MHz), there have never
been seen the Rx FIFO overflow error even with heavy background tasks
executed. I am really puzzled why some context switch causes the error
in your case...

As I said in another thread, some logical MMC-SPI drivers errors may
happen if the native CS is utilized...

On the other hand, if you have a DMA-engine utilized together with
your controller and the Tx DMA-channel is tuned to work faster than
the Rx DMA-channel, then the Rx FIFO overflow will eventually happen.
So replacing the DMA-based transfers with the poll- or IRQ-based ones
shall indeed solve the problem. But the better solution would be to
balance the DMA-channels priority if your DMA-controller is capable of
doing that.

-Sergey

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-core.c | 12 ++++++++----
>  drivers/spi/spi-dw.h      |  1 +
>  2 files changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index c2ef1d8d46d5..16a6fd569145 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -385,14 +385,18 @@ static int dw_spi_poll_transfer(struct dw_spi *dws,
>  	u16 nbits;
>  	int ret;
>  
> -	delay.unit = SPI_DELAY_UNIT_SCK;
> -	nbits = dws->n_bytes * BITS_PER_BYTE;
> +	if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
> +		delay.unit = SPI_DELAY_UNIT_SCK;
> +		nbits = dws->n_bytes * BITS_PER_BYTE;
> +	}
>  
>  	do {
>  		dw_writer(dws);
>  
> -		delay.value = nbits * (dws->rx_len - dws->tx_len);
> -		spi_delay_exec(&delay, transfer);
> +		if (!(dws->caps & DW_SPI_CAP_POLL_NODELAY)) {
> +			delay.value = nbits * (dws->rx_len - dws->tx_len);
> +			spi_delay_exec(&delay, transfer);
> +		}
>  
>  		dw_reader(dws);
>  
> diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
> index 48a11a51a407..25f6372b993a 100644
> --- a/drivers/spi/spi-dw.h
> +++ b/drivers/spi/spi-dw.h
> @@ -130,6 +130,7 @@ enum dw_ssi_type {
>  #define DW_SPI_CAP_KEEMBAY_MST		BIT(1)
>  #define DW_SPI_CAP_DWC_SSI		BIT(2)
>  #define DW_SPI_CAP_DFS_32		BIT(3)
> +#define DW_SPI_CAP_POLL_NODELAY		BIT(4)
>  
>  /* Slave spi_transfer/spi_mem_op related */
>  struct dw_spi_cfg {
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-09 17:44       ` Serge Semin
@ 2020-11-09 20:52         ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 20:52 UTC (permalink / raw)
  To: Serge Semin
  Cc: Andy Shevchenko, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Frank Rowand, devicetree, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel, Sean Anderson

On Mon, Nov 9, 2020 at 11:45 AM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Andy,
>
> On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> > On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> >
> > > @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> > >  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> > >  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> > >  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> > > -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> >
> > Sorry, but the above doesn't sound right to me.
> > It's a generic code and you may imagine how many systems you broke by
> > this change.
>
> Damien replaced the macro above with the code below (your removed it from your
> message):
>
> +static struct device_node *parse_gpios(struct device_node *np,
> +                                      const char *prop_name, int index)
> +{
> +       /*
> +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +        * available. As this conflict with "xx-gpios" reference properties,
> +        * ignore it.
> +        */
> +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +               return NULL;
> +
> +       return parse_suffix_prop_cells(np, prop_name, index,
> +                                      "-gpios", "#gpio-cells");
> +}
>
> So AFAICS removing the macro shouldn't cause any problem.
>
> My concern was whether the quirk has been really needed. As I said the
> "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> "ngpios" one. Due to the problem noted by Damien any deprecated property
> utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> though implicitly but is supposed to encourage people to provide fixes for
> the dts-files with the deprecated property replaced with "ngpios".

May be deprecated, but we've still got 53 cases in upstream dts files.
Plus changing doesn't work well for new DT with old kernels unless we
backport 'ngpios' support.

> On the other hand an encouragement based on breaking the kernel doesn't seem a
> good solution. So as I see it either we should accept the solution provided by
> Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> solution would they prefer.

I'd suggest making failing to parse a warning rather than an error.
The devlink stuff is off by default anyways and is still changing.

Rob

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-09 20:52         ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 20:52 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	linux-spi, open list:GPIO SUBSYSTEM, Andy Shevchenko, Mark Brown,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Sean Anderson,
	Frank Rowand, linux-clk

On Mon, Nov 9, 2020 at 11:45 AM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Andy,
>
> On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> > On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> >
> > > @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> > >  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> > >  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> > >  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> > > -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> >
> > Sorry, but the above doesn't sound right to me.
> > It's a generic code and you may imagine how many systems you broke by
> > this change.
>
> Damien replaced the macro above with the code below (your removed it from your
> message):
>
> +static struct device_node *parse_gpios(struct device_node *np,
> +                                      const char *prop_name, int index)
> +{
> +       /*
> +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +        * available. As this conflict with "xx-gpios" reference properties,
> +        * ignore it.
> +        */
> +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +               return NULL;
> +
> +       return parse_suffix_prop_cells(np, prop_name, index,
> +                                      "-gpios", "#gpio-cells");
> +}
>
> So AFAICS removing the macro shouldn't cause any problem.
>
> My concern was whether the quirk has been really needed. As I said the
> "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> "ngpios" one. Due to the problem noted by Damien any deprecated property
> utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> though implicitly but is supposed to encourage people to provide fixes for
> the dts-files with the deprecated property replaced with "ngpios".

May be deprecated, but we've still got 53 cases in upstream dts files.
Plus changing doesn't work well for new DT with old kernels unless we
backport 'ngpios' support.

> On the other hand an encouragement based on breaking the kernel doesn't seem a
> good solution. So as I see it either we should accept the solution provided by
> Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> solution would they prefer.

I'd suggest making failing to parse a warning rather than an error.
The devlink stuff is off by default anyways and is still changing.

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 20:20             ` Mark Brown
@ 2020-11-09 21:05               ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 21:05 UTC (permalink / raw)
  To: Mark Brown
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

On Mon, Nov 09, 2020 at 08:20:52PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 10:19:09PM +0300, Serge Semin wrote:
> > On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> 
> > > I'd expect it'd perform better, especially on systems that are
> > > apparently struggling for CPU bandwidth like yours seems to.
> 
> > CPU-wise. RO-mode won't help in that case. Moreover it will be even
> > more errors-prone for the systems with small CPU bandwidth. As I said
> 
> Right, these are two separate issues - one is that the client device
> has requirements on the transmit data at times when the driver isn't
> defining what should be transmitted, the other is that the controller
> driver is using full duplex mode even for single duplex data.  I just
> happened to notice the second issue while reviewing the change - there
> shouldn't be any code for setting the dummy transmit pattern in the
> driver in the first place.
> 
> > 2) Rx-only with atomic CPU utilization. In order to make sure that the
> > CPU keeps up with fetching the data from the Rx FIFO, we have to
> > disable the local CPU IRQs while performing the Rx-only transfers, so
> > to prevent the Rx FIFO overflow while the CPU is doing something else.
> 
> ...
> 
> > So in all other cases for normal CPU-based SPI-transfers when
> > GPIO-based chip-select is available the safest solution would be to
> > use a normal Push-Pull mode. In this case we have no risk in getting
> > the Rx FIFO overflow unless there is a bug in the code, which is
> > fixable anyway.
> 

> I'm not clear why we would have issues with the FIFO overflowing in PIO
> mode, especially with a GPIO chip select - even if we're forced to tell
> the controller how big the transfer is if we're using a GPIO chip select

> we could just tell it we're doing a series of FIFO sized transfers?

Hm, you are right. Splitting the Rx-only transfers on the chunks with
lengths smaller than the FIFO size indeed would have solved the
problem of the Rx FIFO overflow with GPIO-based CS hardware. Don't
really know how I missed that. Most likely because when concerning the
Tx-only/Rx-only/EEPROM-read modes I always think about the native
chip-select automatic assertion/de-assertion, in which case we have no
other way but to provide the SPI-transfers/message atomicity.

> 
> > Another possible solution for the problem would be to fix the SPI core
> > so aside with tx_buf being set to the NULL-pointer, a client driver
> > would provide a default level or some specific value being put to the
> > SPI bus on Rx-only transfers. If an SPI-controller is capable of
> > satisfying the request, then it will accept the transfer. If it's not,
> > then the SPI core may try to convert the Rx-only transfer into the
> > Full-duplex transfer with the Tx-buffer being initialized with the
> > requested level.
> 

> We do have support in the core for creating dummy data buffers for
> controllers that can't do half duplex - that's the SPI_MUST_TX and
> matching SPI_MUST_RX that I mentioned in my initial reply.  Currently we
> always zero fill transmit buffers, the expected semantic is that if the
> client driver isn't supplying data that means the device doesn't care
> what gets sent and it's not clear to me that it isn't sensible to just
> keep that like I said earlier,

> I don't know how common it's going to be
> to need this since most half duplex transfers generally are half duplex.
> The whole point with the SPI_MUST_ flags was to remove the need for
> controller drivers to open code handling this, it was adding
> complication and supporting configuration of the dummy data feels like
> it's adding room for things to go wrong.

If by general Rx-only half-duplex transfers you meant that the client
SPI-device shall just not care what the MOSI level, then the only
acceptable solution of the noted in this patch problem is to fix the
client driver. Since in case of the MMC-SPI client device sometimes it
does care about the level.

-Sergey


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-09 21:05               ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 21:05 UTC (permalink / raw)
  To: Mark Brown
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk

On Mon, Nov 09, 2020 at 08:20:52PM +0000, Mark Brown wrote:
> On Mon, Nov 09, 2020 at 10:19:09PM +0300, Serge Semin wrote:
> > On Mon, Nov 09, 2020 at 02:14:22PM +0000, Mark Brown wrote:
> 
> > > I'd expect it'd perform better, especially on systems that are
> > > apparently struggling for CPU bandwidth like yours seems to.
> 
> > CPU-wise. RO-mode won't help in that case. Moreover it will be even
> > more errors-prone for the systems with small CPU bandwidth. As I said
> 
> Right, these are two separate issues - one is that the client device
> has requirements on the transmit data at times when the driver isn't
> defining what should be transmitted, the other is that the controller
> driver is using full duplex mode even for single duplex data.  I just
> happened to notice the second issue while reviewing the change - there
> shouldn't be any code for setting the dummy transmit pattern in the
> driver in the first place.
> 
> > 2) Rx-only with atomic CPU utilization. In order to make sure that the
> > CPU keeps up with fetching the data from the Rx FIFO, we have to
> > disable the local CPU IRQs while performing the Rx-only transfers, so
> > to prevent the Rx FIFO overflow while the CPU is doing something else.
> 
> ...
> 
> > So in all other cases for normal CPU-based SPI-transfers when
> > GPIO-based chip-select is available the safest solution would be to
> > use a normal Push-Pull mode. In this case we have no risk in getting
> > the Rx FIFO overflow unless there is a bug in the code, which is
> > fixable anyway.
> 

> I'm not clear why we would have issues with the FIFO overflowing in PIO
> mode, especially with a GPIO chip select - even if we're forced to tell
> the controller how big the transfer is if we're using a GPIO chip select

> we could just tell it we're doing a series of FIFO sized transfers?

Hm, you are right. Splitting the Rx-only transfers on the chunks with
lengths smaller than the FIFO size indeed would have solved the
problem of the Rx FIFO overflow with GPIO-based CS hardware. Don't
really know how I missed that. Most likely because when concerning the
Tx-only/Rx-only/EEPROM-read modes I always think about the native
chip-select automatic assertion/de-assertion, in which case we have no
other way but to provide the SPI-transfers/message atomicity.

> 
> > Another possible solution for the problem would be to fix the SPI core
> > so aside with tx_buf being set to the NULL-pointer, a client driver
> > would provide a default level or some specific value being put to the
> > SPI bus on Rx-only transfers. If an SPI-controller is capable of
> > satisfying the request, then it will accept the transfer. If it's not,
> > then the SPI core may try to convert the Rx-only transfer into the
> > Full-duplex transfer with the Tx-buffer being initialized with the
> > requested level.
> 

> We do have support in the core for creating dummy data buffers for
> controllers that can't do half duplex - that's the SPI_MUST_TX and
> matching SPI_MUST_RX that I mentioned in my initial reply.  Currently we
> always zero fill transmit buffers, the expected semantic is that if the
> client driver isn't supplying data that means the device doesn't care
> what gets sent and it's not clear to me that it isn't sensible to just
> keep that like I said earlier,

> I don't know how common it's going to be
> to need this since most half duplex transfers generally are half duplex.
> The whole point with the SPI_MUST_ flags was to remove the need for
> controller drivers to open code handling this, it was adding
> complication and supporting configuration of the dummy data feels like
> it's adding room for things to go wrong.

If by general Rx-only half-duplex transfers you meant that the client
SPI-device shall just not care what the MOSI level, then the only
acceptable solution of the noted in this patch problem is to fix the
client driver. Since in case of the MMC-SPI client device sometimes it
does care about the level.

-Sergey


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-09 21:21     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 21:21 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> ctrlr0 register format. This SoC is also quite slow and gets significant
> SD card performance improvements from using no-delay polled transfers.
> Add the dw_spi_k210_init() function tied to the
> "canaan,kendryte-k210-spi" compatible string to set the
> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> for this SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index 3f1bc384cb45..a00def6c5b39 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int dw_spi_k210_init(struct platform_device *pdev,
> +			    struct dw_spi_mmio *dwsmmio)
> +{
> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> +
> +	return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>  	int (*init_func)(struct platform_device *pdev,
> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},

> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},

Other than the comments from Sean and Mark regarding the DFS_32
feature runtime detectability, I couldn't find a patch with adding the
new new compatible string into the DW APB SSI DT schema. Have I missed
it? If I haven't could you add one to the next version of the series?

-Sergey

>  	{ /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 21:21     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-09 21:21 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> ctrlr0 register format. This SoC is also quite slow and gets significant
> SD card performance improvements from using no-delay polled transfers.
> Add the dw_spi_k210_init() function tied to the
> "canaan,kendryte-k210-spi" compatible string to set the
> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> for this SoC.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index 3f1bc384cb45..a00def6c5b39 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +static int dw_spi_k210_init(struct platform_device *pdev,
> +			    struct dw_spi_mmio *dwsmmio)
> +{
> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> +
> +	return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>  	int (*init_func)(struct platform_device *pdev,
> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},

> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},

Other than the comments from Sean and Mark regarding the DFS_32
feature runtime detectability, I couldn't find a patch with adding the
new new compatible string into the DW APB SSI DT schema. Have I missed
it? If I haven't could you add one to the next version of the series?

-Sergey

>  	{ /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-09 21:21     ` Serge Semin
@ 2020-11-09 21:39       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 21:39 UTC (permalink / raw)
  To: Serge Semin
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On 2020/11/10 6:22, Serge Semin wrote:
> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>> ctrlr0 register format. This SoC is also quite slow and gets significant
>> SD card performance improvements from using no-delay polled transfers.
>> Add the dw_spi_k210_init() function tied to the
>> "canaan,kendryte-k210-spi" compatible string to set the
>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>> for this SoC.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>> index 3f1bc384cb45..a00def6c5b39 100644
>> --- a/drivers/spi/spi-dw-mmio.c
>> +++ b/drivers/spi/spi-dw-mmio.c
>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>  	return 0;
>>  }
>>  
>> +static int dw_spi_k210_init(struct platform_device *pdev,
>> +			    struct dw_spi_mmio *dwsmmio)
>> +{
>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>> +
>> +	return 0;
>> +}
>> +
>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>  {
>>  	int (*init_func)(struct platform_device *pdev,
>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> 
>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> 
> Other than the comments from Sean and Mark regarding the DFS_32
> feature runtime detectability, I couldn't find a patch with adding the
> new new compatible string into the DW APB SSI DT schema. Have I missed
> it? If I haven't could you add one to the next version of the series?

Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
patch for the "polling" property but forgot the compatible string.

In any case, I think that this new compatible string change can be dropped by
switching to automatically detecting the DFS32 and using a different solution
than the polling property change I sent for the RX fifo overflow problem.

I am still going through all the emails trying to understand what to try next to
avoid the polling "hack".

Thanks !

> 
> -Sergey
> 
>>  	{ /* end of table */}
>>  };
>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>> -- 
>> 2.28.0
>>
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 21:39       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 21:39 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, linux-spi,
	linux-gpio, Rob Herring, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On 2020/11/10 6:22, Serge Semin wrote:
> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>> ctrlr0 register format. This SoC is also quite slow and gets significant
>> SD card performance improvements from using no-delay polled transfers.
>> Add the dw_spi_k210_init() function tied to the
>> "canaan,kendryte-k210-spi" compatible string to set the
>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>> for this SoC.
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>> index 3f1bc384cb45..a00def6c5b39 100644
>> --- a/drivers/spi/spi-dw-mmio.c
>> +++ b/drivers/spi/spi-dw-mmio.c
>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>  	return 0;
>>  }
>>  
>> +static int dw_spi_k210_init(struct platform_device *pdev,
>> +			    struct dw_spi_mmio *dwsmmio)
>> +{
>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>> +
>> +	return 0;
>> +}
>> +
>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>  {
>>  	int (*init_func)(struct platform_device *pdev,
>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> 
>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> 
> Other than the comments from Sean and Mark regarding the DFS_32
> feature runtime detectability, I couldn't find a patch with adding the
> new new compatible string into the DW APB SSI DT schema. Have I missed
> it? If I haven't could you add one to the next version of the series?

Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
patch for the "polling" property but forgot the compatible string.

In any case, I think that this new compatible string change can be dropped by
switching to automatically detecting the DFS32 and using a different solution
than the polling property change I sent for the RX fifo overflow problem.

I am still going through all the emails trying to understand what to try next to
avoid the polling "hack".

Thanks !

> 
> -Sergey
> 
>>  	{ /* end of table */}
>>  };
>>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
>> -- 
>> 2.28.0
>>
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-09 21:39       ` Damien Le Moal
@ 2020-11-09 21:55         ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:55 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
> On 2020/11/10 6:22, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> >> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> >> ctrlr0 register format. This SoC is also quite slow and gets significant
> >> SD card performance improvements from using no-delay polled transfers.
> >> Add the dw_spi_k210_init() function tied to the
> >> "canaan,kendryte-k210-spi" compatible string to set the
> >> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> >> for this SoC.
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >> ---
> >>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >>
> >> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> >> index 3f1bc384cb45..a00def6c5b39 100644
> >> --- a/drivers/spi/spi-dw-mmio.c
> >> +++ b/drivers/spi/spi-dw-mmio.c
> >> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >>  	return 0;
> >>  }
> >>  
> >> +static int dw_spi_k210_init(struct platform_device *pdev,
> >> +			    struct dw_spi_mmio *dwsmmio)
> >> +{
> >> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >>  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >>  {
> >>  	int (*init_func)(struct platform_device *pdev,
> >> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> > 
> >> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> > 
> > Other than the comments from Sean and Mark regarding the DFS_32
> > feature runtime detectability, I couldn't find a patch with adding the
> > new new compatible string into the DW APB SSI DT schema. Have I missed
> > it? If I haven't could you add one to the next version of the series?
> 
> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
> patch for the "polling" property but forgot the compatible string.
> 
> In any case, I think that this new compatible string change can be dropped by
> switching to automatically detecting the DFS32 and using a different solution
> than the polling property change I sent for the RX fifo overflow problem.

No, new SoC needs new compatible string. Especially if a new vendor. 

> 
> I am still going through all the emails trying to understand what to try next to
> avoid the polling "hack".

Use compatible.

Rob

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 21:55         ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:55 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
> On 2020/11/10 6:22, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> >> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> >> ctrlr0 register format. This SoC is also quite slow and gets significant
> >> SD card performance improvements from using no-delay polled transfers.
> >> Add the dw_spi_k210_init() function tied to the
> >> "canaan,kendryte-k210-spi" compatible string to set the
> >> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> >> for this SoC.
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >> ---
> >>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >>
> >> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> >> index 3f1bc384cb45..a00def6c5b39 100644
> >> --- a/drivers/spi/spi-dw-mmio.c
> >> +++ b/drivers/spi/spi-dw-mmio.c
> >> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >>  	return 0;
> >>  }
> >>  
> >> +static int dw_spi_k210_init(struct platform_device *pdev,
> >> +			    struct dw_spi_mmio *dwsmmio)
> >> +{
> >> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >>  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >>  {
> >>  	int (*init_func)(struct platform_device *pdev,
> >> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> > 
> >> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> > 
> > Other than the comments from Sean and Mark regarding the DFS_32
> > feature runtime detectability, I couldn't find a patch with adding the
> > new new compatible string into the DW APB SSI DT schema. Have I missed
> > it? If I haven't could you add one to the next version of the series?
> 
> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
> patch for the "polling" property but forgot the compatible string.
> 
> In any case, I think that this new compatible string change can be dropped by
> switching to automatically detecting the DFS32 and using a different solution
> than the polling property change I sent for the RX fifo overflow problem.

No, new SoC needs new compatible string. Especially if a new vendor. 

> 
> I am still going through all the emails trying to understand what to try next to
> avoid the polling "hack".

Use compatible.

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 21:58     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:58 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:14:11PM +0900, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC clock driver
> in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml

This and the header go in 1 patch. And before the driver patch.

> 
> diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> new file mode 100644
> index 000000000000..02f5f8a86bc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Clock Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 clock controller driver which support the system controller
> +  subsystem supplied clocks for the various controllers and peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/clock/k210-clk.h
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-clk
> +
> +  clocks:
> +    maxItems: 1
> +    description: System fixed rate oscillator clock
> +
> +  '#clock-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - '#clock-cells'
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/k210-clk.h>
> +
> +    clocks {
> +      in0: oscillator {
> +        compatible = "fixed-clock";
> +        #clock-cells = <0>;
> +        clock-frequency = <26000000>;
> +      };
> +    };
> +
> +    soc {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      /* ... */
> +
> +      sysctl: system-controller@50440000 {
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        compatible = "kendryte,k210-sysctl",
> +                     "syscon", "simple-mfd";
> +        reg = <0x50440000 0x1000>;
> +        /* ... */
> +        sysclk: clock-controller {
> +          #clock-cells = <1>;
> +          compatible = "kendryte,k210-clk";
> +          clocks = <&in0>;
> +        };
> +        /* ... */
> +      };
> +    };
> +
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings
@ 2020-11-09 21:58     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:58 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:14:11PM +0900, Damien Le Moal wrote:
> Document the device tree bindings of the Kendryte K210 SoC clock driver
> in Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml.
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  .../bindings/clock/kendryte,k210-clk.yaml     | 70 +++++++++++++++++++
>  1 file changed, 70 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml

This and the header go in 1 patch. And before the driver patch.

> 
> diff --git a/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> new file mode 100644
> index 000000000000..02f5f8a86bc8
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/clock/kendryte,k210-clk.yaml
> @@ -0,0 +1,70 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/clock/kendryte,k210-clk.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Kendryte K210 Clock Device Tree Bindings
> +
> +maintainers:
> +  - Damien Le Moal <damien.lemoal@wdc.com>
> +
> +description: |
> +  Kendryte K210 clock controller driver which support the system controller
> +  subsystem supplied clocks for the various controllers and peripherals within
> +  the SoC.
> +
> +  See also:
> +  - dt-bindings/clock/k210-clk.h
> +
> +properties:
> +  compatible:
> +    const: kendryte,k210-clk
> +
> +  clocks:
> +    maxItems: 1
> +    description: System fixed rate oscillator clock
> +
> +  '#clock-cells':
> +    const: 1
> +
> +required:
> +  - compatible
> +  - '#clock-cells'
> +  - clocks
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +    #include <dt-bindings/clock/k210-clk.h>
> +
> +    clocks {
> +      in0: oscillator {
> +        compatible = "fixed-clock";
> +        #clock-cells = <0>;
> +        clock-frequency = <26000000>;
> +      };
> +    };
> +
> +    soc {
> +      #address-cells = <1>;
> +      #size-cells = <1>;
> +      /* ... */
> +
> +      sysctl: system-controller@50440000 {
> +        #address-cells = <1>;
> +        #size-cells = <1>;
> +        compatible = "kendryte,k210-sysctl",
> +                     "syscon", "simple-mfd";
> +        reg = <0x50440000 0x1000>;
> +        /* ... */
> +        sysclk: clock-controller {
> +          #clock-cells = <1>;
> +          compatible = "kendryte,k210-clk";
> +          clocks = <&in0>;
> +        };
> +        /* ... */
> +      };
> +    };
> +
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 21:59     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:59 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> define the offset of all registers of the K210 system controller.

We generally don't have defines for registers in DT.

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
> 
> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
> new file mode 100644
> index 000000000000..5cc386d3c9ca
> --- /dev/null
> +++ b/include/dt-bindings/mfd/k210-sysctl.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef MFD_K210_SYSCTL_H
> +#define MFD_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller registers offsets.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
> +
> +#endif /* MFD_K210_SYSCTL_H */
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
@ 2020-11-09 21:59     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 21:59 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> define the offset of all registers of the K210 system controller.

We generally don't have defines for registers in DT.

> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
> 
> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
> new file mode 100644
> index 000000000000..5cc386d3c9ca
> --- /dev/null
> +++ b/include/dt-bindings/mfd/k210-sysctl.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> + */
> +#ifndef MFD_K210_SYSCTL_H
> +#define MFD_K210_SYSCTL_H
> +
> +/*
> + * Kendryte K210 SoC system controller registers offsets.
> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
> + */
> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
> +
> +#endif /* MFD_K210_SYSCTL_H */
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-09 21:55         ` Rob Herring
@ 2020-11-09 22:00           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 22:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On 2020/11/10 6:55, Rob Herring wrote:
> On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
>> On 2020/11/10 6:22, Serge Semin wrote:
>>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>>> SD card performance improvements from using no-delay polled transfers.
>>>> Add the dw_spi_k210_init() function tied to the
>>>> "canaan,kendryte-k210-spi" compatible string to set the
>>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>>> for this SoC.
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>> ---
>>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>>  1 file changed, 9 insertions(+)
>>>>
>>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>>> index 3f1bc384cb45..a00def6c5b39 100644
>>>> --- a/drivers/spi/spi-dw-mmio.c
>>>> +++ b/drivers/spi/spi-dw-mmio.c
>>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>>  	return 0;
>>>>  }
>>>>  
>>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>>> +			    struct dw_spi_mmio *dwsmmio)
>>>> +{
>>>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>>  {
>>>>  	int (*init_func)(struct platform_device *pdev,
>>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>>
>>>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>
>>> Other than the comments from Sean and Mark regarding the DFS_32
>>> feature runtime detectability, I couldn't find a patch with adding the
>>> new new compatible string into the DW APB SSI DT schema. Have I missed
>>> it? If I haven't could you add one to the next version of the series?
>>
>> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
>> patch for the "polling" property but forgot the compatible string.
>>
>> In any case, I think that this new compatible string change can be dropped by
>> switching to automatically detecting the DFS32 and using a different solution
>> than the polling property change I sent for the RX fifo overflow problem.
> 
> No, new SoC needs new compatible string. Especially if a new vendor. 

My apologies for the bad wording: I meant to say the change to the list of
compatible strings that the DW SPI support would not be needed. So from the DW
SPI point of view, there would be no new compatible string to add/document.

> 
>>
>> I am still going through all the emails trying to understand what to try next to
>> avoid the polling "hack".
> 
> Use compatible.

Yes, that is what this patch used. Again, I think there is a chance this change
can be dropped.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 22:00           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 22:00 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On 2020/11/10 6:55, Rob Herring wrote:
> On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
>> On 2020/11/10 6:22, Serge Semin wrote:
>>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>>> SD card performance improvements from using no-delay polled transfers.
>>>> Add the dw_spi_k210_init() function tied to the
>>>> "canaan,kendryte-k210-spi" compatible string to set the
>>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>>> for this SoC.
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>> ---
>>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>>  1 file changed, 9 insertions(+)
>>>>
>>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>>> index 3f1bc384cb45..a00def6c5b39 100644
>>>> --- a/drivers/spi/spi-dw-mmio.c
>>>> +++ b/drivers/spi/spi-dw-mmio.c
>>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>>  	return 0;
>>>>  }
>>>>  
>>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>>> +			    struct dw_spi_mmio *dwsmmio)
>>>> +{
>>>> +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>>> +
>>>> +	return 0;
>>>> +}
>>>> +
>>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>>  {
>>>>  	int (*init_func)(struct platform_device *pdev,
>>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>>  	{ .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>>  	{ .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>>  	{ .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>>
>>>> +	{ .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>
>>> Other than the comments from Sean and Mark regarding the DFS_32
>>> feature runtime detectability, I couldn't find a patch with adding the
>>> new new compatible string into the DW APB SSI DT schema. Have I missed
>>> it? If I haven't could you add one to the next version of the series?
>>
>> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
>> patch for the "polling" property but forgot the compatible string.
>>
>> In any case, I think that this new compatible string change can be dropped by
>> switching to automatically detecting the DFS32 and using a different solution
>> than the polling property change I sent for the RX fifo overflow problem.
> 
> No, new SoC needs new compatible string. Especially if a new vendor. 

My apologies for the bad wording: I meant to say the change to the list of
compatible strings that the DW SPI support would not be needed. So from the DW
SPI point of view, there would be no new compatible string to add/document.

> 
>>
>> I am still going through all the emails trying to understand what to try next to
>> avoid the polling "hack".
> 
> Use compatible.

Yes, that is what this patch used. Again, I think there is a chance this change
can be dropped.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-09 22:01     ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 22:01 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Sat, Nov 07, 2020 at 05:14:09PM +0900, Damien Le Moal wrote:
> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index 2735be1a8470..f53d4d8e7f2a 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -179,6 +179,8 @@ patternProperties:
>      description: CALAO Systems SAS
>    "^calxeda,.*":
>      description: Calxeda
> +  "^canaan,.*":
> +    description: Canaan, Inc.
>    "^caninos,.*":
>      description: Caninos Loucos Program
>    "^capella,.*":
> @@ -537,6 +539,8 @@ patternProperties:
>      description: Ka-Ro electronics GmbH
>    "^keithkoep,.*":
>      description: Keith & Koep GmbH
> +  "^kendryte,.*":

AFAICT, this is a marketing name for a series of SoCs? That's not a 
vendor.

> +    description: Canaan, Inc.
>    "^keymile,.*":
>      description: Keymile GmbH
>    "^khadas,.*":
> -- 
> 2.28.0
> 

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
@ 2020-11-09 22:01     ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 22:01 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Sat, Nov 07, 2020 at 05:14:09PM +0900, Damien Le Moal wrote:
> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> 
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> index 2735be1a8470..f53d4d8e7f2a 100644
> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> @@ -179,6 +179,8 @@ patternProperties:
>      description: CALAO Systems SAS
>    "^calxeda,.*":
>      description: Calxeda
> +  "^canaan,.*":
> +    description: Canaan, Inc.
>    "^caninos,.*":
>      description: Caninos Loucos Program
>    "^capella,.*":
> @@ -537,6 +539,8 @@ patternProperties:
>      description: Ka-Ro electronics GmbH
>    "^keithkoep,.*":
>      description: Keith & Koep GmbH
> +  "^kendryte,.*":

AFAICT, this is a marketing name for a series of SoCs? That's not a 
vendor.

> +    description: Canaan, Inc.
>    "^keymile,.*":
>      description: Keymile GmbH
>    "^khadas,.*":
> -- 
> 2.28.0
> 

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
  2020-11-09 22:01     ` Rob Herring
@ 2020-11-09 22:04       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 22:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On 2020/11/10 7:01, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:09PM +0900, Damien Le Moal wrote:
>> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
>> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> index 2735be1a8470..f53d4d8e7f2a 100644
>> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> @@ -179,6 +179,8 @@ patternProperties:
>>      description: CALAO Systems SAS
>>    "^calxeda,.*":
>>      description: Calxeda
>> +  "^canaan,.*":
>> +    description: Canaan, Inc.
>>    "^caninos,.*":
>>      description: Caninos Loucos Program
>>    "^capella,.*":
>> @@ -537,6 +539,8 @@ patternProperties:
>>      description: Ka-Ro electronics GmbH
>>    "^keithkoep,.*":
>>      description: Keith & Koep GmbH
>> +  "^kendryte,.*":
> 
> AFAICT, this is a marketing name for a series of SoCs? That's not a 
> vendor.

Correct. Sean pointed this out to me already. The vendor is "Canaan".
I will change in V2 all compatible strings to have the proper format starting
with the vendor, e.g. "canaan,kendryte-k210-..." or may be more simply "canaan,
k210-...".

> 
>> +    description: Canaan, Inc.
>>    "^keymile,.*":
>>      description: Keymile GmbH
>>    "^khadas,.*":
>> -- 
>> 2.28.0
>>
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
@ 2020-11-09 22:04       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-09 22:04 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On 2020/11/10 7:01, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:09PM +0900, Damien Le Moal wrote:
>> Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
>> "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> index 2735be1a8470..f53d4d8e7f2a 100644
>> --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
>> @@ -179,6 +179,8 @@ patternProperties:
>>      description: CALAO Systems SAS
>>    "^calxeda,.*":
>>      description: Calxeda
>> +  "^canaan,.*":
>> +    description: Canaan, Inc.
>>    "^caninos,.*":
>>      description: Caninos Loucos Program
>>    "^capella,.*":
>> @@ -537,6 +539,8 @@ patternProperties:
>>      description: Ka-Ro electronics GmbH
>>    "^keithkoep,.*":
>>      description: Keith & Koep GmbH
>> +  "^kendryte,.*":
> 
> AFAICT, this is a marketing name for a series of SoCs? That's not a 
> vendor.

Correct. Sean pointed this out to me already. The vendor is "Canaan".
I will change in V2 all compatible strings to have the proper format starting
with the vendor, e.g. "canaan,kendryte-k210-..." or may be more simply "canaan,
k210-...".

> 
>> +    description: Canaan, Inc.
>>    "^keymile,.*":
>>      description: Keymile GmbH
>>    "^khadas,.*":
>> -- 
>> 2.28.0
>>
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
  2020-11-09 21:59     ` Rob Herring
@ 2020-11-09 22:10       ` Sean Anderson
  -1 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 22:10 UTC (permalink / raw)
  To: Rob Herring, Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Frank Rowand, devicetree,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel

On 11/9/20 4:59 PM, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
>> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
>> define the offset of all registers of the K210 system controller.
> 
> We generally don't have defines for registers in DT.

At least K210_SYSCTL_SOFT_RESET is necessary for the syscon-reboot driver.

--Sean

> 
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>>  1 file changed, 41 insertions(+)
>>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
>>
>> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
>> new file mode 100644
>> index 000000000000..5cc386d3c9ca
>> --- /dev/null
>> +++ b/include/dt-bindings/mfd/k210-sysctl.h
>> @@ -0,0 +1,41 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
>> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>> + */
>> +#ifndef MFD_K210_SYSCTL_H
>> +#define MFD_K210_SYSCTL_H
>> +
>> +/*
>> + * Kendryte K210 SoC system controller registers offsets.
>> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
>> + */
>> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
>> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
>> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
>> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
>> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
>> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
>> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
>> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
>> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
>> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
>> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
>> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
>> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
>> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
>> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
>> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
>> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
>> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
>> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
>> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
>> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
>> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
>> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
>> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
>> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
>> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
>> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
>> +
>> +#endif /* MFD_K210_SYSCTL_H */
>> -- 
>> 2.28.0
>>


^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
@ 2020-11-09 22:10       ` Sean Anderson
  0 siblings, 0 replies; 297+ messages in thread
From: Sean Anderson @ 2020-11-09 22:10 UTC (permalink / raw)
  To: Rob Herring, Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Frank Rowand, linux-clk

On 11/9/20 4:59 PM, Rob Herring wrote:
> On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
>> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
>> define the offset of all registers of the K210 system controller.
> 
> We generally don't have defines for registers in DT.

At least K210_SYSCTL_SOFT_RESET is necessary for the syscon-reboot driver.

--Sean

> 
>>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>> ---
>>  include/dt-bindings/mfd/k210-sysctl.h | 41 +++++++++++++++++++++++++++
>>  1 file changed, 41 insertions(+)
>>  create mode 100644 include/dt-bindings/mfd/k210-sysctl.h
>>
>> diff --git a/include/dt-bindings/mfd/k210-sysctl.h b/include/dt-bindings/mfd/k210-sysctl.h
>> new file mode 100644
>> index 000000000000..5cc386d3c9ca
>> --- /dev/null
>> +++ b/include/dt-bindings/mfd/k210-sysctl.h
>> @@ -0,0 +1,41 @@
>> +/* SPDX-License-Identifier: GPL-2.0+ */
>> +/*
>> + * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
>> + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
>> + */
>> +#ifndef MFD_K210_SYSCTL_H
>> +#define MFD_K210_SYSCTL_H
>> +
>> +/*
>> + * Kendryte K210 SoC system controller registers offsets.
>> + * Taken from Kendryte SDK (kendryte-standalone-sdk).
>> + */
>> +#define K210_SYSCTL_GIT_ID	0x00 /* Git short commit id */
>> +#define K210_SYSCTL_UART_BAUD	0x04 /* Default UARTHS baud rate */
>> +#define K210_SYSCTL_PLL0	0x08 /* PLL0 controller */
>> +#define K210_SYSCTL_PLL1	0x0C /* PLL1 controller */
>> +#define K210_SYSCTL_PLL2	0x10 /* PLL2 controller */
>> +#define K210_SYSCTL_PLL_LOCK	0x18 /* PLL lock tester */
>> +#define K210_SYSCTL_ROM_ERROR	0x1C /* AXI ROM detector */
>> +#define K210_SYSCTL_SEL0	0x20 /* Clock select controller 0 */
>> +#define K210_SYSCTL_SEL1	0x24 /* Clock select controller 1 */
>> +#define K210_SYSCTL_EN_CENT	0x28 /* Central clock enable */
>> +#define K210_SYSCTL_EN_PERI	0x2C /* Peripheral clock enable */
>> +#define K210_SYSCTL_SOFT_RESET	0x30 /* Soft reset ctrl */
>> +#define K210_SYSCTL_PERI_RESET	0x34 /* Peripheral reset controller */
>> +#define K210_SYSCTL_THR0	0x38 /* Clock threshold controller 0 */
>> +#define K210_SYSCTL_THR1	0x3C /* Clock threshold controller 1 */
>> +#define K210_SYSCTL_THR2	0x40 /* Clock threshold controller 2 */
>> +#define K210_SYSCTL_THR3	0x44 /* Clock threshold controller 3 */
>> +#define K210_SYSCTL_THR4	0x48 /* Clock threshold controller 4 */
>> +#define K210_SYSCTL_THR5	0x4C /* Clock threshold controller 5 */
>> +#define K210_SYSCTL_THR6	0x50 /* Clock threshold controller 6 */
>> +#define K210_SYSCTL_MISC	0x54 /* Miscellaneous controller */
>> +#define K210_SYSCTL_PERI	0x58 /* Peripheral controller */
>> +#define K210_SYSCTL_SPI_SLEEP	0x5C /* SPI sleep controller */
>> +#define K210_SYSCTL_RESET_STAT	0x60 /* Reset source status */
>> +#define K210_SYSCTL_DMA_SEL0	0x64 /* DMA handshake selector 0 */
>> +#define K210_SYSCTL_DMA_SEL1	0x68 /* DMA handshake selector 1 */
>> +#define K210_SYSCTL_POWER_SEL	0x6C /* IO Power Mode Select controller */
>> +
>> +#endif /* MFD_K210_SYSCTL_H */
>> -- 
>> 2.28.0
>>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
  2020-11-09 22:10       ` Sean Anderson
@ 2020-11-09 23:01         ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 23:01 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On Mon, Nov 9, 2020 at 4:10 PM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 11/9/20 4:59 PM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
> >> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> >> define the offset of all registers of the K210 system controller.
> >
> > We generally don't have defines for registers in DT.
>
> At least K210_SYSCTL_SOFT_RESET is necessary for the syscon-reboot driver.

How does a generic driver need your platform specific define? I meant
just use numbers directly.

Rob

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers
@ 2020-11-09 23:01         ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 23:01 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Mark Brown,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk

On Mon, Nov 9, 2020 at 4:10 PM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 11/9/20 4:59 PM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:03PM +0900, Damien Le Moal wrote:
> >> Introduce the dt-bindings file include/dt-bindings/mfd/k210_sysctl.h to
> >> define the offset of all registers of the K210 system controller.
> >
> > We generally don't have defines for registers in DT.
>
> At least K210_SYSCTL_SOFT_RESET is necessary for the syscon-reboot driver.

How does a generic driver need your platform specific define? I meant
just use numbers directly.

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-09 22:00           ` Damien Le Moal
@ 2020-11-09 23:07             ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 23:07 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Serge Semin, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On Mon, Nov 9, 2020 at 4:00 PM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
>
> On 2020/11/10 6:55, Rob Herring wrote:
> > On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
> >> On 2020/11/10 6:22, Serge Semin wrote:
> >>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> >>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> >>>> ctrlr0 register format. This SoC is also quite slow and gets significant
> >>>> SD card performance improvements from using no-delay polled transfers.
> >>>> Add the dw_spi_k210_init() function tied to the
> >>>> "canaan,kendryte-k210-spi" compatible string to set the
> >>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> >>>> for this SoC.
> >>>>
> >>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >>>> ---
> >>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >>>>  1 file changed, 9 insertions(+)
> >>>>
> >>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> >>>> index 3f1bc384cb45..a00def6c5b39 100644
> >>>> --- a/drivers/spi/spi-dw-mmio.c
> >>>> +++ b/drivers/spi/spi-dw-mmio.c
> >>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >>>>    return 0;
> >>>>  }
> >>>>
> >>>> +static int dw_spi_k210_init(struct platform_device *pdev,
> >>>> +                      struct dw_spi_mmio *dwsmmio)
> >>>> +{
> >>>> +  dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> >>>> +
> >>>> +  return 0;
> >>>> +}
> >>>> +
> >>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >>>>  {
> >>>>    int (*init_func)(struct platform_device *pdev,
> >>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >>>>    { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >>>>    { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >>>>    { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> >>>
> >>>> +  { .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> >>>
> >>> Other than the comments from Sean and Mark regarding the DFS_32
> >>> feature runtime detectability, I couldn't find a patch with adding the
> >>> new new compatible string into the DW APB SSI DT schema. Have I missed
> >>> it? If I haven't could you add one to the next version of the series?
> >>
> >> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
> >> patch for the "polling" property but forgot the compatible string.
> >>
> >> In any case, I think that this new compatible string change can be dropped by
> >> switching to automatically detecting the DFS32 and using a different solution
> >> than the polling property change I sent for the RX fifo overflow problem.
> >
> > No, new SoC needs new compatible string. Especially if a new vendor.
>
> My apologies for the bad wording: I meant to say the change to the list of
> compatible strings that the DW SPI support would not be needed. So from the DW
> SPI point of view, there would be no new compatible string to add/document.

No, there is a need for a new compatible string to add/document. You
might not need it in the driver if you have a fallback.

Compatible strings should be SoC specific so you can handle quirks
without a DT change. Otherwise, it's a never ending stream of new
properties and DT updates.

> >> I am still going through all the emails trying to understand what to try next to
> >> avoid the polling "hack".
> >
> > Use compatible.
>
> Yes, that is what this patch used. Again, I think there is a chance this change
> can be dropped.

Looks to me like it used a 'polling' property...

Rob

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-09 23:07             ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-09 23:07 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On Mon, Nov 9, 2020 at 4:00 PM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
>
> On 2020/11/10 6:55, Rob Herring wrote:
> > On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
> >> On 2020/11/10 6:22, Serge Semin wrote:
> >>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
> >>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> >>>> ctrlr0 register format. This SoC is also quite slow and gets significant
> >>>> SD card performance improvements from using no-delay polled transfers.
> >>>> Add the dw_spi_k210_init() function tied to the
> >>>> "canaan,kendryte-k210-spi" compatible string to set the
> >>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> >>>> for this SoC.
> >>>>
> >>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >>>> ---
> >>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >>>>  1 file changed, 9 insertions(+)
> >>>>
> >>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> >>>> index 3f1bc384cb45..a00def6c5b39 100644
> >>>> --- a/drivers/spi/spi-dw-mmio.c
> >>>> +++ b/drivers/spi/spi-dw-mmio.c
> >>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >>>>    return 0;
> >>>>  }
> >>>>
> >>>> +static int dw_spi_k210_init(struct platform_device *pdev,
> >>>> +                      struct dw_spi_mmio *dwsmmio)
> >>>> +{
> >>>> +  dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> >>>> +
> >>>> +  return 0;
> >>>> +}
> >>>> +
> >>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >>>>  {
> >>>>    int (*init_func)(struct platform_device *pdev,
> >>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >>>>    { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >>>>    { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >>>>    { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> >>>
> >>>> +  { .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
> >>>
> >>> Other than the comments from Sean and Mark regarding the DFS_32
> >>> feature runtime detectability, I couldn't find a patch with adding the
> >>> new new compatible string into the DW APB SSI DT schema. Have I missed
> >>> it? If I haven't could you add one to the next version of the series?
> >>
> >> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
> >> patch for the "polling" property but forgot the compatible string.
> >>
> >> In any case, I think that this new compatible string change can be dropped by
> >> switching to automatically detecting the DFS32 and using a different solution
> >> than the polling property change I sent for the RX fifo overflow problem.
> >
> > No, new SoC needs new compatible string. Especially if a new vendor.
>
> My apologies for the bad wording: I meant to say the change to the list of
> compatible strings that the DW SPI support would not be needed. So from the DW
> SPI point of view, there would be no new compatible string to add/document.

No, there is a need for a new compatible string to add/document. You
might not need it in the driver if you have a fallback.

Compatible strings should be SoC specific so you can handle quirks
without a DT change. Otherwise, it's a never ending stream of new
properties and DT updates.

> >> I am still going through all the emails trying to understand what to try next to
> >> avoid the polling "hack".
> >
> > Use compatible.
>
> Yes, that is what this patch used. Again, I think there is a chance this change
> can be dropped.

Looks to me like it used a 'polling' property...

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-09 23:07             ` Rob Herring
@ 2020-11-10  0:35               ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-10  0:35 UTC (permalink / raw)
  To: Rob Herring
  Cc: Serge Semin, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, linux-gpio, Philipp Zabel, Sean Anderson

On 2020/11/10 8:08, Rob Herring wrote:
> On Mon, Nov 9, 2020 at 4:00 PM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
>>
>> On 2020/11/10 6:55, Rob Herring wrote:
>>> On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
>>>> On 2020/11/10 6:22, Serge Semin wrote:
>>>>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>>>>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>>>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>>>>> SD card performance improvements from using no-delay polled transfers.
>>>>>> Add the dw_spi_k210_init() function tied to the
>>>>>> "canaan,kendryte-k210-spi" compatible string to set the
>>>>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>>>>> for this SoC.
>>>>>>
>>>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>>>> ---
>>>>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>>>>  1 file changed, 9 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>>>>> index 3f1bc384cb45..a00def6c5b39 100644
>>>>>> --- a/drivers/spi/spi-dw-mmio.c
>>>>>> +++ b/drivers/spi/spi-dw-mmio.c
>>>>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>>>>    return 0;
>>>>>>  }
>>>>>>
>>>>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>>>>> +                      struct dw_spi_mmio *dwsmmio)
>>>>>> +{
>>>>>> +  dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>>>>> +
>>>>>> +  return 0;
>>>>>> +}
>>>>>> +
>>>>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>>>>  {
>>>>>>    int (*init_func)(struct platform_device *pdev,
>>>>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>>>>    { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>>>>    { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>>>>    { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>>>>
>>>>>> +  { .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>>>
>>>>> Other than the comments from Sean and Mark regarding the DFS_32
>>>>> feature runtime detectability, I couldn't find a patch with adding the
>>>>> new new compatible string into the DW APB SSI DT schema. Have I missed
>>>>> it? If I haven't could you add one to the next version of the series?
>>>>
>>>> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
>>>> patch for the "polling" property but forgot the compatible string.
>>>>
>>>> In any case, I think that this new compatible string change can be dropped by
>>>> switching to automatically detecting the DFS32 and using a different solution
>>>> than the polling property change I sent for the RX fifo overflow problem.
>>>
>>> No, new SoC needs new compatible string. Especially if a new vendor.
>>
>> My apologies for the bad wording: I meant to say the change to the list of
>> compatible strings that the DW SPI support would not be needed. So from the DW
>> SPI point of view, there would be no new compatible string to add/document.
> 
> No, there is a need for a new compatible string to add/document. You
> might not need it in the driver if you have a fallback.
> 
> Compatible strings should be SoC specific so you can handle quirks
> without a DT change. Otherwise, it's a never ending stream of new
> properties and DT updates.

Ah. OK. I get it now. Thanks for clarifying. So I will keep the new compatible
string (renamed with proper vendor name instead of brand) and document it.

> 
>>>> I am still going through all the emails trying to understand what to try next to
>>>> avoid the polling "hack".
>>>
>>> Use compatible.
>>
>> Yes, that is what this patch used. Again, I think there is a chance this change
>> can be dropped.
> 
> Looks to me like it used a 'polling' property...

I hope to be able to get rid of this change if a proper solution can be found to
the transfer speed problem I am seeing.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-10  0:35               ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-10  0:35 UTC (permalink / raw)
  To: Rob Herring
  Cc: devicetree, Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	linux-gpio, Mark Brown, Palmer Dabbelt, Philipp Zabel,
	linux-riscv, Sean Anderson, Frank Rowand, linux-clk

On 2020/11/10 8:08, Rob Herring wrote:
> On Mon, Nov 9, 2020 at 4:00 PM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
>>
>> On 2020/11/10 6:55, Rob Herring wrote:
>>> On Mon, Nov 09, 2020 at 09:39:19PM +0000, Damien Le Moal wrote:
>>>> On 2020/11/10 6:22, Serge Semin wrote:
>>>>> On Sat, Nov 07, 2020 at 05:13:54PM +0900, Damien Le Moal wrote:
>>>>>> The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
>>>>>> ctrlr0 register format. This SoC is also quite slow and gets significant
>>>>>> SD card performance improvements from using no-delay polled transfers.
>>>>>> Add the dw_spi_k210_init() function tied to the
>>>>>> "canaan,kendryte-k210-spi" compatible string to set the
>>>>>> DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
>>>>>> for this SoC.
>>>>>>
>>>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>>>> ---
>>>>>>  drivers/spi/spi-dw-mmio.c | 9 +++++++++
>>>>>>  1 file changed, 9 insertions(+)
>>>>>>
>>>>>> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
>>>>>> index 3f1bc384cb45..a00def6c5b39 100644
>>>>>> --- a/drivers/spi/spi-dw-mmio.c
>>>>>> +++ b/drivers/spi/spi-dw-mmio.c
>>>>>> @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
>>>>>>    return 0;
>>>>>>  }
>>>>>>
>>>>>> +static int dw_spi_k210_init(struct platform_device *pdev,
>>>>>> +                      struct dw_spi_mmio *dwsmmio)
>>>>>> +{
>>>>>> +  dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
>>>>>> +
>>>>>> +  return 0;
>>>>>> +}
>>>>>> +
>>>>>>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>>>>>>  {
>>>>>>    int (*init_func)(struct platform_device *pdev,
>>>>>> @@ -340,6 +348,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>>>>>>    { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>>>>>>    { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>>>>>>    { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
>>>>>
>>>>>> +  { .compatible = "canaan,kendryte-k210-spi", .data = dw_spi_k210_init},
>>>>>
>>>>> Other than the comments from Sean and Mark regarding the DFS_32
>>>>> feature runtime detectability, I couldn't find a patch with adding the
>>>>> new new compatible string into the DW APB SSI DT schema. Have I missed
>>>>> it? If I haven't could you add one to the next version of the series?
>>>>
>>>> Yes, I will. I forgot to change the DW DT binding doc for this. I did add a
>>>> patch for the "polling" property but forgot the compatible string.
>>>>
>>>> In any case, I think that this new compatible string change can be dropped by
>>>> switching to automatically detecting the DFS32 and using a different solution
>>>> than the polling property change I sent for the RX fifo overflow problem.
>>>
>>> No, new SoC needs new compatible string. Especially if a new vendor.
>>
>> My apologies for the bad wording: I meant to say the change to the list of
>> compatible strings that the DW SPI support would not be needed. So from the DW
>> SPI point of view, there would be no new compatible string to add/document.
> 
> No, there is a need for a new compatible string to add/document. You
> might not need it in the driver if you have a fallback.
> 
> Compatible strings should be SoC specific so you can handle quirks
> without a DT change. Otherwise, it's a never ending stream of new
> properties and DT updates.

Ah. OK. I get it now. Thanks for clarifying. So I will keep the new compatible
string (renamed with proper vendor name instead of brand) and document it.

> 
>>>> I am still going through all the emails trying to understand what to try next to
>>>> avoid the polling "hack".
>>>
>>> Use compatible.
>>
>> Yes, that is what this patch used. Again, I think there is a chance this change
>> can be dropped.
> 
> Looks to me like it used a 'polling' property...

I hope to be able to get rid of this change if a proper solution can be found to
the transfer speed problem I am seeing.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
  2020-11-09 21:05               ` Serge Semin
@ 2020-11-10 13:43                 ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-10 13:43 UTC (permalink / raw)
  To: Serge Semin
  Cc: Sean Anderson, Damien Le Moal, Palmer Dabbelt, linux-riscv,
	Rob Herring, Frank Rowand, devicetree, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel

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

On Tue, Nov 10, 2020 at 12:05:31AM +0300, Serge Semin wrote:

> If by general Rx-only half-duplex transfers you meant that the client
> SPI-device shall just not care what the MOSI level, then the only
> acceptable solution of the noted in this patch problem is to fix the
> client driver. Since in case of the MMC-SPI client device sometimes it
> does care about the level.

Yes, that's how the API is at present (as you say) and is the more
general case for SPI devices that I've seen - I'm not *totally* against
adding something to the core if there's enough users that could usefully
use it but if it's just one or two then it seems like it'll be more
robust to stick with the current API.

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving
@ 2020-11-10 13:43                 ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-10 13:43 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Sean Anderson, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, linux-spi, Frank Rowand, linux-clk


[-- Attachment #1.1: Type: text/plain, Size: 694 bytes --]

On Tue, Nov 10, 2020 at 12:05:31AM +0300, Serge Semin wrote:

> If by general Rx-only half-duplex transfers you meant that the client
> SPI-device shall just not care what the MOSI level, then the only
> acceptable solution of the noted in this patch problem is to fix the
> client driver. Since in case of the MMC-SPI client device sometimes it
> does care about the level.

Yes, that's how the API is at present (as you say) and is the more
general case for SPI devices that I've seen - I'm not *totally* against
adding something to the core if there's enough users that could usefully
use it but if it's just one or two then it seems like it'll be more
robust to stick with the current API.

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-10 14:39     ` Linus Walleij
  -1 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-10 14:39 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, Philipp Zabel, Sean Anderson

On Sat, Nov 7, 2020 at 9:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> Fix the check on the number of IRQs to allow up to the maximum (32)
> instead of only the maximum minus one.
>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

I just ripped this patch out of your patch set and applied it to
the GPIO tree with some minor change to the subject.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
@ 2020-11-10 14:39     ` Linus Walleij
  0 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-10 14:39 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Mark Brown, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Sat, Nov 7, 2020 at 9:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> Fix the check on the number of IRQs to allow up to the maximum (32)
> instead of only the maximum minus one.
>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

I just ripped this patch out of your patch set and applied it to
the GPIO tree with some minor change to the subject.

Yours,
Linus Walleij

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
  2020-11-10 14:39     ` Linus Walleij
@ 2020-11-11  7:00       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11  7:00 UTC (permalink / raw)
  To: linus.walleij; +Cc: palmer, linux-riscv, linux-gpio

On Tue, 2020-11-10 at 15:39 +0100, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
> > Fix the check on the number of IRQs to allow up to the maximum (32)
> > instead of only the maximum minus one.
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> I just ripped this patch out of your patch set and applied it to
> the GPIO tree with some minor change to the subject.

Thanks for that. I will remove this patch from V2 of the series.

I just realized that I forgot to add a Fixes and CC stable tags. The patch
should have:

Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
Cc: stable@vger.kernel.org

Do you want me to resend the patch with the added tags ?

> 
> Yours,
> Linus Walleij

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
@ 2020-11-11  7:00       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11  7:00 UTC (permalink / raw)
  To: linus.walleij; +Cc: linux-gpio, linux-riscv, palmer

On Tue, 2020-11-10 at 15:39 +0100, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
> > Fix the check on the number of IRQs to allow up to the maximum (32)
> > instead of only the maximum minus one.
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> I just ripped this patch out of your patch set and applied it to
> the GPIO tree with some minor change to the subject.

Thanks for that. I will remove this patch from V2 of the series.

I just realized that I forgot to add a Fixes and CC stable tags. The patch
should have:

Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
Cc: stable@vger.kernel.org

Do you want me to resend the patch with the added tags ?

> 
> Yours,
> Linus Walleij

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
  2020-11-11  7:00       ` Damien Le Moal
@ 2020-11-11  8:54         ` Linus Walleij
  -1 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-11  8:54 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: palmer, linux-riscv, linux-gpio

On Wed, Nov 11, 2020 at 8:00 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:

> I just realized that I forgot to add a Fixes and CC stable tags. The patch
> should have:
>
> Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
> Cc: stable@vger.kernel.org
>
> Do you want me to resend the patch with the added tags ?

No I just moved the path to the fixes branch and added the tags.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
@ 2020-11-11  8:54         ` Linus Walleij
  0 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-11  8:54 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-gpio, linux-riscv, palmer

On Wed, Nov 11, 2020 at 8:00 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:

> I just realized that I forgot to add a Fixes and CC stable tags. The patch
> should have:
>
> Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
> Cc: stable@vger.kernel.org
>
> Do you want me to resend the patch with the added tags ?

No I just moved the path to the fixes branch and added the tags.

Yours,
Linus Walleij

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
  2020-11-11  8:54         ` Linus Walleij
@ 2020-11-11  8:56           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11  8:56 UTC (permalink / raw)
  To: Linus Walleij; +Cc: palmer, linux-riscv, linux-gpio

On 2020/11/11 17:54, Linus Walleij wrote:
> On Wed, Nov 11, 2020 at 8:00 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> 
>> I just realized that I forgot to add a Fixes and CC stable tags. The patch
>> should have:
>>
>> Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
>> Cc: stable@vger.kernel.org
>>
>> Do you want me to resend the patch with the added tags ?
> 
> No I just moved the path to the fixes branch and added the tags.
> 
> Yours,
> Linus Walleij
> 

Thanks !

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 09/32] riscv: Fix SiFive gpio probe
@ 2020-11-11  8:56           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11  8:56 UTC (permalink / raw)
  To: Linus Walleij; +Cc: linux-gpio, linux-riscv, palmer

On 2020/11/11 17:54, Linus Walleij wrote:
> On Wed, Nov 11, 2020 at 8:00 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> 
>> I just realized that I forgot to add a Fixes and CC stable tags. The patch
>> should have:
>>
>> Fixes: 96868dce644d ("gpio/sifive: Add GPIO driver for SiFive SoCs")
>> Cc: stable@vger.kernel.org
>>
>> Do you want me to resend the patch with the added tags ?
> 
> No I just moved the path to the fixes branch and added the tags.
> 
> Yours,
> Linus Walleij
> 

Thanks !

-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-09 15:45       ` Sean Anderson
@ 2020-11-11 14:32         ` Rob Herring
  -1 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-11 14:32 UTC (permalink / raw)
  To: Sean Anderson
  Cc: Damien Le Moal, Palmer Dabbelt, linux-riscv, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, open list:GPIO SUBSYSTEM,
	Philipp Zabel

On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 11/9/20 10:36 AM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> >> Document the device tree bindings for the Kendryte K210 SoC Fully
> >> Programmable IO Array (FPIOA) pinctrl driver in
> >> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >> ---
> >>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
> >>  1 file changed, 106 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >> new file mode 100644
> >> index 000000000000..8730add88ee0
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >> @@ -0,0 +1,106 @@
> >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> >> +%YAML 1.2
> >> +---
> >> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> >> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >> +
> >> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> >> +
> >> +maintainers:
> >> +  - Damien Le Moal <damien.lemoal@wdc.com>
> >> +
> >> +description:
> >> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> >> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> >> +  is performed on a per-pin basis.
> >> +
> >> +properties:
> >> +  compatible:
> >> +    const: kendryte,k210-fpioa
> >> +
> >> +  reg:
> >> +    description: FPIOA controller register space base address and size
> >> +
> >> +  clocks:
> >> +    minItems: 2
> >> +    maxItems: 2
> >
> > Can drop these. Implied by 'items' length.
> >
> >> +    items:
> >> +      - description: Controller reference clock source
> >> +      - description: APB interface clock source
> >> +
> >> +  clock-names:
> >> +    minItems: 2
> >> +    maxItems: 2
> >> +    items:
> >> +      - const: ref
> >> +      - const: pclk
> >> +
> >> +  resets:
> >> +    maxItems: 1
> >> +
> >> +  kendryte,sysctl:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> >> +    description: |
> >> +      phandle to the system controller node
> >> +
> >> +  kendryte,power-offset:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/uint32
> >> +    description: |
> >> +      Offset of the power domain control register of the system controller.
> >
> > Sounds like you should be using power-domains binding.
>
> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

Okay, please make that clear in the description. You can combine the
above 2 properties into one which is a phandle+offset.

Rob

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-11 14:32         ` Rob Herring
  0 siblings, 0 replies; 297+ messages in thread
From: Rob Herring @ 2020-11-11 14:32 UTC (permalink / raw)
  To: Sean Anderson
  Cc: devicetree, Damien Le Moal, Stephen Boyd, Linus Walleij,
	Serge Semin, linux-spi, open list:GPIO SUBSYSTEM, Mark Brown,
	Palmer Dabbelt, Philipp Zabel, linux-riscv, Frank Rowand,
	linux-clk

On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
>
> On 11/9/20 10:36 AM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> >> Document the device tree bindings for the Kendryte K210 SoC Fully
> >> Programmable IO Array (FPIOA) pinctrl driver in
> >> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> >> ---
> >>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
> >>  1 file changed, 106 insertions(+)
> >>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >> new file mode 100644
> >> index 000000000000..8730add88ee0
> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >> @@ -0,0 +1,106 @@
> >> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> >> +%YAML 1.2
> >> +---
> >> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> >> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> >> +
> >> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> >> +
> >> +maintainers:
> >> +  - Damien Le Moal <damien.lemoal@wdc.com>
> >> +
> >> +description:
> >> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> >> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> >> +  is performed on a per-pin basis.
> >> +
> >> +properties:
> >> +  compatible:
> >> +    const: kendryte,k210-fpioa
> >> +
> >> +  reg:
> >> +    description: FPIOA controller register space base address and size
> >> +
> >> +  clocks:
> >> +    minItems: 2
> >> +    maxItems: 2
> >
> > Can drop these. Implied by 'items' length.
> >
> >> +    items:
> >> +      - description: Controller reference clock source
> >> +      - description: APB interface clock source
> >> +
> >> +  clock-names:
> >> +    minItems: 2
> >> +    maxItems: 2
> >> +    items:
> >> +      - const: ref
> >> +      - const: pclk
> >> +
> >> +  resets:
> >> +    maxItems: 1
> >> +
> >> +  kendryte,sysctl:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/phandle-array
> >> +    description: |
> >> +      phandle to the system controller node
> >> +
> >> +  kendryte,power-offset:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/uint32
> >> +    description: |
> >> +      Offset of the power domain control register of the system controller.
> >
> > Sounds like you should be using power-domains binding.
>
> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

Okay, please make that clear in the description. You can combine the
above 2 properties into one which is a phandle+offset.

Rob

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-11 14:32         ` Rob Herring
@ 2020-11-11 15:06           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11 15:06 UTC (permalink / raw)
  To: Rob Herring, Sean Anderson; +Cc: Palmer Dabbelt, linux-riscv, devicetree

On 2020/11/11 23:32, Rob Herring wrote:
> On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> On 11/9/20 10:36 AM, Rob Herring wrote:
>>> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>>>> Document the device tree bindings for the Kendryte K210 SoC Fully
>>>> Programmable IO Array (FPIOA) pinctrl driver in
>>>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>> ---
>>>>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>>>>  1 file changed, 106 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>> new file mode 100644
>>>> index 000000000000..8730add88ee0
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>> @@ -0,0 +1,106 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
>>>> +
>>>> +maintainers:
>>>> +  - Damien Le Moal <damien.lemoal@wdc.com>
>>>> +
>>>> +description:
>>>> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
>>>> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
>>>> +  is performed on a per-pin basis.
>>>> +
>>>> +properties:
>>>> +  compatible:
>>>> +    const: kendryte,k210-fpioa
>>>> +
>>>> +  reg:
>>>> +    description: FPIOA controller register space base address and size
>>>> +
>>>> +  clocks:
>>>> +    minItems: 2
>>>> +    maxItems: 2
>>>
>>> Can drop these. Implied by 'items' length.
>>>
>>>> +    items:
>>>> +      - description: Controller reference clock source
>>>> +      - description: APB interface clock source
>>>> +
>>>> +  clock-names:
>>>> +    minItems: 2
>>>> +    maxItems: 2
>>>> +    items:
>>>> +      - const: ref
>>>> +      - const: pclk
>>>> +
>>>> +  resets:
>>>> +    maxItems: 1
>>>> +
>>>> +  kendryte,sysctl:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/phandle-array
>>>> +    description: |
>>>> +      phandle to the system controller node
>>>> +
>>>> +  kendryte,power-offset:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>> +    description: |
>>>> +      Offset of the power domain control register of the system controller.
>>>
>>> Sounds like you should be using power-domains binding.
>>
>> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> 
> Okay, please make that clear in the description. You can combine the
> above 2 properties into one which is a phandle+offset.

Could you point me to an example of such property ? I am not sure how to do that
so an example would help. Thanks.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-11 15:06           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-11 15:06 UTC (permalink / raw)
  To: Rob Herring, Sean Anderson; +Cc: devicetree, linux-riscv, Palmer Dabbelt

On 2020/11/11 23:32, Rob Herring wrote:
> On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
>>
>> On 11/9/20 10:36 AM, Rob Herring wrote:
>>> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>>>> Document the device tree bindings for the Kendryte K210 SoC Fully
>>>> Programmable IO Array (FPIOA) pinctrl driver in
>>>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
>>>> ---
>>>>  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
>>>>  1 file changed, 106 insertions(+)
>>>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>> new file mode 100644
>>>> index 000000000000..8730add88ee0
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>> @@ -0,0 +1,106 @@
>>>> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
>>>> +%YAML 1.2
>>>> +---
>>>> +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
>>>> +$schema: http://devicetree.org/meta-schemas/core.yaml#
>>>> +
>>>> +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
>>>> +
>>>> +maintainers:
>>>> +  - Damien Le Moal <damien.lemoal@wdc.com>
>>>> +
>>>> +description:
>>>> +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
>>>> +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
>>>> +  is performed on a per-pin basis.
>>>> +
>>>> +properties:
>>>> +  compatible:
>>>> +    const: kendryte,k210-fpioa
>>>> +
>>>> +  reg:
>>>> +    description: FPIOA controller register space base address and size
>>>> +
>>>> +  clocks:
>>>> +    minItems: 2
>>>> +    maxItems: 2
>>>
>>> Can drop these. Implied by 'items' length.
>>>
>>>> +    items:
>>>> +      - description: Controller reference clock source
>>>> +      - description: APB interface clock source
>>>> +
>>>> +  clock-names:
>>>> +    minItems: 2
>>>> +    maxItems: 2
>>>> +    items:
>>>> +      - const: ref
>>>> +      - const: pclk
>>>> +
>>>> +  resets:
>>>> +    maxItems: 1
>>>> +
>>>> +  kendryte,sysctl:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/phandle-array
>>>> +    description: |
>>>> +      phandle to the system controller node
>>>> +
>>>> +  kendryte,power-offset:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>> +    description: |
>>>> +      Offset of the power domain control register of the system controller.
>>>
>>> Sounds like you should be using power-domains binding.
>>
>> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> 
> Okay, please make that clear in the description. You can combine the
> above 2 properties into one which is a phandle+offset.

Could you point me to an example of such property ? I am not sure how to do that
so an example would help. Thanks.

> 
> Rob
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-12  7:21     ` Atish Patra
  -1 siblings, 0 replies; 297+ messages in thread
From: Atish Patra @ 2020-11-12  7:21 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	devicetree, Serge Semin, Mark Brown, linux-spi, Stephen Boyd,
	linux-clk, Linus Walleij, linux-gpio, Philipp Zabel,
	Sean Anderson

On Sat, Nov 7, 2020 at 12:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
>
> If of_clk_init() is not called in time_init(), clock providers defined
> in the system device tree are not initialized, resulting in failures for
> other devices to initialize due to missing clocks.
> Similarly to other architectures and to the default kernel time_init()
> implementation, call of_clk_init() before executing timer_probe() in
> time_init().
>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/kernel/time.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
> index 4d3a1048ad8b..8a5cf99c0776 100644
> --- a/arch/riscv/kernel/time.c
> +++ b/arch/riscv/kernel/time.c
> @@ -4,6 +4,7 @@
>   * Copyright (C) 2017 SiFive
>   */
>
> +#include <linux/of_clk.h>
>  #include <linux/clocksource.h>
>  #include <linux/delay.h>
>  #include <asm/sbi.h>
> @@ -24,6 +25,8 @@ void __init time_init(void)
>         riscv_timebase = prop;
>
>         lpj_fine = riscv_timebase / HZ;
> +
> +       of_clk_init(NULL);
>         timer_probe();
>  }
>
> --
> 2.28.0
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Reviewed-by: Atish Patra <atish.patra@wdc.com>

-- 
Regards,
Atish

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-12  7:21     ` Atish Patra
  0 siblings, 0 replies; 297+ messages in thread
From: Atish Patra @ 2020-11-12  7:21 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Stephen Boyd, Mark Brown, Serge Semin,
	linux-spi, linux-gpio, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Sat, Nov 7, 2020 at 12:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
>
> If of_clk_init() is not called in time_init(), clock providers defined
> in the system device tree are not initialized, resulting in failures for
> other devices to initialize due to missing clocks.
> Similarly to other architectures and to the default kernel time_init()
> implementation, call of_clk_init() before executing timer_probe() in
> time_init().
>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> ---
>  arch/riscv/kernel/time.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/riscv/kernel/time.c b/arch/riscv/kernel/time.c
> index 4d3a1048ad8b..8a5cf99c0776 100644
> --- a/arch/riscv/kernel/time.c
> +++ b/arch/riscv/kernel/time.c
> @@ -4,6 +4,7 @@
>   * Copyright (C) 2017 SiFive
>   */
>
> +#include <linux/of_clk.h>
>  #include <linux/clocksource.h>
>  #include <linux/delay.h>
>  #include <asm/sbi.h>
> @@ -24,6 +25,8 @@ void __init time_init(void)
>         riscv_timebase = prop;
>
>         lpj_fine = riscv_timebase / HZ;
> +
> +       of_clk_init(NULL);
>         timer_probe();
>  }
>
> --
> 2.28.0
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Reviewed-by: Atish Patra <atish.patra@wdc.com>

-- 
Regards,
Atish

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-11 15:06           ` Damien Le Moal
@ 2020-11-12 11:03             ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-12 11:03 UTC (permalink / raw)
  To: robh, seanga2; +Cc: palmer, linux-riscv, devicetree

On Wed, 2020-11-11 at 15:06 +0000, Damien Le Moal wrote:
> On 2020/11/11 23:32, Rob Herring wrote:
> > On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
> > > 
> > > On 11/9/20 10:36 AM, Rob Herring wrote:
> > > > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> > > > > Document the device tree bindings for the Kendryte K210 SoC Fully
> > > > > Programmable IO Array (FPIOA) pinctrl driver in
> > > > > Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > 
> > > > > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > > > > ---
> > > > >  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
> > > > >  1 file changed, 106 insertions(+)
> > > > >  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..8730add88ee0
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > @@ -0,0 +1,106 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> > > > > +
> > > > > +maintainers:
> > > > > +  - Damien Le Moal <damien.lemoal@wdc.com>
> > > > > +
> > > > > +description:
> > > > > +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> > > > > +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> > > > > +  is performed on a per-pin basis.
> > > > > +
> > > > > +properties:
> > > > > +  compatible:
> > > > > +    const: kendryte,k210-fpioa
> > > > > +
> > > > > +  reg:
> > > > > +    description: FPIOA controller register space base address and size
> > > > > +
> > > > > +  clocks:
> > > > > +    minItems: 2
> > > > > +    maxItems: 2
> > > > 
> > > > Can drop these. Implied by 'items' length.
> > > > 
> > > > > +    items:
> > > > > +      - description: Controller reference clock source
> > > > > +      - description: APB interface clock source
> > > > > +
> > > > > +  clock-names:
> > > > > +    minItems: 2
> > > > > +    maxItems: 2
> > > > > +    items:
> > > > > +      - const: ref
> > > > > +      - const: pclk
> > > > > +
> > > > > +  resets:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  kendryte,sysctl:
> > > > > +    minItems: 1
> > > > > +    maxItems: 1
> > > > > +    $ref: /schemas/types.yaml#/definitions/phandle-array
> > > > > +    description: |
> > > > > +      phandle to the system controller node
> > > > > +
> > > > > +  kendryte,power-offset:
> > > > > +    minItems: 1
> > > > > +    maxItems: 1
> > > > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > > > +    description: |
> > > > > +      Offset of the power domain control register of the system controller.
> > > > 
> > > > Sounds like you should be using power-domains binding.
> > > 
> > > This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> > 
> > Okay, please make that clear in the description. You can combine the
> > above 2 properties into one which is a phandle+offset.
> 
> Could you point me to an example of such property ? I am not sure how to do that
> so an example would help. Thanks.

Please ignore. Found what I need. Thanks.

> 
> > 
> > Rob
> > 
> 
> 

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-12 11:03             ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-12 11:03 UTC (permalink / raw)
  To: robh, seanga2; +Cc: devicetree, linux-riscv, palmer

On Wed, 2020-11-11 at 15:06 +0000, Damien Le Moal wrote:
> On 2020/11/11 23:32, Rob Herring wrote:
> > On Mon, Nov 9, 2020 at 9:45 AM Sean Anderson <seanga2@gmail.com> wrote:
> > > 
> > > On 11/9/20 10:36 AM, Rob Herring wrote:
> > > > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> > > > > Document the device tree bindings for the Kendryte K210 SoC Fully
> > > > > Programmable IO Array (FPIOA) pinctrl driver in
> > > > > Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > 
> > > > > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > > > > ---
> > > > >  .../bindings/pinctrl/kendryte,k210-fpioa.yaml | 106 ++++++++++++++++++
> > > > >  1 file changed, 106 insertions(+)
> > > > >  create mode 100644 Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > 
> > > > > diff --git a/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > new file mode 100644
> > > > > index 000000000000..8730add88ee0
> > > > > --- /dev/null
> > > > > +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> > > > > @@ -0,0 +1,106 @@
> > > > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > > > +%YAML 1.2
> > > > > +---
> > > > > +$id: http://devicetree.org/schemas/pinctrl/kendryte,k210-fpioa.yaml#
> > > > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > > > +
> > > > > +title: Kendryte K210 FPIOA (Fully Programmable IO Array) Device Tree Bindings
> > > > > +
> > > > > +maintainers:
> > > > > +  - Damien Le Moal <damien.lemoal@wdc.com>
> > > > > +
> > > > > +description:
> > > > > +  The Kendryte K210 SoC Fully Programmable IO Array controller allows assiging
> > > > > +  any of 256 possible functions to any of 48 IO pins. Pin function configuration
> > > > > +  is performed on a per-pin basis.
> > > > > +
> > > > > +properties:
> > > > > +  compatible:
> > > > > +    const: kendryte,k210-fpioa
> > > > > +
> > > > > +  reg:
> > > > > +    description: FPIOA controller register space base address and size
> > > > > +
> > > > > +  clocks:
> > > > > +    minItems: 2
> > > > > +    maxItems: 2
> > > > 
> > > > Can drop these. Implied by 'items' length.
> > > > 
> > > > > +    items:
> > > > > +      - description: Controller reference clock source
> > > > > +      - description: APB interface clock source
> > > > > +
> > > > > +  clock-names:
> > > > > +    minItems: 2
> > > > > +    maxItems: 2
> > > > > +    items:
> > > > > +      - const: ref
> > > > > +      - const: pclk
> > > > > +
> > > > > +  resets:
> > > > > +    maxItems: 1
> > > > > +
> > > > > +  kendryte,sysctl:
> > > > > +    minItems: 1
> > > > > +    maxItems: 1
> > > > > +    $ref: /schemas/types.yaml#/definitions/phandle-array
> > > > > +    description: |
> > > > > +      phandle to the system controller node
> > > > > +
> > > > > +  kendryte,power-offset:
> > > > > +    minItems: 1
> > > > > +    maxItems: 1
> > > > > +    $ref: /schemas/types.yaml#/definitions/uint32
> > > > > +    description: |
> > > > > +      Offset of the power domain control register of the system controller.
> > > > 
> > > > Sounds like you should be using power-domains binding.
> > > 
> > > This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> > 
> > Okay, please make that clear in the description. You can combine the
> > above 2 properties into one which is a phandle+offset.
> 
> Could you point me to an example of such property ? I am not sure how to do that
> so an example would help. Thanks.

Please ignore. Found what I need. Thanks.

> 
> > 
> > Rob
> > 
> 
> 

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-07  8:13   ` Damien Le Moal
@ 2020-11-13  7:31     ` Stephen Boyd
  -1 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  7:31 UTC (permalink / raw)
  To: Damien Le Moal, Frank Rowand, Linus Walleij, Mark Brown,
	Palmer Dabbelt, Philipp Zabel, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-gpio, linux-riscv, linux-spi
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-07 00:13:56)
> If of_clk_init() is not called in time_init(), clock providers defined
> in the system device tree are not initialized, resulting in failures for
> other devices to initialize due to missing clocks.
> Similarly to other architectures and to the default kernel time_init()
> implementation, call of_clk_init() before executing timer_probe() in
> time_init().

Do you have timers that need clks to be running or queryable this early?
This of_clk_init() call is made here when architectures need to call
things like clk_get_rate() to figure out some clk frequency for their
clockevent or clocksource. It is OK to have this call here, I'm just
curious if this is actually necessary vs. delaying it to later.

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  7:31     ` Stephen Boyd
  0 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  7:31 UTC (permalink / raw)
  To: Damien Le Moal, Frank Rowand, Linus Walleij, Mark Brown,
	Palmer Dabbelt, Philipp Zabel, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-gpio, linux-riscv, linux-spi
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-07 00:13:56)
> If of_clk_init() is not called in time_init(), clock providers defined
> in the system device tree are not initialized, resulting in failures for
> other devices to initialize due to missing clocks.
> Similarly to other architectures and to the default kernel time_init()
> implementation, call of_clk_init() before executing timer_probe() in
> time_init().

Do you have timers that need clks to be running or queryable this early?
This of_clk_init() call is made here when architectures need to call
things like clk_get_rate() to figure out some clk frequency for their
clockevent or clocksource. It is OK to have this call here, I'm just
curious if this is actually necessary vs. delaying it to later.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  7:31     ` Stephen Boyd
@ 2020-11-13  7:40       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  7:40 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 16:31, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-07 00:13:56)
>> If of_clk_init() is not called in time_init(), clock providers defined
>> in the system device tree are not initialized, resulting in failures for
>> other devices to initialize due to missing clocks.
>> Similarly to other architectures and to the default kernel time_init()
>> implementation, call of_clk_init() before executing timer_probe() in
>> time_init().
> 
> Do you have timers that need clks to be running or queryable this early?
> This of_clk_init() call is made here when architectures need to call
> things like clk_get_rate() to figure out some clk frequency for their
> clockevent or clocksource. It is OK to have this call here, I'm just
> curious if this is actually necessary vs. delaying it to later.
> 

I think the clocks could be initialized later, but at least the CLINT will
depend on one of the clocks, same for the CPU frequency information. So need
checking.

What this patch fixes is not the need for a super early initialization though,
it is that _nothing_ was being initialized without it: the clock driver probe
function was never called with the current riscv time_init() as is. I looked at
other architectures and at the default kernel time_init(), and mimicked what was
done, that is, added of_clk_init(). Is there any other way to make sure that the
needed clock drivers are initialized ?

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  7:40       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  7:40 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 16:31, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-07 00:13:56)
>> If of_clk_init() is not called in time_init(), clock providers defined
>> in the system device tree are not initialized, resulting in failures for
>> other devices to initialize due to missing clocks.
>> Similarly to other architectures and to the default kernel time_init()
>> implementation, call of_clk_init() before executing timer_probe() in
>> time_init().
> 
> Do you have timers that need clks to be running or queryable this early?
> This of_clk_init() call is made here when architectures need to call
> things like clk_get_rate() to figure out some clk frequency for their
> clockevent or clocksource. It is OK to have this call here, I'm just
> curious if this is actually necessary vs. delaying it to later.
> 

I think the clocks could be initialized later, but at least the CLINT will
depend on one of the clocks, same for the CPU frequency information. So need
checking.

What this patch fixes is not the need for a super early initialization though,
it is that _nothing_ was being initialized without it: the clock driver probe
function was never called with the current riscv time_init() as is. I looked at
other architectures and at the default kernel time_init(), and mimicked what was
done, that is, added of_clk_init(). Is there any other way to make sure that the
needed clock drivers are initialized ?

-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  7:40       ` Damien Le Moal
@ 2020-11-13  7:53         ` Stephen Boyd
  -1 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  7:53 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-12 23:40:17)
> On 2020/11/13 16:31, Stephen Boyd wrote:
> > Quoting Damien Le Moal (2020-11-07 00:13:56)
> >> If of_clk_init() is not called in time_init(), clock providers defined
> >> in the system device tree are not initialized, resulting in failures for
> >> other devices to initialize due to missing clocks.
> >> Similarly to other architectures and to the default kernel time_init()
> >> implementation, call of_clk_init() before executing timer_probe() in
> >> time_init().
> > 
> > Do you have timers that need clks to be running or queryable this early?
> > This of_clk_init() call is made here when architectures need to call
> > things like clk_get_rate() to figure out some clk frequency for their
> > clockevent or clocksource. It is OK to have this call here, I'm just
> > curious if this is actually necessary vs. delaying it to later.
> > 
> 
> I think the clocks could be initialized later, but at least the CLINT will
> depend on one of the clocks, same for the CPU frequency information. So need
> checking.
> 
> What this patch fixes is not the need for a super early initialization though,
> it is that _nothing_ was being initialized without it: the clock driver probe
> function was never called with the current riscv time_init() as is. I looked at
> other architectures and at the default kernel time_init(), and mimicked what was
> done, that is, added of_clk_init(). Is there any other way to make sure that the
> needed clock drivers are initialized ?
> 

Yes it's fine. Just the commit text reads as "If of_clk_init() is not
called in time_init() then nothing works" which is true but made me
wonder if it was because it needed to be super early or not. The commit
text could be a little clearer here.

We don't have any good solution for a fallback to call of_clk_init()
somewhere later. I do wonder if we should generalize this though and
call of_clk_init() from start_kernel() directly via some Kconfig that
architectures select if they need it for their timer and then move it to
an initcall if architectures don't select the config. Or throw it into
the of_platform_default_populate_init() hook if the architecture doesn't
need to call it early.

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  7:53         ` Stephen Boyd
  0 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  7:53 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-12 23:40:17)
> On 2020/11/13 16:31, Stephen Boyd wrote:
> > Quoting Damien Le Moal (2020-11-07 00:13:56)
> >> If of_clk_init() is not called in time_init(), clock providers defined
> >> in the system device tree are not initialized, resulting in failures for
> >> other devices to initialize due to missing clocks.
> >> Similarly to other architectures and to the default kernel time_init()
> >> implementation, call of_clk_init() before executing timer_probe() in
> >> time_init().
> > 
> > Do you have timers that need clks to be running or queryable this early?
> > This of_clk_init() call is made here when architectures need to call
> > things like clk_get_rate() to figure out some clk frequency for their
> > clockevent or clocksource. It is OK to have this call here, I'm just
> > curious if this is actually necessary vs. delaying it to later.
> > 
> 
> I think the clocks could be initialized later, but at least the CLINT will
> depend on one of the clocks, same for the CPU frequency information. So need
> checking.
> 
> What this patch fixes is not the need for a super early initialization though,
> it is that _nothing_ was being initialized without it: the clock driver probe
> function was never called with the current riscv time_init() as is. I looked at
> other architectures and at the default kernel time_init(), and mimicked what was
> done, that is, added of_clk_init(). Is there any other way to make sure that the
> needed clock drivers are initialized ?
> 

Yes it's fine. Just the commit text reads as "If of_clk_init() is not
called in time_init() then nothing works" which is true but made me
wonder if it was because it needed to be super early or not. The commit
text could be a little clearer here.

We don't have any good solution for a fallback to call of_clk_init()
somewhere later. I do wonder if we should generalize this though and
call of_clk_init() from start_kernel() directly via some Kconfig that
architectures select if they need it for their timer and then move it to
an initcall if architectures don't select the config. Or throw it into
the of_platform_default_populate_init() hook if the architecture doesn't
need to call it early.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  7:53         ` Stephen Boyd
@ 2020-11-13  7:57           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  7:57 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 16:53, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-12 23:40:17)
>> On 2020/11/13 16:31, Stephen Boyd wrote:
>>> Quoting Damien Le Moal (2020-11-07 00:13:56)
>>>> If of_clk_init() is not called in time_init(), clock providers defined
>>>> in the system device tree are not initialized, resulting in failures for
>>>> other devices to initialize due to missing clocks.
>>>> Similarly to other architectures and to the default kernel time_init()
>>>> implementation, call of_clk_init() before executing timer_probe() in
>>>> time_init().
>>>
>>> Do you have timers that need clks to be running or queryable this early?
>>> This of_clk_init() call is made here when architectures need to call
>>> things like clk_get_rate() to figure out some clk frequency for their
>>> clockevent or clocksource. It is OK to have this call here, I'm just
>>> curious if this is actually necessary vs. delaying it to later.
>>>
>>
>> I think the clocks could be initialized later, but at least the CLINT will
>> depend on one of the clocks, same for the CPU frequency information. So need
>> checking.
>>
>> What this patch fixes is not the need for a super early initialization though,
>> it is that _nothing_ was being initialized without it: the clock driver probe
>> function was never called with the current riscv time_init() as is. I looked at
>> other architectures and at the default kernel time_init(), and mimicked what was
>> done, that is, added of_clk_init(). Is there any other way to make sure that the
>> needed clock drivers are initialized ?
>>
> 
> Yes it's fine. Just the commit text reads as "If of_clk_init() is not
> called in time_init() then nothing works" which is true but made me
> wonder if it was because it needed to be super early or not. The commit
> text could be a little clearer here.

OK. I will clarify the commit message in V2. Working on it now.

> We don't have any good solution for a fallback to call of_clk_init()
> somewhere later. I do wonder if we should generalize this though and
> call of_clk_init() from start_kernel() directly via some Kconfig that
> architectures select if they need it for their timer and then move it to
> an initcall if architectures don't select the config. Or throw it into
> the of_platform_default_populate_init() hook if the architecture doesn't
> need to call it early.

This last idea seems reasonable and probably the easiest. And I think it could
be done unconditionally even if the arch calls of_clk_init() early as the
already populated clock provider nodes would not be initialized again.


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  7:57           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  7:57 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 16:53, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-12 23:40:17)
>> On 2020/11/13 16:31, Stephen Boyd wrote:
>>> Quoting Damien Le Moal (2020-11-07 00:13:56)
>>>> If of_clk_init() is not called in time_init(), clock providers defined
>>>> in the system device tree are not initialized, resulting in failures for
>>>> other devices to initialize due to missing clocks.
>>>> Similarly to other architectures and to the default kernel time_init()
>>>> implementation, call of_clk_init() before executing timer_probe() in
>>>> time_init().
>>>
>>> Do you have timers that need clks to be running or queryable this early?
>>> This of_clk_init() call is made here when architectures need to call
>>> things like clk_get_rate() to figure out some clk frequency for their
>>> clockevent or clocksource. It is OK to have this call here, I'm just
>>> curious if this is actually necessary vs. delaying it to later.
>>>
>>
>> I think the clocks could be initialized later, but at least the CLINT will
>> depend on one of the clocks, same for the CPU frequency information. So need
>> checking.
>>
>> What this patch fixes is not the need for a super early initialization though,
>> it is that _nothing_ was being initialized without it: the clock driver probe
>> function was never called with the current riscv time_init() as is. I looked at
>> other architectures and at the default kernel time_init(), and mimicked what was
>> done, that is, added of_clk_init(). Is there any other way to make sure that the
>> needed clock drivers are initialized ?
>>
> 
> Yes it's fine. Just the commit text reads as "If of_clk_init() is not
> called in time_init() then nothing works" which is true but made me
> wonder if it was because it needed to be super early or not. The commit
> text could be a little clearer here.

OK. I will clarify the commit message in V2. Working on it now.

> We don't have any good solution for a fallback to call of_clk_init()
> somewhere later. I do wonder if we should generalize this though and
> call of_clk_init() from start_kernel() directly via some Kconfig that
> architectures select if they need it for their timer and then move it to
> an initcall if architectures don't select the config. Or throw it into
> the of_platform_default_populate_init() hook if the architecture doesn't
> need to call it early.

This last idea seems reasonable and probably the easiest. And I think it could
be done unconditionally even if the arch calls of_clk_init() early as the
already populated clock provider nodes would not be initialized again.


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
  2020-11-07 13:31     ` Sean Anderson
@ 2020-11-13  8:00       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:00 UTC (permalink / raw)
  To: linux-spi, palmer, linux-riscv, broonie, seanga2, fancer.lancer

On Sat, 2020-11-07 at 08:31 -0500, Sean Anderson wrote:
> On 11/7/20 3:13 AM, Damien Le Moal wrote:
> > The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> > ctrlr0 register format. This SoC is also quite slow and gets significant
> > SD card performance improvements from using no-delay polled transfers.
> > Add the dw_spi_k210_init() function tied to the
> > "canaan,kendryte-k210-spi" compatible string to set the
> > DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> > for this SoC.
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > ---
> >  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> > index 3f1bc384cb45..a00def6c5b39 100644
> > --- a/drivers/spi/spi-dw-mmio.c
> > +++ b/drivers/spi/spi-dw-mmio.c
> > @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >  	return 0;
> >  }
> >  
> > 
> > 
> > 
> > +static int dw_spi_k210_init(struct platform_device *pdev,
> > +			    struct dw_spi_mmio *dwsmmio)
> > +{
> > +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> 
> Can't you do runtime detection of DFS_32 in probe?

Done ! Sending that in V2 (I will split the spi dw from the rest of the
series).



-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC
@ 2020-11-13  8:00       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:00 UTC (permalink / raw)
  To: linux-spi, palmer, linux-riscv, broonie, seanga2, fancer.lancer

On Sat, 2020-11-07 at 08:31 -0500, Sean Anderson wrote:
> On 11/7/20 3:13 AM, Damien Le Moal wrote:
> > The DW SPI master of the Kendryte K210 RISC-V SoC uses the 32-bits
> > ctrlr0 register format. This SoC is also quite slow and gets significant
> > SD card performance improvements from using no-delay polled transfers.
> > Add the dw_spi_k210_init() function tied to the
> > "canaan,kendryte-k210-spi" compatible string to set the
> > DW_SPI_CAP_DFS_32 and DW_SPI_CAP_POLL_NODELAY DW SPI capability fields
> > for this SoC.
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > ---
> >  drivers/spi/spi-dw-mmio.c | 9 +++++++++
> >  1 file changed, 9 insertions(+)
> > 
> > diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> > index 3f1bc384cb45..a00def6c5b39 100644
> > --- a/drivers/spi/spi-dw-mmio.c
> > +++ b/drivers/spi/spi-dw-mmio.c
> > @@ -223,6 +223,14 @@ static int dw_spi_keembay_init(struct platform_device *pdev,
> >  	return 0;
> >  }
> >  
> > 
> > 
> > 
> > +static int dw_spi_k210_init(struct platform_device *pdev,
> > +			    struct dw_spi_mmio *dwsmmio)
> > +{
> > +	dwsmmio->dws.caps = DW_SPI_CAP_DFS_32 | DW_SPI_CAP_POLL_NODELAY;
> 
> Can't you do runtime detection of DFS_32 in probe?

Done ! Sending that in V2 (I will split the spi dw from the rest of the
series).



-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  7:57           ` Damien Le Moal
@ 2020-11-13  8:11             ` Stephen Boyd
  -1 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  8:11 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-12 23:57:19)
> On 2020/11/13 16:53, Stephen Boyd wrote:
> > 
> > Yes it's fine. Just the commit text reads as "If of_clk_init() is not
> > called in time_init() then nothing works" which is true but made me
> > wonder if it was because it needed to be super early or not. The commit
> > text could be a little clearer here.
> 
> OK. I will clarify the commit message in V2. Working on it now.

Thanks!

> 
> > We don't have any good solution for a fallback to call of_clk_init()
> > somewhere later. I do wonder if we should generalize this though and
> > call of_clk_init() from start_kernel() directly via some Kconfig that
> > architectures select if they need it for their timer and then move it to
> > an initcall if architectures don't select the config. Or throw it into
> > the of_platform_default_populate_init() hook if the architecture doesn't
> > need to call it early.
> 
> This last idea seems reasonable and probably the easiest. And I think it could
> be done unconditionally even if the arch calls of_clk_init() early as the
> already populated clock provider nodes would not be initialized again.
> 

Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
wait to platform bus population time then they could be converted to
regular old platform device drivers. Maybe the problem is the clk driver
you're using is only using CLK_OF_DECLARE() and not registering a
platform driver?

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  8:11             ` Stephen Boyd
  0 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-13  8:11 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-12 23:57:19)
> On 2020/11/13 16:53, Stephen Boyd wrote:
> > 
> > Yes it's fine. Just the commit text reads as "If of_clk_init() is not
> > called in time_init() then nothing works" which is true but made me
> > wonder if it was because it needed to be super early or not. The commit
> > text could be a little clearer here.
> 
> OK. I will clarify the commit message in V2. Working on it now.

Thanks!

> 
> > We don't have any good solution for a fallback to call of_clk_init()
> > somewhere later. I do wonder if we should generalize this though and
> > call of_clk_init() from start_kernel() directly via some Kconfig that
> > architectures select if they need it for their timer and then move it to
> > an initcall if architectures don't select the config. Or throw it into
> > the of_platform_default_populate_init() hook if the architecture doesn't
> > need to call it early.
> 
> This last idea seems reasonable and probably the easiest. And I think it could
> be done unconditionally even if the arch calls of_clk_init() early as the
> already populated clock provider nodes would not be initialized again.
> 

Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
wait to platform bus population time then they could be converted to
regular old platform device drivers. Maybe the problem is the clk driver
you're using is only using CLK_OF_DECLARE() and not registering a
platform driver?

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
  2020-11-07 13:48     ` Sean Anderson
@ 2020-11-13  8:14       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:14 UTC (permalink / raw)
  To: palmer, linux-riscv, linux-clk, seanga2, sboyd

On Sat, 2020-11-07 at 08:48 -0500, Sean Anderson wrote:
[...]
> > +static void k210_pll_disable_hw(struct k210_pll *pll)
> > +{
> > +	unsigned long flags;
> > +	u32 reg;
> > +
> > +	/*
> > +	 * Bypassing before powering off is important so child clocks don't stop
> > +	 * working. This is especially important for pll0, the indirect parent
> > +	 * of the cpu clock.
> > +	 */
> 
> Did you get the bypass bit to work? I'm still having to bypass via
> re-parenting ACLK in U-boot. Perhaps it is only necessary if you change
> the rate as well?

Nope. No luck there. The Kendryte SDK also does a reparenting of ACLK to IN0
when changing the PLL rate. So I guess I should remove the comment maybe.

In any case, this is all running with the default rates, except for PLL1 rate
which is changed in early init code to end up with matching frequencies for all
SRAM banks. So I do not think that the not-so-effective bypass is an issue
here.

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver
@ 2020-11-13  8:14       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:14 UTC (permalink / raw)
  To: palmer, linux-riscv, linux-clk, seanga2, sboyd

On Sat, 2020-11-07 at 08:48 -0500, Sean Anderson wrote:
[...]
> > +static void k210_pll_disable_hw(struct k210_pll *pll)
> > +{
> > +	unsigned long flags;
> > +	u32 reg;
> > +
> > +	/*
> > +	 * Bypassing before powering off is important so child clocks don't stop
> > +	 * working. This is especially important for pll0, the indirect parent
> > +	 * of the cpu clock.
> > +	 */
> 
> Did you get the bypass bit to work? I'm still having to bypass via
> re-parenting ACLK in U-boot. Perhaps it is only necessary if you change
> the rate as well?

Nope. No luck there. The Kendryte SDK also does a reparenting of ACLK to IN0
when changing the PLL rate. So I guess I should remove the comment maybe.

In any case, this is all running with the default rates, except for PLL1 rate
which is changed in early init code to end up with matching frequencies for all
SRAM banks. So I do not think that the not-so-effective bypass is an issue
here.

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
  2020-11-07 14:03     ` Sean Anderson
@ 2020-11-13  8:17       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:17 UTC (permalink / raw)
  To: linux-spi, linux-riscv, linux-gpio, broonie, devicetree, sboyd,
	palmer, frowand.list, seanga2, fancer.lancer, linus.walleij,
	robh+dt, linux-clk, p.zabel

On Sat, 2020-11-07 at 09:03 -0500, Sean Anderson wrote:
> On 11/7/20 3:14 AM, Damien Le Moal wrote:
> > Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> > "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > ---
> >  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > index 2735be1a8470..f53d4d8e7f2a 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > @@ -179,6 +179,8 @@ patternProperties:
> >      description: CALAO Systems SAS
> >    "^calxeda,.*":
> >      description: Calxeda
> > +  "^canaan,.*":
> > +    description: Canaan, Inc.
> >    "^caninos,.*":
> >      description: Caninos Loucos Program
> >    "^capella,.*":
> > @@ -537,6 +539,8 @@ patternProperties:
> >      description: Ka-Ro electronics GmbH
> >    "^keithkoep,.*":
> >      description: Keith & Koep GmbH
> > +  "^kendryte,.*":
> > +    description: Canaan, Inc.
> >    "^keymile,.*":
> >      description: Keymile GmbH
> >    "^khadas,.*":
> > 
> 
> So AFAIK Canaan is the company, and Kendryte is the brand. However, I
> was unaware of this when I did my initial porting work. So all the
> compatible strings like "kendryte,k210-foo" should really be
> "canaan,kendryte-k210-foo". These _should_ all get fixed in the device
> tree, but no one has done it yet.

I fixed everything using "canaan,k210-foo", a little shorter than
"canaan,kendryte-k210-foo" (The "k" in k210 already probably standing for
Kendryte...). But I can use the longer version too.

Will I was at it, I also changed directory names and config option names to
also use canaan/CANAAN instead of kendryte/KENDRYTE.


> 
> --Sean

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix
@ 2020-11-13  8:17       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:17 UTC (permalink / raw)
  To: linux-spi, linux-riscv, linux-gpio, broonie, devicetree, sboyd,
	palmer, frowand.list, seanga2, fancer.lancer, linus.walleij,
	robh+dt, linux-clk, p.zabel

On Sat, 2020-11-07 at 09:03 -0500, Sean Anderson wrote:
> On 11/7/20 3:14 AM, Damien Le Moal wrote:
> > Update Documentation/devicetree/bindings/vendor-prefixes.yaml to include
> > "Kendryte" and "canaan" as a vendor prefix for "Canaan Inc."
> > 
> > Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> > ---
> >  Documentation/devicetree/bindings/vendor-prefixes.yaml | 4 ++++
> >  1 file changed, 4 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > index 2735be1a8470..f53d4d8e7f2a 100644
> > --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
> > @@ -179,6 +179,8 @@ patternProperties:
> >      description: CALAO Systems SAS
> >    "^calxeda,.*":
> >      description: Calxeda
> > +  "^canaan,.*":
> > +    description: Canaan, Inc.
> >    "^caninos,.*":
> >      description: Caninos Loucos Program
> >    "^capella,.*":
> > @@ -537,6 +539,8 @@ patternProperties:
> >      description: Ka-Ro electronics GmbH
> >    "^keithkoep,.*":
> >      description: Keith & Koep GmbH
> > +  "^kendryte,.*":
> > +    description: Canaan, Inc.
> >    "^keymile,.*":
> >      description: Keymile GmbH
> >    "^khadas,.*":
> > 
> 
> So AFAIK Canaan is the company, and Kendryte is the brand. However, I
> was unaware of this when I did my initial porting work. So all the
> compatible strings like "kendryte,k210-foo" should really be
> "canaan,kendryte-k210-foo". These _should_ all get fixed in the device
> tree, but no one has done it yet.

I fixed everything using "canaan,k210-foo", a little shorter than
"canaan,kendryte-k210-foo" (The "k" in k210 already probably standing for
Kendryte...). But I can use the longer version too.

Will I was at it, I also changed directory names and config option names to
also use canaan/CANAAN instead of kendryte/KENDRYTE.


> 
> --Sean

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  8:11             ` Stephen Boyd
@ 2020-11-13  8:23               ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:23 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 17:11, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-12 23:57:19)
>> On 2020/11/13 16:53, Stephen Boyd wrote:
>>>
>>> Yes it's fine. Just the commit text reads as "If of_clk_init() is not
>>> called in time_init() then nothing works" which is true but made me
>>> wonder if it was because it needed to be super early or not. The commit
>>> text could be a little clearer here.
>>
>> OK. I will clarify the commit message in V2. Working on it now.
> 
> Thanks!
> 
>>
>>> We don't have any good solution for a fallback to call of_clk_init()
>>> somewhere later. I do wonder if we should generalize this though and
>>> call of_clk_init() from start_kernel() directly via some Kconfig that
>>> architectures select if they need it for their timer and then move it to
>>> an initcall if architectures don't select the config. Or throw it into
>>> the of_platform_default_populate_init() hook if the architecture doesn't
>>> need to call it early.
>>
>> This last idea seems reasonable and probably the easiest. And I think it could
>> be done unconditionally even if the arch calls of_clk_init() early as the
>> already populated clock provider nodes would not be initialized again.
>>
> 
> Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
> wait to platform bus population time then they could be converted to
> regular old platform device drivers. Maybe the problem is the clk driver
> you're using is only using CLK_OF_DECLARE() and not registering a
> platform driver?

Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
platform_driver, then the of_clk_init() change would not be needed.

For the clock driver, I followed the pattern used by most other drivers with the
majority I think using CLK_OF_DECLARE(). I did see some using the platform
driver declaration though.

I could spend time trying to figure out if I can get away without using
CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
we may as well keep that of_clk_init() change, no ?


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-13  8:23               ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  8:23 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

On 2020/11/13 17:11, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-12 23:57:19)
>> On 2020/11/13 16:53, Stephen Boyd wrote:
>>>
>>> Yes it's fine. Just the commit text reads as "If of_clk_init() is not
>>> called in time_init() then nothing works" which is true but made me
>>> wonder if it was because it needed to be super early or not. The commit
>>> text could be a little clearer here.
>>
>> OK. I will clarify the commit message in V2. Working on it now.
> 
> Thanks!
> 
>>
>>> We don't have any good solution for a fallback to call of_clk_init()
>>> somewhere later. I do wonder if we should generalize this though and
>>> call of_clk_init() from start_kernel() directly via some Kconfig that
>>> architectures select if they need it for their timer and then move it to
>>> an initcall if architectures don't select the config. Or throw it into
>>> the of_platform_default_populate_init() hook if the architecture doesn't
>>> need to call it early.
>>
>> This last idea seems reasonable and probably the easiest. And I think it could
>> be done unconditionally even if the arch calls of_clk_init() early as the
>> already populated clock provider nodes would not be initialized again.
>>
> 
> Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
> wait to platform bus population time then they could be converted to
> regular old platform device drivers. Maybe the problem is the clk driver
> you're using is only using CLK_OF_DECLARE() and not registering a
> platform driver?

Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
platform_driver, then the of_clk_init() change would not be needed.

For the clock driver, I followed the pattern used by most other drivers with the
majority I think using CLK_OF_DECLARE(). I did see some using the platform
driver declaration though.

I could spend time trying to figure out if I can get away without using
CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
we may as well keep that of_clk_init() change, no ?


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-09 19:59     ` Serge Semin
@ 2020-11-13  9:22       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  9:22 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-spi, palmer, linux-riscv, broonie, seanga2

On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > With boards that have slow interrupts context switch, and a fast device
> > connected to a spi master, e.g. an SD card through mmc-spi,
> 
> > using
> > dw_spi_poll_transfer() intead of the regular interrupt based
> > dw_spi_transfer_handler() function is more efficient and
> 
> I can believe in that. But the next part seems questionable:
> 
> > can avoid a lot
> > of RX FIFO overflow errors while keeping the device SPI frequency
> > reasonnably high (for speed).
> 
> No matter whether it's an IRQ-based or poll-based transfer, as long as a
> client SPI-device is connected with a GPIO-based chip-select (or the
> DW APB SSI-controller feature of the automatic chip-select toggling is
> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> algorithm design by calculating the rxtx_gap in the dw_writer()
> method. If the error still happens then there must be some bug in
> the code.
> 
> It's also strange to hear that the polling-based transfer helps
> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> causes them. Both of those methods are based on the same dw_writer()
> and dw_reader() methods. So basically they both should either work
> well or cause the errors at same time.
> 
> So to speak could you more through debug your case?

I did. And I have much better results now. Let me explain:
1) The device tree was setting up the SPI controller using the controller
internal chip select, not a GPIO-based chip select. Until now, I could never
get the GPIO-based chip select to work. I finally found out why: I simply
needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
CS gpio is correctly driven active-high instead of the default active-low and
the SD card works.
2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
MOSI low while receiving" became completely unnecessary. The SD card works
without it.

Now for testing, I also removed this polling change. Results are these:
1) With the same SPI frequency as before (4MHz), I can run the SD card at about
300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
but enough to be annoying, especially on boot as the partition scan sometimes
fails because of these errors. In most cases, the block layer retry of failed
read/writes cover and no bad errors happen, but the RX FIFO overflow error
messages still pop up.
2) Looking into the code further, I realized that RXFLTR is set to half the
fifo size minus 1. That sound reasonable, but as that delays interrupt
generation until the RX fifo is almost full, I decided to try a value of 0 to
get the interrupt as soon as data is available rather than waiting for a chunk.
With that, all RX FIFO overflow errors go away, and I could even double the SPI
frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
at all.

My take:
* This controller internal CS seems to be totally broken.
* This SoC has really slow interrupts, so generating these earlier rather than
later gives time to the IRQ handler to kick in before the FIFO overflows.

In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
to set RXFLTR to 0, always. That works well, but this is may be still similar
to the "polling" hack in the sense that it is tuning for this SoC rather than a
property of the controller. But I do not see any other simple way of removing
these annoying RX FIFO overflow errors.

> On the other hand the errors (but not the Rx FIFO overflow) might be
> caused by the DW APB SSI nasty feature of the native chip-select
> automatic assertion/de-assertion. So if your MMC-spi port is handled
> by the native DW APB SSI CS lane, then it won't work well for sure.
> No matter whether you use the poll- or IRQ-based transfers.

Indeed. The GPIO-based CS does behave much more nicely, and it does not require
that "drive MOSI line high" hack. But for reasons that I still do not clearly
understand, occasional RX FIFO overflow errors still show up.


Thanks for all the useful comments !

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-13  9:22       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-13  9:22 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > With boards that have slow interrupts context switch, and a fast device
> > connected to a spi master, e.g. an SD card through mmc-spi,
> 
> > using
> > dw_spi_poll_transfer() intead of the regular interrupt based
> > dw_spi_transfer_handler() function is more efficient and
> 
> I can believe in that. But the next part seems questionable:
> 
> > can avoid a lot
> > of RX FIFO overflow errors while keeping the device SPI frequency
> > reasonnably high (for speed).
> 
> No matter whether it's an IRQ-based or poll-based transfer, as long as a
> client SPI-device is connected with a GPIO-based chip-select (or the
> DW APB SSI-controller feature of the automatic chip-select toggling is
> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> algorithm design by calculating the rxtx_gap in the dw_writer()
> method. If the error still happens then there must be some bug in
> the code.
> 
> It's also strange to hear that the polling-based transfer helps
> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> causes them. Both of those methods are based on the same dw_writer()
> and dw_reader() methods. So basically they both should either work
> well or cause the errors at same time.
> 
> So to speak could you more through debug your case?

I did. And I have much better results now. Let me explain:
1) The device tree was setting up the SPI controller using the controller
internal chip select, not a GPIO-based chip select. Until now, I could never
get the GPIO-based chip select to work. I finally found out why: I simply
needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
CS gpio is correctly driven active-high instead of the default active-low and
the SD card works.
2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
MOSI low while receiving" became completely unnecessary. The SD card works
without it.

Now for testing, I also removed this polling change. Results are these:
1) With the same SPI frequency as before (4MHz), I can run the SD card at about
300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
but enough to be annoying, especially on boot as the partition scan sometimes
fails because of these errors. In most cases, the block layer retry of failed
read/writes cover and no bad errors happen, but the RX FIFO overflow error
messages still pop up.
2) Looking into the code further, I realized that RXFLTR is set to half the
fifo size minus 1. That sound reasonable, but as that delays interrupt
generation until the RX fifo is almost full, I decided to try a value of 0 to
get the interrupt as soon as data is available rather than waiting for a chunk.
With that, all RX FIFO overflow errors go away, and I could even double the SPI
frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
at all.

My take:
* This controller internal CS seems to be totally broken.
* This SoC has really slow interrupts, so generating these earlier rather than
later gives time to the IRQ handler to kick in before the FIFO overflows.

In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
to set RXFLTR to 0, always. That works well, but this is may be still similar
to the "polling" hack in the sense that it is tuning for this SoC rather than a
property of the controller. But I do not see any other simple way of removing
these annoying RX FIFO overflow errors.

> On the other hand the errors (but not the Rx FIFO overflow) might be
> caused by the DW APB SSI nasty feature of the native chip-select
> automatic assertion/de-assertion. So if your MMC-spi port is handled
> by the native DW APB SSI CS lane, then it won't work well for sure.
> No matter whether you use the poll- or IRQ-based transfers.

Indeed. The GPIO-based CS does behave much more nicely, and it does not require
that "drive MOSI line high" hack. But for reasons that I still do not clearly
understand, occasional RX FIFO overflow errors still show up.


Thanks for all the useful comments !

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-07  8:14   ` Damien Le Moal
  (?)
@ 2020-11-15  0:28     ` kernel test robot
  -1 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  0:28 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: kbuild-all, clang-built-linux

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-r026-20201109 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 09ec07827b1128504457a93dee80b2ceee1af600)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:556:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inb(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:55:76: note: expanded from macro 'inb'
   #define inb(c)          ({ u8  __v; __io_pbr(); __v = readb_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:87:48: note: expanded from macro 'readb_cpu'
   #define readb_cpu(c)            ({ u8  __r = __raw_readb(c); __r; })
                                                            ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:564:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inw(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:56:76: note: expanded from macro 'inw'
   #define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:88:76: note: expanded from macro 'readw_cpu'
   #define readw_cpu(c)            ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:572:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inl(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:57:76: note: expanded from macro 'inl'
   #define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:89:76: note: expanded from macro 'readl_cpu'
   #define readl_cpu(c)            ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:580:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outb(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:59:68: note: expanded from macro 'outb'
   #define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:91:52: note: expanded from macro 'writeb_cpu'
   #define writeb_cpu(v, c)        ((void)__raw_writeb((v), (c)))
                                                             ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:588:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outw(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:60:68: note: expanded from macro 'outw'
   #define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:92:76: note: expanded from macro 'writew_cpu'
   #define writew_cpu(v, c)        ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:596:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outl(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:61:68: note: expanded from macro 'outl'
   #define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:93:76: note: expanded from macro 'writel_cpu'
   #define writel_cpu(v, c)        ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:1005:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
   drivers/pinctrl/pinctrl-k210.c:135:2: error: initializer element is not a compile-time constant
           K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
           ^~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-k210.c:132:45: note: expanded from macro 'K210_PIN_NAME'
   #define K210_PIN_NAME(i)        [i] = k210_pins[i].name
                                         ~~~~~~~~~~~~~^~~~
>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for function 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
       ^
   drivers/pinctrl/pinctrl-k210.c:848:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   ^
   static 
   8 warnings and 1 error generated.

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32635 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-15  0:28     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  0:28 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: clang-built-linux, kbuild-all

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-r026-20201109 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 09ec07827b1128504457a93dee80b2ceee1af600)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:556:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inb(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:55:76: note: expanded from macro 'inb'
   #define inb(c)          ({ u8  __v; __io_pbr(); __v = readb_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:87:48: note: expanded from macro 'readb_cpu'
   #define readb_cpu(c)            ({ u8  __r = __raw_readb(c); __r; })
                                                            ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:564:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inw(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:56:76: note: expanded from macro 'inw'
   #define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:88:76: note: expanded from macro 'readw_cpu'
   #define readw_cpu(c)            ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:572:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inl(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:57:76: note: expanded from macro 'inl'
   #define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:89:76: note: expanded from macro 'readl_cpu'
   #define readl_cpu(c)            ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:580:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outb(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:59:68: note: expanded from macro 'outb'
   #define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:91:52: note: expanded from macro 'writeb_cpu'
   #define writeb_cpu(v, c)        ((void)__raw_writeb((v), (c)))
                                                             ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:588:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outw(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:60:68: note: expanded from macro 'outw'
   #define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:92:76: note: expanded from macro 'writew_cpu'
   #define writew_cpu(v, c)        ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:596:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outl(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:61:68: note: expanded from macro 'outl'
   #define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:93:76: note: expanded from macro 'writel_cpu'
   #define writel_cpu(v, c)        ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:1005:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
   drivers/pinctrl/pinctrl-k210.c:135:2: error: initializer element is not a compile-time constant
           K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
           ^~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-k210.c:132:45: note: expanded from macro 'K210_PIN_NAME'
   #define K210_PIN_NAME(i)        [i] = k210_pins[i].name
                                         ~~~~~~~~~~~~~^~~~
>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for function 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
       ^
   drivers/pinctrl/pinctrl-k210.c:848:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   ^
   static 
   8 warnings and 1 error generated.

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 32635 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-15  0:28     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  0:28 UTC (permalink / raw)
  To: kbuild-all

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

Hi Damien,

I love your patch! Perhaps something to improve:

[auto build test WARNING on robh/for-next]
[also build test WARNING on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-r026-20201109 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 09ec07827b1128504457a93dee80b2ceee1af600)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install riscv cross compiling tool for clang build
        # apt-get install binutils-riscv64-linux-gnu
        # https://github.com/0day-ci/linux/commit/b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout b53c7c4d3b5b4658b4951955fd69c0ceb4bfac4d
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:556:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inb(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:55:76: note: expanded from macro 'inb'
   #define inb(c)          ({ u8  __v; __io_pbr(); __v = readb_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:87:48: note: expanded from macro 'readb_cpu'
   #define readb_cpu(c)            ({ u8  __r = __raw_readb(c); __r; })
                                                            ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:564:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inw(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:56:76: note: expanded from macro 'inw'
   #define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:88:76: note: expanded from macro 'readw_cpu'
   #define readw_cpu(c)            ({ u16 __r = le16_to_cpu((__force __le16)__raw_readw(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:36:51: note: expanded from macro '__le16_to_cpu'
   #define __le16_to_cpu(x) ((__force __u16)(__le16)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:572:9: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return inl(addr);
                  ^~~~~~~~~
   arch/riscv/include/asm/io.h:57:76: note: expanded from macro 'inl'
   #define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
                                                                           ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:89:76: note: expanded from macro 'readl_cpu'
   #define readl_cpu(c)            ({ u32 __r = le32_to_cpu((__force __le32)__raw_readl(c)); __r; })
                                                                                        ^
   include/uapi/linux/byteorder/little_endian.h:34:51: note: expanded from macro '__le32_to_cpu'
   #define __le32_to_cpu(x) ((__force __u32)(__le32)(x))
                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:580:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outb(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:59:68: note: expanded from macro 'outb'
   #define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:91:52: note: expanded from macro 'writeb_cpu'
   #define writeb_cpu(v, c)        ((void)__raw_writeb((v), (c)))
                                                             ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:588:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outw(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:60:68: note: expanded from macro 'outw'
   #define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:92:76: note: expanded from macro 'writew_cpu'
   #define writew_cpu(v, c)        ((void)__raw_writew((__force u16)cpu_to_le16(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:596:2: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           outl(value, addr);
           ^~~~~~~~~~~~~~~~~
   arch/riscv/include/asm/io.h:61:68: note: expanded from macro 'outl'
   #define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
                                                                 ~~~~~~~~~~ ^
   arch/riscv/include/asm/mmio.h:93:76: note: expanded from macro 'writel_cpu'
   #define writel_cpu(v, c)        ((void)__raw_writel((__force u32)cpu_to_le32(v), (c)))
                                                                                     ^
   In file included from drivers/pinctrl/pinctrl-k210.c:6:
   In file included from include/linux/io.h:13:
   In file included from arch/riscv/include/asm/io.h:149:
   include/asm-generic/io.h:1005:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
           return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
                                                     ~~~~~~~~~~ ^
   drivers/pinctrl/pinctrl-k210.c:135:2: error: initializer element is not a compile-time constant
           K210_PIN_NAME(0),  K210_PIN_NAME(1),  K210_PIN_NAME(2),
           ^~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-k210.c:132:45: note: expanded from macro 'K210_PIN_NAME'
   #define K210_PIN_NAME(i)        [i] = k210_pins[i].name
                                         ~~~~~~~~~~~~~^~~~
>> drivers/pinctrl/pinctrl-k210.c:848:5: warning: no previous prototype for function 'k210_pinctrl_dt_node_to_map' [-Wmissing-prototypes]
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
       ^
   drivers/pinctrl/pinctrl-k210.c:848:1: note: declare 'static' if the function is not intended to be used outside of this translation unit
   int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   ^
   static 
   8 warnings and 1 error generated.

vim +/k210_pinctrl_dt_node_to_map +848 drivers/pinctrl/pinctrl-k210.c

   847	
 > 848	int k210_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
   849				struct device_node *np_config,
   850				struct pinctrl_map **map, unsigned int *num_maps)
   851	{
   852		unsigned int reserved_maps;
   853		struct device_node *np;
   854		int ret;
   855	
   856		reserved_maps = 0;
   857		*map = NULL;
   858		*num_maps = 0;
   859	
   860		ret = k210_pinctrl_dt_subnode_to_map(pctldev, np_config, map,
   861						     &reserved_maps, num_maps);
   862		if (ret < 0)
   863			goto err;
   864	
   865		for_each_available_child_of_node(np_config, np) {
   866			ret = k210_pinctrl_dt_subnode_to_map(pctldev, np, map,
   867							     &reserved_maps, num_maps);
   868			if (ret < 0)
   869				goto err;
   870		}
   871		return 0;
   872	
   873	err:
   874		pinctrl_utils_free_map(pctldev, *map, *num_maps);
   875		return ret;
   876	}
   877	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 32635 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 13/32] riscv: Fix builtin DTB handling
  2020-11-07  8:14   ` Damien Le Moal
  (?)
@ 2020-11-15  4:17     ` kernel test robot
  -1 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  4:17 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: kbuild-all

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

Hi Damien,

I love your patch! Yet something to improve:

[auto build test ERROR on robh/for-next]
[also build test ERROR on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-p001-20201109 (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ec1240e1739d5d0703571eaf23e82ec9932e3d42
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout ec1240e1739d5d0703571eaf23e82ec9932e3d42
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> make[3]: *** No rule to make target 'arch/riscv/boot/dts/kendryte/.dtb', needed by '__build'.
   make[3]: Target '__build' not remade because of errors.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37722 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 13/32] riscv: Fix builtin DTB handling
@ 2020-11-15  4:17     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  4:17 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, linux-riscv, Rob Herring,
	Frank Rowand, devicetree, Serge Semin, Mark Brown, linux-spi,
	Stephen Boyd, linux-clk
  Cc: kbuild-all

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

Hi Damien,

I love your patch! Yet something to improve:

[auto build test ERROR on robh/for-next]
[also build test ERROR on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-p001-20201109 (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ec1240e1739d5d0703571eaf23e82ec9932e3d42
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout ec1240e1739d5d0703571eaf23e82ec9932e3d42
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> make[3]: *** No rule to make target 'arch/riscv/boot/dts/kendryte/.dtb', needed by '__build'.
   make[3]: Target '__build' not remade because of errors.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 37722 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 13/32] riscv: Fix builtin DTB handling
@ 2020-11-15  4:17     ` kernel test robot
  0 siblings, 0 replies; 297+ messages in thread
From: kernel test robot @ 2020-11-15  4:17 UTC (permalink / raw)
  To: kbuild-all

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

Hi Damien,

I love your patch! Yet something to improve:

[auto build test ERROR on robh/for-next]
[also build test ERROR on spi/for-next pza/reset/next v5.10-rc3]
[cannot apply to linus/master next-20201113]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
base:   https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next
config: riscv-randconfig-p001-20201109 (attached as .config)
compiler: riscv64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/ec1240e1739d5d0703571eaf23e82ec9932e3d42
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Damien-Le-Moal/RISC-V-Kendryte-K210-support-improvments/20201109-095540
        git checkout ec1240e1739d5d0703571eaf23e82ec9932e3d42
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=riscv 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

>> make[3]: *** No rule to make target 'arch/riscv/boot/dts/kendryte/.dtb', needed by '__build'.
   make[3]: Target '__build' not remade because of errors.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 37722 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-13  9:22       ` Damien Le Moal
@ 2020-11-15 16:01         ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-15 16:01 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-spi, palmer, linux-riscv, broonie, seanga2

On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > With boards that have slow interrupts context switch, and a fast device
> > > connected to a spi master, e.g. an SD card through mmc-spi,
> > 
> > > using
> > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > dw_spi_transfer_handler() function is more efficient and
> > 
> > I can believe in that. But the next part seems questionable:
> > 
> > > can avoid a lot
> > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > reasonnably high (for speed).
> > 
> > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > client SPI-device is connected with a GPIO-based chip-select (or the
> > DW APB SSI-controller feature of the automatic chip-select toggling is
> > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > algorithm design by calculating the rxtx_gap in the dw_writer()
> > method. If the error still happens then there must be some bug in
> > the code.
> > 
> > It's also strange to hear that the polling-based transfer helps
> > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > causes them. Both of those methods are based on the same dw_writer()
> > and dw_reader() methods. So basically they both should either work
> > well or cause the errors at same time.
> > 
> > So to speak could you more through debug your case?
> 
> I did. And I have much better results now. Let me explain:

> 1) The device tree was setting up the SPI controller using the controller
> internal chip select, not a GPIO-based chip select. Until now, I could never
> get the GPIO-based chip select to work. I finally found out why: I simply
> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> CS gpio is correctly driven active-high instead of the default active-low and
> the SD card works.

Yeap, that's the main problem of the standard DW APB SSI controller
released by Synopsys. Currently SPI-flash'es are the only SPI
peripheral devices which are capable to work with native DW APB SSI
chip-selects. I've fixed that for flashes recently by atomizing the
SPI memory operations (executing them with the local IRQs disabled)
and performing them on the poll-based basis. Alas the normal
SPI-transfers still can't be properly executed with native
chip-selects.

> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> MOSI low while receiving" became completely unnecessary. The SD card works
> without it.

Hm, that's weird. MOSI level has nothing todo with the chip-selects.
Are you sure the original problem has been connected with the Tx lane
level? On the other hand are you sure the problem has gone away after
all?

Moreover I've just taken alook at the MMC SPI driver. Turns out it
has already been fixed to send ones to the MMC port when it's
required. So If you still experience the MOSI-level problem
then that fix might have been done incorrect at some extent...

> 
> Now for testing, I also removed this polling change. Results are these:
> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> but enough to be annoying, especially on boot as the partition scan sometimes
> fails because of these errors. In most cases, the block layer retry of failed
> read/writes cover and no bad errors happen, but the RX FIFO overflow error
> messages still pop up.
> 2) Looking into the code further, I realized that RXFLTR is set to half the
> fifo size minus 1. That sound reasonable, but as that delays interrupt
> generation until the RX fifo is almost full, I decided to try a value of 0 to
> get the interrupt as soon as data is available rather than waiting for a chunk.
> With that, all RX FIFO overflow errors go away, and I could even double the SPI
> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> at all.
> 

Please, see my last comment...

> My take:
> * This controller internal CS seems to be totally broken.

Native CS aren't broken, they just have been designed so it isn't that
easy to use them in the linux kernel. Linux kernel SPI-core expects
the chip-select being driven the way it needs at the certain moments,
while DW APB SSI toggles them automatically at the moment of the data
pushing/popping to/from the SPI bus. Some hardware vendors that bought
the DW APB SSI IP-core have fixed that by providing a way of direct
CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
platforms).

> * This SoC has really slow interrupts, so generating these earlier rather than
> later gives time to the IRQ handler to kick in before the FIFO overflows.

I am pretty sure that's not the reason. See my next comment.

> 
> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> to set RXFLTR to 0, always. That works well, but this is may be still similar
> to the "polling" hack in the sense that it is tuning for this SoC rather than a
> property of the controller. But I do not see any other simple way of removing
> these annoying RX FIFO overflow errors.

Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
execution results. I'll try to explain it one more time. DW APB SSI
provides three modes of transfers (TMOD-es, see the chip manual for
details). One of them is TMOD=0x0 - Transmit and Receive. Simply
speaking the mode essence is if you push a byte of data to the Tx
FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
later from the internal shift register. The IRQ-based transfers have
been developed full based on that mode. So it's absolutely possible to
implement a stable algorithm, which would work without a risk of
getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
should just preserve a balance of sent data so the received data
wouldn't cause the Rx FIFO overrun. As you understand such algorithm
doesn't depend on the IRQes performance. No matter how slow the IRQs
handler is execute, as long as it's executed, the SPI transfers
procedure shall go on with no errors including the Rx FIFO overflows.
At least that's what the original DW APB SSI driver developer
implied when created the code and what I was trying to preserve in my
patches. If you still get the errors (you sure it's Rx FIFO overflows,
aren't you?), then something went wrong and either me or the original
author or someone else has broken the code.

What we currently need is to carefully analyze at what moment you get
the overflows, what really caused them and fix the problem in the
code. The capabilities flag isn't an option in this case. I've tried
to reproduce the errors by slowing the system down, executing the
SPI-transfers of various length, but with no lick. So it's only you
for now who observes and can try to debug the problem.

Anyway after we get to fix it, you'll be able to run the MMC port with
speed as fast as it's possible.

---
One more thing about MMC SPI. Please note, that using MMC SPI and
DMA-based DW APB SSI transfers might not work well. The thing is that
the DMA-part of the MMC SPI driver relies on the legacy
spi_message->is_dma_mapped interface. It performs some specific
DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
In its turn the DMA-part of the DW APB SSI driver uses the generic
SPI-core and the DMA-engine interface to execute the SPI-transfers.
Since the SPI-core performs the DMA buffers synchronizations
internally at the moment of the buffers mapping, in case if the DMA
accesses aren't coherent on your platform, the data buffers might get
synchronized/flushed with/by caches incorrectly corrupting a part of
actual data. At least that's what we observed in kernel 4.9... So for
now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
transfers.

-Sergey

> 
> > On the other hand the errors (but not the Rx FIFO overflow) might be
> > caused by the DW APB SSI nasty feature of the native chip-select
> > automatic assertion/de-assertion. So if your MMC-spi port is handled
> > by the native DW APB SSI CS lane, then it won't work well for sure.
> > No matter whether you use the poll- or IRQ-based transfers.
> 
> Indeed. The GPIO-based CS does behave much more nicely, and it does not require
> that "drive MOSI line high" hack. But for reasons that I still do not clearly
> understand, occasional RX FIFO overflow errors still show up.
> 
> 
> Thanks for all the useful comments !
> 
> -- 
> Damien Le Moal
> Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-15 16:01         ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-15 16:01 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > With boards that have slow interrupts context switch, and a fast device
> > > connected to a spi master, e.g. an SD card through mmc-spi,
> > 
> > > using
> > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > dw_spi_transfer_handler() function is more efficient and
> > 
> > I can believe in that. But the next part seems questionable:
> > 
> > > can avoid a lot
> > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > reasonnably high (for speed).
> > 
> > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > client SPI-device is connected with a GPIO-based chip-select (or the
> > DW APB SSI-controller feature of the automatic chip-select toggling is
> > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > algorithm design by calculating the rxtx_gap in the dw_writer()
> > method. If the error still happens then there must be some bug in
> > the code.
> > 
> > It's also strange to hear that the polling-based transfer helps
> > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > causes them. Both of those methods are based on the same dw_writer()
> > and dw_reader() methods. So basically they both should either work
> > well or cause the errors at same time.
> > 
> > So to speak could you more through debug your case?
> 
> I did. And I have much better results now. Let me explain:

> 1) The device tree was setting up the SPI controller using the controller
> internal chip select, not a GPIO-based chip select. Until now, I could never
> get the GPIO-based chip select to work. I finally found out why: I simply
> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> CS gpio is correctly driven active-high instead of the default active-low and
> the SD card works.

Yeap, that's the main problem of the standard DW APB SSI controller
released by Synopsys. Currently SPI-flash'es are the only SPI
peripheral devices which are capable to work with native DW APB SSI
chip-selects. I've fixed that for flashes recently by atomizing the
SPI memory operations (executing them with the local IRQs disabled)
and performing them on the poll-based basis. Alas the normal
SPI-transfers still can't be properly executed with native
chip-selects.

> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> MOSI low while receiving" became completely unnecessary. The SD card works
> without it.

Hm, that's weird. MOSI level has nothing todo with the chip-selects.
Are you sure the original problem has been connected with the Tx lane
level? On the other hand are you sure the problem has gone away after
all?

Moreover I've just taken alook at the MMC SPI driver. Turns out it
has already been fixed to send ones to the MMC port when it's
required. So If you still experience the MOSI-level problem
then that fix might have been done incorrect at some extent...

> 
> Now for testing, I also removed this polling change. Results are these:
> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> but enough to be annoying, especially on boot as the partition scan sometimes
> fails because of these errors. In most cases, the block layer retry of failed
> read/writes cover and no bad errors happen, but the RX FIFO overflow error
> messages still pop up.
> 2) Looking into the code further, I realized that RXFLTR is set to half the
> fifo size minus 1. That sound reasonable, but as that delays interrupt
> generation until the RX fifo is almost full, I decided to try a value of 0 to
> get the interrupt as soon as data is available rather than waiting for a chunk.
> With that, all RX FIFO overflow errors go away, and I could even double the SPI
> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> at all.
> 

Please, see my last comment...

> My take:
> * This controller internal CS seems to be totally broken.

Native CS aren't broken, they just have been designed so it isn't that
easy to use them in the linux kernel. Linux kernel SPI-core expects
the chip-select being driven the way it needs at the certain moments,
while DW APB SSI toggles them automatically at the moment of the data
pushing/popping to/from the SPI bus. Some hardware vendors that bought
the DW APB SSI IP-core have fixed that by providing a way of direct
CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
platforms).

> * This SoC has really slow interrupts, so generating these earlier rather than
> later gives time to the IRQ handler to kick in before the FIFO overflows.

I am pretty sure that's not the reason. See my next comment.

> 
> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> to set RXFLTR to 0, always. That works well, but this is may be still similar
> to the "polling" hack in the sense that it is tuning for this SoC rather than a
> property of the controller. But I do not see any other simple way of removing
> these annoying RX FIFO overflow errors.

Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
execution results. I'll try to explain it one more time. DW APB SSI
provides three modes of transfers (TMOD-es, see the chip manual for
details). One of them is TMOD=0x0 - Transmit and Receive. Simply
speaking the mode essence is if you push a byte of data to the Tx
FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
later from the internal shift register. The IRQ-based transfers have
been developed full based on that mode. So it's absolutely possible to
implement a stable algorithm, which would work without a risk of
getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
should just preserve a balance of sent data so the received data
wouldn't cause the Rx FIFO overrun. As you understand such algorithm
doesn't depend on the IRQes performance. No matter how slow the IRQs
handler is execute, as long as it's executed, the SPI transfers
procedure shall go on with no errors including the Rx FIFO overflows.
At least that's what the original DW APB SSI driver developer
implied when created the code and what I was trying to preserve in my
patches. If you still get the errors (you sure it's Rx FIFO overflows,
aren't you?), then something went wrong and either me or the original
author or someone else has broken the code.

What we currently need is to carefully analyze at what moment you get
the overflows, what really caused them and fix the problem in the
code. The capabilities flag isn't an option in this case. I've tried
to reproduce the errors by slowing the system down, executing the
SPI-transfers of various length, but with no lick. So it's only you
for now who observes and can try to debug the problem.

Anyway after we get to fix it, you'll be able to run the MMC port with
speed as fast as it's possible.

---
One more thing about MMC SPI. Please note, that using MMC SPI and
DMA-based DW APB SSI transfers might not work well. The thing is that
the DMA-part of the MMC SPI driver relies on the legacy
spi_message->is_dma_mapped interface. It performs some specific
DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
In its turn the DMA-part of the DW APB SSI driver uses the generic
SPI-core and the DMA-engine interface to execute the SPI-transfers.
Since the SPI-core performs the DMA buffers synchronizations
internally at the moment of the buffers mapping, in case if the DMA
accesses aren't coherent on your platform, the data buffers might get
synchronized/flushed with/by caches incorrectly corrupting a part of
actual data. At least that's what we observed in kernel 4.9... So for
now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
transfers.

-Sergey

> 
> > On the other hand the errors (but not the Rx FIFO overflow) might be
> > caused by the DW APB SSI nasty feature of the native chip-select
> > automatic assertion/de-assertion. So if your MMC-spi port is handled
> > by the native DW APB SSI CS lane, then it won't work well for sure.
> > No matter whether you use the poll- or IRQ-based transfers.
> 
> Indeed. The GPIO-based CS does behave much more nicely, and it does not require
> that "drive MOSI line high" hack. But for reasons that I still do not clearly
> understand, occasional RX FIFO overflow errors still show up.
> 
> 
> Thanks for all the useful comments !
> 
> -- 
> Damien Le Moal
> Western Digital

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-13  8:23               ` Damien Le Moal
@ 2020-11-16  7:06                 ` Stephen Boyd
  -1 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-16  7:06 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-13 00:23:52)
> On 2020/11/13 17:11, Stephen Boyd wrote:
> > 
> > Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
> > wait to platform bus population time then they could be converted to
> > regular old platform device drivers. Maybe the problem is the clk driver
> > you're using is only using CLK_OF_DECLARE() and not registering a
> > platform driver?
> 
> Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
> platform_driver, then the of_clk_init() change would not be needed.
> 
> For the clock driver, I followed the pattern used by most other drivers with the
> majority I think using CLK_OF_DECLARE(). I did see some using the platform
> driver declaration though.
> 
> I could spend time trying to figure out if I can get away without using
> CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
> we may as well keep that of_clk_init() change, no ?
> 

Sure keeping of_clk_init() in riscv architecture code is fine. It would
be good to use a platform driver though and avoid the use of
CLK_OF_DECLARE() so we don't burden ourselves with more code that
registers clks early unnecessarily.

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-16  7:06                 ` Stephen Boyd
  0 siblings, 0 replies; 297+ messages in thread
From: Stephen Boyd @ 2020-11-16  7:06 UTC (permalink / raw)
  To: Damien Le Moal, Palmer Dabbelt, Rob Herring, Serge Semin,
	devicetree, linux-clk, linux-riscv
  Cc: Sean Anderson

Quoting Damien Le Moal (2020-11-13 00:23:52)
> On 2020/11/13 17:11, Stephen Boyd wrote:
> > 
> > Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
> > wait to platform bus population time then they could be converted to
> > regular old platform device drivers. Maybe the problem is the clk driver
> > you're using is only using CLK_OF_DECLARE() and not registering a
> > platform driver?
> 
> Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
> platform_driver, then the of_clk_init() change would not be needed.
> 
> For the clock driver, I followed the pattern used by most other drivers with the
> majority I think using CLK_OF_DECLARE(). I did see some using the platform
> driver declaration though.
> 
> I could spend time trying to figure out if I can get away without using
> CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
> we may as well keep that of_clk_init() change, no ?
> 

Sure keeping of_clk_init() in riscv architecture code is fine. It would
be good to use a platform driver though and avoid the use of
CLK_OF_DECLARE() so we don't burden ourselves with more code that
registers clks early unnecessarily.

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
  2020-11-16  7:06                 ` Stephen Boyd
@ 2020-11-16  7:18                   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:18 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, linux-clk, linux-riscv, Michael Turquette
  Cc: Sean Anderson

On 2020/11/16 16:06, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-13 00:23:52)
>> On 2020/11/13 17:11, Stephen Boyd wrote:
>>>
>>> Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
>>> wait to platform bus population time then they could be converted to
>>> regular old platform device drivers. Maybe the problem is the clk driver
>>> you're using is only using CLK_OF_DECLARE() and not registering a
>>> platform driver?
>>
>> Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
>> platform_driver, then the of_clk_init() change would not be needed.
>>
>> For the clock driver, I followed the pattern used by most other drivers with the
>> majority I think using CLK_OF_DECLARE(). I did see some using the platform
>> driver declaration though.
>>
>> I could spend time trying to figure out if I can get away without using
>> CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
>> we may as well keep that of_clk_init() change, no ?
>>
> 
> Sure keeping of_clk_init() in riscv architecture code is fine. It would
> be good to use a platform driver though and avoid the use of
> CLK_OF_DECLARE() so we don't burden ourselves with more code that
> registers clks early unnecessarily.

OK. Please let me check if that works. It may not be possible to delay
initialization as the CLINT/sched clocksource depends on the clocks being ready.


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 08/32] riscv: Fix kernel time_init()
@ 2020-11-16  7:18                   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:18 UTC (permalink / raw)
  To: Stephen Boyd, Palmer Dabbelt, linux-clk, linux-riscv, Michael Turquette
  Cc: Sean Anderson

On 2020/11/16 16:06, Stephen Boyd wrote:
> Quoting Damien Le Moal (2020-11-13 00:23:52)
>> On 2020/11/13 17:11, Stephen Boyd wrote:
>>>
>>> Also of_clk_init() is for the CLK_OF_DECLARE() users and if they can
>>> wait to platform bus population time then they could be converted to
>>> regular old platform device drivers. Maybe the problem is the clk driver
>>> you're using is only using CLK_OF_DECLARE() and not registering a
>>> platform driver?
>>
>> Yep, correct, that is what I did. SO yes, indeed, if I where to use a regular
>> platform_driver, then the of_clk_init() change would not be needed.
>>
>> For the clock driver, I followed the pattern used by most other drivers with the
>> majority I think using CLK_OF_DECLARE(). I did see some using the platform
>> driver declaration though.
>>
>> I could spend time trying to figure out if I can get away without using
>> CLK_OF_DECLARE(), but since I think other riscv board clock driver are arriving,
>> we may as well keep that of_clk_init() change, no ?
>>
> 
> Sure keeping of_clk_init() in riscv architecture code is fine. It would
> be good to use a platform driver though and avoid the use of
> CLK_OF_DECLARE() so we don't burden ourselves with more code that
> registers clks early unnecessarily.

OK. Please let me check if that works. It may not be possible to delay
initialization as the CLINT/sched clocksource depends on the clocks being ready.


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-09 17:44       ` Serge Semin
@ 2020-11-16  7:30         ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:30 UTC (permalink / raw)
  To: Serge Semin
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, devicetree,
	Linus Walleij, open list:GPIO SUBSYSTEM, Philipp Zabel,
	Sean Anderson

On 2020/11/10 2:45, Serge Semin wrote:
> Hello Andy,
> 
> On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
>> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
>>
>>> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>>>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>>>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>>>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
>>> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
>>
>> Sorry, but the above doesn't sound right to me.
>> It's a generic code and you may imagine how many systems you broke by
>> this change.
> 
> Damien replaced the macro above with the code below (your removed it from your
> message):
> 
> +static struct device_node *parse_gpios(struct device_node *np,
> +                                      const char *prop_name, int index)
> +{
> +       /*
> +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +        * available. As this conflict with "xx-gpios" reference properties,
> +        * ignore it.
> +        */
> +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +               return NULL;
> +
> +       return parse_suffix_prop_cells(np, prop_name, index,
> +                                      "-gpios", "#gpio-cells");
> +}
> 
> So AFAICS removing the macro shouldn't cause any problem.
> 
> My concern was whether the quirk has been really needed. As I said the
> "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> "ngpios" one. Due to the problem noted by Damien any deprecated property
> utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> though implicitly but is supposed to encourage people to provide fixes for
> the dts-files with the deprecated property replaced with "ngpios".
> 
> On the other hand an encouragement based on breaking the kernel doesn't seem a
> good solution. So as I see it either we should accept the solution provided by
> Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> solution would they prefer.

As Rob mentioned, there are still a lot of DTS out there using "snps,nr-gpios",
so I think the fix is needed, albeit with an added warning as Rob suggested so
that board maintainers can notice and update their DT. And I can send a patch
for the DW gpio apb driver to first try the default "ngpios" property, and if it
is not defined, fallback to the legacy "snps,nr-gpios". With that, these new
RISC-V boards will not add another use case of the deprecated "snsps,nr-gpios".
Does that sound like a good plan ?


> 
> -Sergey
> 
>>
>> -- 
>> With Best Regards,
>> Andy Shevchenko
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-16  7:30         ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:30 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, Linus Walleij, Sean Anderson,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv

On 2020/11/10 2:45, Serge Semin wrote:
> Hello Andy,
> 
> On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
>> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
>>
>>> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
>>>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
>>>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
>>>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
>>> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
>>
>> Sorry, but the above doesn't sound right to me.
>> It's a generic code and you may imagine how many systems you broke by
>> this change.
> 
> Damien replaced the macro above with the code below (your removed it from your
> message):
> 
> +static struct device_node *parse_gpios(struct device_node *np,
> +                                      const char *prop_name, int index)
> +{
> +       /*
> +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> +        * available. As this conflict with "xx-gpios" reference properties,
> +        * ignore it.
> +        */
> +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> +               return NULL;
> +
> +       return parse_suffix_prop_cells(np, prop_name, index,
> +                                      "-gpios", "#gpio-cells");
> +}
> 
> So AFAICS removing the macro shouldn't cause any problem.
> 
> My concern was whether the quirk has been really needed. As I said the
> "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> "ngpios" one. Due to the problem noted by Damien any deprecated property
> utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> though implicitly but is supposed to encourage people to provide fixes for
> the dts-files with the deprecated property replaced with "ngpios".
> 
> On the other hand an encouragement based on breaking the kernel doesn't seem a
> good solution. So as I see it either we should accept the solution provided by
> Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> solution would they prefer.

As Rob mentioned, there are still a lot of DTS out there using "snps,nr-gpios",
so I think the fix is needed, albeit with an added warning as Rob suggested so
that board maintainers can notice and update their DT. And I can send a patch
for the DW gpio apb driver to first try the default "ngpios" property, and if it
is not defined, fallback to the legacy "snps,nr-gpios". With that, these new
RISC-V boards will not add another use case of the deprecated "snsps,nr-gpios".
Does that sound like a good plan ?


> 
> -Sergey
> 
>>
>> -- 
>> With Best Regards,
>> Andy Shevchenko
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-15 16:01         ` Serge Semin
@ 2020-11-16  7:47           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:47 UTC (permalink / raw)
  To: Serge Semin; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On 2020/11/16 1:02, Serge Semin wrote:
> On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
>> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
>>> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
>>>> With boards that have slow interrupts context switch, and a fast device
>>>> connected to a spi master, e.g. an SD card through mmc-spi,
>>>
>>>> using
>>>> dw_spi_poll_transfer() intead of the regular interrupt based
>>>> dw_spi_transfer_handler() function is more efficient and
>>>
>>> I can believe in that. But the next part seems questionable:
>>>
>>>> can avoid a lot
>>>> of RX FIFO overflow errors while keeping the device SPI frequency
>>>> reasonnably high (for speed).
>>>
>>> No matter whether it's an IRQ-based or poll-based transfer, as long as a
>>> client SPI-device is connected with a GPIO-based chip-select (or the
>>> DW APB SSI-controller feature of the automatic chip-select toggling is
>>> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
>>> algorithm design by calculating the rxtx_gap in the dw_writer()
>>> method. If the error still happens then there must be some bug in
>>> the code.
>>>
>>> It's also strange to hear that the polling-based transfer helps
>>> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
>>> causes them. Both of those methods are based on the same dw_writer()
>>> and dw_reader() methods. So basically they both should either work
>>> well or cause the errors at same time.
>>>
>>> So to speak could you more through debug your case?
>>
>> I did. And I have much better results now. Let me explain:
> 
>> 1) The device tree was setting up the SPI controller using the controller
>> internal chip select, not a GPIO-based chip select. Until now, I could never
>> get the GPIO-based chip select to work. I finally found out why: I simply
>> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
>> CS gpio is correctly driven active-high instead of the default active-low and
>> the SD card works.
> 
> Yeap, that's the main problem of the standard DW APB SSI controller
> released by Synopsys. Currently SPI-flash'es are the only SPI
> peripheral devices which are capable to work with native DW APB SSI
> chip-selects. I've fixed that for flashes recently by atomizing the
> SPI memory operations (executing them with the local IRQs disabled)
> and performing them on the poll-based basis. Alas the normal
> SPI-transfers still can't be properly executed with native
> chip-selects.
> 
>> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
>> MOSI low while receiving" became completely unnecessary. The SD card works
>> without it.
> 
> Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> Are you sure the original problem has been connected with the Tx lane
> level? On the other hand are you sure the problem has gone away after
> all?

Not sure of anything here :) But removing the patch changing MOSI level did not
prevent the SD card to be scanned & accessed correctly. Before (with native chip
select), the first command would not even complete...

> Moreover I've just taken alook at the MMC SPI driver. Turns out it
> has already been fixed to send ones to the MMC port when it's
> required. So If you still experience the MOSI-level problem
> then that fix might have been done incorrect at some extent...

OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
scripts/get_maintainer.pl does not mention any. Where is that hosted ?


>> Now for testing, I also removed this polling change. Results are these:
>> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
>> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
>> but enough to be annoying, especially on boot as the partition scan sometimes
>> fails because of these errors. In most cases, the block layer retry of failed
>> read/writes cover and no bad errors happen, but the RX FIFO overflow error
>> messages still pop up.
>> 2) Looking into the code further, I realized that RXFLTR is set to half the
>> fifo size minus 1. That sound reasonable, but as that delays interrupt
>> generation until the RX fifo is almost full, I decided to try a value of 0 to
>> get the interrupt as soon as data is available rather than waiting for a chunk.
>> With that, all RX FIFO overflow errors go away, and I could even double the SPI
>> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
>> at all.
>>
> 
> Please, see my last comment...
> 
>> My take:
>> * This controller internal CS seems to be totally broken.
> 
> Native CS aren't broken, they just have been designed so it isn't that
> easy to use them in the linux kernel. Linux kernel SPI-core expects
> the chip-select being driven the way it needs at the certain moments,
> while DW APB SSI toggles them automatically at the moment of the data
> pushing/popping to/from the SPI bus. Some hardware vendors that bought
> the DW APB SSI IP-core have fixed that by providing a way of direct
> CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> platforms).

OK. Thanks for the details.

>> * This SoC has really slow interrupts, so generating these earlier rather than
>> later gives time to the IRQ handler to kick in before the FIFO overflows.
> 
> I am pretty sure that's not the reason. See my next comment.
> 
>>
>> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
>> to set RXFLTR to 0, always. That works well, but this is may be still similar
>> to the "polling" hack in the sense that it is tuning for this SoC rather than a
>> property of the controller. But I do not see any other simple way of removing
>> these annoying RX FIFO overflow errors.
> 
> Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> execution results. I'll try to explain it one more time. DW APB SSI
> provides three modes of transfers (TMOD-es, see the chip manual for
> details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> speaking the mode essence is if you push a byte of data to the Tx
> FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> later from the internal shift register. The IRQ-based transfers have
> been developed full based on that mode. So it's absolutely possible to
> implement a stable algorithm, which would work without a risk of
> getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> should just preserve a balance of sent data so the received data
> wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> doesn't depend on the IRQes performance. No matter how slow the IRQs
> handler is execute, as long as it's executed, the SPI transfers
> procedure shall go on with no errors including the Rx FIFO overflows.

OK. I get it now.

> At least that's what the original DW APB SSI driver developer
> implied when created the code and what I was trying to preserve in my
> patches. If you still get the errors (you sure it's Rx FIFO overflows,
> aren't you?), then something went wrong and either me or the original
> author or someone else has broken the code.

Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
Checked it. And that is the trigger for the error message which exactly says
that "RX FIFO overflow". So that would mean that too many bytes are being
written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
writes more bytes than what is available in the RX FIFO ?

If that is the case, then it seems to me that tx_max() should be modified a
little: rx_len may be large (say a sector), in which case rxtx_gap overflows
(becomes super large), with the result that tx_max() returns tx_room. But that
may be larger than the free space in the RX FIFO, no ?

I think I need to do a round of debug again, tracing these values to figure out
what is going on. I can reproduce the errors very easily (I just need to crank
up the SPI frequency).

> What we currently need is to carefully analyze at what moment you get
> the overflows, what really caused them and fix the problem in the
> code. The capabilities flag isn't an option in this case. I've tried
> to reproduce the errors by slowing the system down, executing the
> SPI-transfers of various length, but with no lick. So it's only you
> for now who observes and can try to debug the problem.

OK. Will do.

> Anyway after we get to fix it, you'll be able to run the MMC port with
> speed as fast as it's possible.

That is my current goal :)

> 
> ---
> One more thing about MMC SPI. Please note, that using MMC SPI and
> DMA-based DW APB SSI transfers might not work well. The thing is that
> the DMA-part of the MMC SPI driver relies on the legacy
> spi_message->is_dma_mapped interface. It performs some specific
> DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
> In its turn the DMA-part of the DW APB SSI driver uses the generic
> SPI-core and the DMA-engine interface to execute the SPI-transfers.
> Since the SPI-core performs the DMA buffers synchronizations
> internally at the moment of the buffers mapping, in case if the DMA
> accesses aren't coherent on your platform, the data buffers might get
> synchronized/flushed with/by caches incorrectly corrupting a part of
> actual data. At least that's what we observed in kernel 4.9... So for
> now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
> transfers.

The K210 has a DW DMA engine, but I do not have it enabled. I tried that too to
be frank, but it fails to initialize the DMA rx/tx channels. I have not dig into
that one since DMA is not at all required for this board given the devices on it.

Thanks for all the help !


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-16  7:47           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-16  7:47 UTC (permalink / raw)
  To: Serge Semin; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On 2020/11/16 1:02, Serge Semin wrote:
> On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
>> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
>>> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
>>>> With boards that have slow interrupts context switch, and a fast device
>>>> connected to a spi master, e.g. an SD card through mmc-spi,
>>>
>>>> using
>>>> dw_spi_poll_transfer() intead of the regular interrupt based
>>>> dw_spi_transfer_handler() function is more efficient and
>>>
>>> I can believe in that. But the next part seems questionable:
>>>
>>>> can avoid a lot
>>>> of RX FIFO overflow errors while keeping the device SPI frequency
>>>> reasonnably high (for speed).
>>>
>>> No matter whether it's an IRQ-based or poll-based transfer, as long as a
>>> client SPI-device is connected with a GPIO-based chip-select (or the
>>> DW APB SSI-controller feature of the automatic chip-select toggling is
>>> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
>>> algorithm design by calculating the rxtx_gap in the dw_writer()
>>> method. If the error still happens then there must be some bug in
>>> the code.
>>>
>>> It's also strange to hear that the polling-based transfer helps
>>> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
>>> causes them. Both of those methods are based on the same dw_writer()
>>> and dw_reader() methods. So basically they both should either work
>>> well or cause the errors at same time.
>>>
>>> So to speak could you more through debug your case?
>>
>> I did. And I have much better results now. Let me explain:
> 
>> 1) The device tree was setting up the SPI controller using the controller
>> internal chip select, not a GPIO-based chip select. Until now, I could never
>> get the GPIO-based chip select to work. I finally found out why: I simply
>> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
>> CS gpio is correctly driven active-high instead of the default active-low and
>> the SD card works.
> 
> Yeap, that's the main problem of the standard DW APB SSI controller
> released by Synopsys. Currently SPI-flash'es are the only SPI
> peripheral devices which are capable to work with native DW APB SSI
> chip-selects. I've fixed that for flashes recently by atomizing the
> SPI memory operations (executing them with the local IRQs disabled)
> and performing them on the poll-based basis. Alas the normal
> SPI-transfers still can't be properly executed with native
> chip-selects.
> 
>> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
>> MOSI low while receiving" became completely unnecessary. The SD card works
>> without it.
> 
> Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> Are you sure the original problem has been connected with the Tx lane
> level? On the other hand are you sure the problem has gone away after
> all?

Not sure of anything here :) But removing the patch changing MOSI level did not
prevent the SD card to be scanned & accessed correctly. Before (with native chip
select), the first command would not even complete...

> Moreover I've just taken alook at the MMC SPI driver. Turns out it
> has already been fixed to send ones to the MMC port when it's
> required. So If you still experience the MOSI-level problem
> then that fix might have been done incorrect at some extent...

OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
scripts/get_maintainer.pl does not mention any. Where is that hosted ?


>> Now for testing, I also removed this polling change. Results are these:
>> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
>> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
>> but enough to be annoying, especially on boot as the partition scan sometimes
>> fails because of these errors. In most cases, the block layer retry of failed
>> read/writes cover and no bad errors happen, but the RX FIFO overflow error
>> messages still pop up.
>> 2) Looking into the code further, I realized that RXFLTR is set to half the
>> fifo size minus 1. That sound reasonable, but as that delays interrupt
>> generation until the RX fifo is almost full, I decided to try a value of 0 to
>> get the interrupt as soon as data is available rather than waiting for a chunk.
>> With that, all RX FIFO overflow errors go away, and I could even double the SPI
>> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
>> at all.
>>
> 
> Please, see my last comment...
> 
>> My take:
>> * This controller internal CS seems to be totally broken.
> 
> Native CS aren't broken, they just have been designed so it isn't that
> easy to use them in the linux kernel. Linux kernel SPI-core expects
> the chip-select being driven the way it needs at the certain moments,
> while DW APB SSI toggles them automatically at the moment of the data
> pushing/popping to/from the SPI bus. Some hardware vendors that bought
> the DW APB SSI IP-core have fixed that by providing a way of direct
> CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> platforms).

OK. Thanks for the details.

>> * This SoC has really slow interrupts, so generating these earlier rather than
>> later gives time to the IRQ handler to kick in before the FIFO overflows.
> 
> I am pretty sure that's not the reason. See my next comment.
> 
>>
>> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
>> to set RXFLTR to 0, always. That works well, but this is may be still similar
>> to the "polling" hack in the sense that it is tuning for this SoC rather than a
>> property of the controller. But I do not see any other simple way of removing
>> these annoying RX FIFO overflow errors.
> 
> Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> execution results. I'll try to explain it one more time. DW APB SSI
> provides three modes of transfers (TMOD-es, see the chip manual for
> details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> speaking the mode essence is if you push a byte of data to the Tx
> FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> later from the internal shift register. The IRQ-based transfers have
> been developed full based on that mode. So it's absolutely possible to
> implement a stable algorithm, which would work without a risk of
> getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> should just preserve a balance of sent data so the received data
> wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> doesn't depend on the IRQes performance. No matter how slow the IRQs
> handler is execute, as long as it's executed, the SPI transfers
> procedure shall go on with no errors including the Rx FIFO overflows.

OK. I get it now.

> At least that's what the original DW APB SSI driver developer
> implied when created the code and what I was trying to preserve in my
> patches. If you still get the errors (you sure it's Rx FIFO overflows,
> aren't you?), then something went wrong and either me or the original
> author or someone else has broken the code.

Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
Checked it. And that is the trigger for the error message which exactly says
that "RX FIFO overflow". So that would mean that too many bytes are being
written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
writes more bytes than what is available in the RX FIFO ?

If that is the case, then it seems to me that tx_max() should be modified a
little: rx_len may be large (say a sector), in which case rxtx_gap overflows
(becomes super large), with the result that tx_max() returns tx_room. But that
may be larger than the free space in the RX FIFO, no ?

I think I need to do a round of debug again, tracing these values to figure out
what is going on. I can reproduce the errors very easily (I just need to crank
up the SPI frequency).

> What we currently need is to carefully analyze at what moment you get
> the overflows, what really caused them and fix the problem in the
> code. The capabilities flag isn't an option in this case. I've tried
> to reproduce the errors by slowing the system down, executing the
> SPI-transfers of various length, but with no lick. So it's only you
> for now who observes and can try to debug the problem.

OK. Will do.

> Anyway after we get to fix it, you'll be able to run the MMC port with
> speed as fast as it's possible.

That is my current goal :)

> 
> ---
> One more thing about MMC SPI. Please note, that using MMC SPI and
> DMA-based DW APB SSI transfers might not work well. The thing is that
> the DMA-part of the MMC SPI driver relies on the legacy
> spi_message->is_dma_mapped interface. It performs some specific
> DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
> In its turn the DMA-part of the DW APB SSI driver uses the generic
> SPI-core and the DMA-engine interface to execute the SPI-transfers.
> Since the SPI-core performs the DMA buffers synchronizations
> internally at the moment of the buffers mapping, in case if the DMA
> accesses aren't coherent on your platform, the data buffers might get
> synchronized/flushed with/by caches incorrectly corrupting a part of
> actual data. At least that's what we observed in kernel 4.9... So for
> now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
> transfers.

The K210 has a DW DMA engine, but I do not have it enabled. I tried that too to
be frank, but it fails to initialize the DMA rx/tx channels. I have not dig into
that one since DMA is not at all required for this board given the devices on it.

Thanks for all the help !


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-16  7:47           ` Damien Le Moal
@ 2020-11-16 12:33             ` Mark Brown
  -1 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-16 12:33 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: Serge Semin, linux-riscv, palmer, seanga2, linux-spi

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

On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> On 2020/11/16 1:02, Serge Semin wrote:

> > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > has already been fixed to send ones to the MMC port when it's
> > required. So If you still experience the MOSI-level problem
> > then that fix might have been done incorrect at some extent...

> OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> scripts/get_maintainer.pl does not mention any. Where is that hosted ?

You can read MAINTAINERS directly if there's some bug with
get_maintainer:

SPI SUBSYSTEM
M:      Mark Brown <broonie@kernel.org>
L:      linux-spi@vger.kernel.org
S:      Maintained
Q:      http://patchwork.kernel.org/project/spi-devel-general/list/
T:      git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
F:      Documentation/devicetree/bindings/spi/
F:      Documentation/spi/
F:      drivers/spi/
F:      include/linux/spi/
F:      include/uapi/linux/spi/
F:      tools/spi/

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

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-16 12:33             ` Mark Brown
  0 siblings, 0 replies; 297+ messages in thread
From: Mark Brown @ 2020-11-16 12:33 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, linux-spi, palmer, Serge Semin, seanga2


[-- Attachment #1.1: Type: text/plain, Size: 1029 bytes --]

On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> On 2020/11/16 1:02, Serge Semin wrote:

> > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > has already been fixed to send ones to the MMC port when it's
> > required. So If you still experience the MOSI-level problem
> > then that fix might have been done incorrect at some extent...

> OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> scripts/get_maintainer.pl does not mention any. Where is that hosted ?

You can read MAINTAINERS directly if there's some bug with
get_maintainer:

SPI SUBSYSTEM
M:      Mark Brown <broonie@kernel.org>
L:      linux-spi@vger.kernel.org
S:      Maintained
Q:      http://patchwork.kernel.org/project/spi-devel-general/list/
T:      git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
F:      Documentation/devicetree/bindings/spi/
F:      Documentation/spi/
F:      drivers/spi/
F:      include/linux/spi/
F:      include/uapi/linux/spi/
F:      tools/spi/

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

[-- Attachment #2: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-16  7:47           ` Damien Le Moal
@ 2020-11-16 21:55             ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-16 21:55 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> On 2020/11/16 1:02, Serge Semin wrote:
> > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> >> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> >>> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> >>>> With boards that have slow interrupts context switch, and a fast device
> >>>> connected to a spi master, e.g. an SD card through mmc-spi,
> >>>
> >>>> using
> >>>> dw_spi_poll_transfer() intead of the regular interrupt based
> >>>> dw_spi_transfer_handler() function is more efficient and
> >>>
> >>> I can believe in that. But the next part seems questionable:
> >>>
> >>>> can avoid a lot
> >>>> of RX FIFO overflow errors while keeping the device SPI frequency
> >>>> reasonnably high (for speed).
> >>>
> >>> No matter whether it's an IRQ-based or poll-based transfer, as long as a
> >>> client SPI-device is connected with a GPIO-based chip-select (or the
> >>> DW APB SSI-controller feature of the automatic chip-select toggling is
> >>> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> >>> algorithm design by calculating the rxtx_gap in the dw_writer()
> >>> method. If the error still happens then there must be some bug in
> >>> the code.
> >>>
> >>> It's also strange to hear that the polling-based transfer helps
> >>> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> >>> causes them. Both of those methods are based on the same dw_writer()
> >>> and dw_reader() methods. So basically they both should either work
> >>> well or cause the errors at same time.
> >>>
> >>> So to speak could you more through debug your case?
> >>
> >> I did. And I have much better results now. Let me explain:
> > 
> >> 1) The device tree was setting up the SPI controller using the controller
> >> internal chip select, not a GPIO-based chip select. Until now, I could never
> >> get the GPIO-based chip select to work. I finally found out why: I simply
> >> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> >> CS gpio is correctly driven active-high instead of the default active-low and
> >> the SD card works.
> > 
> > Yeap, that's the main problem of the standard DW APB SSI controller
> > released by Synopsys. Currently SPI-flash'es are the only SPI
> > peripheral devices which are capable to work with native DW APB SSI
> > chip-selects. I've fixed that for flashes recently by atomizing the
> > SPI memory operations (executing them with the local IRQs disabled)
> > and performing them on the poll-based basis. Alas the normal
> > SPI-transfers still can't be properly executed with native
> > chip-selects.
> > 
> >> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> >> MOSI low while receiving" became completely unnecessary. The SD card works
> >> without it.
> > 
> > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > Are you sure the original problem has been connected with the Tx lane
> > level? On the other hand are you sure the problem has gone away after
> > all?
> 
> Not sure of anything here :) But removing the patch changing MOSI level did not
> prevent the SD card to be scanned & accessed correctly. Before (with native chip
> select), the first command would not even complete...
> 
> > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > has already been fixed to send ones to the MMC port when it's
> > required. So If you still experience the MOSI-level problem
> > then that fix might have been done incorrect at some extent...
> 

> OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> scripts/get_maintainer.pl does not mention any. Where is that hosted ?

I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
being used as spi_transfer->tx_buf sometimes there? That's what is
supposed to fix the MOSI level problem. So if at some point the MMC
SPI driver performs an Rx-only SPI transfer with no ones-buffer
specified as the tx_buf one, but the MMC SPI protocol requires for an SD
card to receive ones, then the protocol problem will happen.

> 
> 
> >> Now for testing, I also removed this polling change. Results are these:
> >> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> >> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> >> but enough to be annoying, especially on boot as the partition scan sometimes
> >> fails because of these errors. In most cases, the block layer retry of failed
> >> read/writes cover and no bad errors happen, but the RX FIFO overflow error
> >> messages still pop up.
> >> 2) Looking into the code further, I realized that RXFLTR is set to half the
> >> fifo size minus 1. That sound reasonable, but as that delays interrupt
> >> generation until the RX fifo is almost full, I decided to try a value of 0 to
> >> get the interrupt as soon as data is available rather than waiting for a chunk.
> >> With that, all RX FIFO overflow errors go away, and I could even double the SPI
> >> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> >> at all.
> >>
> > 
> > Please, see my last comment...
> > 
> >> My take:
> >> * This controller internal CS seems to be totally broken.
> > 
> > Native CS aren't broken, they just have been designed so it isn't that
> > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > the chip-select being driven the way it needs at the certain moments,
> > while DW APB SSI toggles them automatically at the moment of the data
> > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > the DW APB SSI IP-core have fixed that by providing a way of direct
> > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > platforms).
> 
> OK. Thanks for the details.
> 
> >> * This SoC has really slow interrupts, so generating these earlier rather than
> >> later gives time to the IRQ handler to kick in before the FIFO overflows.
> > 
> > I am pretty sure that's not the reason. See my next comment.
> > 
> >>
> >> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> >> to set RXFLTR to 0, always. That works well, but this is may be still similar
> >> to the "polling" hack in the sense that it is tuning for this SoC rather than a
> >> property of the controller. But I do not see any other simple way of removing
> >> these annoying RX FIFO overflow errors.
> > 
> > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > execution results. I'll try to explain it one more time. DW APB SSI
> > provides three modes of transfers (TMOD-es, see the chip manual for
> > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > speaking the mode essence is if you push a byte of data to the Tx
> > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > later from the internal shift register. The IRQ-based transfers have
> > been developed full based on that mode. So it's absolutely possible to
> > implement a stable algorithm, which would work without a risk of
> > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > should just preserve a balance of sent data so the received data
> > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > handler is execute, as long as it's executed, the SPI transfers
> > procedure shall go on with no errors including the Rx FIFO overflows.
> 
> OK. I get it now.
> 
> > At least that's what the original DW APB SSI driver developer
> > implied when created the code and what I was trying to preserve in my
> > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > aren't you?), then something went wrong and either me or the original
> > author or someone else has broken the code.
> 

> Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> Checked it. And that is the trigger for the error message which exactly says
> that "RX FIFO overflow". So that would mean that too many bytes are being
> written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> writes more bytes than what is available in the RX FIFO ?

I'd say that in appliance to the implemented in the driver algorithm
the error has been indeed caused by writing too many bytes to the Tx
FIFO. But that in its turn implicitly caused the Rx FIFO overflow.

The error you see in the log specifically means that the Rx FIFO has
been full and there has been more data to receive, but due to not
having any free space in the Rx FIFO that data has been discarded. In
appliance to DW APB SSI driver, as I said, it means that there is a
mistake in the IRQ-based SPI-transfer execution procedure. We've
written too much data to the Tx FIFO so the balance between the sent
and received bytes has been violated. ISR couldn't handle the
interrupt on time and the Rx FIFO has got overrun. If the balance
wasn't violated or the ISR was executed on time we wouldn't have got
the overrun. Supposedly that's why the error hasn't been seen on my or
other platforms but only on yours and only with normal RXFTL register
value. The ISR is executed on time so the balance violation doesn't
affect the transfer that much as in your case. My guess that the
problem might be connected with the off-by-one bug. But that's just a
hypothesis.

> 
> If that is the case, then it seems to me that tx_max() should be modified a
> little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> (becomes super large), with the result that tx_max() returns tx_room. But that
> may be larger than the free space in the RX FIFO, no ?

Yeah, I also considered the tx_max() method as a first place to blame.
But alas I failed to see what might be wrong there.

Let's analyze what tx_max() does. It may get us to a better
understanding what is going on during each send operation.

Here we calculate a free space in the Tx FIFO:
> tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
for new data to send. If it's empty we can send data up to of FIFO
length.

The next is a magic formulae, which makes sure the length of the sent data
always doesn't exceed the Rx FIFO length. In other words it preserve
the so called balance: (rx_len - tx_len <= fifo_len).
> rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
(rx_len - tx_len) gives us a number of data which has already been
written to the Tx FIFO, but the corresponding incoming data still
hasn't been read back from the bus. The formulae above works well
while the next statements are valid:
1) rx_len is always greater than or equal to tx_len. Indeed due to the
SPI nature first we write data to the Tx FIFO and decrement the tx_len
variable accordingly, then we read data from the Rx FIFO and decrement
the rx_len variable.
2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
really see when this could be incorrect, especially seeing we always
send and received data by no more than the FIFO length chunks and
make sure the difference between the sent and received data length
doesn't exceed the FIFO length. The reading is always done before
writing.

Finally we get to select an allowed number of data to send. It's
the minimum of the Tx data length, Rx FIFO free space and the length
of the data which doesn't let the Rx FIFO to oveflow:
> return min3((u32)dws->tx_len, tx_room, rxtx_gap);

Alas currently I don't see at what point the algorithm could be
incorrectly implemented...

> 
> I think I need to do a round of debug again, tracing these values to figure out
> what is going on. I can reproduce the errors very easily (I just need to crank
> up the SPI frequency).

Yeap, that what I would have been doing if I had the problem
reproducible.

-Sergey

> 
> > What we currently need is to carefully analyze at what moment you get
> > the overflows, what really caused them and fix the problem in the
> > code. The capabilities flag isn't an option in this case. I've tried
> > to reproduce the errors by slowing the system down, executing the
> > SPI-transfers of various length, but with no lick. So it's only you
> > for now who observes and can try to debug the problem.
> 
> OK. Will do.
> 
> > Anyway after we get to fix it, you'll be able to run the MMC port with
> > speed as fast as it's possible.
> 
> That is my current goal :)
> 
> > 
> > ---
> > One more thing about MMC SPI. Please note, that using MMC SPI and
> > DMA-based DW APB SSI transfers might not work well. The thing is that
> > the DMA-part of the MMC SPI driver relies on the legacy
> > spi_message->is_dma_mapped interface. It performs some specific
> > DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
> > In its turn the DMA-part of the DW APB SSI driver uses the generic
> > SPI-core and the DMA-engine interface to execute the SPI-transfers.
> > Since the SPI-core performs the DMA buffers synchronizations
> > internally at the moment of the buffers mapping, in case if the DMA
> > accesses aren't coherent on your platform, the data buffers might get
> > synchronized/flushed with/by caches incorrectly corrupting a part of
> > actual data. At least that's what we observed in kernel 4.9... So for
> > now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
> > transfers.
> 
> The K210 has a DW DMA engine, but I do not have it enabled. I tried that too to
> be frank, but it fails to initialize the DMA rx/tx channels. I have not dig into
> that one since DMA is not at all required for this board given the devices on it.
> 
> Thanks for all the help !
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-16 21:55             ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-16 21:55 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> On 2020/11/16 1:02, Serge Semin wrote:
> > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> >> On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> >>> On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> >>>> With boards that have slow interrupts context switch, and a fast device
> >>>> connected to a spi master, e.g. an SD card through mmc-spi,
> >>>
> >>>> using
> >>>> dw_spi_poll_transfer() intead of the regular interrupt based
> >>>> dw_spi_transfer_handler() function is more efficient and
> >>>
> >>> I can believe in that. But the next part seems questionable:
> >>>
> >>>> can avoid a lot
> >>>> of RX FIFO overflow errors while keeping the device SPI frequency
> >>>> reasonnably high (for speed).
> >>>
> >>> No matter whether it's an IRQ-based or poll-based transfer, as long as a
> >>> client SPI-device is connected with a GPIO-based chip-select (or the
> >>> DW APB SSI-controller feature of the automatic chip-select toggling is
> >>> fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> >>> algorithm design by calculating the rxtx_gap in the dw_writer()
> >>> method. If the error still happens then there must be some bug in
> >>> the code.
> >>>
> >>> It's also strange to hear that the polling-based transfer helps
> >>> to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> >>> causes them. Both of those methods are based on the same dw_writer()
> >>> and dw_reader() methods. So basically they both should either work
> >>> well or cause the errors at same time.
> >>>
> >>> So to speak could you more through debug your case?
> >>
> >> I did. And I have much better results now. Let me explain:
> > 
> >> 1) The device tree was setting up the SPI controller using the controller
> >> internal chip select, not a GPIO-based chip select. Until now, I could never
> >> get the GPIO-based chip select to work. I finally found out why: I simply
> >> needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> >> CS gpio is correctly driven active-high instead of the default active-low and
> >> the SD card works.
> > 
> > Yeap, that's the main problem of the standard DW APB SSI controller
> > released by Synopsys. Currently SPI-flash'es are the only SPI
> > peripheral devices which are capable to work with native DW APB SSI
> > chip-selects. I've fixed that for flashes recently by atomizing the
> > SPI memory operations (executing them with the local IRQs disabled)
> > and performing them on the poll-based basis. Alas the normal
> > SPI-transfers still can't be properly executed with native
> > chip-selects.
> > 
> >> 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> >> MOSI low while receiving" became completely unnecessary. The SD card works
> >> without it.
> > 
> > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > Are you sure the original problem has been connected with the Tx lane
> > level? On the other hand are you sure the problem has gone away after
> > all?
> 
> Not sure of anything here :) But removing the patch changing MOSI level did not
> prevent the SD card to be scanned & accessed correctly. Before (with native chip
> select), the first command would not even complete...
> 
> > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > has already been fixed to send ones to the MMC port when it's
> > required. So If you still experience the MOSI-level problem
> > then that fix might have been done incorrect at some extent...
> 

> OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> scripts/get_maintainer.pl does not mention any. Where is that hosted ?

I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
being used as spi_transfer->tx_buf sometimes there? That's what is
supposed to fix the MOSI level problem. So if at some point the MMC
SPI driver performs an Rx-only SPI transfer with no ones-buffer
specified as the tx_buf one, but the MMC SPI protocol requires for an SD
card to receive ones, then the protocol problem will happen.

> 
> 
> >> Now for testing, I also removed this polling change. Results are these:
> >> 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> >> 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> >> but enough to be annoying, especially on boot as the partition scan sometimes
> >> fails because of these errors. In most cases, the block layer retry of failed
> >> read/writes cover and no bad errors happen, but the RX FIFO overflow error
> >> messages still pop up.
> >> 2) Looking into the code further, I realized that RXFLTR is set to half the
> >> fifo size minus 1. That sound reasonable, but as that delays interrupt
> >> generation until the RX fifo is almost full, I decided to try a value of 0 to
> >> get the interrupt as soon as data is available rather than waiting for a chunk.
> >> With that, all RX FIFO overflow errors go away, and I could even double the SPI
> >> frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> >> at all.
> >>
> > 
> > Please, see my last comment...
> > 
> >> My take:
> >> * This controller internal CS seems to be totally broken.
> > 
> > Native CS aren't broken, they just have been designed so it isn't that
> > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > the chip-select being driven the way it needs at the certain moments,
> > while DW APB SSI toggles them automatically at the moment of the data
> > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > the DW APB SSI IP-core have fixed that by providing a way of direct
> > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > platforms).
> 
> OK. Thanks for the details.
> 
> >> * This SoC has really slow interrupts, so generating these earlier rather than
> >> later gives time to the IRQ handler to kick in before the FIFO overflows.
> > 
> > I am pretty sure that's not the reason. See my next comment.
> > 
> >>
> >> In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> >> to set RXFLTR to 0, always. That works well, but this is may be still similar
> >> to the "polling" hack in the sense that it is tuning for this SoC rather than a
> >> property of the controller. But I do not see any other simple way of removing
> >> these annoying RX FIFO overflow errors.
> > 
> > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > execution results. I'll try to explain it one more time. DW APB SSI
> > provides three modes of transfers (TMOD-es, see the chip manual for
> > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > speaking the mode essence is if you push a byte of data to the Tx
> > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > later from the internal shift register. The IRQ-based transfers have
> > been developed full based on that mode. So it's absolutely possible to
> > implement a stable algorithm, which would work without a risk of
> > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > should just preserve a balance of sent data so the received data
> > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > handler is execute, as long as it's executed, the SPI transfers
> > procedure shall go on with no errors including the Rx FIFO overflows.
> 
> OK. I get it now.
> 
> > At least that's what the original DW APB SSI driver developer
> > implied when created the code and what I was trying to preserve in my
> > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > aren't you?), then something went wrong and either me or the original
> > author or someone else has broken the code.
> 

> Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> Checked it. And that is the trigger for the error message which exactly says
> that "RX FIFO overflow". So that would mean that too many bytes are being
> written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> writes more bytes than what is available in the RX FIFO ?

I'd say that in appliance to the implemented in the driver algorithm
the error has been indeed caused by writing too many bytes to the Tx
FIFO. But that in its turn implicitly caused the Rx FIFO overflow.

The error you see in the log specifically means that the Rx FIFO has
been full and there has been more data to receive, but due to not
having any free space in the Rx FIFO that data has been discarded. In
appliance to DW APB SSI driver, as I said, it means that there is a
mistake in the IRQ-based SPI-transfer execution procedure. We've
written too much data to the Tx FIFO so the balance between the sent
and received bytes has been violated. ISR couldn't handle the
interrupt on time and the Rx FIFO has got overrun. If the balance
wasn't violated or the ISR was executed on time we wouldn't have got
the overrun. Supposedly that's why the error hasn't been seen on my or
other platforms but only on yours and only with normal RXFTL register
value. The ISR is executed on time so the balance violation doesn't
affect the transfer that much as in your case. My guess that the
problem might be connected with the off-by-one bug. But that's just a
hypothesis.

> 
> If that is the case, then it seems to me that tx_max() should be modified a
> little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> (becomes super large), with the result that tx_max() returns tx_room. But that
> may be larger than the free space in the RX FIFO, no ?

Yeah, I also considered the tx_max() method as a first place to blame.
But alas I failed to see what might be wrong there.

Let's analyze what tx_max() does. It may get us to a better
understanding what is going on during each send operation.

Here we calculate a free space in the Tx FIFO:
> tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
for new data to send. If it's empty we can send data up to of FIFO
length.

The next is a magic formulae, which makes sure the length of the sent data
always doesn't exceed the Rx FIFO length. In other words it preserve
the so called balance: (rx_len - tx_len <= fifo_len).
> rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
(rx_len - tx_len) gives us a number of data which has already been
written to the Tx FIFO, but the corresponding incoming data still
hasn't been read back from the bus. The formulae above works well
while the next statements are valid:
1) rx_len is always greater than or equal to tx_len. Indeed due to the
SPI nature first we write data to the Tx FIFO and decrement the tx_len
variable accordingly, then we read data from the Rx FIFO and decrement
the rx_len variable.
2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
really see when this could be incorrect, especially seeing we always
send and received data by no more than the FIFO length chunks and
make sure the difference between the sent and received data length
doesn't exceed the FIFO length. The reading is always done before
writing.

Finally we get to select an allowed number of data to send. It's
the minimum of the Tx data length, Rx FIFO free space and the length
of the data which doesn't let the Rx FIFO to oveflow:
> return min3((u32)dws->tx_len, tx_room, rxtx_gap);

Alas currently I don't see at what point the algorithm could be
incorrectly implemented...

> 
> I think I need to do a round of debug again, tracing these values to figure out
> what is going on. I can reproduce the errors very easily (I just need to crank
> up the SPI frequency).

Yeap, that what I would have been doing if I had the problem
reproducible.

-Sergey

> 
> > What we currently need is to carefully analyze at what moment you get
> > the overflows, what really caused them and fix the problem in the
> > code. The capabilities flag isn't an option in this case. I've tried
> > to reproduce the errors by slowing the system down, executing the
> > SPI-transfers of various length, but with no lick. So it's only you
> > for now who observes and can try to debug the problem.
> 
> OK. Will do.
> 
> > Anyway after we get to fix it, you'll be able to run the MMC port with
> > speed as fast as it's possible.
> 
> That is my current goal :)
> 
> > 
> > ---
> > One more thing about MMC SPI. Please note, that using MMC SPI and
> > DMA-based DW APB SSI transfers might not work well. The thing is that
> > the DMA-part of the MMC SPI driver relies on the legacy
> > spi_message->is_dma_mapped interface. It performs some specific
> > DEV-to-MEM and MEM-to-DEV DMA-buffers splitting and synchronizations.
> > In its turn the DMA-part of the DW APB SSI driver uses the generic
> > SPI-core and the DMA-engine interface to execute the SPI-transfers.
> > Since the SPI-core performs the DMA buffers synchronizations
> > internally at the moment of the buffers mapping, in case if the DMA
> > accesses aren't coherent on your platform, the data buffers might get
> > synchronized/flushed with/by caches incorrectly corrupting a part of
> > actual data. At least that's what we observed in kernel 4.9... So for
> > now I'd suggest to use either the poll- or the IRQ-based DW APB SSI
> > transfers.
> 
> The K210 has a DW DMA engine, but I do not have it enabled. I tried that too to
> be frank, but it fails to initialize the DMA rx/tx channels. I have not dig into
> that one since DMA is not at all required for this board given the devices on it.
> 
> Thanks for all the help !
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
  2020-11-16  7:30         ` Damien Le Moal
@ 2020-11-16 22:06           ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-16 22:06 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, devicetree,
	Linus Walleij, open list:GPIO SUBSYSTEM, Philipp Zabel,
	Sean Anderson

On Mon, Nov 16, 2020 at 07:30:15AM +0000, Damien Le Moal wrote:
> On 2020/11/10 2:45, Serge Semin wrote:
> > Hello Andy,
> > 
> > On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> >> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> >>
> >>> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> >>>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> >>>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> >>>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> >>> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> >>
> >> Sorry, but the above doesn't sound right to me.
> >> It's a generic code and you may imagine how many systems you broke by
> >> this change.
> > 
> > Damien replaced the macro above with the code below (your removed it from your
> > message):
> > 
> > +static struct device_node *parse_gpios(struct device_node *np,
> > +                                      const char *prop_name, int index)
> > +{
> > +       /*
> > +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> > +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> > +        * available. As this conflict with "xx-gpios" reference properties,
> > +        * ignore it.
> > +        */
> > +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> > +               return NULL;
> > +
> > +       return parse_suffix_prop_cells(np, prop_name, index,
> > +                                      "-gpios", "#gpio-cells");
> > +}
> > 
> > So AFAICS removing the macro shouldn't cause any problem.
> > 
> > My concern was whether the quirk has been really needed. As I said the
> > "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> > "ngpios" one. Due to the problem noted by Damien any deprecated property
> > utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> > though implicitly but is supposed to encourage people to provide fixes for
> > the dts-files with the deprecated property replaced with "ngpios".
> > 
> > On the other hand an encouragement based on breaking the kernel doesn't seem a
> > good solution. So as I see it either we should accept the solution provided by
> > Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> > DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> > solution would they prefer.
> 

> As Rob mentioned, there are still a lot of DTS out there using "snps,nr-gpios",
> so I think the fix is needed,

Yes.

> albeit with an added warning as Rob suggested so
> that board maintainers can notice and update their DT.

Yes.

> And I can send a patch
> for the DW gpio apb driver to first try the default "ngpios" property, and if it
> is not defined, fallback to the legacy "snps,nr-gpios". With that, these new
> RISC-V boards will not add another use case of the deprecated "snsps,nr-gpios".
> Does that sound like a good plan ?

It has already been added in 5.10:
https://elixir.bootlin.com/linux/v5.10-rc4/source/drivers/gpio/gpio-dwapb.c#L585
so there is no need in sending a patch for the gpio-dwapb.c driver.

-Sergey

> 
> 
> > 
> > -Sergey
> > 
> >>
> >> -- 
> >> With Best Regards,
> >> Andy Shevchenko
> > 
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 01/32] of: Fix property supplier parsing
@ 2020-11-16 22:06           ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-16 22:06 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, Linus Walleij, Sean Anderson,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv

On Mon, Nov 16, 2020 at 07:30:15AM +0000, Damien Le Moal wrote:
> On 2020/11/10 2:45, Serge Semin wrote:
> > Hello Andy,
> > 
> > On Mon, Nov 09, 2020 at 05:14:21PM +0200, Andy Shevchenko wrote:
> >> On Sat, Nov 7, 2020 at 10:14 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> >>
> >>> @@ -1308,7 +1308,6 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL)
> >>>  DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL)
> >>>  DEFINE_SUFFIX_PROP(regulators, "-supply", NULL)
> >>>  DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells")
> >>> -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells")
> >>
> >> Sorry, but the above doesn't sound right to me.
> >> It's a generic code and you may imagine how many systems you broke by
> >> this change.
> > 
> > Damien replaced the macro above with the code below (your removed it from your
> > message):
> > 
> > +static struct device_node *parse_gpios(struct device_node *np,
> > +                                      const char *prop_name, int index)
> > +{
> > +       /*
> > +        * Quirck for the DesignWare gpio-dwapb GPIO driver which defines
> > +        * the "snps,nr-gpios" property to indicate the total number of GPIOs
> > +        * available. As this conflict with "xx-gpios" reference properties,
> > +        * ignore it.
> > +        */
> > +       if (strcmp(prop_name, "snps,nr-gpios") == 0)
> > +               return NULL;
> > +
> > +       return parse_suffix_prop_cells(np, prop_name, index,
> > +                                      "-gpios", "#gpio-cells");
> > +}
> > 
> > So AFAICS removing the macro shouldn't cause any problem.
> > 
> > My concern was whether the quirk has been really needed. As I said the
> > "snps,nr-gpios" property has been marked as deprecated in favor of the standard
> > "ngpios" one. Due to the problem noted by Damien any deprecated property
> > utilization will cause the DW APB SSI DT-nodes probe malfunction. That
> > though implicitly but is supposed to encourage people to provide fixes for
> > the dts-files with the deprecated property replaced with "ngpios".
> > 
> > On the other hand an encouragement based on breaking the kernel doesn't seem a
> > good solution. So as I see it either we should accept the solution provided by
> > Damien, or replace it with a series of fixes for all dts-es with DW APB SSI
> > DT-node defined. I suggest to hear the OF-subsystem maintainers out what
> > solution would they prefer.
> 

> As Rob mentioned, there are still a lot of DTS out there using "snps,nr-gpios",
> so I think the fix is needed,

Yes.

> albeit with an added warning as Rob suggested so
> that board maintainers can notice and update their DT.

Yes.

> And I can send a patch
> for the DW gpio apb driver to first try the default "ngpios" property, and if it
> is not defined, fallback to the legacy "snps,nr-gpios". With that, these new
> RISC-V boards will not add another use case of the deprecated "snsps,nr-gpios".
> Does that sound like a good plan ?

It has already been added in 5.10:
https://elixir.bootlin.com/linux/v5.10-rc4/source/drivers/gpio/gpio-dwapb.c#L585
so there is no need in sending a patch for the gpio-dwapb.c driver.

-Sergey

> 
> 
> > 
> > -Sergey
> > 
> >>
> >> -- 
> >> With Best Regards,
> >> Andy Shevchenko
> > 
> 
> 
> -- 
> Damien Le Moal
> Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-16 21:55             ` Serge Semin
@ 2020-11-17 14:44               ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-17 14:44 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Tue, 2020-11-17 at 00:55 +0300, Serge Semin wrote:
> On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> > On 2020/11/16 1:02, Serge Semin wrote:
> > > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> > > > On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > > > > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > > > > With boards that have slow interrupts context switch, and a fast device
> > > > > > connected to a spi master, e.g. an SD card through mmc-spi,
> > > > > 
> > > > > > using
> > > > > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > > > > dw_spi_transfer_handler() function is more efficient and
> > > > > 
> > > > > I can believe in that. But the next part seems questionable:
> > > > > 
> > > > > > can avoid a lot
> > > > > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > > > > reasonnably high (for speed).
> > > > > 
> > > > > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > > > > client SPI-device is connected with a GPIO-based chip-select (or the
> > > > > DW APB SSI-controller feature of the automatic chip-select toggling is
> > > > > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > > > > algorithm design by calculating the rxtx_gap in the dw_writer()
> > > > > method. If the error still happens then there must be some bug in
> > > > > the code.
> > > > > 
> > > > > It's also strange to hear that the polling-based transfer helps
> > > > > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > > > > causes them. Both of those methods are based on the same dw_writer()
> > > > > and dw_reader() methods. So basically they both should either work
> > > > > well or cause the errors at same time.
> > > > > 
> > > > > So to speak could you more through debug your case?
> > > > 
> > > > I did. And I have much better results now. Let me explain:
> > > 
> > > > 1) The device tree was setting up the SPI controller using the controller
> > > > internal chip select, not a GPIO-based chip select. Until now, I could never
> > > > get the GPIO-based chip select to work. I finally found out why: I simply
> > > > needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> > > > CS gpio is correctly driven active-high instead of the default active-low and
> > > > the SD card works.
> > > 
> > > Yeap, that's the main problem of the standard DW APB SSI controller
> > > released by Synopsys. Currently SPI-flash'es are the only SPI
> > > peripheral devices which are capable to work with native DW APB SSI
> > > chip-selects. I've fixed that for flashes recently by atomizing the
> > > SPI memory operations (executing them with the local IRQs disabled)
> > > and performing them on the poll-based basis. Alas the normal
> > > SPI-transfers still can't be properly executed with native
> > > chip-selects.
> > > 
> > > > 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> > > > MOSI low while receiving" became completely unnecessary. The SD card works
> > > > without it.
> > > 
> > > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > > Are you sure the original problem has been connected with the Tx lane
> > > level? On the other hand are you sure the problem has gone away after
> > > all?
> > 
> > Not sure of anything here :) But removing the patch changing MOSI level did not
> > prevent the SD card to be scanned & accessed correctly. Before (with native chip
> > select), the first command would not even complete...
> > 
> > > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > > has already been fixed to send ones to the MMC port when it's
> > > required. So If you still experience the MOSI-level problem
> > > then that fix might have been done incorrect at some extent...
> > 
> 
> > OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> > scripts/get_maintainer.pl does not mention any. Where is that hosted ?
> 
> I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
> being used as spi_transfer->tx_buf sometimes there? That's what is
> supposed to fix the MOSI level problem. So if at some point the MMC
> SPI driver performs an Rx-only SPI transfer with no ones-buffer
> specified as the tx_buf one, but the MMC SPI protocol requires for an SD
> card to receive ones, then the protocol problem will happen.
> 
> > 
> > 
> > > > Now for testing, I also removed this polling change. Results are these:
> > > > 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> > > > 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> > > > but enough to be annoying, especially on boot as the partition scan sometimes
> > > > fails because of these errors. In most cases, the block layer retry of failed
> > > > read/writes cover and no bad errors happen, but the RX FIFO overflow error
> > > > messages still pop up.
> > > > 2) Looking into the code further, I realized that RXFLTR is set to half the
> > > > fifo size minus 1. That sound reasonable, but as that delays interrupt
> > > > generation until the RX fifo is almost full, I decided to try a value of 0 to
> > > > get the interrupt as soon as data is available rather than waiting for a chunk.
> > > > With that, all RX FIFO overflow errors go away, and I could even double the SPI
> > > > frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> > > > at all.
> > > > 
> > > 
> > > Please, see my last comment...
> > > 
> > > > My take:
> > > > * This controller internal CS seems to be totally broken.
> > > 
> > > Native CS aren't broken, they just have been designed so it isn't that
> > > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > > the chip-select being driven the way it needs at the certain moments,
> > > while DW APB SSI toggles them automatically at the moment of the data
> > > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > > the DW APB SSI IP-core have fixed that by providing a way of direct
> > > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > > platforms).
> > 
> > OK. Thanks for the details.
> > 
> > > > * This SoC has really slow interrupts, so generating these earlier rather than
> > > > later gives time to the IRQ handler to kick in before the FIFO overflows.
> > > 
> > > I am pretty sure that's not the reason. See my next comment.
> > > 
> > > > 
> > > > In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> > > > to set RXFLTR to 0, always. That works well, but this is may be still similar
> > > > to the "polling" hack in the sense that it is tuning for this SoC rather than a
> > > > property of the controller. But I do not see any other simple way of removing
> > > > these annoying RX FIFO overflow errors.
> > > 
> > > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > > execution results. I'll try to explain it one more time. DW APB SSI
> > > provides three modes of transfers (TMOD-es, see the chip manual for
> > > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > > speaking the mode essence is if you push a byte of data to the Tx
> > > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > > later from the internal shift register. The IRQ-based transfers have
> > > been developed full based on that mode. So it's absolutely possible to
> > > implement a stable algorithm, which would work without a risk of
> > > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > > should just preserve a balance of sent data so the received data
> > > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > > handler is execute, as long as it's executed, the SPI transfers
> > > procedure shall go on with no errors including the Rx FIFO overflows.
> > 
> > OK. I get it now.
> > 
> > > At least that's what the original DW APB SSI driver developer
> > > implied when created the code and what I was trying to preserve in my
> > > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > > aren't you?), then something went wrong and either me or the original
> > > author or someone else has broken the code.
> > 
> 
> > Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> > Checked it. And that is the trigger for the error message which exactly says
> > that "RX FIFO overflow". So that would mean that too many bytes are being
> > written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> > writes more bytes than what is available in the RX FIFO ?
> 
> I'd say that in appliance to the implemented in the driver algorithm
> the error has been indeed caused by writing too many bytes to the Tx
> FIFO. But that in its turn implicitly caused the Rx FIFO overflow.
> 
> The error you see in the log specifically means that the Rx FIFO has
> been full and there has been more data to receive, but due to not
> having any free space in the Rx FIFO that data has been discarded. In
> appliance to DW APB SSI driver, as I said, it means that there is a
> mistake in the IRQ-based SPI-transfer execution procedure. We've
> written too much data to the Tx FIFO so the balance between the sent
> and received bytes has been violated. ISR couldn't handle the
> interrupt on time and the Rx FIFO has got overrun. If the balance
> wasn't violated or the ISR was executed on time we wouldn't have got
> the overrun. Supposedly that's why the error hasn't been seen on my or
> other platforms but only on yours and only with normal RXFTL register
> value. The ISR is executed on time so the balance violation doesn't
> affect the transfer that much as in your case. My guess that the
> problem might be connected with the off-by-one bug. But that's just a
> hypothesis.
> 
> > 
> > If that is the case, then it seems to me that tx_max() should be modified a
> > little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> > (becomes super large), with the result that tx_max() returns tx_room. But that
> > may be larger than the free space in the RX FIFO, no ?
> 
> Yeah, I also considered the tx_max() method as a first place to blame.
> But alas I failed to see what might be wrong there.
> 
> Let's analyze what tx_max() does. It may get us to a better
> understanding what is going on during each send operation.
> 
> Here we calculate a free space in the Tx FIFO:
> > tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
> It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
> for new data to send. If it's empty we can send data up to of FIFO
> length.
> 
> The next is a magic formulae, which makes sure the length of the sent data
> always doesn't exceed the Rx FIFO length. In other words it preserve
> the so called balance: (rx_len - tx_len <= fifo_len).
> > rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
> (rx_len - tx_len) gives us a number of data which has already been
> written to the Tx FIFO, but the corresponding incoming data still
> hasn't been read back from the bus. The formulae above works well
> while the next statements are valid:
> 1) rx_len is always greater than or equal to tx_len. Indeed due to the
> SPI nature first we write data to the Tx FIFO and decrement the tx_len
> variable accordingly, then we read data from the Rx FIFO and decrement
> the rx_len variable.
> 2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
> really see when this could be incorrect, especially seeing we always
> send and received data by no more than the FIFO length chunks and
> make sure the difference between the sent and received data length
> doesn't exceed the FIFO length. The reading is always done before
> writing.
> 
> Finally we get to select an allowed number of data to send. It's
> the minimum of the Tx data length, Rx FIFO free space and the length
> of the data which doesn't let the Rx FIFO to oveflow:
> > return min3((u32)dws->tx_len, tx_room, rxtx_gap);
> 
> Alas currently I don't see at what point the algorithm could be
> incorrectly implemented...
> 
> > 
> > I think I need to do a round of debug again, tracing these values to figure out
> > what is going on. I can reproduce the errors very easily (I just need to crank
> > up the SPI frequency).
> 
> Yeap, that what I would have been doing if I had the problem
> reproducible.

Found the bug :)
The fix is:

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index e3b76e40ed73..b7538093c7ef 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
*dws)
                }
                dw_writel(dws, DW_SPI_TXFTLR, 0);
 
-               dws->fifo_len = (fifo == 1) ? 0 : fifo;
+               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
                dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
        }

Basically, fifo_len is off by one, one too large and that causes the RX FIFO
overflow error. The loop above breaks when the written fifo value does not
match the read one, which means that the last correct one is at step fifo - 1.

I realized that by tracing the transfers RX first, then TX in
dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
rx_max(), all the numbers always added up correctly either up to transfer len
or to fifo_len, as they should. It looked all good. But then I realized that RX
FIFO errors would trigger 100% of the time for:
1) transfers larger than fifo size (32 in my case)
2) FIFO slots used for TX + RX adding up to 32
After some tweaking, found the above. Since that bug should be affecting all
dw-apb spi devices, not sure why it does not manifest itself more often.

With the above fix, the SD card is now running flawlessly at 1.2MB/s with
maximum SPI frequency, zero errors no matter how hard I hit it with traffic.

Dropping all other patches (except 32-bits CR0 support that is still needed).
The MOSI line drive patch does not seem to be necessary after all. My guess is
that it was the fact that sometimes one more byte than necessary was being sent
due to fifo len being of by one. With that fixed, there is never any "0" byte
transmitted, so no need to set the value of txw to "0xffff".

Will send proper patches tomorrow, only 2 :)

-- 
Damien Le Moal
Western Digital

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-17 14:44               ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-17 14:44 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Tue, 2020-11-17 at 00:55 +0300, Serge Semin wrote:
> On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> > On 2020/11/16 1:02, Serge Semin wrote:
> > > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> > > > On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > > > > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > > > > With boards that have slow interrupts context switch, and a fast device
> > > > > > connected to a spi master, e.g. an SD card through mmc-spi,
> > > > > 
> > > > > > using
> > > > > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > > > > dw_spi_transfer_handler() function is more efficient and
> > > > > 
> > > > > I can believe in that. But the next part seems questionable:
> > > > > 
> > > > > > can avoid a lot
> > > > > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > > > > reasonnably high (for speed).
> > > > > 
> > > > > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > > > > client SPI-device is connected with a GPIO-based chip-select (or the
> > > > > DW APB SSI-controller feature of the automatic chip-select toggling is
> > > > > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > > > > algorithm design by calculating the rxtx_gap in the dw_writer()
> > > > > method. If the error still happens then there must be some bug in
> > > > > the code.
> > > > > 
> > > > > It's also strange to hear that the polling-based transfer helps
> > > > > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > > > > causes them. Both of those methods are based on the same dw_writer()
> > > > > and dw_reader() methods. So basically they both should either work
> > > > > well or cause the errors at same time.
> > > > > 
> > > > > So to speak could you more through debug your case?
> > > > 
> > > > I did. And I have much better results now. Let me explain:
> > > 
> > > > 1) The device tree was setting up the SPI controller using the controller
> > > > internal chip select, not a GPIO-based chip select. Until now, I could never
> > > > get the GPIO-based chip select to work. I finally found out why: I simply
> > > > needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> > > > CS gpio is correctly driven active-high instead of the default active-low and
> > > > the SD card works.
> > > 
> > > Yeap, that's the main problem of the standard DW APB SSI controller
> > > released by Synopsys. Currently SPI-flash'es are the only SPI
> > > peripheral devices which are capable to work with native DW APB SSI
> > > chip-selects. I've fixed that for flashes recently by atomizing the
> > > SPI memory operations (executing them with the local IRQs disabled)
> > > and performing them on the poll-based basis. Alas the normal
> > > SPI-transfers still can't be properly executed with native
> > > chip-selects.
> > > 
> > > > 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> > > > MOSI low while receiving" became completely unnecessary. The SD card works
> > > > without it.
> > > 
> > > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > > Are you sure the original problem has been connected with the Tx lane
> > > level? On the other hand are you sure the problem has gone away after
> > > all?
> > 
> > Not sure of anything here :) But removing the patch changing MOSI level did not
> > prevent the SD card to be scanned & accessed correctly. Before (with native chip
> > select), the first command would not even complete...
> > 
> > > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > > has already been fixed to send ones to the MMC port when it's
> > > required. So If you still experience the MOSI-level problem
> > > then that fix might have been done incorrect at some extent...
> > 
> 
> > OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> > scripts/get_maintainer.pl does not mention any. Where is that hosted ?
> 
> I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
> being used as spi_transfer->tx_buf sometimes there? That's what is
> supposed to fix the MOSI level problem. So if at some point the MMC
> SPI driver performs an Rx-only SPI transfer with no ones-buffer
> specified as the tx_buf one, but the MMC SPI protocol requires for an SD
> card to receive ones, then the protocol problem will happen.
> 
> > 
> > 
> > > > Now for testing, I also removed this polling change. Results are these:
> > > > 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> > > > 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> > > > but enough to be annoying, especially on boot as the partition scan sometimes
> > > > fails because of these errors. In most cases, the block layer retry of failed
> > > > read/writes cover and no bad errors happen, but the RX FIFO overflow error
> > > > messages still pop up.
> > > > 2) Looking into the code further, I realized that RXFLTR is set to half the
> > > > fifo size minus 1. That sound reasonable, but as that delays interrupt
> > > > generation until the RX fifo is almost full, I decided to try a value of 0 to
> > > > get the interrupt as soon as data is available rather than waiting for a chunk.
> > > > With that, all RX FIFO overflow errors go away, and I could even double the SPI
> > > > frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> > > > at all.
> > > > 
> > > 
> > > Please, see my last comment...
> > > 
> > > > My take:
> > > > * This controller internal CS seems to be totally broken.
> > > 
> > > Native CS aren't broken, they just have been designed so it isn't that
> > > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > > the chip-select being driven the way it needs at the certain moments,
> > > while DW APB SSI toggles them automatically at the moment of the data
> > > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > > the DW APB SSI IP-core have fixed that by providing a way of direct
> > > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > > platforms).
> > 
> > OK. Thanks for the details.
> > 
> > > > * This SoC has really slow interrupts, so generating these earlier rather than
> > > > later gives time to the IRQ handler to kick in before the FIFO overflows.
> > > 
> > > I am pretty sure that's not the reason. See my next comment.
> > > 
> > > > 
> > > > In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> > > > to set RXFLTR to 0, always. That works well, but this is may be still similar
> > > > to the "polling" hack in the sense that it is tuning for this SoC rather than a
> > > > property of the controller. But I do not see any other simple way of removing
> > > > these annoying RX FIFO overflow errors.
> > > 
> > > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > > execution results. I'll try to explain it one more time. DW APB SSI
> > > provides three modes of transfers (TMOD-es, see the chip manual for
> > > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > > speaking the mode essence is if you push a byte of data to the Tx
> > > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > > later from the internal shift register. The IRQ-based transfers have
> > > been developed full based on that mode. So it's absolutely possible to
> > > implement a stable algorithm, which would work without a risk of
> > > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > > should just preserve a balance of sent data so the received data
> > > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > > handler is execute, as long as it's executed, the SPI transfers
> > > procedure shall go on with no errors including the Rx FIFO overflows.
> > 
> > OK. I get it now.
> > 
> > > At least that's what the original DW APB SSI driver developer
> > > implied when created the code and what I was trying to preserve in my
> > > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > > aren't you?), then something went wrong and either me or the original
> > > author or someone else has broken the code.
> > 
> 
> > Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> > Checked it. And that is the trigger for the error message which exactly says
> > that "RX FIFO overflow". So that would mean that too many bytes are being
> > written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> > writes more bytes than what is available in the RX FIFO ?
> 
> I'd say that in appliance to the implemented in the driver algorithm
> the error has been indeed caused by writing too many bytes to the Tx
> FIFO. But that in its turn implicitly caused the Rx FIFO overflow.
> 
> The error you see in the log specifically means that the Rx FIFO has
> been full and there has been more data to receive, but due to not
> having any free space in the Rx FIFO that data has been discarded. In
> appliance to DW APB SSI driver, as I said, it means that there is a
> mistake in the IRQ-based SPI-transfer execution procedure. We've
> written too much data to the Tx FIFO so the balance between the sent
> and received bytes has been violated. ISR couldn't handle the
> interrupt on time and the Rx FIFO has got overrun. If the balance
> wasn't violated or the ISR was executed on time we wouldn't have got
> the overrun. Supposedly that's why the error hasn't been seen on my or
> other platforms but only on yours and only with normal RXFTL register
> value. The ISR is executed on time so the balance violation doesn't
> affect the transfer that much as in your case. My guess that the
> problem might be connected with the off-by-one bug. But that's just a
> hypothesis.
> 
> > 
> > If that is the case, then it seems to me that tx_max() should be modified a
> > little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> > (becomes super large), with the result that tx_max() returns tx_room. But that
> > may be larger than the free space in the RX FIFO, no ?
> 
> Yeah, I also considered the tx_max() method as a first place to blame.
> But alas I failed to see what might be wrong there.
> 
> Let's analyze what tx_max() does. It may get us to a better
> understanding what is going on during each send operation.
> 
> Here we calculate a free space in the Tx FIFO:
> > tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
> It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
> for new data to send. If it's empty we can send data up to of FIFO
> length.
> 
> The next is a magic formulae, which makes sure the length of the sent data
> always doesn't exceed the Rx FIFO length. In other words it preserve
> the so called balance: (rx_len - tx_len <= fifo_len).
> > rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
> (rx_len - tx_len) gives us a number of data which has already been
> written to the Tx FIFO, but the corresponding incoming data still
> hasn't been read back from the bus. The formulae above works well
> while the next statements are valid:
> 1) rx_len is always greater than or equal to tx_len. Indeed due to the
> SPI nature first we write data to the Tx FIFO and decrement the tx_len
> variable accordingly, then we read data from the Rx FIFO and decrement
> the rx_len variable.
> 2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
> really see when this could be incorrect, especially seeing we always
> send and received data by no more than the FIFO length chunks and
> make sure the difference between the sent and received data length
> doesn't exceed the FIFO length. The reading is always done before
> writing.
> 
> Finally we get to select an allowed number of data to send. It's
> the minimum of the Tx data length, Rx FIFO free space and the length
> of the data which doesn't let the Rx FIFO to oveflow:
> > return min3((u32)dws->tx_len, tx_room, rxtx_gap);
> 
> Alas currently I don't see at what point the algorithm could be
> incorrectly implemented...
> 
> > 
> > I think I need to do a round of debug again, tracing these values to figure out
> > what is going on. I can reproduce the errors very easily (I just need to crank
> > up the SPI frequency).
> 
> Yeap, that what I would have been doing if I had the problem
> reproducible.

Found the bug :)
The fix is:

diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index e3b76e40ed73..b7538093c7ef 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
*dws)
                }
                dw_writel(dws, DW_SPI_TXFTLR, 0);
 
-               dws->fifo_len = (fifo == 1) ? 0 : fifo;
+               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
                dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
        }

Basically, fifo_len is off by one, one too large and that causes the RX FIFO
overflow error. The loop above breaks when the written fifo value does not
match the read one, which means that the last correct one is at step fifo - 1.

I realized that by tracing the transfers RX first, then TX in
dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
rx_max(), all the numbers always added up correctly either up to transfer len
or to fifo_len, as they should. It looked all good. But then I realized that RX
FIFO errors would trigger 100% of the time for:
1) transfers larger than fifo size (32 in my case)
2) FIFO slots used for TX + RX adding up to 32
After some tweaking, found the above. Since that bug should be affecting all
dw-apb spi devices, not sure why it does not manifest itself more often.

With the above fix, the SD card is now running flawlessly at 1.2MB/s with
maximum SPI frequency, zero errors no matter how hard I hit it with traffic.

Dropping all other patches (except 32-bits CR0 support that is still needed).
The MOSI line drive patch does not seem to be necessary after all. My guess is
that it was the fact that sometimes one more byte than necessary was being sent
due to fifo len being of by one. With that fixed, there is never any "0" byte
transmitted, so no need to set the value of txw to "0xffff".

Will send proper patches tomorrow, only 2 :)

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-17 14:44               ` Damien Le Moal
@ 2020-11-17 18:26                 ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-17 18:26 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Tue, Nov 17, 2020 at 02:44:13PM +0000, Damien Le Moal wrote:
> On Tue, 2020-11-17 at 00:55 +0300, Serge Semin wrote:
> > On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> > > On 2020/11/16 1:02, Serge Semin wrote:
> > > > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> > > > > On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > > > > > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > > > > > With boards that have slow interrupts context switch, and a fast device
> > > > > > > connected to a spi master, e.g. an SD card through mmc-spi,
> > > > > > 
> > > > > > > using
> > > > > > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > > > > > dw_spi_transfer_handler() function is more efficient and
> > > > > > 
> > > > > > I can believe in that. But the next part seems questionable:
> > > > > > 
> > > > > > > can avoid a lot
> > > > > > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > > > > > reasonnably high (for speed).
> > > > > > 
> > > > > > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > > > > > client SPI-device is connected with a GPIO-based chip-select (or the
> > > > > > DW APB SSI-controller feature of the automatic chip-select toggling is
> > > > > > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > > > > > algorithm design by calculating the rxtx_gap in the dw_writer()
> > > > > > method. If the error still happens then there must be some bug in
> > > > > > the code.
> > > > > > 
> > > > > > It's also strange to hear that the polling-based transfer helps
> > > > > > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > > > > > causes them. Both of those methods are based on the same dw_writer()
> > > > > > and dw_reader() methods. So basically they both should either work
> > > > > > well or cause the errors at same time.
> > > > > > 
> > > > > > So to speak could you more through debug your case?
> > > > > 
> > > > > I did. And I have much better results now. Let me explain:
> > > > 
> > > > > 1) The device tree was setting up the SPI controller using the controller
> > > > > internal chip select, not a GPIO-based chip select. Until now, I could never
> > > > > get the GPIO-based chip select to work. I finally found out why: I simply
> > > > > needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> > > > > CS gpio is correctly driven active-high instead of the default active-low and
> > > > > the SD card works.
> > > > 
> > > > Yeap, that's the main problem of the standard DW APB SSI controller
> > > > released by Synopsys. Currently SPI-flash'es are the only SPI
> > > > peripheral devices which are capable to work with native DW APB SSI
> > > > chip-selects. I've fixed that for flashes recently by atomizing the
> > > > SPI memory operations (executing them with the local IRQs disabled)
> > > > and performing them on the poll-based basis. Alas the normal
> > > > SPI-transfers still can't be properly executed with native
> > > > chip-selects.
> > > > 
> > > > > 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> > > > > MOSI low while receiving" became completely unnecessary. The SD card works
> > > > > without it.
> > > > 
> > > > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > > > Are you sure the original problem has been connected with the Tx lane
> > > > level? On the other hand are you sure the problem has gone away after
> > > > all?
> > > 
> > > Not sure of anything here :) But removing the patch changing MOSI level did not
> > > prevent the SD card to be scanned & accessed correctly. Before (with native chip
> > > select), the first command would not even complete...
> > > 
> > > > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > > > has already been fixed to send ones to the MMC port when it's
> > > > required. So If you still experience the MOSI-level problem
> > > > then that fix might have been done incorrect at some extent...
> > > 
> > 
> > > OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> > > scripts/get_maintainer.pl does not mention any. Where is that hosted ?
> > 
> > I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
> > being used as spi_transfer->tx_buf sometimes there? That's what is
> > supposed to fix the MOSI level problem. So if at some point the MMC
> > SPI driver performs an Rx-only SPI transfer with no ones-buffer
> > specified as the tx_buf one, but the MMC SPI protocol requires for an SD
> > card to receive ones, then the protocol problem will happen.
> > 
> > > 
> > > 
> > > > > Now for testing, I also removed this polling change. Results are these:
> > > > > 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> > > > > 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> > > > > but enough to be annoying, especially on boot as the partition scan sometimes
> > > > > fails because of these errors. In most cases, the block layer retry of failed
> > > > > read/writes cover and no bad errors happen, but the RX FIFO overflow error
> > > > > messages still pop up.
> > > > > 2) Looking into the code further, I realized that RXFLTR is set to half the
> > > > > fifo size minus 1. That sound reasonable, but as that delays interrupt
> > > > > generation until the RX fifo is almost full, I decided to try a value of 0 to
> > > > > get the interrupt as soon as data is available rather than waiting for a chunk.
> > > > > With that, all RX FIFO overflow errors go away, and I could even double the SPI
> > > > > frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> > > > > at all.
> > > > > 
> > > > 
> > > > Please, see my last comment...
> > > > 
> > > > > My take:
> > > > > * This controller internal CS seems to be totally broken.
> > > > 
> > > > Native CS aren't broken, they just have been designed so it isn't that
> > > > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > > > the chip-select being driven the way it needs at the certain moments,
> > > > while DW APB SSI toggles them automatically at the moment of the data
> > > > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > > > the DW APB SSI IP-core have fixed that by providing a way of direct
> > > > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > > > platforms).
> > > 
> > > OK. Thanks for the details.
> > > 
> > > > > * This SoC has really slow interrupts, so generating these earlier rather than
> > > > > later gives time to the IRQ handler to kick in before the FIFO overflows.
> > > > 
> > > > I am pretty sure that's not the reason. See my next comment.
> > > > 
> > > > > 
> > > > > In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> > > > > to set RXFLTR to 0, always. That works well, but this is may be still similar
> > > > > to the "polling" hack in the sense that it is tuning for this SoC rather than a
> > > > > property of the controller. But I do not see any other simple way of removing
> > > > > these annoying RX FIFO overflow errors.
> > > > 
> > > > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > > > execution results. I'll try to explain it one more time. DW APB SSI
> > > > provides three modes of transfers (TMOD-es, see the chip manual for
> > > > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > > > speaking the mode essence is if you push a byte of data to the Tx
> > > > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > > > later from the internal shift register. The IRQ-based transfers have
> > > > been developed full based on that mode. So it's absolutely possible to
> > > > implement a stable algorithm, which would work without a risk of
> > > > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > > > should just preserve a balance of sent data so the received data
> > > > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > > > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > > > handler is execute, as long as it's executed, the SPI transfers
> > > > procedure shall go on with no errors including the Rx FIFO overflows.
> > > 
> > > OK. I get it now.
> > > 
> > > > At least that's what the original DW APB SSI driver developer
> > > > implied when created the code and what I was trying to preserve in my
> > > > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > > > aren't you?), then something went wrong and either me or the original
> > > > author or someone else has broken the code.
> > > 
> > 
> > > Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> > > Checked it. And that is the trigger for the error message which exactly says
> > > that "RX FIFO overflow". So that would mean that too many bytes are being
> > > written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> > > writes more bytes than what is available in the RX FIFO ?
> > 
> > I'd say that in appliance to the implemented in the driver algorithm
> > the error has been indeed caused by writing too many bytes to the Tx
> > FIFO. But that in its turn implicitly caused the Rx FIFO overflow.
> > 
> > The error you see in the log specifically means that the Rx FIFO has
> > been full and there has been more data to receive, but due to not
> > having any free space in the Rx FIFO that data has been discarded. In
> > appliance to DW APB SSI driver, as I said, it means that there is a
> > mistake in the IRQ-based SPI-transfer execution procedure. We've
> > written too much data to the Tx FIFO so the balance between the sent
> > and received bytes has been violated. ISR couldn't handle the
> > interrupt on time and the Rx FIFO has got overrun. If the balance
> > wasn't violated or the ISR was executed on time we wouldn't have got
> > the overrun. Supposedly that's why the error hasn't been seen on my or
> > other platforms but only on yours and only with normal RXFTL register
> > value. The ISR is executed on time so the balance violation doesn't
> > affect the transfer that much as in your case. My guess that the
> > problem might be connected with the off-by-one bug. But that's just a
> > hypothesis.
> > 
> > > 
> > > If that is the case, then it seems to me that tx_max() should be modified a
> > > little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> > > (becomes super large), with the result that tx_max() returns tx_room. But that
> > > may be larger than the free space in the RX FIFO, no ?
> > 
> > Yeah, I also considered the tx_max() method as a first place to blame.
> > But alas I failed to see what might be wrong there.
> > 
> > Let's analyze what tx_max() does. It may get us to a better
> > understanding what is going on during each send operation.
> > 
> > Here we calculate a free space in the Tx FIFO:
> > > tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
> > It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
> > for new data to send. If it's empty we can send data up to of FIFO
> > length.
> > 
> > The next is a magic formulae, which makes sure the length of the sent data
> > always doesn't exceed the Rx FIFO length. In other words it preserve
> > the so called balance: (rx_len - tx_len <= fifo_len).
> > > rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
> > (rx_len - tx_len) gives us a number of data which has already been
> > written to the Tx FIFO, but the corresponding incoming data still
> > hasn't been read back from the bus. The formulae above works well
> > while the next statements are valid:
> > 1) rx_len is always greater than or equal to tx_len. Indeed due to the
> > SPI nature first we write data to the Tx FIFO and decrement the tx_len
> > variable accordingly, then we read data from the Rx FIFO and decrement
> > the rx_len variable.
> > 2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
> > really see when this could be incorrect, especially seeing we always
> > send and received data by no more than the FIFO length chunks and
> > make sure the difference between the sent and received data length
> > doesn't exceed the FIFO length. The reading is always done before
> > writing.
> > 
> > Finally we get to select an allowed number of data to send. It's
> > the minimum of the Tx data length, Rx FIFO free space and the length
> > of the data which doesn't let the Rx FIFO to oveflow:
> > > return min3((u32)dws->tx_len, tx_room, rxtx_gap);
> > 
> > Alas currently I don't see at what point the algorithm could be
> > incorrectly implemented...
> > 
> > > 
> > > I think I need to do a round of debug again, tracing these values to figure out
> > > what is going on. I can reproduce the errors very easily (I just need to crank
> > > up the SPI frequency).
> > 
> > Yeap, that what I would have been doing if I had the problem
> > reproducible.
> 

> Found the bug :)
> The fix is:
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index e3b76e40ed73..b7538093c7ef 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> *dws)
>                 }
>                 dw_writel(dws, DW_SPI_TXFTLR, 0);
>  
> -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
>                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
>         }
> 
> Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> overflow error. The loop above breaks when the written fifo value does not
> match the read one, which means that the last correct one is at step fifo - 1.
> 
> I realized that by tracing the transfers RX first, then TX in
> dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> rx_max(), all the numbers always added up correctly either up to transfer len
> or to fifo_len, as they should. It looked all good. But then I realized that RX
> FIFO errors would trigger 100% of the time for:
> 1) transfers larger than fifo size (32 in my case)
> 2) FIFO slots used for TX + RX adding up to 32
> After some tweaking, found the above. Since that bug should be affecting all
> dw-apb spi devices, not sure why it does not manifest itself more often.
> 
> With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> maximum SPI frequency, zero errors no matter how hard I hit it with traffic.

Hm, what you've found is the clue to getting where the problem lies,
but I don't see fifo_len being calculated incorrectly in my HW. In my
case it equals to 64 and 8 bytes for two different controllers. Those
are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
our controllers have been synthesized with.

But I've just realized that DW APB SSI controller can be synthesized
with Rx and Tx FIFO having different depths. (Synopsys, really, what
scenario did you imagine to provide such configuration?..). Anyway is
it possible that you've got a controller which (most likely by
mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
then that will explain the problem you are having, but everyone else
isn't. The algorithm thinks that both FIFOs length match and equals to
the Tx FIFO length. If Rx FIFO length is smaller even with a single
byte, you'll end up with occasional overflows.

Note if you don't have a manual with the parameters selected for your
IP-core, you can just fix the fifo_len detection loop by replacing the
TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
lengths out. If they don't match, then, bingo, that's the root cause
of the problem.

-Sergey

> 
> Dropping all other patches (except 32-bits CR0 support that is still needed).
> The MOSI line drive patch does not seem to be necessary after all. My guess is
> that it was the fact that sometimes one more byte than necessary was being sent
> due to fifo len being of by one. With that fixed, there is never any "0" byte
> transmitted, so no need to set the value of txw to "0xffff".
> 
> Will send proper patches tomorrow, only 2 :)
> 
> -- 
> Damien Le Moal
> Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-17 18:26                 ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-17 18:26 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Tue, Nov 17, 2020 at 02:44:13PM +0000, Damien Le Moal wrote:
> On Tue, 2020-11-17 at 00:55 +0300, Serge Semin wrote:
> > On Mon, Nov 16, 2020 at 07:47:47AM +0000, Damien Le Moal wrote:
> > > On 2020/11/16 1:02, Serge Semin wrote:
> > > > On Fri, Nov 13, 2020 at 09:22:54AM +0000, Damien Le Moal wrote:
> > > > > On Mon, 2020-11-09 at 22:59 +0300, Serge Semin wrote:
> > > > > > On Sat, Nov 07, 2020 at 05:13:52PM +0900, Damien Le Moal wrote:
> > > > > > > With boards that have slow interrupts context switch, and a fast device
> > > > > > > connected to a spi master, e.g. an SD card through mmc-spi,
> > > > > > 
> > > > > > > using
> > > > > > > dw_spi_poll_transfer() intead of the regular interrupt based
> > > > > > > dw_spi_transfer_handler() function is more efficient and
> > > > > > 
> > > > > > I can believe in that. But the next part seems questionable:
> > > > > > 
> > > > > > > can avoid a lot
> > > > > > > of RX FIFO overflow errors while keeping the device SPI frequency
> > > > > > > reasonnably high (for speed).
> > > > > > 
> > > > > > No matter whether it's an IRQ-based or poll-based transfer, as long as a
> > > > > > client SPI-device is connected with a GPIO-based chip-select (or the
> > > > > > DW APB SSI-controller feature of the automatic chip-select toggling is
> > > > > > fixed), the Rx FIFO should never overrun. It's ensured by the transfer
> > > > > > algorithm design by calculating the rxtx_gap in the dw_writer()
> > > > > > method. If the error still happens then there must be some bug in
> > > > > > the code.
> > > > > > 
> > > > > > It's also strange to hear that the polling-based transfer helps
> > > > > > to avoid the Rx FIFO overflow errors, while the IRQ-based transfer
> > > > > > causes them. Both of those methods are based on the same dw_writer()
> > > > > > and dw_reader() methods. So basically they both should either work
> > > > > > well or cause the errors at same time.
> > > > > > 
> > > > > > So to speak could you more through debug your case?
> > > > > 
> > > > > I did. And I have much better results now. Let me explain:
> > > > 
> > > > > 1) The device tree was setting up the SPI controller using the controller
> > > > > internal chip select, not a GPIO-based chip select. Until now, I could never
> > > > > get the GPIO-based chip select to work. I finally found out why: I simply
> > > > > needed to add the "spi-cs-high" property to the mmc-slot node. With that, the
> > > > > CS gpio is correctly driven active-high instead of the default active-low and
> > > > > the SD card works.
> > > > 
> > > > Yeap, that's the main problem of the standard DW APB SSI controller
> > > > released by Synopsys. Currently SPI-flash'es are the only SPI
> > > > peripheral devices which are capable to work with native DW APB SSI
> > > > chip-selects. I've fixed that for flashes recently by atomizing the
> > > > SPI memory operations (executing them with the local IRQs disabled)
> > > > and performing them on the poll-based basis. Alas the normal
> > > > SPI-transfers still can't be properly executed with native
> > > > chip-selects.
> > > > 
> > > > > 2) With this change using the GPIO-based CS, the patch "spi: dw: Fix driving
> > > > > MOSI low while receiving" became completely unnecessary. The SD card works
> > > > > without it.
> > > > 
> > > > Hm, that's weird. MOSI level has nothing todo with the chip-selects.
> > > > Are you sure the original problem has been connected with the Tx lane
> > > > level? On the other hand are you sure the problem has gone away after
> > > > all?
> > > 
> > > Not sure of anything here :) But removing the patch changing MOSI level did not
> > > prevent the SD card to be scanned & accessed correctly. Before (with native chip
> > > select), the first command would not even complete...
> > > 
> > > > Moreover I've just taken alook at the MMC SPI driver. Turns out it
> > > > has already been fixed to send ones to the MMC port when it's
> > > > required. So If you still experience the MOSI-level problem
> > > > then that fix might have been done incorrect at some extent...
> > > 
> > 
> > > OK. Thanks for the info. I need to rebase on the latest SPI tree then. However,
> > > scripts/get_maintainer.pl does not mention any. Where is that hosted ?
> > 
> > I meant the drivers/mmc/host/mmc_spi.c driver. See the "ones" buffer
> > being used as spi_transfer->tx_buf sometimes there? That's what is
> > supposed to fix the MOSI level problem. So if at some point the MMC
> > SPI driver performs an Rx-only SPI transfer with no ones-buffer
> > specified as the tx_buf one, but the MMC SPI protocol requires for an SD
> > card to receive ones, then the protocol problem will happen.
> > 
> > > 
> > > 
> > > > > Now for testing, I also removed this polling change. Results are these:
> > > > > 1) With the same SPI frequency as before (4MHz), I can run the SD card at about
> > > > > 300 KB/s (read) but I am still seeing some RX FIFO overflow errors. Not a lot,
> > > > > but enough to be annoying, especially on boot as the partition scan sometimes
> > > > > fails because of these errors. In most cases, the block layer retry of failed
> > > > > read/writes cover and no bad errors happen, but the RX FIFO overflow error
> > > > > messages still pop up.
> > > > > 2) Looking into the code further, I realized that RXFLTR is set to half the
> > > > > fifo size minus 1. That sound reasonable, but as that delays interrupt
> > > > > generation until the RX fifo is almost full, I decided to try a value of 0 to
> > > > > get the interrupt as soon as data is available rather than waiting for a chunk.
> > > > > With that, all RX FIFO overflow errors go away, and I could even double the SPI
> > > > > frequency to 8MHz, getting a solid 650KB/s from the SD card without any error
> > > > > at all.
> > > > > 
> > > > 
> > > > Please, see my last comment...
> > > > 
> > > > > My take:
> > > > > * This controller internal CS seems to be totally broken.
> > > > 
> > > > Native CS aren't broken, they just have been designed so it isn't that
> > > > easy to use them in the linux kernel. Linux kernel SPI-core expects
> > > > the chip-select being driven the way it needs at the certain moments,
> > > > while DW APB SSI toggles them automatically at the moment of the data
> > > > pushing/popping to/from the SPI bus. Some hardware vendors that bought
> > > > the DW APB SSI IP-core have fixed that by providing a way of direct
> > > > CS lane control (see spi-dw-mmio.c: Microsemi, Sparx5, Alpine
> > > > platforms).
> > > 
> > > OK. Thanks for the details.
> > > 
> > > > > * This SoC has really slow interrupts, so generating these earlier rather than
> > > > > later gives time to the IRQ handler to kick in before the FIFO overflows.
> > > > 
> > > > I am pretty sure that's not the reason. See my next comment.
> > > > 
> > > > > 
> > > > > In the V2 series for SPI DW, I added a DW_SPI_CAP_RXFLTR_CLEAR capability flag
> > > > > to set RXFLTR to 0, always. That works well, but this is may be still similar
> > > > > to the "polling" hack in the sense that it is tuning for this SoC rather than a
> > > > > property of the controller. But I do not see any other simple way of removing
> > > > > these annoying RX FIFO overflow errors.
> > > > 
> > > > Alas no, RX-FIFO level value shouldn't affect the SPI-transfers
> > > > execution results. I'll try to explain it one more time. DW APB SSI
> > > > provides three modes of transfers (TMOD-es, see the chip manual for
> > > > details). One of them is TMOD=0x0 - Transmit and Receive. Simply
> > > > speaking the mode essence is if you push a byte of data to the Tx
> > > > FIFO you'll synchronously get a byte of data back in the Rx FIFO a bit
> > > > later from the internal shift register. The IRQ-based transfers have
> > > > been developed full based on that mode. So it's absolutely possible to
> > > > implement a stable algorithm, which would work without a risk of
> > > > getting the Rx FIFO overflow or the Tx FIFO overrun. Such algorithm
> > > > should just preserve a balance of sent data so the received data
> > > > wouldn't cause the Rx FIFO overrun. As you understand such algorithm
> > > > doesn't depend on the IRQes performance. No matter how slow the IRQs
> > > > handler is execute, as long as it's executed, the SPI transfers
> > > > procedure shall go on with no errors including the Rx FIFO overflows.
> > > 
> > > OK. I get it now.
> > > 
> > > > At least that's what the original DW APB SSI driver developer
> > > > implied when created the code and what I was trying to preserve in my
> > > > patches. If you still get the errors (you sure it's Rx FIFO overflows,
> > > > aren't you?), then something went wrong and either me or the original
> > > > author or someone else has broken the code.
> > > 
> > 
> > > Yep, 100% sure it is RX FIFO overflow error. The bit in the IRQ status is set.
> > > Checked it. And that is the trigger for the error message which exactly says
> > > that "RX FIFO overflow". So that would mean that too many bytes are being
> > > written to the TX FIFO, right ? Or rather, that when the TX FIFO is written, it
> > > writes more bytes than what is available in the RX FIFO ?
> > 
> > I'd say that in appliance to the implemented in the driver algorithm
> > the error has been indeed caused by writing too many bytes to the Tx
> > FIFO. But that in its turn implicitly caused the Rx FIFO overflow.
> > 
> > The error you see in the log specifically means that the Rx FIFO has
> > been full and there has been more data to receive, but due to not
> > having any free space in the Rx FIFO that data has been discarded. In
> > appliance to DW APB SSI driver, as I said, it means that there is a
> > mistake in the IRQ-based SPI-transfer execution procedure. We've
> > written too much data to the Tx FIFO so the balance between the sent
> > and received bytes has been violated. ISR couldn't handle the
> > interrupt on time and the Rx FIFO has got overrun. If the balance
> > wasn't violated or the ISR was executed on time we wouldn't have got
> > the overrun. Supposedly that's why the error hasn't been seen on my or
> > other platforms but only on yours and only with normal RXFTL register
> > value. The ISR is executed on time so the balance violation doesn't
> > affect the transfer that much as in your case. My guess that the
> > problem might be connected with the off-by-one bug. But that's just a
> > hypothesis.
> > 
> > > 
> > > If that is the case, then it seems to me that tx_max() should be modified a
> > > little: rx_len may be large (say a sector), in which case rxtx_gap overflows
> > > (becomes super large), with the result that tx_max() returns tx_room. But that
> > > may be larger than the free space in the RX FIFO, no ?
> > 
> > Yeah, I also considered the tx_max() method as a first place to blame.
> > But alas I failed to see what might be wrong there.
> > 
> > Let's analyze what tx_max() does. It may get us to a better
> > understanding what is going on during each send operation.
> > 
> > Here we calculate a free space in the Tx FIFO:
> > > tx_room = dws->fifo_len - dw_readl(dws, DW_SPI_TXFLR);
> > It can be within [0, fifo_len]. So if Tx FIFO is full there is no room
> > for new data to send. If it's empty we can send data up to of FIFO
> > length.
> > 
> > The next is a magic formulae, which makes sure the length of the sent data
> > always doesn't exceed the Rx FIFO length. In other words it preserve
> > the so called balance: (rx_len - tx_len <= fifo_len).
> > > rxtx_gap = dws->fifo_len - (dws->rx_len - dws->tx_len);
> > (rx_len - tx_len) gives us a number of data which has already been
> > written to the Tx FIFO, but the corresponding incoming data still
> > hasn't been read back from the bus. The formulae above works well
> > while the next statements are valid:
> > 1) rx_len is always greater than or equal to tx_len. Indeed due to the
> > SPI nature first we write data to the Tx FIFO and decrement the tx_len
> > variable accordingly, then we read data from the Rx FIFO and decrement
> > the rx_len variable.
> > 2) (rx_len - tx_len) is always less than or equal to fifo_len. I don't
> > really see when this could be incorrect, especially seeing we always
> > send and received data by no more than the FIFO length chunks and
> > make sure the difference between the sent and received data length
> > doesn't exceed the FIFO length. The reading is always done before
> > writing.
> > 
> > Finally we get to select an allowed number of data to send. It's
> > the minimum of the Tx data length, Rx FIFO free space and the length
> > of the data which doesn't let the Rx FIFO to oveflow:
> > > return min3((u32)dws->tx_len, tx_room, rxtx_gap);
> > 
> > Alas currently I don't see at what point the algorithm could be
> > incorrectly implemented...
> > 
> > > 
> > > I think I need to do a round of debug again, tracing these values to figure out
> > > what is going on. I can reproduce the errors very easily (I just need to crank
> > > up the SPI frequency).
> > 
> > Yeap, that what I would have been doing if I had the problem
> > reproducible.
> 

> Found the bug :)
> The fix is:
> 
> diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> index e3b76e40ed73..b7538093c7ef 100644
> --- a/drivers/spi/spi-dw-core.c
> +++ b/drivers/spi/spi-dw-core.c
> @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> *dws)
>                 }
>                 dw_writel(dws, DW_SPI_TXFTLR, 0);
>  
> -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
>                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
>         }
> 
> Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> overflow error. The loop above breaks when the written fifo value does not
> match the read one, which means that the last correct one is at step fifo - 1.
> 
> I realized that by tracing the transfers RX first, then TX in
> dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> rx_max(), all the numbers always added up correctly either up to transfer len
> or to fifo_len, as they should. It looked all good. But then I realized that RX
> FIFO errors would trigger 100% of the time for:
> 1) transfers larger than fifo size (32 in my case)
> 2) FIFO slots used for TX + RX adding up to 32
> After some tweaking, found the above. Since that bug should be affecting all
> dw-apb spi devices, not sure why it does not manifest itself more often.
> 
> With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> maximum SPI frequency, zero errors no matter how hard I hit it with traffic.

Hm, what you've found is the clue to getting where the problem lies,
but I don't see fifo_len being calculated incorrectly in my HW. In my
case it equals to 64 and 8 bytes for two different controllers. Those
are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
our controllers have been synthesized with.

But I've just realized that DW APB SSI controller can be synthesized
with Rx and Tx FIFO having different depths. (Synopsys, really, what
scenario did you imagine to provide such configuration?..). Anyway is
it possible that you've got a controller which (most likely by
mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
then that will explain the problem you are having, but everyone else
isn't. The algorithm thinks that both FIFOs length match and equals to
the Tx FIFO length. If Rx FIFO length is smaller even with a single
byte, you'll end up with occasional overflows.

Note if you don't have a manual with the parameters selected for your
IP-core, you can just fix the fifo_len detection loop by replacing the
TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
lengths out. If they don't match, then, bingo, that's the root cause
of the problem.

-Sergey

> 
> Dropping all other patches (except 32-bits CR0 support that is still needed).
> The MOSI line drive patch does not seem to be necessary after all. My guess is
> that it was the fact that sometimes one more byte than necessary was being sent
> due to fifo len being of by one. With that fixed, there is never any "0" byte
> transmitted, so no need to set the value of txw to "0xffff".
> 
> Will send proper patches tomorrow, only 2 :)
> 
> -- 
> Damien Le Moal
> Western Digital

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-17 18:26                 ` Serge Semin
@ 2020-11-18  4:41                   ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-18  4:41 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
[...]
> > Found the bug :)
> > The fix is:
> > 
> > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > index e3b76e40ed73..b7538093c7ef 100644
> > --- a/drivers/spi/spi-dw-core.c
> > +++ b/drivers/spi/spi-dw-core.c
> > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > *dws)
> >                 }
> >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> >  
> > 
> > 
> > 
> > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> >         }
> > 
> > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > overflow error. The loop above breaks when the written fifo value does not
> > match the read one, which means that the last correct one is at step fifo - 1.
> > 
> > I realized that by tracing the transfers RX first, then TX in
> > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > rx_max(), all the numbers always added up correctly either up to transfer len
> > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > FIFO errors would trigger 100% of the time for:
> > 1) transfers larger than fifo size (32 in my case)
> > 2) FIFO slots used for TX + RX adding up to 32
> > After some tweaking, found the above. Since that bug should be affecting all
> > dw-apb spi devices, not sure why it does not manifest itself more often.
> > 
> > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> 
> Hm, what you've found is the clue to getting where the problem lies,
> but I don't see fifo_len being calculated incorrectly in my HW. In my
> case it equals to 64 and 8 bytes for two different controllers. Those
> are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> our controllers have been synthesized with.
> 
> But I've just realized that DW APB SSI controller can be synthesized
> with Rx and Tx FIFO having different depths. (Synopsys, really, what
> scenario did you imagine to provide such configuration?..). Anyway is
> it possible that you've got a controller which (most likely by
> mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> then that will explain the problem you are having, but everyone else
> isn't. The algorithm thinks that both FIFOs length match and equals to
> the Tx FIFO length. If Rx FIFO length is smaller even with a single
> byte, you'll end up with occasional overflows.
> 
> Note if you don't have a manual with the parameters selected for your
> IP-core, you can just fix the fifo_len detection loop by replacing the
> TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> lengths out. If they don't match, then, bingo, that's the root cause
> of the problem.

Just checked: TX and RX fifo depth match and the maximum size I can see in both
RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:

"If you attempt to set this value greater than the depth of the FIFO,
this field is not written and retains its current value."

So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
but that information is written), the loop should stop for fifo=33 with the
registers indicating 32. My fix should be correct.

However (I think this may be the catch), the spec also says:

"This register is sized to the number of address bits needed to access the
FIFO."

So for a fifo depth of 32, the register would be 5 bits only, preventing it
from ever indicating 32. I think that this spec clause takes precedence over
the previous one, and for a fifo max depth that is a power of 2 (which I assume
is the case on most synthesis of the device), the detection loop actually
works. But it would be buggy (off by one) for any other value of the fifo max
depth that is not a power of 2.

If the above is correct, and my SoC spec sheet is also correct, then all I can
think of now is a HW bug. Because no matter what I do or how I look at it, the
RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
really look like 31 is the value to use.

Here is a trace for a 64B transfer (errors happen only for transfers larger
than 32 B):

IRQ(1):
[    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
[    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
32

IRQ(2):
[    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
[    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
15

IRQ(3):
[    1.088932] spi_master spi1: RX FIFO overflow detected
[    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49

Each pair of line correspond to one execution of dw_spi_transfer_handler() on
an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
called, the second line is what tx_max() sees when dw_writer() is executed. The
"used x/y" part of the messages shows TXFLR/RXFLR values.

(1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
(2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
so writes only 15B. All good, again expected. Note that when dw_writer() runs,
the remaining 17B to be received are already available, but that is likely due
to the delay from the pr_info() message print.
(3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
that the RX fifo is full with 32B.

If the RX fifo max depth is indeed 32, I do not understand why the overflow
error is triggered at step (3). There are no more than 32B that can possibly be
received. Putting back the "drive MOSI lne high" patch does not change
anything. Same behavior.

I am out of ideas at this point and can only think that I am facing a HW bug
that needs a quirk somewhere.

Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
fifo_len reduced by one ? Adding a DT property to manually force a value for
fifo_len would work too.

-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-18  4:41                   ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-18  4:41 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
[...]
> > Found the bug :)
> > The fix is:
> > 
> > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > index e3b76e40ed73..b7538093c7ef 100644
> > --- a/drivers/spi/spi-dw-core.c
> > +++ b/drivers/spi/spi-dw-core.c
> > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > *dws)
> >                 }
> >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> >  
> > 
> > 
> > 
> > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> >         }
> > 
> > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > overflow error. The loop above breaks when the written fifo value does not
> > match the read one, which means that the last correct one is at step fifo - 1.
> > 
> > I realized that by tracing the transfers RX first, then TX in
> > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > rx_max(), all the numbers always added up correctly either up to transfer len
> > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > FIFO errors would trigger 100% of the time for:
> > 1) transfers larger than fifo size (32 in my case)
> > 2) FIFO slots used for TX + RX adding up to 32
> > After some tweaking, found the above. Since that bug should be affecting all
> > dw-apb spi devices, not sure why it does not manifest itself more often.
> > 
> > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> 
> Hm, what you've found is the clue to getting where the problem lies,
> but I don't see fifo_len being calculated incorrectly in my HW. In my
> case it equals to 64 and 8 bytes for two different controllers. Those
> are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> our controllers have been synthesized with.
> 
> But I've just realized that DW APB SSI controller can be synthesized
> with Rx and Tx FIFO having different depths. (Synopsys, really, what
> scenario did you imagine to provide such configuration?..). Anyway is
> it possible that you've got a controller which (most likely by
> mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> then that will explain the problem you are having, but everyone else
> isn't. The algorithm thinks that both FIFOs length match and equals to
> the Tx FIFO length. If Rx FIFO length is smaller even with a single
> byte, you'll end up with occasional overflows.
> 
> Note if you don't have a manual with the parameters selected for your
> IP-core, you can just fix the fifo_len detection loop by replacing the
> TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> lengths out. If they don't match, then, bingo, that's the root cause
> of the problem.

Just checked: TX and RX fifo depth match and the maximum size I can see in both
RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:

"If you attempt to set this value greater than the depth of the FIFO,
this field is not written and retains its current value."

So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
but that information is written), the loop should stop for fifo=33 with the
registers indicating 32. My fix should be correct.

However (I think this may be the catch), the spec also says:

"This register is sized to the number of address bits needed to access the
FIFO."

So for a fifo depth of 32, the register would be 5 bits only, preventing it
from ever indicating 32. I think that this spec clause takes precedence over
the previous one, and for a fifo max depth that is a power of 2 (which I assume
is the case on most synthesis of the device), the detection loop actually
works. But it would be buggy (off by one) for any other value of the fifo max
depth that is not a power of 2.

If the above is correct, and my SoC spec sheet is also correct, then all I can
think of now is a HW bug. Because no matter what I do or how I look at it, the
RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
really look like 31 is the value to use.

Here is a trace for a 64B transfer (errors happen only for transfers larger
than 32 B):

IRQ(1):
[    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
[    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
32

IRQ(2):
[    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
[    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
15

IRQ(3):
[    1.088932] spi_master spi1: RX FIFO overflow detected
[    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49

Each pair of line correspond to one execution of dw_spi_transfer_handler() on
an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
called, the second line is what tx_max() sees when dw_writer() is executed. The
"used x/y" part of the messages shows TXFLR/RXFLR values.

(1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
(2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
so writes only 15B. All good, again expected. Note that when dw_writer() runs,
the remaining 17B to be received are already available, but that is likely due
to the delay from the pr_info() message print.
(3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
that the RX fifo is full with 32B.

If the RX fifo max depth is indeed 32, I do not understand why the overflow
error is triggered at step (3). There are no more than 32B that can possibly be
received. Putting back the "drive MOSI lne high" patch does not change
anything. Same behavior.

I am out of ideas at this point and can only think that I am facing a HW bug
that needs a quirk somewhere.

Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
fifo_len reduced by one ? Adding a DT property to manually force a value for
fifo_len would work too.

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-18  4:41                   ` Damien Le Moal
@ 2020-11-18 15:16                     ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-18 15:16 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

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

On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> [...]
> > > Found the bug :)
> > > The fix is:
> > > 
> > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > index e3b76e40ed73..b7538093c7ef 100644
> > > --- a/drivers/spi/spi-dw-core.c
> > > +++ b/drivers/spi/spi-dw-core.c
> > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > *dws)
> > >                 }
> > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > >  
> > > 
> > > 
> > > 
> > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > >         }
> > > 
> > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > overflow error. The loop above breaks when the written fifo value does not
> > > match the read one, which means that the last correct one is at step fifo - 1.
> > > 
> > > I realized that by tracing the transfers RX first, then TX in
> > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > FIFO errors would trigger 100% of the time for:
> > > 1) transfers larger than fifo size (32 in my case)
> > > 2) FIFO slots used for TX + RX adding up to 32
> > > After some tweaking, found the above. Since that bug should be affecting all
> > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > 
> > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > 
> > Hm, what you've found is the clue to getting where the problem lies,
> > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > case it equals to 64 and 8 bytes for two different controllers. Those
> > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > our controllers have been synthesized with.
> > 
> > But I've just realized that DW APB SSI controller can be synthesized
> > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > scenario did you imagine to provide such configuration?..). Anyway is
> > it possible that you've got a controller which (most likely by
> > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > then that will explain the problem you are having, but everyone else
> > isn't. The algorithm thinks that both FIFOs length match and equals to
> > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > byte, you'll end up with occasional overflows.
> > 
> > Note if you don't have a manual with the parameters selected for your
> > IP-core, you can just fix the fifo_len detection loop by replacing the
> > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > lengths out. If they don't match, then, bingo, that's the root cause
> > of the problem.
> 

> Just checked: TX and RX fifo depth match and the maximum size I can see in both
> RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> 
> "If you attempt to set this value greater than the depth of the FIFO,
> this field is not written and retains its current value."
> 
> So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> but that information is written), the loop should stop for fifo=33 with the
> registers indicating 32. My fix should be correct.

v3.22a spec says "greater than or equal to the depth of the FIFO" for
TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
case both of the formulations make sense. Seeing the semantic of the
registers is different and recollecting how vague vendors can describe
the essence of regs, in both cases FIFO depth would be detected as
(MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
but isn't for RXFTLR. In the later case we need to keep in mind that
the controller internally increments (RXFTLR.RFT + 1) then compares it
with RXFLR.RXTFL. Most likely the RXFTLR description text means that
incremented value when says: "If you attempt to set this value greater
than the depth of the FIFO, this field is not written and retains its
current value." but not the actual value written into the register.

Regarding DW APB SSI v4 spec. I don't really know why the description
has changed for TXFTLR. I also don't have the v4 spec to better
understand what they really meant there. But if the TXFTLR/RXFTLR
registers semantic has changed, then I'd start to dig in the aspects
of that change and whether it affects the FIFO-depth calculation
algorithm...

Anyway regarding your fix. Please see the next two commits, which have
already attempted to introduce a change proposed by you, but then
reverted it back:
d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
9d239d353c31 ("spi: dw: revisit FIFO size detection again")

I don't think Andy was wrong reverting the fix back, especially seeing
the current FIFO-depth detection algorithm implementation is correct
for both types of my controllers (with 8 and 64 words depths). I know
with what parameters the controllers have been synthesized and the
detected depths match them.

> 
> However (I think this may be the catch), the spec also says:
> 
> "This register is sized to the number of address bits needed to access the
> FIFO."
> 
> So for a fifo depth of 32, the register would be 5 bits only, preventing it
> from ever indicating 32.

In accordance with the registers semantic we shall never write a
FIFO-depth value into them and actually we aren't able to do that.
First of all indeed there is no point in setting the FIFO-depth value
into the TXFTLR because that will cause the TXE-IRQ being constantly
generated (because the level of the Tx FIFO will be always less than
or equal to the FIFO-depth). There is no point in setting the
FIFO-depth into the RXFTLR because that will effectively disable the
RXF-IRQ (the level of the Rx FIFO will be never greater than
FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
value wider than the register is.

> I think that this spec clause takes precedence over
> the previous one, and for a fifo max depth that is a power of 2 (which I assume
> is the case on most synthesis of the device), the detection loop actually
> works. But it would be buggy (off by one) for any other value of the fifo max
> depth that is not a power of 2.
> 
> If the above is correct, and my SoC spec sheet is also correct, then all I can
> think of now is a HW bug. Because no matter what I do or how I look at it, the
> RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> really look like 31 is the value to use.

Of course we shouldn't reject a possibility of having a HW bug here,
but that is always a last resort and needs to be firmly proved.
In your case we may assume one of two causes of the problem:
1) There is the depths mismatch.
   But how come you still get the RXFLR to be filled with data of
   greater length than we think the Rx FIFO depth is?.. Anyway the
   weird behaviour still can be explained by the non-standard
   configuration especially if the depth isn't power of 2, that
   Synopsys might haven't even tested it, etc.
2) There is a HW bug, due to which the RXO interrupt is generated even
   though there is no actual overrun.
Let's try to prove or disprove them.

Let's assume that there is indeed the depths mismatch here:
(SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
reason (due to for instance the TXFTLR/RXFTLR semantic change or
the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
in the driver. If so we can't rely on the depth detection loop and
need to try to prove the depths mismatch somehow else. It would be
also better to exclude the driver code from the problem equation...

Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
we can just try to manually execute a small SPI transfer of the Tx FIFO
depth length. If the mismatch takes place or an HW bug with false RXO,
then we'll get the Rx FIFO overflow flag set.

I've created a small shell-script (you can find it in the attachment)
which runs a single SPI transfer of the passed length by manually
setting a DW APB SSI controller up with help of the devmem utility.
In our case the length is supposed to be equal to the FIFO depth.
Here is what happens if I run it on my hardware (depth equals to 64
and the controller registers physical address is 0x1f04e000):

root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011

See, after sending and receiving all the data the status register
detects the normal TXE and RXF interrupts. But if our assumptions are
correct in your case it shall be something like 0x00000019 also
presenting the RXO interrupt.

* Note AFAIU you might need to fix the script a bit to set the DFS
* field at the correct place of CTRLR0...

If after running the attached script you get the RXO status set, then
indeed there is either the depths mismatch or there is a HW bug. If
the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
of the algorithm implemented in the driver. Then we have no choice but
to manually set the FIFO depth for the K210 SPI controller.

> 
> Here is a trace for a 64B transfer (errors happen only for transfers larger
> than 32 B):
> 
> IRQ(1):
> [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> 32
> 
> IRQ(2):
> [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> 15
> 
> IRQ(3):
> [    1.088932] spi_master spi1: RX FIFO overflow detected
> [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> 
> Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> called, the second line is what tx_max() sees when dw_writer() is executed. The
> "used x/y" part of the messages shows TXFLR/RXFLR values.
> 
> (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> the remaining 17B to be received are already available, but that is likely due
> to the delay from the pr_info() message print.
> (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> that the RX fifo is full with 32B.
> 
> If the RX fifo max depth is indeed 32, I do not understand why the overflow
> error is triggered at step (3). There are no more than 32B that can possibly be
> received. Putting back the "drive MOSI lne high" patch does not change
> anything. Same behavior.

The log you've sent indeed looks weird. I'd one more time performed
the next steps:
1) Study the spec paying special attention to the TXFTLR/RXFTLR and
   TXFLR/RXFLR registers descriptions. Mostly we need to make sure
   that nothing has changed since the older controller revisions and
   what the driver implements is correct for your controller.
2) Try to find an internal doc with the DW APB SSI IP-core parameters
   initialized during the controller synthesize. Try to find the
   SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
3) Try to find an errata doc for your controller revision and make
   sure it doesn't have anything about the problem you are getting
   here.
4) Run the attached script to make sure that the problem isn't
   connected with a bug in the driver, but either with the depths
   mismatch or with an HW bug.

> 
> I am out of ideas at this point and can only think that I am facing a HW bug
> that needs a quirk somewhere.
> 
> Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> fifo_len reduced by one ? Adding a DT property to manually force a value for
> fifo_len would work too.

So if none of the steps above gives us an answer, then we need to dig
dipper into the driver code and we missing something. If 2) - 4) proves the
depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
a custom fifo_len for the K210 SPI controller.

Anyway I don't think a quirk flag would be a good solution here because
the problem seems very specific to your controller...

-Sergey

> 
> -- 
> Damien Le Moal
> Western Digital

[-- Attachment #2: check_mismatch.sh --]
[-- Type: application/x-sh, Size: 1795 bytes --]

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-18 15:16                     ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-18 15:16 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

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

On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> [...]
> > > Found the bug :)
> > > The fix is:
> > > 
> > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > index e3b76e40ed73..b7538093c7ef 100644
> > > --- a/drivers/spi/spi-dw-core.c
> > > +++ b/drivers/spi/spi-dw-core.c
> > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > *dws)
> > >                 }
> > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > >  
> > > 
> > > 
> > > 
> > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > >         }
> > > 
> > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > overflow error. The loop above breaks when the written fifo value does not
> > > match the read one, which means that the last correct one is at step fifo - 1.
> > > 
> > > I realized that by tracing the transfers RX first, then TX in
> > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > FIFO errors would trigger 100% of the time for:
> > > 1) transfers larger than fifo size (32 in my case)
> > > 2) FIFO slots used for TX + RX adding up to 32
> > > After some tweaking, found the above. Since that bug should be affecting all
> > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > 
> > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > 
> > Hm, what you've found is the clue to getting where the problem lies,
> > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > case it equals to 64 and 8 bytes for two different controllers. Those
> > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > our controllers have been synthesized with.
> > 
> > But I've just realized that DW APB SSI controller can be synthesized
> > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > scenario did you imagine to provide such configuration?..). Anyway is
> > it possible that you've got a controller which (most likely by
> > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > then that will explain the problem you are having, but everyone else
> > isn't. The algorithm thinks that both FIFOs length match and equals to
> > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > byte, you'll end up with occasional overflows.
> > 
> > Note if you don't have a manual with the parameters selected for your
> > IP-core, you can just fix the fifo_len detection loop by replacing the
> > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > lengths out. If they don't match, then, bingo, that's the root cause
> > of the problem.
> 

> Just checked: TX and RX fifo depth match and the maximum size I can see in both
> RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> 
> "If you attempt to set this value greater than the depth of the FIFO,
> this field is not written and retains its current value."
> 
> So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> but that information is written), the loop should stop for fifo=33 with the
> registers indicating 32. My fix should be correct.

v3.22a spec says "greater than or equal to the depth of the FIFO" for
TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
case both of the formulations make sense. Seeing the semantic of the
registers is different and recollecting how vague vendors can describe
the essence of regs, in both cases FIFO depth would be detected as
(MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
but isn't for RXFTLR. In the later case we need to keep in mind that
the controller internally increments (RXFTLR.RFT + 1) then compares it
with RXFLR.RXTFL. Most likely the RXFTLR description text means that
incremented value when says: "If you attempt to set this value greater
than the depth of the FIFO, this field is not written and retains its
current value." but not the actual value written into the register.

Regarding DW APB SSI v4 spec. I don't really know why the description
has changed for TXFTLR. I also don't have the v4 spec to better
understand what they really meant there. But if the TXFTLR/RXFTLR
registers semantic has changed, then I'd start to dig in the aspects
of that change and whether it affects the FIFO-depth calculation
algorithm...

Anyway regarding your fix. Please see the next two commits, which have
already attempted to introduce a change proposed by you, but then
reverted it back:
d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
9d239d353c31 ("spi: dw: revisit FIFO size detection again")

I don't think Andy was wrong reverting the fix back, especially seeing
the current FIFO-depth detection algorithm implementation is correct
for both types of my controllers (with 8 and 64 words depths). I know
with what parameters the controllers have been synthesized and the
detected depths match them.

> 
> However (I think this may be the catch), the spec also says:
> 
> "This register is sized to the number of address bits needed to access the
> FIFO."
> 
> So for a fifo depth of 32, the register would be 5 bits only, preventing it
> from ever indicating 32.

In accordance with the registers semantic we shall never write a
FIFO-depth value into them and actually we aren't able to do that.
First of all indeed there is no point in setting the FIFO-depth value
into the TXFTLR because that will cause the TXE-IRQ being constantly
generated (because the level of the Tx FIFO will be always less than
or equal to the FIFO-depth). There is no point in setting the
FIFO-depth into the RXFTLR because that will effectively disable the
RXF-IRQ (the level of the Rx FIFO will be never greater than
FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
value wider than the register is.

> I think that this spec clause takes precedence over
> the previous one, and for a fifo max depth that is a power of 2 (which I assume
> is the case on most synthesis of the device), the detection loop actually
> works. But it would be buggy (off by one) for any other value of the fifo max
> depth that is not a power of 2.
> 
> If the above is correct, and my SoC spec sheet is also correct, then all I can
> think of now is a HW bug. Because no matter what I do or how I look at it, the
> RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> really look like 31 is the value to use.

Of course we shouldn't reject a possibility of having a HW bug here,
but that is always a last resort and needs to be firmly proved.
In your case we may assume one of two causes of the problem:
1) There is the depths mismatch.
   But how come you still get the RXFLR to be filled with data of
   greater length than we think the Rx FIFO depth is?.. Anyway the
   weird behaviour still can be explained by the non-standard
   configuration especially if the depth isn't power of 2, that
   Synopsys might haven't even tested it, etc.
2) There is a HW bug, due to which the RXO interrupt is generated even
   though there is no actual overrun.
Let's try to prove or disprove them.

Let's assume that there is indeed the depths mismatch here:
(SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
reason (due to for instance the TXFTLR/RXFTLR semantic change or
the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
in the driver. If so we can't rely on the depth detection loop and
need to try to prove the depths mismatch somehow else. It would be
also better to exclude the driver code from the problem equation...

Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
we can just try to manually execute a small SPI transfer of the Tx FIFO
depth length. If the mismatch takes place or an HW bug with false RXO,
then we'll get the Rx FIFO overflow flag set.

I've created a small shell-script (you can find it in the attachment)
which runs a single SPI transfer of the passed length by manually
setting a DW APB SSI controller up with help of the devmem utility.
In our case the length is supposed to be equal to the FIFO depth.
Here is what happens if I run it on my hardware (depth equals to 64
and the controller registers physical address is 0x1f04e000):

root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011

See, after sending and receiving all the data the status register
detects the normal TXE and RXF interrupts. But if our assumptions are
correct in your case it shall be something like 0x00000019 also
presenting the RXO interrupt.

* Note AFAIU you might need to fix the script a bit to set the DFS
* field at the correct place of CTRLR0...

If after running the attached script you get the RXO status set, then
indeed there is either the depths mismatch or there is a HW bug. If
the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
of the algorithm implemented in the driver. Then we have no choice but
to manually set the FIFO depth for the K210 SPI controller.

> 
> Here is a trace for a 64B transfer (errors happen only for transfers larger
> than 32 B):
> 
> IRQ(1):
> [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> 32
> 
> IRQ(2):
> [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> 15
> 
> IRQ(3):
> [    1.088932] spi_master spi1: RX FIFO overflow detected
> [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> 
> Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> called, the second line is what tx_max() sees when dw_writer() is executed. The
> "used x/y" part of the messages shows TXFLR/RXFLR values.
> 
> (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> the remaining 17B to be received are already available, but that is likely due
> to the delay from the pr_info() message print.
> (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> that the RX fifo is full with 32B.
> 
> If the RX fifo max depth is indeed 32, I do not understand why the overflow
> error is triggered at step (3). There are no more than 32B that can possibly be
> received. Putting back the "drive MOSI lne high" patch does not change
> anything. Same behavior.

The log you've sent indeed looks weird. I'd one more time performed
the next steps:
1) Study the spec paying special attention to the TXFTLR/RXFTLR and
   TXFLR/RXFLR registers descriptions. Mostly we need to make sure
   that nothing has changed since the older controller revisions and
   what the driver implements is correct for your controller.
2) Try to find an internal doc with the DW APB SSI IP-core parameters
   initialized during the controller synthesize. Try to find the
   SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
3) Try to find an errata doc for your controller revision and make
   sure it doesn't have anything about the problem you are getting
   here.
4) Run the attached script to make sure that the problem isn't
   connected with a bug in the driver, but either with the depths
   mismatch or with an HW bug.

> 
> I am out of ideas at this point and can only think that I am facing a HW bug
> that needs a quirk somewhere.
> 
> Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> fifo_len reduced by one ? Adding a DT property to manually force a value for
> fifo_len would work too.

So if none of the steps above gives us an answer, then we need to dig
dipper into the driver code and we missing something. If 2) - 4) proves the
depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
a custom fifo_len for the K210 SPI controller.

Anyway I don't think a quirk flag would be a good solution here because
the problem seems very specific to your controller...

-Sergey

> 
> -- 
> Damien Le Moal
> Western Digital

[-- Attachment #2: check_mismatch.sh --]
[-- Type: application/x-sh, Size: 1795 bytes --]

[-- Attachment #3: Type: text/plain, Size: 161 bytes --]

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-18 15:16                     ` Serge Semin
@ 2020-11-19  5:12                       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19  5:12 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > [...]
> > > > Found the bug :)
> > > > The fix is:
> > > > 
> > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > --- a/drivers/spi/spi-dw-core.c
> > > > +++ b/drivers/spi/spi-dw-core.c
> > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > *dws)
> > > >                 }
> > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > >  
> > > > 
> > > > 
> > > > 
> > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > >         }
> > > > 
> > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > overflow error. The loop above breaks when the written fifo value does not
> > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > 
> > > > I realized that by tracing the transfers RX first, then TX in
> > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > FIFO errors would trigger 100% of the time for:
> > > > 1) transfers larger than fifo size (32 in my case)
> > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > 
> > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > 
> > > Hm, what you've found is the clue to getting where the problem lies,
> > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > our controllers have been synthesized with.
> > > 
> > > But I've just realized that DW APB SSI controller can be synthesized
> > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > scenario did you imagine to provide such configuration?..). Anyway is
> > > it possible that you've got a controller which (most likely by
> > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > then that will explain the problem you are having, but everyone else
> > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > byte, you'll end up with occasional overflows.
> > > 
> > > Note if you don't have a manual with the parameters selected for your
> > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > lengths out. If they don't match, then, bingo, that's the root cause
> > > of the problem.
> > 
> 
> > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > 
> > "If you attempt to set this value greater than the depth of the FIFO,
> > this field is not written and retains its current value."
> > 
> > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > but that information is written), the loop should stop for fifo=33 with the
> > registers indicating 32. My fix should be correct.
> 
> v3.22a spec says "greater than or equal to the depth of the FIFO" for
> TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> case both of the formulations make sense. Seeing the semantic of the
> registers is different and recollecting how vague vendors can describe
> the essence of regs, in both cases FIFO depth would be detected as
> (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> but isn't for RXFTLR. In the later case we need to keep in mind that
> the controller internally increments (RXFTLR.RFT + 1) then compares it
> with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> incremented value when says: "If you attempt to set this value greater
> than the depth of the FIFO, this field is not written and retains its
> current value." but not the actual value written into the register.
> 
> Regarding DW APB SSI v4 spec. I don't really know why the description
> has changed for TXFTLR. I also don't have the v4 spec to better
> understand what they really meant there. But if the TXFTLR/RXFTLR
> registers semantic has changed, then I'd start to dig in the aspects
> of that change and whether it affects the FIFO-depth calculation
> algorithm...

I spent a lot of time reading the spec yesterday and did not see any text that
conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
still as you describe above for v3, the internal +1 increment for RXFTLR is
still there.

> Anyway regarding your fix. Please see the next two commits, which have
> already attempted to introduce a change proposed by you, but then
> reverted it back:
> d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> 
> I don't think Andy was wrong reverting the fix back, especially seeing
> the current FIFO-depth detection algorithm implementation is correct
> for both types of my controllers (with 8 and 64 words depths). I know
> with what parameters the controllers have been synthesized and the
> detected depths match them.

OK. Got it.

> 
> > 
> > However (I think this may be the catch), the spec also says:
> > 
> > "This register is sized to the number of address bits needed to access the
> > FIFO."
> > 
> > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > from ever indicating 32.
> 
> In accordance with the registers semantic we shall never write a
> FIFO-depth value into them and actually we aren't able to do that.
> First of all indeed there is no point in setting the FIFO-depth value
> into the TXFTLR because that will cause the TXE-IRQ being constantly
> generated (because the level of the Tx FIFO will be always less than
> or equal to the FIFO-depth). There is no point in setting the
> FIFO-depth into the RXFTLR because that will effectively disable the
> RXF-IRQ (the level of the Rx FIFO will be never greater than
> FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> value wider than the register is.

Yep, understood.

> 
> > I think that this spec clause takes precedence over
> > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > is the case on most synthesis of the device), the detection loop actually
> > works. But it would be buggy (off by one) for any other value of the fifo max
> > depth that is not a power of 2.
> > 
> > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > really look like 31 is the value to use.
> 
> Of course we shouldn't reject a possibility of having a HW bug here,
> but that is always a last resort and needs to be firmly proved.
> In your case we may assume one of two causes of the problem:
> 1) There is the depths mismatch.
>    But how come you still get the RXFLR to be filled with data of
>    greater length than we think the Rx FIFO depth is?.. Anyway the
>    weird behaviour still can be explained by the non-standard
>    configuration especially if the depth isn't power of 2, that
>    Synopsys might haven't even tested it, etc.

I have never seen RXFLR being larger than 32, which is the assumed TX and RX
fifo depth. However, the spec do mention that in case of overrun, the extra
bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
thought of the following possibilities as potential bugs:
a) the trace shows that the driver is not trying to ask for more bytes than the
fifo can hold, so the controller may be trying to push one more byte than was
requested.
b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.

(b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
not seem to be the case. Changing txw init value has no effect. So I kind of
ruled (a) out.

> 2) There is a HW bug, due to which the RXO interrupt is generated even
>    though there is no actual overrun.
> Let's try to prove or disprove them.
> 
> Let's assume that there is indeed the depths mismatch here:
> (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> reason (due to for instance the TXFTLR/RXFTLR semantic change or
> the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> in the driver. If so we can't rely on the depth detection loop and
> need to try to prove the depths mismatch somehow else. It would be
> also better to exclude the driver code from the problem equation...
> 
> Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> we can just try to manually execute a small SPI transfer of the Tx FIFO
> depth length. If the mismatch takes place or an HW bug with false RXO,
> then we'll get the Rx FIFO overflow flag set.
> 
> I've created a small shell-script (you can find it in the attachment)
> which runs a single SPI transfer of the passed length by manually
> setting a DW APB SSI controller up with help of the devmem utility.
> In our case the length is supposed to be equal to the FIFO depth.
> Here is what happens if I run it on my hardware (depth equals to 64
> and the controller registers physical address is 0x1f04e000):
> 
> root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> 
> See, after sending and receiving all the data the status register
> detects the normal TXE and RXF interrupts. But if our assumptions are
> correct in your case it shall be something like 0x00000019 also
> presenting the RXO interrupt.
> 
> * Note AFAIU you might need to fix the script a bit to set the DFS
> * field at the correct place of CTRLR0...

After adjusting for the CTRLR0 32 bits format, I get this:

For DEPTH = 32:

1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019

Et voila: RX overrun which matches what I was seeing with the driver trace.

Now for DEPTH = 31:

1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011

Normal transfer...

> If after running the attached script you get the RXO status set, then
> indeed there is either the depths mismatch or there is a HW bug. If
> the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> of the algorithm implemented in the driver. Then we have no choice but
> to manually set the FIFO depth for the K210 SPI controller.

I do not have the older v3 specs on hand now, but I can get them. I will and
compare but from reading the v4 specs yesterday, I have not seen anything that
does not match the driver behavior.

> 
> > 
> > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > than 32 B):
> > 
> > IRQ(1):
> > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > 32
> > 
> > IRQ(2):
> > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > 15
> > 
> > IRQ(3):
> > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > 
> > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > 
> > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > the remaining 17B to be received are already available, but that is likely due
> > to the delay from the pr_info() message print.
> > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > that the RX fifo is full with 32B.
> > 
> > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > error is triggered at step (3). There are no more than 32B that can possibly be
> > received. Putting back the "drive MOSI lne high" patch does not change
> > anything. Same behavior.
> 
> The log you've sent indeed looks weird. I'd one more time performed
> the next steps:
> 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
>    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
>    that nothing has changed since the older controller revisions and
>    what the driver implements is correct for your controller.
> 2) Try to find an internal doc with the DW APB SSI IP-core parameters
>    initialized during the controller synthesize. Try to find the
>    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> 3) Try to find an errata doc for your controller revision and make
>    sure it doesn't have anything about the problem you are getting
>    here.

The K210 documentation is extremely poor. All that is available is here:

https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf

And as you can see, that is all very high level. The best source of information
is the SDK code here:

https://github.com/kendryte/kendryte-standalone-sdk

In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
doing a loop up to RXFLR to receive bytes.

> 4) Run the attached script to make sure that the problem isn't
>    connected with a bug in the driver, but either with the depths
>    mismatch or with an HW bug.

Since applying the fifo depth detection loop to RXFLTR leads to the same result
(max register value = 31, meaning a fifo depth of 32), it really looks like an
off-by-one HW bug on the trigger for the RX overrun status.

> 
> > 
> > I am out of ideas at this point and can only think that I am facing a HW bug
> > that needs a quirk somewhere.
> > 
> > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > fifo_len would work too.
> 
> So if none of the steps above gives us an answer, then we need to dig
> dipper into the driver code and we missing something. If 2) - 4) proves the
> depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> a custom fifo_len for the K210 SPI controller.
> 
> Anyway I don't think a quirk flag would be a good solution here because
> the problem seems very specific to your controller...

Indeed. So what about this:

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..17c06039a74d 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
*pdev,
        return 0;
 }
 
+static int dw_spi_canaan_k210_init(struct platform_device *pdev,
+                                  struct dw_spi_mmio *dwsmmio)
+{
+       /*
+        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
+        * documented to have a 32 words deep TX and RX FIFO, which
+        * spi_hw_init() detects. However, when the RX FIFO is filled up to
+        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
+        * problem by force setting fifo_len to 31.
+        */
+       dwsmmio->dws.fifo_len = 31;
+
+       return 0;
+}
+
 static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
        int (*init_func)(struct platform_device *pdev,
@@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
        { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
        { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
        { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
+       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
        { /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);

No added capability flag and problem solved: no RX overrun errors and the SD
card is running at 1.2 MB/s.

-- 
Damien Le Moal
Western Digital

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-19  5:12                       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19  5:12 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > [...]
> > > > Found the bug :)
> > > > The fix is:
> > > > 
> > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > --- a/drivers/spi/spi-dw-core.c
> > > > +++ b/drivers/spi/spi-dw-core.c
> > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > *dws)
> > > >                 }
> > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > >  
> > > > 
> > > > 
> > > > 
> > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > >         }
> > > > 
> > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > overflow error. The loop above breaks when the written fifo value does not
> > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > 
> > > > I realized that by tracing the transfers RX first, then TX in
> > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > FIFO errors would trigger 100% of the time for:
> > > > 1) transfers larger than fifo size (32 in my case)
> > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > 
> > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > 
> > > Hm, what you've found is the clue to getting where the problem lies,
> > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > our controllers have been synthesized with.
> > > 
> > > But I've just realized that DW APB SSI controller can be synthesized
> > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > scenario did you imagine to provide such configuration?..). Anyway is
> > > it possible that you've got a controller which (most likely by
> > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > then that will explain the problem you are having, but everyone else
> > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > byte, you'll end up with occasional overflows.
> > > 
> > > Note if you don't have a manual with the parameters selected for your
> > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > lengths out. If they don't match, then, bingo, that's the root cause
> > > of the problem.
> > 
> 
> > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > 
> > "If you attempt to set this value greater than the depth of the FIFO,
> > this field is not written and retains its current value."
> > 
> > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > but that information is written), the loop should stop for fifo=33 with the
> > registers indicating 32. My fix should be correct.
> 
> v3.22a spec says "greater than or equal to the depth of the FIFO" for
> TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> case both of the formulations make sense. Seeing the semantic of the
> registers is different and recollecting how vague vendors can describe
> the essence of regs, in both cases FIFO depth would be detected as
> (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> but isn't for RXFTLR. In the later case we need to keep in mind that
> the controller internally increments (RXFTLR.RFT + 1) then compares it
> with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> incremented value when says: "If you attempt to set this value greater
> than the depth of the FIFO, this field is not written and retains its
> current value." but not the actual value written into the register.
> 
> Regarding DW APB SSI v4 spec. I don't really know why the description
> has changed for TXFTLR. I also don't have the v4 spec to better
> understand what they really meant there. But if the TXFTLR/RXFTLR
> registers semantic has changed, then I'd start to dig in the aspects
> of that change and whether it affects the FIFO-depth calculation
> algorithm...

I spent a lot of time reading the spec yesterday and did not see any text that
conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
still as you describe above for v3, the internal +1 increment for RXFTLR is
still there.

> Anyway regarding your fix. Please see the next two commits, which have
> already attempted to introduce a change proposed by you, but then
> reverted it back:
> d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> 
> I don't think Andy was wrong reverting the fix back, especially seeing
> the current FIFO-depth detection algorithm implementation is correct
> for both types of my controllers (with 8 and 64 words depths). I know
> with what parameters the controllers have been synthesized and the
> detected depths match them.

OK. Got it.

> 
> > 
> > However (I think this may be the catch), the spec also says:
> > 
> > "This register is sized to the number of address bits needed to access the
> > FIFO."
> > 
> > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > from ever indicating 32.
> 
> In accordance with the registers semantic we shall never write a
> FIFO-depth value into them and actually we aren't able to do that.
> First of all indeed there is no point in setting the FIFO-depth value
> into the TXFTLR because that will cause the TXE-IRQ being constantly
> generated (because the level of the Tx FIFO will be always less than
> or equal to the FIFO-depth). There is no point in setting the
> FIFO-depth into the RXFTLR because that will effectively disable the
> RXF-IRQ (the level of the Rx FIFO will be never greater than
> FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> value wider than the register is.

Yep, understood.

> 
> > I think that this spec clause takes precedence over
> > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > is the case on most synthesis of the device), the detection loop actually
> > works. But it would be buggy (off by one) for any other value of the fifo max
> > depth that is not a power of 2.
> > 
> > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > really look like 31 is the value to use.
> 
> Of course we shouldn't reject a possibility of having a HW bug here,
> but that is always a last resort and needs to be firmly proved.
> In your case we may assume one of two causes of the problem:
> 1) There is the depths mismatch.
>    But how come you still get the RXFLR to be filled with data of
>    greater length than we think the Rx FIFO depth is?.. Anyway the
>    weird behaviour still can be explained by the non-standard
>    configuration especially if the depth isn't power of 2, that
>    Synopsys might haven't even tested it, etc.

I have never seen RXFLR being larger than 32, which is the assumed TX and RX
fifo depth. However, the spec do mention that in case of overrun, the extra
bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
thought of the following possibilities as potential bugs:
a) the trace shows that the driver is not trying to ask for more bytes than the
fifo can hold, so the controller may be trying to push one more byte than was
requested.
b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.

(b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
not seem to be the case. Changing txw init value has no effect. So I kind of
ruled (a) out.

> 2) There is a HW bug, due to which the RXO interrupt is generated even
>    though there is no actual overrun.
> Let's try to prove or disprove them.
> 
> Let's assume that there is indeed the depths mismatch here:
> (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> reason (due to for instance the TXFTLR/RXFTLR semantic change or
> the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> in the driver. If so we can't rely on the depth detection loop and
> need to try to prove the depths mismatch somehow else. It would be
> also better to exclude the driver code from the problem equation...
> 
> Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> we can just try to manually execute a small SPI transfer of the Tx FIFO
> depth length. If the mismatch takes place or an HW bug with false RXO,
> then we'll get the Rx FIFO overflow flag set.
> 
> I've created a small shell-script (you can find it in the attachment)
> which runs a single SPI transfer of the passed length by manually
> setting a DW APB SSI controller up with help of the devmem utility.
> In our case the length is supposed to be equal to the FIFO depth.
> Here is what happens if I run it on my hardware (depth equals to 64
> and the controller registers physical address is 0x1f04e000):
> 
> root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> 
> See, after sending and receiving all the data the status register
> detects the normal TXE and RXF interrupts. But if our assumptions are
> correct in your case it shall be something like 0x00000019 also
> presenting the RXO interrupt.
> 
> * Note AFAIU you might need to fix the script a bit to set the DFS
> * field at the correct place of CTRLR0...

After adjusting for the CTRLR0 32 bits format, I get this:

For DEPTH = 32:

1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019

Et voila: RX overrun which matches what I was seeing with the driver trace.

Now for DEPTH = 31:

1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011

Normal transfer...

> If after running the attached script you get the RXO status set, then
> indeed there is either the depths mismatch or there is a HW bug. If
> the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> of the algorithm implemented in the driver. Then we have no choice but
> to manually set the FIFO depth for the K210 SPI controller.

I do not have the older v3 specs on hand now, but I can get them. I will and
compare but from reading the v4 specs yesterday, I have not seen anything that
does not match the driver behavior.

> 
> > 
> > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > than 32 B):
> > 
> > IRQ(1):
> > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > 32
> > 
> > IRQ(2):
> > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > 15
> > 
> > IRQ(3):
> > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > 
> > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > 
> > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > the remaining 17B to be received are already available, but that is likely due
> > to the delay from the pr_info() message print.
> > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > that the RX fifo is full with 32B.
> > 
> > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > error is triggered at step (3). There are no more than 32B that can possibly be
> > received. Putting back the "drive MOSI lne high" patch does not change
> > anything. Same behavior.
> 
> The log you've sent indeed looks weird. I'd one more time performed
> the next steps:
> 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
>    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
>    that nothing has changed since the older controller revisions and
>    what the driver implements is correct for your controller.
> 2) Try to find an internal doc with the DW APB SSI IP-core parameters
>    initialized during the controller synthesize. Try to find the
>    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> 3) Try to find an errata doc for your controller revision and make
>    sure it doesn't have anything about the problem you are getting
>    here.

The K210 documentation is extremely poor. All that is available is here:

https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf

And as you can see, that is all very high level. The best source of information
is the SDK code here:

https://github.com/kendryte/kendryte-standalone-sdk

In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
doing a loop up to RXFLR to receive bytes.

> 4) Run the attached script to make sure that the problem isn't
>    connected with a bug in the driver, but either with the depths
>    mismatch or with an HW bug.

Since applying the fifo depth detection loop to RXFLTR leads to the same result
(max register value = 31, meaning a fifo depth of 32), it really looks like an
off-by-one HW bug on the trigger for the RX overrun status.

> 
> > 
> > I am out of ideas at this point and can only think that I am facing a HW bug
> > that needs a quirk somewhere.
> > 
> > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > fifo_len would work too.
> 
> So if none of the steps above gives us an answer, then we need to dig
> dipper into the driver code and we missing something. If 2) - 4) proves the
> depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> a custom fifo_len for the K210 SPI controller.
> 
> Anyway I don't think a quirk flag would be a good solution here because
> the problem seems very specific to your controller...

Indeed. So what about this:

diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index d0cc5bf4fa4e..17c06039a74d 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
*pdev,
        return 0;
 }
 
+static int dw_spi_canaan_k210_init(struct platform_device *pdev,
+                                  struct dw_spi_mmio *dwsmmio)
+{
+       /*
+        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
+        * documented to have a 32 words deep TX and RX FIFO, which
+        * spi_hw_init() detects. However, when the RX FIFO is filled up to
+        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
+        * problem by force setting fifo_len to 31.
+        */
+       dwsmmio->dws.fifo_len = 31;
+
+       return 0;
+}
+
 static int dw_spi_mmio_probe(struct platform_device *pdev)
 {
        int (*init_func)(struct platform_device *pdev,
@@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
        { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
        { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
        { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
+       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
        { /* end of table */}
 };
 MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);

No added capability flag and problem solved: no RX overrun errors and the SD
card is running at 1.2 MB/s.

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-19  5:12                       ` Damien Le Moal
@ 2020-11-19  8:51                         ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-19  8:51 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Thu, Nov 19, 2020 at 05:12:40AM +0000, Damien Le Moal wrote:
> On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> > On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > > [...]
> > > > > Found the bug :)
> > > > > The fix is:
> > > > > 
> > > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > > --- a/drivers/spi/spi-dw-core.c
> > > > > +++ b/drivers/spi/spi-dw-core.c
> > > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > > *dws)
> > > > >                 }
> > > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > > >  
> > > > > 
> > > > > 
> > > > > 
> > > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > > >         }
> > > > > 
> > > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > > overflow error. The loop above breaks when the written fifo value does not
> > > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > > 
> > > > > I realized that by tracing the transfers RX first, then TX in
> > > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > > FIFO errors would trigger 100% of the time for:
> > > > > 1) transfers larger than fifo size (32 in my case)
> > > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > > 
> > > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > > 
> > > > Hm, what you've found is the clue to getting where the problem lies,
> > > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > > our controllers have been synthesized with.
> > > > 
> > > > But I've just realized that DW APB SSI controller can be synthesized
> > > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > > scenario did you imagine to provide such configuration?..). Anyway is
> > > > it possible that you've got a controller which (most likely by
> > > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > > then that will explain the problem you are having, but everyone else
> > > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > > byte, you'll end up with occasional overflows.
> > > > 
> > > > Note if you don't have a manual with the parameters selected for your
> > > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > > lengths out. If they don't match, then, bingo, that's the root cause
> > > > of the problem.
> > > 
> > 
> > > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > > 
> > > "If you attempt to set this value greater than the depth of the FIFO,
> > > this field is not written and retains its current value."
> > > 
> > > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > > but that information is written), the loop should stop for fifo=33 with the
> > > registers indicating 32. My fix should be correct.
> > 
> > v3.22a spec says "greater than or equal to the depth of the FIFO" for
> > TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> > case both of the formulations make sense. Seeing the semantic of the
> > registers is different and recollecting how vague vendors can describe
> > the essence of regs, in both cases FIFO depth would be detected as
> > (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> > but isn't for RXFTLR. In the later case we need to keep in mind that
> > the controller internally increments (RXFTLR.RFT + 1) then compares it
> > with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> > incremented value when says: "If you attempt to set this value greater
> > than the depth of the FIFO, this field is not written and retains its
> > current value." but not the actual value written into the register.
> > 
> > Regarding DW APB SSI v4 spec. I don't really know why the description
> > has changed for TXFTLR. I also don't have the v4 spec to better
> > understand what they really meant there. But if the TXFTLR/RXFTLR
> > registers semantic has changed, then I'd start to dig in the aspects
> > of that change and whether it affects the FIFO-depth calculation
> > algorithm...
> 
> I spent a lot of time reading the spec yesterday and did not see any text that
> conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
> still as you describe above for v3, the internal +1 increment for RXFTLR is
> still there.
> 
> > Anyway regarding your fix. Please see the next two commits, which have
> > already attempted to introduce a change proposed by you, but then
> > reverted it back:
> > d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> > 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> > 
> > I don't think Andy was wrong reverting the fix back, especially seeing
> > the current FIFO-depth detection algorithm implementation is correct
> > for both types of my controllers (with 8 and 64 words depths). I know
> > with what parameters the controllers have been synthesized and the
> > detected depths match them.
> 
> OK. Got it.
> 
> > 
> > > 
> > > However (I think this may be the catch), the spec also says:
> > > 
> > > "This register is sized to the number of address bits needed to access the
> > > FIFO."
> > > 
> > > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > > from ever indicating 32.
> > 
> > In accordance with the registers semantic we shall never write a
> > FIFO-depth value into them and actually we aren't able to do that.
> > First of all indeed there is no point in setting the FIFO-depth value
> > into the TXFTLR because that will cause the TXE-IRQ being constantly
> > generated (because the level of the Tx FIFO will be always less than
> > or equal to the FIFO-depth). There is no point in setting the
> > FIFO-depth into the RXFTLR because that will effectively disable the
> > RXF-IRQ (the level of the Rx FIFO will be never greater than
> > FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> > defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> > TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> > value wider than the register is.
> 
> Yep, understood.
> 
> > 
> > > I think that this spec clause takes precedence over
> > > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > > is the case on most synthesis of the device), the detection loop actually
> > > works. But it would be buggy (off by one) for any other value of the fifo max
> > > depth that is not a power of 2.
> > > 
> > > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > > really look like 31 is the value to use.
> > 
> > Of course we shouldn't reject a possibility of having a HW bug here,
> > but that is always a last resort and needs to be firmly proved.
> > In your case we may assume one of two causes of the problem:
> > 1) There is the depths mismatch.
> >    But how come you still get the RXFLR to be filled with data of
> >    greater length than we think the Rx FIFO depth is?.. Anyway the
> >    weird behaviour still can be explained by the non-standard
> >    configuration especially if the depth isn't power of 2, that
> >    Synopsys might haven't even tested it, etc.
> 

> I have never seen RXFLR being larger than 32, which is the assumed TX and RX
> fifo depth. However, the spec do mention that in case of overrun, the extra
> bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
> is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
> thought of the following possibilities as potential bugs:
> a) the trace shows that the driver is not trying to ask for more bytes than the
> fifo can hold, so the controller may be trying to push one more byte than was
> requested.
> b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
> c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
> when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.
> 
> (b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
> high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
> not seem to be the case. Changing txw init value has no effect. So I kind of
> ruled (a) out.

I am more inclined in thinking of what we having is either b) or c)
here. Who knows how synopsys implemented Tx/Rx FIFOs infrastructure
in hardware? It might be that depths mismatch just makes the both
FIFOs having the same size like max(SSI_TX_FIFO_DEPTH,
SSI_RX_FIFO_DEPTH) but will cause the Rx FIFO overrun interrupt in
case of the overflow. We can only guess in this matter. On the other
hand if there is no mismatch it might be just a bug in the IP-core. In
that case the problem must be fixed by the vendor in further IP-core
releases. But the current revision needs to be worked around in
software anyway.

> 
> > 2) There is a HW bug, due to which the RXO interrupt is generated even
> >    though there is no actual overrun.
> > Let's try to prove or disprove them.
> > 
> > Let's assume that there is indeed the depths mismatch here:
> > (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> > reason (due to for instance the TXFTLR/RXFTLR semantic change or
> > the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> > in the driver. If so we can't rely on the depth detection loop and
> > need to try to prove the depths mismatch somehow else. It would be
> > also better to exclude the driver code from the problem equation...
> > 
> > Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> > depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> > we can just try to manually execute a small SPI transfer of the Tx FIFO
> > depth length. If the mismatch takes place or an HW bug with false RXO,
> > then we'll get the Rx FIFO overflow flag set.
> > 
> > I've created a small shell-script (you can find it in the attachment)
> > which runs a single SPI transfer of the passed length by manually
> > setting a DW APB SSI controller up with help of the devmem utility.
> > In our case the length is supposed to be equal to the FIFO depth.
> > Here is what happens if I run it on my hardware (depth equals to 64
> > and the controller registers physical address is 0x1f04e000):
> > 
> > root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> > 
> > See, after sending and receiving all the data the status register
> > detects the normal TXE and RXF interrupts. But if our assumptions are
> > correct in your case it shall be something like 0x00000019 also
> > presenting the RXO interrupt.
> > 
> > * Note AFAIU you might need to fix the script a bit to set the DFS
> > * field at the correct place of CTRLR0...
> 

> After adjusting for the CTRLR0 32 bits format, I get this:
> 
> For DEPTH = 32:
> 
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019
> 
> Et voila: RX overrun which matches what I was seeing with the driver trace.
> 
> Now for DEPTH = 31:
> 
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011
> 
> Normal transfer...

Yeap, that proves the assumption of having either the depths mismatch
or a HW bug.

> 
> > If after running the attached script you get the RXO status set, then
> > indeed there is either the depths mismatch or there is a HW bug. If
> > the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> > mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> > of the algorithm implemented in the driver. Then we have no choice but
> > to manually set the FIFO depth for the K210 SPI controller.
> 
> I do not have the older v3 specs on hand now, but I can get them. I will and
> compare but from reading the v4 specs yesterday, I have not seen anything that
> does not match the driver behavior.
> 
> > 
> > > 
> > > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > > than 32 B):
> > > 
> > > IRQ(1):
> > > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > > 32
> > > 
> > > IRQ(2):
> > > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > > 15
> > > 
> > > IRQ(3):
> > > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > > 
> > > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > > 
> > > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > > the remaining 17B to be received are already available, but that is likely due
> > > to the delay from the pr_info() message print.
> > > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > > that the RX fifo is full with 32B.
> > > 
> > > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > > error is triggered at step (3). There are no more than 32B that can possibly be
> > > received. Putting back the "drive MOSI lne high" patch does not change
> > > anything. Same behavior.
> > 
> > The log you've sent indeed looks weird. I'd one more time performed
> > the next steps:
> > 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
> >    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
> >    that nothing has changed since the older controller revisions and
> >    what the driver implements is correct for your controller.
> > 2) Try to find an internal doc with the DW APB SSI IP-core parameters
> >    initialized during the controller synthesize. Try to find the
> >    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> > 3) Try to find an errata doc for your controller revision and make
> >    sure it doesn't have anything about the problem you are getting
> >    here.
> 

> The K210 documentation is extremely poor. All that is available is here:
> 
> https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf

That's just a datasheet. It can't be used to find the reason of the
problem.

> 
> And as you can see, that is all very high level. The best source of information
> is the SDK code here:
> 
> https://github.com/kendryte/kendryte-standalone-sdk
> 
> In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
> is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
> doing a loop up to RXFLR to receive bytes.
> 
> > 4) Run the attached script to make sure that the problem isn't
> >    connected with a bug in the driver, but either with the depths
> >    mismatch or with an HW bug.
> 
> Since applying the fifo depth detection loop to RXFLTR leads to the same result
> (max register value = 31, meaning a fifo depth of 32), it really looks like an
> off-by-one HW bug on the trigger for the RX overrun status. 
> > 
> > > 
> > > I am out of ideas at this point and can only think that I am facing a HW bug
> > > that needs a quirk somewhere.
> > > 
> > > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > > fifo_len would work too.
> > 
> > So if none of the steps above gives us an answer, then we need to dig
> > dipper into the driver code and we missing something. If 2) - 4) proves the
> > depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> > a custom fifo_len for the K210 SPI controller.
> > 
> > Anyway I don't think a quirk flag would be a good solution here because
> > the problem seems very specific to your controller...
> 

> Indeed. So what about this:
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index d0cc5bf4fa4e..17c06039a74d 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
> *pdev,
>         return 0;
>  }
>  
> +static int dw_spi_canaan_k210_init(struct platform_device *pdev,
> +                                  struct dw_spi_mmio *dwsmmio)
> +{
> +       /*
> +        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
> +        * documented to have a 32 words deep TX and RX FIFO, which
> +        * spi_hw_init() detects. However, when the RX FIFO is filled up to
> +        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
> +        * problem by force setting fifo_len to 31.
> +        */
> +       dwsmmio->dws.fifo_len = 31;
> +
> +       return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>         int (*init_func)(struct platform_device *pdev,
> @@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>         { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>         { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>         { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> +       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
>         { /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> 
> No added capability flag and problem solved: no RX overrun errors and the SD
> card is running at 1.2 MB/s.

Looks good to me. Let's fix it this way and be done with it seeing the
problem is indeed in the k210 SPI controller peculiarity.)

-Sergey

> 
> -- 
> Damien Le Moal
> Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-19  8:51                         ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-19  8:51 UTC (permalink / raw)
  To: Damien Le Moal; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Thu, Nov 19, 2020 at 05:12:40AM +0000, Damien Le Moal wrote:
> On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> > On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > > [...]
> > > > > Found the bug :)
> > > > > The fix is:
> > > > > 
> > > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > > --- a/drivers/spi/spi-dw-core.c
> > > > > +++ b/drivers/spi/spi-dw-core.c
> > > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > > *dws)
> > > > >                 }
> > > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > > >  
> > > > > 
> > > > > 
> > > > > 
> > > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > > >         }
> > > > > 
> > > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > > overflow error. The loop above breaks when the written fifo value does not
> > > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > > 
> > > > > I realized that by tracing the transfers RX first, then TX in
> > > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > > FIFO errors would trigger 100% of the time for:
> > > > > 1) transfers larger than fifo size (32 in my case)
> > > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > > 
> > > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > > 
> > > > Hm, what you've found is the clue to getting where the problem lies,
> > > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > > our controllers have been synthesized with.
> > > > 
> > > > But I've just realized that DW APB SSI controller can be synthesized
> > > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > > scenario did you imagine to provide such configuration?..). Anyway is
> > > > it possible that you've got a controller which (most likely by
> > > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > > then that will explain the problem you are having, but everyone else
> > > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > > byte, you'll end up with occasional overflows.
> > > > 
> > > > Note if you don't have a manual with the parameters selected for your
> > > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > > lengths out. If they don't match, then, bingo, that's the root cause
> > > > of the problem.
> > > 
> > 
> > > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > > 
> > > "If you attempt to set this value greater than the depth of the FIFO,
> > > this field is not written and retains its current value."
> > > 
> > > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > > but that information is written), the loop should stop for fifo=33 with the
> > > registers indicating 32. My fix should be correct.
> > 
> > v3.22a spec says "greater than or equal to the depth of the FIFO" for
> > TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> > case both of the formulations make sense. Seeing the semantic of the
> > registers is different and recollecting how vague vendors can describe
> > the essence of regs, in both cases FIFO depth would be detected as
> > (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> > but isn't for RXFTLR. In the later case we need to keep in mind that
> > the controller internally increments (RXFTLR.RFT + 1) then compares it
> > with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> > incremented value when says: "If you attempt to set this value greater
> > than the depth of the FIFO, this field is not written and retains its
> > current value." but not the actual value written into the register.
> > 
> > Regarding DW APB SSI v4 spec. I don't really know why the description
> > has changed for TXFTLR. I also don't have the v4 spec to better
> > understand what they really meant there. But if the TXFTLR/RXFTLR
> > registers semantic has changed, then I'd start to dig in the aspects
> > of that change and whether it affects the FIFO-depth calculation
> > algorithm...
> 
> I spent a lot of time reading the spec yesterday and did not see any text that
> conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
> still as you describe above for v3, the internal +1 increment for RXFTLR is
> still there.
> 
> > Anyway regarding your fix. Please see the next two commits, which have
> > already attempted to introduce a change proposed by you, but then
> > reverted it back:
> > d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> > 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> > 
> > I don't think Andy was wrong reverting the fix back, especially seeing
> > the current FIFO-depth detection algorithm implementation is correct
> > for both types of my controllers (with 8 and 64 words depths). I know
> > with what parameters the controllers have been synthesized and the
> > detected depths match them.
> 
> OK. Got it.
> 
> > 
> > > 
> > > However (I think this may be the catch), the spec also says:
> > > 
> > > "This register is sized to the number of address bits needed to access the
> > > FIFO."
> > > 
> > > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > > from ever indicating 32.
> > 
> > In accordance with the registers semantic we shall never write a
> > FIFO-depth value into them and actually we aren't able to do that.
> > First of all indeed there is no point in setting the FIFO-depth value
> > into the TXFTLR because that will cause the TXE-IRQ being constantly
> > generated (because the level of the Tx FIFO will be always less than
> > or equal to the FIFO-depth). There is no point in setting the
> > FIFO-depth into the RXFTLR because that will effectively disable the
> > RXF-IRQ (the level of the Rx FIFO will be never greater than
> > FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> > defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> > TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> > value wider than the register is.
> 
> Yep, understood.
> 
> > 
> > > I think that this spec clause takes precedence over
> > > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > > is the case on most synthesis of the device), the detection loop actually
> > > works. But it would be buggy (off by one) for any other value of the fifo max
> > > depth that is not a power of 2.
> > > 
> > > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > > really look like 31 is the value to use.
> > 
> > Of course we shouldn't reject a possibility of having a HW bug here,
> > but that is always a last resort and needs to be firmly proved.
> > In your case we may assume one of two causes of the problem:
> > 1) There is the depths mismatch.
> >    But how come you still get the RXFLR to be filled with data of
> >    greater length than we think the Rx FIFO depth is?.. Anyway the
> >    weird behaviour still can be explained by the non-standard
> >    configuration especially if the depth isn't power of 2, that
> >    Synopsys might haven't even tested it, etc.
> 

> I have never seen RXFLR being larger than 32, which is the assumed TX and RX
> fifo depth. However, the spec do mention that in case of overrun, the extra
> bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
> is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
> thought of the following possibilities as potential bugs:
> a) the trace shows that the driver is not trying to ask for more bytes than the
> fifo can hold, so the controller may be trying to push one more byte than was
> requested.
> b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
> c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
> when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.
> 
> (b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
> high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
> not seem to be the case. Changing txw init value has no effect. So I kind of
> ruled (a) out.

I am more inclined in thinking of what we having is either b) or c)
here. Who knows how synopsys implemented Tx/Rx FIFOs infrastructure
in hardware? It might be that depths mismatch just makes the both
FIFOs having the same size like max(SSI_TX_FIFO_DEPTH,
SSI_RX_FIFO_DEPTH) but will cause the Rx FIFO overrun interrupt in
case of the overflow. We can only guess in this matter. On the other
hand if there is no mismatch it might be just a bug in the IP-core. In
that case the problem must be fixed by the vendor in further IP-core
releases. But the current revision needs to be worked around in
software anyway.

> 
> > 2) There is a HW bug, due to which the RXO interrupt is generated even
> >    though there is no actual overrun.
> > Let's try to prove or disprove them.
> > 
> > Let's assume that there is indeed the depths mismatch here:
> > (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> > reason (due to for instance the TXFTLR/RXFTLR semantic change or
> > the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> > in the driver. If so we can't rely on the depth detection loop and
> > need to try to prove the depths mismatch somehow else. It would be
> > also better to exclude the driver code from the problem equation...
> > 
> > Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> > depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> > we can just try to manually execute a small SPI transfer of the Tx FIFO
> > depth length. If the mismatch takes place or an HW bug with false RXO,
> > then we'll get the Rx FIFO overflow flag set.
> > 
> > I've created a small shell-script (you can find it in the attachment)
> > which runs a single SPI transfer of the passed length by manually
> > setting a DW APB SSI controller up with help of the devmem utility.
> > In our case the length is supposed to be equal to the FIFO depth.
> > Here is what happens if I run it on my hardware (depth equals to 64
> > and the controller registers physical address is 0x1f04e000):
> > 
> > root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> > 
> > See, after sending and receiving all the data the status register
> > detects the normal TXE and RXF interrupts. But if our assumptions are
> > correct in your case it shall be something like 0x00000019 also
> > presenting the RXO interrupt.
> > 
> > * Note AFAIU you might need to fix the script a bit to set the DFS
> > * field at the correct place of CTRLR0...
> 

> After adjusting for the CTRLR0 32 bits format, I get this:
> 
> For DEPTH = 32:
> 
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019
> 
> Et voila: RX overrun which matches what I was seeing with the driver trace.
> 
> Now for DEPTH = 31:
> 
> 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> 1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
> 2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011
> 
> Normal transfer...

Yeap, that proves the assumption of having either the depths mismatch
or a HW bug.

> 
> > If after running the attached script you get the RXO status set, then
> > indeed there is either the depths mismatch or there is a HW bug. If
> > the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> > mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> > of the algorithm implemented in the driver. Then we have no choice but
> > to manually set the FIFO depth for the K210 SPI controller.
> 
> I do not have the older v3 specs on hand now, but I can get them. I will and
> compare but from reading the v4 specs yesterday, I have not seen anything that
> does not match the driver behavior.
> 
> > 
> > > 
> > > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > > than 32 B):
> > > 
> > > IRQ(1):
> > > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > > 32
> > > 
> > > IRQ(2):
> > > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > > 15
> > > 
> > > IRQ(3):
> > > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > > 
> > > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > > 
> > > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > > the remaining 17B to be received are already available, but that is likely due
> > > to the delay from the pr_info() message print.
> > > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > > that the RX fifo is full with 32B.
> > > 
> > > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > > error is triggered at step (3). There are no more than 32B that can possibly be
> > > received. Putting back the "drive MOSI lne high" patch does not change
> > > anything. Same behavior.
> > 
> > The log you've sent indeed looks weird. I'd one more time performed
> > the next steps:
> > 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
> >    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
> >    that nothing has changed since the older controller revisions and
> >    what the driver implements is correct for your controller.
> > 2) Try to find an internal doc with the DW APB SSI IP-core parameters
> >    initialized during the controller synthesize. Try to find the
> >    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> > 3) Try to find an errata doc for your controller revision and make
> >    sure it doesn't have anything about the problem you are getting
> >    here.
> 

> The K210 documentation is extremely poor. All that is available is here:
> 
> https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf

That's just a datasheet. It can't be used to find the reason of the
problem.

> 
> And as you can see, that is all very high level. The best source of information
> is the SDK code here:
> 
> https://github.com/kendryte/kendryte-standalone-sdk
> 
> In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
> is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
> doing a loop up to RXFLR to receive bytes.
> 
> > 4) Run the attached script to make sure that the problem isn't
> >    connected with a bug in the driver, but either with the depths
> >    mismatch or with an HW bug.
> 
> Since applying the fifo depth detection loop to RXFLTR leads to the same result
> (max register value = 31, meaning a fifo depth of 32), it really looks like an
> off-by-one HW bug on the trigger for the RX overrun status. 
> > 
> > > 
> > > I am out of ideas at this point and can only think that I am facing a HW bug
> > > that needs a quirk somewhere.
> > > 
> > > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > > fifo_len would work too.
> > 
> > So if none of the steps above gives us an answer, then we need to dig
> > dipper into the driver code and we missing something. If 2) - 4) proves the
> > depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> > a custom fifo_len for the K210 SPI controller.
> > 
> > Anyway I don't think a quirk flag would be a good solution here because
> > the problem seems very specific to your controller...
> 

> Indeed. So what about this:
> 
> diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> index d0cc5bf4fa4e..17c06039a74d 100644
> --- a/drivers/spi/spi-dw-mmio.c
> +++ b/drivers/spi/spi-dw-mmio.c
> @@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
> *pdev,
>         return 0;
>  }
>  
> +static int dw_spi_canaan_k210_init(struct platform_device *pdev,
> +                                  struct dw_spi_mmio *dwsmmio)
> +{
> +       /*
> +        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
> +        * documented to have a 32 words deep TX and RX FIFO, which
> +        * spi_hw_init() detects. However, when the RX FIFO is filled up to
> +        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
> +        * problem by force setting fifo_len to 31.
> +        */
> +       dwsmmio->dws.fifo_len = 31;
> +
> +       return 0;
> +}
> +
>  static int dw_spi_mmio_probe(struct platform_device *pdev)
>  {
>         int (*init_func)(struct platform_device *pdev,
> @@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
>         { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
>         { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
>         { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> +       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
>         { /* end of table */}
>  };
>  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> 
> No added capability flag and problem solved: no RX overrun errors and the SD
> card is running at 1.2 MB/s.

Looks good to me. Let's fix it this way and be done with it seeing the
problem is indeed in the k210 SPI controller peculiarity.)

-Sergey

> 
> -- 
> Damien Le Moal
> Western Digital

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
  2020-11-19  8:51                         ` Serge Semin
@ 2020-11-19  8:57                           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19  8:57 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-spi, linux-riscv, broonie, palmer, seanga2

On Thu, 2020-11-19 at 11:51 +0300, Serge Semin wrote:
> On Thu, Nov 19, 2020 at 05:12:40AM +0000, Damien Le Moal wrote:
> > On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> > > On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > > > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > > > [...]
> > > > > > Found the bug :)
> > > > > > The fix is:
> > > > > > 
> > > > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > > > --- a/drivers/spi/spi-dw-core.c
> > > > > > +++ b/drivers/spi/spi-dw-core.c
> > > > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > > > *dws)
> > > > > >                 }
> > > > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > > > >  
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > > > >         }
> > > > > > 
> > > > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > > > overflow error. The loop above breaks when the written fifo value does not
> > > > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > > > 
> > > > > > I realized that by tracing the transfers RX first, then TX in
> > > > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > > > FIFO errors would trigger 100% of the time for:
> > > > > > 1) transfers larger than fifo size (32 in my case)
> > > > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > > > 
> > > > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > > > 
> > > > > Hm, what you've found is the clue to getting where the problem lies,
> > > > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > > > our controllers have been synthesized with.
> > > > > 
> > > > > But I've just realized that DW APB SSI controller can be synthesized
> > > > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > > > scenario did you imagine to provide such configuration?..). Anyway is
> > > > > it possible that you've got a controller which (most likely by
> > > > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > > > then that will explain the problem you are having, but everyone else
> > > > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > > > byte, you'll end up with occasional overflows.
> > > > > 
> > > > > Note if you don't have a manual with the parameters selected for your
> > > > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > > > lengths out. If they don't match, then, bingo, that's the root cause
> > > > > of the problem.
> > > > 
> > > 
> > > > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > > > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > > > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > > > 
> > > > "If you attempt to set this value greater than the depth of the FIFO,
> > > > this field is not written and retains its current value."
> > > > 
> > > > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > > > but that information is written), the loop should stop for fifo=33 with the
> > > > registers indicating 32. My fix should be correct.
> > > 
> > > v3.22a spec says "greater than or equal to the depth of the FIFO" for
> > > TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> > > case both of the formulations make sense. Seeing the semantic of the
> > > registers is different and recollecting how vague vendors can describe
> > > the essence of regs, in both cases FIFO depth would be detected as
> > > (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> > > but isn't for RXFTLR. In the later case we need to keep in mind that
> > > the controller internally increments (RXFTLR.RFT + 1) then compares it
> > > with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> > > incremented value when says: "If you attempt to set this value greater
> > > than the depth of the FIFO, this field is not written and retains its
> > > current value." but not the actual value written into the register.
> > > 
> > > Regarding DW APB SSI v4 spec. I don't really know why the description
> > > has changed for TXFTLR. I also don't have the v4 spec to better
> > > understand what they really meant there. But if the TXFTLR/RXFTLR
> > > registers semantic has changed, then I'd start to dig in the aspects
> > > of that change and whether it affects the FIFO-depth calculation
> > > algorithm...
> > 
> > I spent a lot of time reading the spec yesterday and did not see any text that
> > conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
> > still as you describe above for v3, the internal +1 increment for RXFTLR is
> > still there.
> > 
> > > Anyway regarding your fix. Please see the next two commits, which have
> > > already attempted to introduce a change proposed by you, but then
> > > reverted it back:
> > > d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> > > 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> > > 
> > > I don't think Andy was wrong reverting the fix back, especially seeing
> > > the current FIFO-depth detection algorithm implementation is correct
> > > for both types of my controllers (with 8 and 64 words depths). I know
> > > with what parameters the controllers have been synthesized and the
> > > detected depths match them.
> > 
> > OK. Got it.
> > 
> > > 
> > > > 
> > > > However (I think this may be the catch), the spec also says:
> > > > 
> > > > "This register is sized to the number of address bits needed to access the
> > > > FIFO."
> > > > 
> > > > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > > > from ever indicating 32.
> > > 
> > > In accordance with the registers semantic we shall never write a
> > > FIFO-depth value into them and actually we aren't able to do that.
> > > First of all indeed there is no point in setting the FIFO-depth value
> > > into the TXFTLR because that will cause the TXE-IRQ being constantly
> > > generated (because the level of the Tx FIFO will be always less than
> > > or equal to the FIFO-depth). There is no point in setting the
> > > FIFO-depth into the RXFTLR because that will effectively disable the
> > > RXF-IRQ (the level of the Rx FIFO will be never greater than
> > > FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> > > defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> > > TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> > > value wider than the register is.
> > 
> > Yep, understood.
> > 
> > > 
> > > > I think that this spec clause takes precedence over
> > > > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > > > is the case on most synthesis of the device), the detection loop actually
> > > > works. But it would be buggy (off by one) for any other value of the fifo max
> > > > depth that is not a power of 2.
> > > > 
> > > > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > > > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > > > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > > > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > > > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > > > really look like 31 is the value to use.
> > > 
> > > Of course we shouldn't reject a possibility of having a HW bug here,
> > > but that is always a last resort and needs to be firmly proved.
> > > In your case we may assume one of two causes of the problem:
> > > 1) There is the depths mismatch.
> > >    But how come you still get the RXFLR to be filled with data of
> > >    greater length than we think the Rx FIFO depth is?.. Anyway the
> > >    weird behaviour still can be explained by the non-standard
> > >    configuration especially if the depth isn't power of 2, that
> > >    Synopsys might haven't even tested it, etc.
> > 
> 
> > I have never seen RXFLR being larger than 32, which is the assumed TX and RX
> > fifo depth. However, the spec do mention that in case of overrun, the extra
> > bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
> > is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
> > thought of the following possibilities as potential bugs:
> > a) the trace shows that the driver is not trying to ask for more bytes than the
> > fifo can hold, so the controller may be trying to push one more byte than was
> > requested.
> > b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
> > c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
> > when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.
> > 
> > (b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
> > high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
> > not seem to be the case. Changing txw init value has no effect. So I kind of
> > ruled (a) out.
> 
> I am more inclined in thinking of what we having is either b) or c)
> here. Who knows how synopsys implemented Tx/Rx FIFOs infrastructure
> in hardware? It might be that depths mismatch just makes the both
> FIFOs having the same size like max(SSI_TX_FIFO_DEPTH,
> SSI_RX_FIFO_DEPTH) but will cause the Rx FIFO overrun interrupt in
> case of the overflow. We can only guess in this matter. On the other
> hand if there is no mismatch it might be just a bug in the IP-core. In
> that case the problem must be fixed by the vendor in further IP-core
> releases. But the current revision needs to be worked around in
> software anyway.
> 
> > 
> > > 2) There is a HW bug, due to which the RXO interrupt is generated even
> > >    though there is no actual overrun.
> > > Let's try to prove or disprove them.
> > > 
> > > Let's assume that there is indeed the depths mismatch here:
> > > (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> > > reason (due to for instance the TXFTLR/RXFTLR semantic change or
> > > the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> > > in the driver. If so we can't rely on the depth detection loop and
> > > need to try to prove the depths mismatch somehow else. It would be
> > > also better to exclude the driver code from the problem equation...
> > > 
> > > Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> > > depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> > > we can just try to manually execute a small SPI transfer of the Tx FIFO
> > > depth length. If the mismatch takes place or an HW bug with false RXO,
> > > then we'll get the Rx FIFO overflow flag set.
> > > 
> > > I've created a small shell-script (you can find it in the attachment)
> > > which runs a single SPI transfer of the passed length by manually
> > > setting a DW APB SSI controller up with help of the devmem utility.
> > > In our case the length is supposed to be equal to the FIFO depth.
> > > Here is what happens if I run it on my hardware (depth equals to 64
> > > and the controller registers physical address is 0x1f04e000):
> > > 
> > > root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> > > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > > 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> > > 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> > > 
> > > See, after sending and receiving all the data the status register
> > > detects the normal TXE and RXF interrupts. But if our assumptions are
> > > correct in your case it shall be something like 0x00000019 also
> > > presenting the RXO interrupt.
> > > 
> > > * Note AFAIU you might need to fix the script a bit to set the DFS
> > > * field at the correct place of CTRLR0...
> > 
> 
> > After adjusting for the CTRLR0 32 bits format, I get this:
> > 
> > For DEPTH = 32:
> > 
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019
> > 
> > Et voila: RX overrun which matches what I was seeing with the driver trace.
> > 
> > Now for DEPTH = 31:
> > 
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011
> > 
> > Normal transfer...
> 
> Yeap, that proves the assumption of having either the depths mismatch
> or a HW bug.
> 
> > 
> > > If after running the attached script you get the RXO status set, then
> > > indeed there is either the depths mismatch or there is a HW bug. If
> > > the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> > > mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> > > of the algorithm implemented in the driver. Then we have no choice but
> > > to manually set the FIFO depth for the K210 SPI controller.
> > 
> > I do not have the older v3 specs on hand now, but I can get them. I will and
> > compare but from reading the v4 specs yesterday, I have not seen anything that
> > does not match the driver behavior.
> > 
> > > 
> > > > 
> > > > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > > > than 32 B):
> > > > 
> > > > IRQ(1):
> > > > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > > > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > > > 32
> > > > 
> > > > IRQ(2):
> > > > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > > > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > > > 15
> > > > 
> > > > IRQ(3):
> > > > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > > > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > > > 
> > > > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > > > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > > > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > > > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > > > 
> > > > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > > > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > > > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > > > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > > > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > > > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > > > the remaining 17B to be received are already available, but that is likely due
> > > > to the delay from the pr_info() message print.
> > > > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > > > that the RX fifo is full with 32B.
> > > > 
> > > > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > > > error is triggered at step (3). There are no more than 32B that can possibly be
> > > > received. Putting back the "drive MOSI lne high" patch does not change
> > > > anything. Same behavior.
> > > 
> > > The log you've sent indeed looks weird. I'd one more time performed
> > > the next steps:
> > > 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
> > >    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
> > >    that nothing has changed since the older controller revisions and
> > >    what the driver implements is correct for your controller.
> > > 2) Try to find an internal doc with the DW APB SSI IP-core parameters
> > >    initialized during the controller synthesize. Try to find the
> > >    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> > > 3) Try to find an errata doc for your controller revision and make
> > >    sure it doesn't have anything about the problem you are getting
> > >    here.
> > 
> 
> > The K210 documentation is extremely poor. All that is available is here:
> > 
> > https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf
> 
> That's just a datasheet. It can't be used to find the reason of the
> problem.

I did say that the documentation was poor :)


> 
> > 
> > And as you can see, that is all very high level. The best source of information
> > is the SDK code here:
> > 
> > https://github.com/kendryte/kendryte-standalone-sdk
> > 
> > In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
> > is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
> > doing a loop up to RXFLR to receive bytes.
> > 
> > > 4) Run the attached script to make sure that the problem isn't
> > >    connected with a bug in the driver, but either with the depths
> > >    mismatch or with an HW bug.
> > 
> > Since applying the fifo depth detection loop to RXFLTR leads to the same result
> > (max register value = 31, meaning a fifo depth of 32), it really looks like an
> > off-by-one HW bug on the trigger for the RX overrun status. 
> > > 
> > > > 
> > > > I am out of ideas at this point and can only think that I am facing a HW bug
> > > > that needs a quirk somewhere.
> > > > 
> > > > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > > > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > > > fifo_len would work too.
> > > 
> > > So if none of the steps above gives us an answer, then we need to dig
> > > dipper into the driver code and we missing something. If 2) - 4) proves the
> > > depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> > > a custom fifo_len for the K210 SPI controller.
> > > 
> > > Anyway I don't think a quirk flag would be a good solution here because
> > > the problem seems very specific to your controller...
> > 
> 
> > Indeed. So what about this:
> > 
> > diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> > index d0cc5bf4fa4e..17c06039a74d 100644
> > --- a/drivers/spi/spi-dw-mmio.c
> > +++ b/drivers/spi/spi-dw-mmio.c
> > @@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
> > *pdev,
> >         return 0;
> >  }
> >  
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> > +static int dw_spi_canaan_k210_init(struct platform_device *pdev,
> > +                                  struct dw_spi_mmio *dwsmmio)
> > +{
> > +       /*
> > +        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
> > +        * documented to have a 32 words deep TX and RX FIFO, which
> > +        * spi_hw_init() detects. However, when the RX FIFO is filled up to
> > +        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
> > +        * problem by force setting fifo_len to 31.
> > +        */
> > +       dwsmmio->dws.fifo_len = 31;
> > +
> > +       return 0;
> > +}
> > +
> >  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >  {
> >         int (*init_func)(struct platform_device *pdev,
> > @@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >         { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >         { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >         { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> > +       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
> >         { /* end of table */}
> >  };
> >  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> > 
> > No added capability flag and problem solved: no RX overrun errors and the SD
> > card is running at 1.2 MB/s.
> 
> Looks good to me. Let's fix it this way and be done with it seeing the
> problem is indeed in the k210 SPI controller peculiarity.)

OK. Sending patches.

Thanks !


-- 
Damien Le Moal
Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 04/32] spi: dw: Introduce polling device tree property
@ 2020-11-19  8:57                           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19  8:57 UTC (permalink / raw)
  To: fancer.lancer; +Cc: linux-riscv, broonie, palmer, seanga2, linux-spi

On Thu, 2020-11-19 at 11:51 +0300, Serge Semin wrote:
> On Thu, Nov 19, 2020 at 05:12:40AM +0000, Damien Le Moal wrote:
> > On Wed, 2020-11-18 at 18:16 +0300, Serge Semin wrote:
> > > On Wed, Nov 18, 2020 at 04:41:27AM +0000, Damien Le Moal wrote:
> > > > On Tue, 2020-11-17 at 21:26 +0300, Serge Semin wrote:
> > > > [...]
> > > > > > Found the bug :)
> > > > > > The fix is:
> > > > > > 
> > > > > > diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
> > > > > > index e3b76e40ed73..b7538093c7ef 100644
> > > > > > --- a/drivers/spi/spi-dw-core.c
> > > > > > +++ b/drivers/spi/spi-dw-core.c
> > > > > > @@ -828,7 +828,7 @@ static void spi_hw_init(struct device *dev, struct dw_spi
> > > > > > *dws)
> > > > > >                 }
> > > > > >                 dw_writel(dws, DW_SPI_TXFTLR, 0);
> > > > > >  
> > > > > > 
> > > > > > 
> > > > > > 
> > > > > > -               dws->fifo_len = (fifo == 1) ? 0 : fifo;
> > > > > > +               dws->fifo_len = (fifo == 1) ? 0 : fifo - 1;
> > > > > >                 dev_dbg(dev, "Detected FIFO size: %u bytes\n", dws->fifo_len);
> > > > > >         }
> > > > > > 
> > > > > > Basically, fifo_len is off by one, one too large and that causes the RX FIFO
> > > > > > overflow error. The loop above breaks when the written fifo value does not
> > > > > > match the read one, which means that the last correct one is at step fifo - 1.
> > > > > > 
> > > > > > I realized that by tracing the transfers RX first, then TX in
> > > > > > dw_spi_transfer_handler().I did not see anything wrong with tx_max() and
> > > > > > rx_max(), all the numbers always added up correctly either up to transfer len
> > > > > > or to fifo_len, as they should. It looked all good. But then I realized that RX
> > > > > > FIFO errors would trigger 100% of the time for:
> > > > > > 1) transfers larger than fifo size (32 in my case)
> > > > > > 2) FIFO slots used for TX + RX adding up to 32
> > > > > > After some tweaking, found the above. Since that bug should be affecting all
> > > > > > dw-apb spi devices, not sure why it does not manifest itself more often.
> > > > > > 
> > > > > > With the above fix, the SD card is now running flawlessly at 1.2MB/s with
> > > > > > maximum SPI frequency, zero errors no matter how hard I hit it with traffic.
> > > > > 
> > > > > Hm, what you've found is the clue to getting where the problem lies,
> > > > > but I don't see fifo_len being calculated incorrectly in my HW. In my
> > > > > case it equals to 64 and 8 bytes for two different controllers. Those
> > > > > are the correct SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters values
> > > > > our controllers have been synthesized with.
> > > > > 
> > > > > But I've just realized that DW APB SSI controller can be synthesized
> > > > > with Rx and Tx FIFO having different depths. (Synopsys, really, what
> > > > > scenario did you imagine to provide such configuration?..). Anyway is
> > > > > it possible that you've got a controller which (most likely by
> > > > > mistake) has been synthesized with Rx_fifo_len != Tx_fifo_len? If so
> > > > > then that will explain the problem you are having, but everyone else
> > > > > isn't. The algorithm thinks that both FIFOs length match and equals to
> > > > > the Tx FIFO length. If Rx FIFO length is smaller even with a single
> > > > > byte, you'll end up with occasional overflows.
> > > > > 
> > > > > Note if you don't have a manual with the parameters selected for your
> > > > > IP-core, you can just fix the fifo_len detection loop by replacing the
> > > > > TXFTLR with RXFTLR. Then just print the detected Rx and Tx FIFO
> > > > > lengths out. If they don't match, then, bingo, that's the root cause
> > > > > of the problem.
> > > > 
> > > 
> > > > Just checked: TX and RX fifo depth match and the maximum size I can see in both
> > > > RXFTLR and TXFTLR is 31, when the fifo for loop stops with fifo=32. I checked
> > > > the Synopsis DW apb_ssi v4 specs and for both RXFTLR and TXFTLR, it says:
> > > > 
> > > > "If you attempt to set this value greater than the depth of the FIFO,
> > > > this field is not written and retains its current value."
> > > > 
> > > > So for a FIFO max depth of 32, as the K210 SoC documents (very poor spec sheet,
> > > > but that information is written), the loop should stop for fifo=33 with the
> > > > registers indicating 32. My fix should be correct.
> > > 
> > > v3.22a spec says "greater than or equal to the depth of the FIFO" for
> > > TXFTLR and "greater than the depth of the FIFO" - for RXFTLR. In my
> > > case both of the formulations make sense. Seeing the semantic of the
> > > registers is different and recollecting how vague vendors can describe
> > > the essence of regs, in both cases FIFO depth would be detected as
> > > (MAX_value + 1). That is obvious for TXFTLR (in v3.22a formulation),
> > > but isn't for RXFTLR. In the later case we need to keep in mind that
> > > the controller internally increments (RXFTLR.RFT + 1) then compares it
> > > with RXFLR.RXTFL. Most likely the RXFTLR description text means that
> > > incremented value when says: "If you attempt to set this value greater
> > > than the depth of the FIFO, this field is not written and retains its
> > > current value." but not the actual value written into the register.
> > > 
> > > Regarding DW APB SSI v4 spec. I don't really know why the description
> > > has changed for TXFTLR. I also don't have the v4 spec to better
> > > understand what they really meant there. But if the TXFTLR/RXFTLR
> > > registers semantic has changed, then I'd start to dig in the aspects
> > > of that change and whether it affects the FIFO-depth calculation
> > > algorithm...
> > 
> > I spent a lot of time reading the spec yesterday and did not see any text that
> > conflicts with what the driver is doing. The semantic of TXFTLR and RXFTLR is
> > still as you describe above for v3, the internal +1 increment for RXFTLR is
> > still there.
> > 
> > > Anyway regarding your fix. Please see the next two commits, which have
> > > already attempted to introduce a change proposed by you, but then
> > > reverted it back:
> > > d297933cc7fc ("spi: dw: Fix detecting FIFO depth")
> > > 9d239d353c31 ("spi: dw: revisit FIFO size detection again")
> > > 
> > > I don't think Andy was wrong reverting the fix back, especially seeing
> > > the current FIFO-depth detection algorithm implementation is correct
> > > for both types of my controllers (with 8 and 64 words depths). I know
> > > with what parameters the controllers have been synthesized and the
> > > detected depths match them.
> > 
> > OK. Got it.
> > 
> > > 
> > > > 
> > > > However (I think this may be the catch), the spec also says:
> > > > 
> > > > "This register is sized to the number of address bits needed to access the
> > > > FIFO."
> > > > 
> > > > So for a fifo depth of 32, the register would be 5 bits only, preventing it
> > > > from ever indicating 32.
> > > 
> > > In accordance with the registers semantic we shall never write a
> > > FIFO-depth value into them and actually we aren't able to do that.
> > > First of all indeed there is no point in setting the FIFO-depth value
> > > into the TXFTLR because that will cause the TXE-IRQ being constantly
> > > generated (because the level of the Tx FIFO will be always less than
> > > or equal to the FIFO-depth). There is no point in setting the
> > > FIFO-depth into the RXFTLR because that will effectively disable the
> > > RXF-IRQ (the level of the Rx FIFO will be never greater than
> > > FIFO-depth + 1). Secondly the TXFTLR/RXFTLR registers width have been
> > > defined as: TX_ABW-1:0 and RX_ABW-1:0 unlike the FIFO level registers
> > > TXFLR/RXFLR: TX_ABW:0 and RX_ABW:0 . So we just literally can't set a
> > > value wider than the register is.
> > 
> > Yep, understood.
> > 
> > > 
> > > > I think that this spec clause takes precedence over
> > > > the previous one, and for a fifo max depth that is a power of 2 (which I assume
> > > > is the case on most synthesis of the device), the detection loop actually
> > > > works. But it would be buggy (off by one) for any other value of the fifo max
> > > > depth that is not a power of 2.
> > > > 
> > > > If the above is correct, and my SoC spec sheet is also correct, then all I can
> > > > think of now is a HW bug. Because no matter what I do or how I look at it, the
> > > > RX FIFO overflow always happen when the sum of TX bytes sent and RX bytes left
> > > > to receive equals exactly 32. Sending 32B on TX fifo does nto seem to cause any
> > > > problem, so the TX fifo seems to indeed be 32B deep. But on the RX side, it
> > > > really look like 31 is the value to use.
> > > 
> > > Of course we shouldn't reject a possibility of having a HW bug here,
> > > but that is always a last resort and needs to be firmly proved.
> > > In your case we may assume one of two causes of the problem:
> > > 1) There is the depths mismatch.
> > >    But how come you still get the RXFLR to be filled with data of
> > >    greater length than we think the Rx FIFO depth is?.. Anyway the
> > >    weird behaviour still can be explained by the non-standard
> > >    configuration especially if the depth isn't power of 2, that
> > >    Synopsys might haven't even tested it, etc.
> > 
> 
> > I have never seen RXFLR being larger than 32, which is the assumed TX and RX
> > fifo depth. However, the spec do mention that in case of overrun, the extra
> > bytes are dropped, so I do not think seeing RXFLR being larger than fifo depth
> > is possible. When the RX fifo overrun error occur, RXFLR always indicate 32. I
> > thought of the following possibilities as potential bugs:
> > a) the trace shows that the driver is not trying to ask for more bytes than the
> > fifo can hold, so the controller may be trying to push one more byte than was
> > requested.
> > b) The RX fifo depth is in fact 31 instead of the documented & detected 32.
> > c) The RX fifo is indeed 32, but the overrun trigger is off-by-one and triggers
> > when RXFLR == 32 instead of when RXFLR == 32 && one more byte was requested.
> > 
> > (b) and (c) being kind-of equivalent. For (a), I thought the MOSI line drive
> > high or low (txw = 0 or txw = 0xffff in dw_writer()) may matter, but that does
> > not seem to be the case. Changing txw init value has no effect. So I kind of
> > ruled (a) out.
> 
> I am more inclined in thinking of what we having is either b) or c)
> here. Who knows how synopsys implemented Tx/Rx FIFOs infrastructure
> in hardware? It might be that depths mismatch just makes the both
> FIFOs having the same size like max(SSI_TX_FIFO_DEPTH,
> SSI_RX_FIFO_DEPTH) but will cause the Rx FIFO overrun interrupt in
> case of the overflow. We can only guess in this matter. On the other
> hand if there is no mismatch it might be just a bug in the IP-core. In
> that case the problem must be fixed by the vendor in further IP-core
> releases. But the current revision needs to be worked around in
> software anyway.
> 
> > 
> > > 2) There is a HW bug, due to which the RXO interrupt is generated even
> > >    though there is no actual overrun.
> > > Let's try to prove or disprove them.
> > > 
> > > Let's assume that there is indeed the depths mismatch here:
> > > (SSI_TX_FIFO_DEPTH = 32) != (SSI_RX_FIFO_DEPTH = 31), and for some
> > > reason (due to for instance the TXFTLR/RXFTLR semantic change or
> > > the HW bug or etc) we can't detect the Rx FIFO depth by the algorithm
> > > in the driver. If so we can't rely on the depth detection loop and
> > > need to try to prove the depths mismatch somehow else. It would be
> > > also better to exclude the driver code from the problem equation...
> > > 
> > > Since we are sure the Rx FIFO depth must be smaller than the Tx FIFO
> > > depth (otherwise you wouldn't be getting the Rx FIFO overflows), then
> > > we can just try to manually execute a small SPI transfer of the Tx FIFO
> > > depth length. If the mismatch takes place or an HW bug with false RXO,
> > > then we'll get the Rx FIFO overflow flag set.
> > > 
> > > I've created a small shell-script (you can find it in the attachment)
> > > which runs a single SPI transfer of the passed length by manually
> > > setting a DW APB SSI controller up with help of the devmem utility.
> > > In our case the length is supposed to be equal to the FIFO depth.
> > > Here is what happens if I run it on my hardware (depth equals to 64
> > > and the controller registers physical address is 0x1f04e000):
> > > 
> > > root@msbt2:~# ./check_mismatch.sh 64 0x1f04e000
> > > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > > 1. Tx FIFO lvl 64, Rx FIFO lvl 0, RISR 0x00000000
> > > 2. Tx FIFO lvl 0, Rx FIFO lvl 64, RISR 0x00000011
> > > 
> > > See, after sending and receiving all the data the status register
> > > detects the normal TXE and RXF interrupts. But if our assumptions are
> > > correct in your case it shall be something like 0x00000019 also
> > > presenting the RXO interrupt.
> > > 
> > > * Note AFAIU you might need to fix the script a bit to set the DFS
> > > * field at the correct place of CTRLR0...
> > 
> 
> > After adjusting for the CTRLR0 32 bits format, I get this:
> > 
> > For DEPTH = 32:
> > 
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 32, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 32, RISR 0x00000019
> > 
> > Et voila: RX overrun which matches what I was seeing with the driver trace.
> > 
> > Now for DEPTH = 31:
> > 
> > 1. Tx FIFO lvl 0, Rx FIFO lvl 0, RISR 0x00000000
> > 1. Tx FIFO lvl 31, Rx FIFO lvl 0, RISR 0x00000000
> > 2. Tx FIFO lvl 0, Rx FIFO lvl 31, RISR 0x00000011
> > 
> > Normal transfer...
> 
> Yeap, that proves the assumption of having either the depths mismatch
> or a HW bug.
> 
> > 
> > > If after running the attached script you get the RXO status set, then
> > > indeed there is either the depths mismatch or there is a HW bug. If
> > > the TXFTLR/RXFTLR semantic hasn't changed in spec v4, then the
> > > mismatch or a HW bug don't let us to detect the Rx FIFO depth by means
> > > of the algorithm implemented in the driver. Then we have no choice but
> > > to manually set the FIFO depth for the K210 SPI controller.
> > 
> > I do not have the older v3 specs on hand now, but I can get them. I will and
> > compare but from reading the v4 specs yesterday, I have not seen anything that
> > does not match the driver behavior.
> > 
> > > 
> > > > 
> > > > Here is a trace for a 64B transfer (errors happen only for transfers larger
> > > > than 32 B):
> > > > 
> > > > IRQ(1):
> > > > [    1.062978] spi_master spi1: ## RX: used 0/0, len 64 -> rx 0
> > > > [    1.068533] spi_master spi1: ## TX: used 0/0, room 32, len 64, gap 32 -> tx
> > > > 32
> > > > 
> > > > IRQ(2):
> > > > [    1.076052] spi_master spi1: ## RX: used 16/15, len 64 -> rx 15
> > > > [    1.081647] spi_master spi1: ## TX: used 0/17, room 32, len 32, gap 15 -> tx
> > > > 15
> > > > 
> > > > IRQ(3):
> > > > [    1.088932] spi_master spi1: RX FIFO overflow detected
> > > > [    1.094053] spi_master spi1: ## TX/RX used 0/32, len 17/49
> > > > 
> > > > Each pair of line correspond to one execution of dw_spi_transfer_handler() on
> > > > an IRQ occurrence. The first line is what rx_max() sees when dw_reader() is
> > > > called, the second line is what tx_max() sees when dw_writer() is executed. The
> > > > "used x/y" part of the messages shows TXFLR/RXFLR values.
> > > > 
> > > > (1) After setup of the transfer and enabling the controller, IRQ(1) occurs,
> > > > nothing to receive yet, TX fifo all empty, 32 B are written. All expected. OK.
> > > > (2) More than fifo_len / 2 - 1 (as RXFTLR is set in dw_spi_irq_setup) become
> > > > available and IRQ(2) trigger, 15 Bytes are received. When dw_writer() runs, it
> > > > sees the rxtxgap at 15B (17B still to receive from the previous 32B written),
> > > > so writes only 15B. All good, again expected. Note that when dw_writer() runs,
> > > > the remaining 17B to be received are already available, but that is likely due
> > > > to the delay from the pr_info() message print.
> > > > (3) Next IRQ(3) is the error, showing that all TX bytes have been processed and
> > > > that the RX fifo is full with 32B.
> > > > 
> > > > If the RX fifo max depth is indeed 32, I do not understand why the overflow
> > > > error is triggered at step (3). There are no more than 32B that can possibly be
> > > > received. Putting back the "drive MOSI lne high" patch does not change
> > > > anything. Same behavior.
> > > 
> > > The log you've sent indeed looks weird. I'd one more time performed
> > > the next steps:
> > > 1) Study the spec paying special attention to the TXFTLR/RXFTLR and
> > >    TXFLR/RXFLR registers descriptions. Mostly we need to make sure
> > >    that nothing has changed since the older controller revisions and
> > >    what the driver implements is correct for your controller.
> > > 2) Try to find an internal doc with the DW APB SSI IP-core parameters
> > >    initialized during the controller synthesize. Try to find the
> > >    SSI_TX_FIFO_DEPTH/SSI_RX_FIFO_DEPTH parameters value.
> > > 3) Try to find an errata doc for your controller revision and make
> > >    sure it doesn't have anything about the problem you are getting
> > >    here.
> > 
> 
> > The K210 documentation is extremely poor. All that is available is here:
> > 
> > https://s3.cn-north-1.amazonaws.com.cn/dl.kendryte.com/documents/kendryte_datasheet_20181011163248_en.pdf
> 
> That's just a datasheet. It can't be used to find the reason of the
> problem.

I did say that the documentation was poor :)


> 
> > 
> > And as you can see, that is all very high level. The best source of information
> > is the SDK code here:
> > 
> > https://github.com/kendryte/kendryte-standalone-sdk
> > 
> > In that code, TX fifo length is clearly hard-coded at 32, but the RX fifo depth
> > is not clear as the code always sets RXFTLR to 0 and the code is rather trivial
> > doing a loop up to RXFLR to receive bytes.
> > 
> > > 4) Run the attached script to make sure that the problem isn't
> > >    connected with a bug in the driver, but either with the depths
> > >    mismatch or with an HW bug.
> > 
> > Since applying the fifo depth detection loop to RXFLTR leads to the same result
> > (max register value = 31, meaning a fifo depth of 32), it really looks like an
> > off-by-one HW bug on the trigger for the RX overrun status. 
> > > 
> > > > 
> > > > I am out of ideas at this point and can only think that I am facing a HW bug
> > > > that needs a quirk somewhere.
> > > > 
> > > > Thoughts ? Do you think it is OK to add a quirk flag for this SoC to have
> > > > fifo_len reduced by one ? Adding a DT property to manually force a value for
> > > > fifo_len would work too.
> > > 
> > > So if none of the steps above gives us an answer, then we need to dig
> > > dipper into the driver code and we missing something. If 2) - 4) proves the
> > > depths mismatch or a HW bug, then you can patch the spi-dw-mmio.c code to set
> > > a custom fifo_len for the K210 SPI controller.
> > > 
> > > Anyway I don't think a quirk flag would be a good solution here because
> > > the problem seems very specific to your controller...
> > 
> 
> > Indeed. So what about this:
> > 
> > diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
> > index d0cc5bf4fa4e..17c06039a74d 100644
> > --- a/drivers/spi/spi-dw-mmio.c
> > +++ b/drivers/spi/spi-dw-mmio.c
> > @@ -222,6 +222,21 @@ static int dw_spi_keembay_init(struct platform_device
> > *pdev,
> >         return 0;
> >  }
> >  
> > 
> > 
> > 
> > 
> > 
> > 
> > 
> > +static int dw_spi_canaan_k210_init(struct platform_device *pdev,
> > +                                  struct dw_spi_mmio *dwsmmio)
> > +{
> > +       /*
> > +        * The Canaan Kendryte K210 SoC DW apb_ssi v4 spi controller is
> > +        * documented to have a 32 words deep TX and RX FIFO, which
> > +        * spi_hw_init() detects. However, when the RX FIFO is filled up to
> > +        * 32 entries (RXFLR = 32), an RX FIFO overrun error occurs. Avoid this
> > +        * problem by force setting fifo_len to 31.
> > +        */
> > +       dwsmmio->dws.fifo_len = 31;
> > +
> > +       return 0;
> > +}
> > +
> >  static int dw_spi_mmio_probe(struct platform_device *pdev)
> >  {
> >         int (*init_func)(struct platform_device *pdev,
> > @@ -335,6 +350,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
> >         { .compatible = "snps,dwc-ssi-1.01a", .data = dw_spi_dwc_ssi_init},
> >         { .compatible = "intel,keembay-ssi", .data = dw_spi_keembay_init},
> >         { .compatible = "microchip,sparx5-spi", dw_spi_mscc_sparx5_init},
> > +       { .compatible = "canaan,k210-spi", dw_spi_canaan_k210_init},
> >         { /* end of table */}
> >  };
> >  MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
> > 
> > No added capability flag and problem solved: no RX overrun errors and the SD
> > card is running at 1.2 MB/s.
> 
> Looks good to me. Let's fix it this way and be done with it seeing the
> problem is indeed in the k210 SPI controller peculiarity.)

OK. Sending patches.

Thanks !


-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-09 15:45       ` Sean Anderson
@ 2020-11-19 10:57         ` Geert Uytterhoeven
  -1 siblings, 0 replies; 297+ messages in thread
From: Geert Uytterhoeven @ 2020-11-19 10:57 UTC (permalink / raw)
  To: Damien Le Moal, Sean Anderson
  Cc: Rob Herring, Palmer Dabbelt, linux-riscv, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, open list:GPIO SUBSYSTEM, Philipp Zabel

Hi Damien, Sean,

On Mon, Nov 9, 2020 at 4:46 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 10:36 AM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> >> Document the device tree bindings for the Kendryte K210 SoC Fully
> >> Programmable IO Array (FPIOA) pinctrl driver in
> >> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

> >> +  kendryte,power-offset:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/uint32
> >> +    description: |
> >> +      Offset of the power domain control register of the system controller.
> >
> > Sounds like you should be using power-domains binding.
>
> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

Which brings to my attention the power-source property is not
documented below...

> >> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> >> +      dt-bindings/mfd/k210-sysctl.h.
> >> +
> >> +patternProperties:
> >> +  '^.*$':
> >> +    if:
> >> +      type: object
> >> +    then:

As the driver supports e.g. bias and drive-strength, these should be
documented here, too.

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	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-19 10:57         ` Geert Uytterhoeven
  0 siblings, 0 replies; 297+ messages in thread
From: Geert Uytterhoeven @ 2020-11-19 10:57 UTC (permalink / raw)
  To: Damien Le Moal, Sean Anderson
  Cc: Rob Herring,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Mark Brown, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk

Hi Damien, Sean,

On Mon, Nov 9, 2020 at 4:46 PM Sean Anderson <seanga2@gmail.com> wrote:
> On 11/9/20 10:36 AM, Rob Herring wrote:
> > On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
> >> Document the device tree bindings for the Kendryte K210 SoC Fully
> >> Programmable IO Array (FPIOA) pinctrl driver in
> >> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> >>
> >> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

> >> --- /dev/null
> >> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml

> >> +  kendryte,power-offset:
> >> +    minItems: 1
> >> +    maxItems: 1
> >> +    $ref: /schemas/types.yaml#/definitions/uint32
> >> +    description: |
> >> +      Offset of the power domain control register of the system controller.
> >
> > Sounds like you should be using power-domains binding.
>
> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.

Which brings to my attention the power-source property is not
documented below...

> >> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
> >> +      dt-bindings/mfd/k210-sysctl.h.
> >> +
> >> +patternProperties:
> >> +  '^.*$':
> >> +    if:
> >> +      type: object
> >> +    then:

As the driver supports e.g. bias and drive-strength, these should be
documented here, too.

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

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
  2020-11-19 10:57         ` Geert Uytterhoeven
@ 2020-11-19 11:22           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19 11:22 UTC (permalink / raw)
  To: Geert Uytterhoeven, Sean Anderson
  Cc: Rob Herring, Palmer Dabbelt, linux-riscv, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	Linus Walleij, open list:GPIO SUBSYSTEM, Philipp Zabel

On 2020/11/19 19:58, Geert Uytterhoeven wrote:
> Hi Damien, Sean,
> 
> On Mon, Nov 9, 2020 at 4:46 PM Sean Anderson <seanga2@gmail.com> wrote:
>> On 11/9/20 10:36 AM, Rob Herring wrote:
>>> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>>>> Document the device tree bindings for the Kendryte K210 SoC Fully
>>>> Programmable IO Array (FPIOA) pinctrl driver in
>>>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
>>>> +  kendryte,power-offset:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>> +    description: |
>>>> +      Offset of the power domain control register of the system controller.
>>>
>>> Sounds like you should be using power-domains binding.
>>
>> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> 
> Which brings to my attention the power-source property is not
> documented below...
> 
>>>> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
>>>> +      dt-bindings/mfd/k210-sysctl.h.
>>>> +
>>>> +patternProperties:
>>>> +  '^.*$':
>>>> +    if:
>>>> +      type: object
>>>> +    then:
> 
> As the driver supports e.g. bias and drive-strength, these should be
> documented here, too.

Thanks for the review. I fixed everything today and ran everything through "make
dt_binding_check". Will send a V2 series tomorrow after some more fixes and tests.

> 
> 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
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings
@ 2020-11-19 11:22           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-19 11:22 UTC (permalink / raw)
  To: Geert Uytterhoeven, Sean Anderson
  Cc: Rob Herring,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Linus Walleij, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Mark Brown, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Frank Rowand, linux-clk

On 2020/11/19 19:58, Geert Uytterhoeven wrote:
> Hi Damien, Sean,
> 
> On Mon, Nov 9, 2020 at 4:46 PM Sean Anderson <seanga2@gmail.com> wrote:
>> On 11/9/20 10:36 AM, Rob Herring wrote:
>>> On Sat, Nov 07, 2020 at 05:14:12PM +0900, Damien Le Moal wrote:
>>>> Document the device tree bindings for the Kendryte K210 SoC Fully
>>>> Programmable IO Array (FPIOA) pinctrl driver in
>>>> Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
>>>>
>>>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/pinctrl/kendryte,k210-fpioa.yaml
> 
>>>> +  kendryte,power-offset:
>>>> +    minItems: 1
>>>> +    maxItems: 1
>>>> +    $ref: /schemas/types.yaml#/definitions/uint32
>>>> +    description: |
>>>> +      Offset of the power domain control register of the system controller.
>>>
>>> Sounds like you should be using power-domains binding.
>>
>> This is for pin power domains. E.g. pins 0-5 can be set to 1V8 or 3V3 logic levels.
> 
> Which brings to my attention the power-source property is not
> documented below...
> 
>>>> +      The value should be the macro K210_SYSCTL_POWER_SEL defined in
>>>> +      dt-bindings/mfd/k210-sysctl.h.
>>>> +
>>>> +patternProperties:
>>>> +  '^.*$':
>>>> +    if:
>>>> +      type: object
>>>> +    then:
> 
> As the driver supports e.g. bias and drive-strength, these should be
> documented here, too.

Thanks for the review. I fixed everything today and ran everything through "make
dt_binding_check". Will send a V2 series tomorrow after some more fixes and tests.

> 
> 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
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-07  8:14   ` Damien Le Moal
@ 2020-11-24  8:43     ` Linus Walleij
  -1 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-24  8:43 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, Philipp Zabel, Sean Anderson

On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
> (fully programmable IO array) to allow configuring the SoC pin
> functions. The K210 has 48 programmable pins which can take any of 256
> possible functions.
>
> This patch is inspired from the k210 pinctrl driver for the u-boot
> project and contains many direct contributions from Sean Anderson.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

The kernel build robot is complaining about this patch so I'm waiting for
a new version.

Would also be nice if the maintainer could add some comments?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-24  8:43     ` Linus Walleij
  0 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-24  8:43 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Mark Brown, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:

> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
> (fully programmable IO array) to allow configuring the SoC pin
> functions. The K210 has 48 programmable pins which can take any of 256
> possible functions.
>
> This patch is inspired from the k210 pinctrl driver for the u-boot
> project and contains many direct contributions from Sean Anderson.
>
> Signed-off-by: Sean Anderson <seanga2@gmail.com>
> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>

The kernel build robot is complaining about this patch so I'm waiting for
a new version.

Would also be nice if the maintainer could add some comments?

Yours,
Linus Walleij

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-24  8:43     ` Linus Walleij
@ 2020-11-24  8:53       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-24  8:53 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, Philipp Zabel, Sean Anderson

On 2020/11/24 17:43, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
>> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
>> (fully programmable IO array) to allow configuring the SoC pin
>> functions. The K210 has 48 programmable pins which can take any of 256
>> possible functions.
>>
>> This patch is inspired from the k210 pinctrl driver for the u-boot
>> project and contains many direct contributions from Sean Anderson.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> The kernel build robot is complaining about this patch so I'm waiting for
> a new version.

I posted V2 of the series earlier today. That version addresses the build bot error.
Note that checkpatch throws a warning on this one for the K210_PIN() macro, but
that is in my opinion a checkpatch false positive since similar macro
definitions exist in many places in the kernel.

> Would also be nice if the maintainer could add some comments?

What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
you are the maintainer of the pinctrl drivers subsystem. Do you mean adding an
entry to the MAINTAINER file for this driver ? I can do that and put my self as
maintainer. Or do you mean you would like a comment from Palmer (riscv arch
maintainer) ?


> 
> Yours,
> Linus Walleij
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-24  8:53       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-24  8:53 UTC (permalink / raw)
  To: Linus Walleij
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Mark Brown, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On 2020/11/24 17:43, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
>> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
>> (fully programmable IO array) to allow configuring the SoC pin
>> functions. The K210 has 48 programmable pins which can take any of 256
>> possible functions.
>>
>> This patch is inspired from the k210 pinctrl driver for the u-boot
>> project and contains many direct contributions from Sean Anderson.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> The kernel build robot is complaining about this patch so I'm waiting for
> a new version.

I posted V2 of the series earlier today. That version addresses the build bot error.
Note that checkpatch throws a warning on this one for the K210_PIN() macro, but
that is in my opinion a checkpatch false positive since similar macro
definitions exist in many places in the kernel.

> Would also be nice if the maintainer could add some comments?

What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
you are the maintainer of the pinctrl drivers subsystem. Do you mean adding an
entry to the MAINTAINER file for this driver ? I can do that and put my self as
maintainer. Or do you mean you would like a comment from Palmer (riscv arch
maintainer) ?


> 
> Yours,
> Linus Walleij
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-24  8:43     ` Linus Walleij
@ 2020-11-24  8:56       ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-24  8:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, Philipp Zabel, Sean Anderson

On 2020/11/24 17:43, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
>> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
>> (fully programmable IO array) to allow configuring the SoC pin
>> functions. The K210 has 48 programmable pins which can take any of 256
>> possible functions.
>>
>> This patch is inspired from the k210 pinctrl driver for the u-boot
>> project and contains many direct contributions from Sean Anderson.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> The kernel build robot is complaining about this patch so I'm waiting for
> a new version.

If you did not receive the V2 patches, please let me know and I will resend.
The patches are all on the riscv list:

http://lists.infradead.org/pipermail/linux-riscv/2020-November/003280.html

And for the fpioa driver:

http://lists.infradead.org/pipermail/linux-riscv/2020-November/003293.html

> 
> Would also be nice if the maintainer could add some comments?
> 
> Yours,
> Linus Walleij
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-24  8:56       ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-24  8:56 UTC (permalink / raw)
  To: Linus Walleij
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Mark Brown, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On 2020/11/24 17:43, Linus Walleij wrote:
> On Sat, Nov 7, 2020 at 9:15 AM Damien Le Moal <damien.lemoal@wdc.com> wrote:
> 
>> Add the pinctrl-k210.c pinctrl driver for the Kendryte K210 FPIOA
>> (fully programmable IO array) to allow configuring the SoC pin
>> functions. The K210 has 48 programmable pins which can take any of 256
>> possible functions.
>>
>> This patch is inspired from the k210 pinctrl driver for the u-boot
>> project and contains many direct contributions from Sean Anderson.
>>
>> Signed-off-by: Sean Anderson <seanga2@gmail.com>
>> Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com>
> 
> The kernel build robot is complaining about this patch so I'm waiting for
> a new version.

If you did not receive the V2 patches, please let me know and I will resend.
The patches are all on the riscv list:

http://lists.infradead.org/pipermail/linux-riscv/2020-November/003280.html

And for the fpioa driver:

http://lists.infradead.org/pipermail/linux-riscv/2020-November/003293.html

> 
> Would also be nice if the maintainer could add some comments?
> 
> Yours,
> Linus Walleij
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-24  8:53       ` Damien Le Moal
@ 2020-11-29 21:33         ` Linus Walleij
  -1 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-29 21:33 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: Palmer Dabbelt, linux-riscv, Rob Herring, Frank Rowand,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Serge Semin, Mark Brown, linux-spi, Stephen Boyd, linux-clk,
	open list:GPIO SUBSYSTEM, Philipp Zabel, Sean Anderson

On Tue, Nov 24, 2020 at 9:53 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> On 2020/11/24 17:43, Linus Walleij wrote:

> > Would also be nice if the maintainer could add some comments?
>
> What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
> you are the maintainer of the pinctrl drivers subsystem.

Sorry I thought we had a RISCV driver already, and we don't
so this is cool.

> Do you mean adding an
> entry to the MAINTAINER file for this driver ? I can do that and put my self as
> maintainer. Or do you mean you would like a comment from Palmer (riscv arch
> maintainer) ?

That would be nice. Whoever will enthusiastically review patches to
this driver and make sure it works and get modernized should ideally
be listed as maintainer. I suggest you list yourself.

The only input I want from the RISCV arch maintainer would
be on this code:

+/*
+ * Most devices on the K210 SoC depend on pin mapping changes to initialize
+ * correctly. So initialize this driver early as part of the post core
+ * initialization.
+ */
+static int __init k210_fpioa_init(void)
+{
+       return platform_driver_register(&k210_fpioa_driver);
+}
+postcore_initcall(k210_fpioa_init);

This is a bit nasty and we do not recommend it. But I will accept it
if the arch maintainer claims it is necessary. What happens if you
just make it initialize at driver level?

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-29 21:33         ` Linus Walleij
  0 siblings, 0 replies; 297+ messages in thread
From: Linus Walleij @ 2020-11-29 21:33 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	Stephen Boyd, Mark Brown, Serge Semin, linux-spi,
	open list:GPIO SUBSYSTEM, Rob Herring, Palmer Dabbelt,
	Philipp Zabel, linux-riscv, Sean Anderson, Frank Rowand,
	linux-clk

On Tue, Nov 24, 2020 at 9:53 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> On 2020/11/24 17:43, Linus Walleij wrote:

> > Would also be nice if the maintainer could add some comments?
>
> What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
> you are the maintainer of the pinctrl drivers subsystem.

Sorry I thought we had a RISCV driver already, and we don't
so this is cool.

> Do you mean adding an
> entry to the MAINTAINER file for this driver ? I can do that and put my self as
> maintainer. Or do you mean you would like a comment from Palmer (riscv arch
> maintainer) ?

That would be nice. Whoever will enthusiastically review patches to
this driver and make sure it works and get modernized should ideally
be listed as maintainer. I suggest you list yourself.

The only input I want from the RISCV arch maintainer would
be on this code:

+/*
+ * Most devices on the K210 SoC depend on pin mapping changes to initialize
+ * correctly. So initialize this driver early as part of the post core
+ * initialization.
+ */
+static int __init k210_fpioa_init(void)
+{
+       return platform_driver_register(&k210_fpioa_driver);
+}
+postcore_initcall(k210_fpioa_init);

This is a bit nasty and we do not recommend it. But I will accept it
if the arch maintainer claims it is necessary. What happens if you
just make it initialize at driver level?

Yours,
Linus Walleij

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-29 21:33         ` Linus Walleij
@ 2020-11-30  3:13           ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-30  3:13 UTC (permalink / raw)
  To: linus.walleij
  Cc: linux-spi, linux-riscv, broonie, devicetree, sboyd, palmer,
	frowand.list, linux-gpio, fancer.lancer, p.zabel, robh+dt,
	linux-clk, seanga2

On Sun, 2020-11-29 at 22:33 +0100, Linus Walleij wrote:
> On Tue, Nov 24, 2020 at 9:53 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> > On 2020/11/24 17:43, Linus Walleij wrote:
> 
> > > Would also be nice if the maintainer could add some comments?
> > 
> > What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
> > you are the maintainer of the pinctrl drivers subsystem.
> 
> Sorry I thought we had a RISCV driver already, and we don't
> so this is cool.
> 
> > Do you mean adding an
> > entry to the MAINTAINER file for this driver ? I can do that and put my self as
> > maintainer. Or do you mean you would like a comment from Palmer (riscv arch
> > maintainer) ?
> 
> That would be nice. Whoever will enthusiastically review patches to
> this driver and make sure it works and get modernized should ideally
> be listed as maintainer. I suggest you list yourself.

OK, no problem. Will do.

> The only input I want from the RISCV arch maintainer would
> be on this code:
> 
> +/*
> + * Most devices on the K210 SoC depend on pin mapping changes to initialize
> + * correctly. So initialize this driver early as part of the post core
> + * initialization.
> + */
> +static int __init k210_fpioa_init(void)
> +{
> +       return platform_driver_register(&k210_fpioa_driver);
> +}
> +postcore_initcall(k210_fpioa_init);
> 
> This is a bit nasty and we do not recommend it. But I will accept it
> if the arch maintainer claims it is necessary. What happens if you
> just make it initialize at driver level?

I checked again and nothing bad happens. Declaring the driver with
builtin_platform_driver() works just fine. I will change back to using this
instead of the postcore_initcall().

Note that I had done the same for the k210 sysctl and reset drivers too to get
these drivers to initialize early and avoid an annoying error messages when the
dwapb GPIO driver is probed (the error being "Cannot get reset descriptor" from
dwapb_get_reset()). But that is not a real error as the error code is
EPROBE_DEFER, which leads to the gpio driver initialization being retried
later, after the reset controller initialization. This annoying boot false
error message can be fixed simply with something like this:

diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 2a9046c0fb16..4a801e83919b 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
 
        gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);
        if (IS_ERR(gpio->rst)) {
-               dev_err(gpio->dev, "Cannot get reset descriptor\n");
-               return PTR_ERR(gpio->rst);
+               err = PTR_ERR(gpio->rst);
+               if (err != -EPROBE_DEFER)
+                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
+               return err;
        }

and all drivers can now use builtin_platform_driver() declaration with a clean
boot log. If you are OK with the above patch, I will send it.

Thanks !

> 
> Yours,
> Linus Walleij

-- 
Damien Le Moal
Western Digital

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-30  3:13           ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-30  3:13 UTC (permalink / raw)
  To: linus.walleij
  Cc: devicetree, robh+dt, sboyd, fancer.lancer, linux-spi, linux-gpio,
	broonie, palmer, p.zabel, linux-riscv, seanga2, frowand.list,
	linux-clk

On Sun, 2020-11-29 at 22:33 +0100, Linus Walleij wrote:
> On Tue, Nov 24, 2020 at 9:53 AM Damien Le Moal <Damien.LeMoal@wdc.com> wrote:
> > On 2020/11/24 17:43, Linus Walleij wrote:
> 
> > > Would also be nice if the maintainer could add some comments?
> > 
> > What do you mean ? I do not understand. scripts/get_maintainer.pl indicates that
> > you are the maintainer of the pinctrl drivers subsystem.
> 
> Sorry I thought we had a RISCV driver already, and we don't
> so this is cool.
> 
> > Do you mean adding an
> > entry to the MAINTAINER file for this driver ? I can do that and put my self as
> > maintainer. Or do you mean you would like a comment from Palmer (riscv arch
> > maintainer) ?
> 
> That would be nice. Whoever will enthusiastically review patches to
> this driver and make sure it works and get modernized should ideally
> be listed as maintainer. I suggest you list yourself.

OK, no problem. Will do.

> The only input I want from the RISCV arch maintainer would
> be on this code:
> 
> +/*
> + * Most devices on the K210 SoC depend on pin mapping changes to initialize
> + * correctly. So initialize this driver early as part of the post core
> + * initialization.
> + */
> +static int __init k210_fpioa_init(void)
> +{
> +       return platform_driver_register(&k210_fpioa_driver);
> +}
> +postcore_initcall(k210_fpioa_init);
> 
> This is a bit nasty and we do not recommend it. But I will accept it
> if the arch maintainer claims it is necessary. What happens if you
> just make it initialize at driver level?

I checked again and nothing bad happens. Declaring the driver with
builtin_platform_driver() works just fine. I will change back to using this
instead of the postcore_initcall().

Note that I had done the same for the k210 sysctl and reset drivers too to get
these drivers to initialize early and avoid an annoying error messages when the
dwapb GPIO driver is probed (the error being "Cannot get reset descriptor" from
dwapb_get_reset()). But that is not a real error as the error code is
EPROBE_DEFER, which leads to the gpio driver initialization being retried
later, after the reset controller initialization. This annoying boot false
error message can be fixed simply with something like this:

diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
index 2a9046c0fb16..4a801e83919b 100644
--- a/drivers/gpio/gpio-dwapb.c
+++ b/drivers/gpio/gpio-dwapb.c
@@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
 
        gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);
        if (IS_ERR(gpio->rst)) {
-               dev_err(gpio->dev, "Cannot get reset descriptor\n");
-               return PTR_ERR(gpio->rst);
+               err = PTR_ERR(gpio->rst);
+               if (err != -EPROBE_DEFER)
+                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
+               return err;
        }

and all drivers can now use builtin_platform_driver() declaration with a clean
boot log. If you are OK with the above patch, I will send it.

Thanks !

> 
> Yours,
> Linus Walleij

-- 
Damien Le Moal
Western Digital
_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-30  3:13           ` Damien Le Moal
@ 2020-11-30  7:05             ` Serge Semin
  -1 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-30  7:05 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: linus.walleij, linux-spi, linux-riscv, broonie, devicetree,
	sboyd, palmer, frowand.list, linux-gpio, p.zabel, robh+dt,
	linux-clk, seanga2

Damien,
Just a tiny nitpick below.

On Mon, Nov 30, 2020 at 03:13:45AM +0000, Damien Le Moal wrote:
> [...]
> 
> diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
> index 2a9046c0fb16..4a801e83919b 100644
> --- a/drivers/gpio/gpio-dwapb.c
> +++ b/drivers/gpio/gpio-dwapb.c
> @@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
>  
>         gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);

>         if (IS_ERR(gpio->rst)) {
> -               dev_err(gpio->dev, "Cannot get reset descriptor\n");
> -               return PTR_ERR(gpio->rst);
> +               err = PTR_ERR(gpio->rst);
> +               if (err != -EPROBE_DEFER)
> +                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
> +               return err;
>         }

There is a dedicated method to generically handle the PROBE_DEFER
error returned by functions like get(resource): dev_err_probe().
So here you'd just need to do:

-	if (IS_ERR(gpio->rst)) {
-		dev_err(gpio->dev, "Cannot get reset descriptor\n");
-		return PTR_ERR(gpio->rst);
-	}
+	if (IS_ERR(gpio->rst))
+		return dev_err_probe(gpio->dev, PTR_ERR(gpio->rst),
+				     "Cannot get reset descriptor\n");

-Sergey

> 
> and all drivers can now use builtin_platform_driver() declaration with a clean
> boot log. If you are OK with the above patch, I will send it.
> 
> Thanks !
> 
> > 
> > Yours,
> > Linus Walleij
> 
> -- 
> Damien Le Moal
> Western Digital

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-30  7:05             ` Serge Semin
  0 siblings, 0 replies; 297+ messages in thread
From: Serge Semin @ 2020-11-30  7:05 UTC (permalink / raw)
  To: Damien Le Moal
  Cc: devicetree, sboyd, linus.walleij, robh+dt, linux-spi, linux-gpio,
	broonie, palmer, p.zabel, linux-riscv, seanga2, frowand.list,
	linux-clk

Damien,
Just a tiny nitpick below.

On Mon, Nov 30, 2020 at 03:13:45AM +0000, Damien Le Moal wrote:
> [...]
> 
> diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
> index 2a9046c0fb16..4a801e83919b 100644
> --- a/drivers/gpio/gpio-dwapb.c
> +++ b/drivers/gpio/gpio-dwapb.c
> @@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
>  
>         gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);

>         if (IS_ERR(gpio->rst)) {
> -               dev_err(gpio->dev, "Cannot get reset descriptor\n");
> -               return PTR_ERR(gpio->rst);
> +               err = PTR_ERR(gpio->rst);
> +               if (err != -EPROBE_DEFER)
> +                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
> +               return err;
>         }

There is a dedicated method to generically handle the PROBE_DEFER
error returned by functions like get(resource): dev_err_probe().
So here you'd just need to do:

-	if (IS_ERR(gpio->rst)) {
-		dev_err(gpio->dev, "Cannot get reset descriptor\n");
-		return PTR_ERR(gpio->rst);
-	}
+	if (IS_ERR(gpio->rst))
+		return dev_err_probe(gpio->dev, PTR_ERR(gpio->rst),
+				     "Cannot get reset descriptor\n");

-Sergey

> 
> and all drivers can now use builtin_platform_driver() declaration with a clean
> boot log. If you are OK with the above patch, I will send it.
> 
> Thanks !
> 
> > 
> > Yours,
> > Linus Walleij
> 
> -- 
> Damien Le Moal
> Western Digital

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
  2020-11-30  7:05             ` Serge Semin
@ 2020-11-30  7:27               ` Damien Le Moal
  -1 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-30  7:27 UTC (permalink / raw)
  To: Serge Semin
  Cc: linus.walleij, linux-spi, linux-riscv, broonie, devicetree,
	sboyd, palmer, frowand.list, linux-gpio, p.zabel, robh+dt,
	linux-clk, seanga2

On 2020/11/30 16:06, Serge Semin wrote:
> Damien,
> Just a tiny nitpick below.
> 
> On Mon, Nov 30, 2020 at 03:13:45AM +0000, Damien Le Moal wrote:
>> [...]
>>
>> diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
>> index 2a9046c0fb16..4a801e83919b 100644
>> --- a/drivers/gpio/gpio-dwapb.c
>> +++ b/drivers/gpio/gpio-dwapb.c
>> @@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
>>  
>>         gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);
> 
>>         if (IS_ERR(gpio->rst)) {
>> -               dev_err(gpio->dev, "Cannot get reset descriptor\n");
>> -               return PTR_ERR(gpio->rst);
>> +               err = PTR_ERR(gpio->rst);
>> +               if (err != -EPROBE_DEFER)
>> +                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
>> +               return err;
>>         }
> 
> There is a dedicated method to generically handle the PROBE_DEFER
> error returned by functions like get(resource): dev_err_probe().
> So here you'd just need to do:
> 
> -	if (IS_ERR(gpio->rst)) {
> -		dev_err(gpio->dev, "Cannot get reset descriptor\n");
> -		return PTR_ERR(gpio->rst);
> -	}
> +	if (IS_ERR(gpio->rst))
> +		return dev_err_probe(gpio->dev, PTR_ERR(gpio->rst),
> +				     "Cannot get reset descriptor\n");
> 

Great to know. Thank you for the hint.
Will send a patch.

> -Sergey
> 
>>
>> and all drivers can now use builtin_platform_driver() declaration with a clean
>> boot log. If you are OK with the above patch, I will send it.
>>
>> Thanks !
>>
>>>
>>> Yours,
>>> Linus Walleij
>>
>> -- 
>> Damien Le Moal
>> Western Digital
> 


-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply	[flat|nested] 297+ messages in thread

* Re: [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver
@ 2020-11-30  7:27               ` Damien Le Moal
  0 siblings, 0 replies; 297+ messages in thread
From: Damien Le Moal @ 2020-11-30  7:27 UTC (permalink / raw)
  To: Serge Semin
  Cc: devicetree, sboyd, linus.walleij, robh+dt, linux-spi, linux-gpio,
	broonie, palmer, p.zabel, linux-riscv, seanga2, frowand.list,
	linux-clk

On 2020/11/30 16:06, Serge Semin wrote:
> Damien,
> Just a tiny nitpick below.
> 
> On Mon, Nov 30, 2020 at 03:13:45AM +0000, Damien Le Moal wrote:
>> [...]
>>
>> diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c
>> index 2a9046c0fb16..4a801e83919b 100644
>> --- a/drivers/gpio/gpio-dwapb.c
>> +++ b/drivers/gpio/gpio-dwapb.c
>> @@ -617,8 +617,10 @@ static int dwapb_get_reset(struct dwapb_gpio *gpio)
>>  
>>         gpio->rst = devm_reset_control_get_optional_shared(gpio->dev, NULL);
> 
>>         if (IS_ERR(gpio->rst)) {
>> -               dev_err(gpio->dev, "Cannot get reset descriptor\n");
>> -               return PTR_ERR(gpio->rst);
>> +               err = PTR_ERR(gpio->rst);
>> +               if (err != -EPROBE_DEFER)
>> +                       dev_err(gpio->dev, "Cannot get reset descriptor\n");
>> +               return err;
>>         }
> 
> There is a dedicated method to generically handle the PROBE_DEFER
> error returned by functions like get(resource): dev_err_probe().
> So here you'd just need to do:
> 
> -	if (IS_ERR(gpio->rst)) {
> -		dev_err(gpio->dev, "Cannot get reset descriptor\n");
> -		return PTR_ERR(gpio->rst);
> -	}
> +	if (IS_ERR(gpio->rst))
> +		return dev_err_probe(gpio->dev, PTR_ERR(gpio->rst),
> +				     "Cannot get reset descriptor\n");
> 

Great to know. Thank you for the hint.
Will send a patch.

> -Sergey
> 
>>
>> and all drivers can now use builtin_platform_driver() declaration with a clean
>> boot log. If you are OK with the above patch, I will send it.
>>
>> Thanks !
>>
>>>
>>> Yours,
>>> Linus Walleij
>>
>> -- 
>> Damien Le Moal
>> Western Digital
> 


-- 
Damien Le Moal
Western Digital Research

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 297+ messages in thread

end of thread, other threads:[~2020-11-30  7:28 UTC | newest]

Thread overview: 297+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-07  8:13 [PATCH 00/32] RISC-V Kendryte K210 support improvments Damien Le Moal
2020-11-07  8:13 ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 01/32] of: Fix property supplier parsing Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-09 15:05   ` Serge Semin
2020-11-09 15:05     ` Serge Semin
2020-11-09 15:14   ` Andy Shevchenko
2020-11-09 15:14     ` Andy Shevchenko
2020-11-09 17:44     ` Serge Semin
2020-11-09 17:44       ` Serge Semin
2020-11-09 20:52       ` Rob Herring
2020-11-09 20:52         ` Rob Herring
2020-11-16  7:30       ` Damien Le Moal
2020-11-16  7:30         ` Damien Le Moal
2020-11-16 22:06         ` Serge Semin
2020-11-16 22:06           ` Serge Semin
2020-11-07  8:13 ` [PATCH 02/32] spi: dw: Add support for 32-bits ctrlr0 layout Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07 13:28   ` Sean Anderson
2020-11-07 13:28     ` Sean Anderson
2020-11-09 14:25   ` Serge Semin
2020-11-09 14:25     ` Serge Semin
2020-11-09 14:33     ` Sean Anderson
2020-11-09 14:33       ` Sean Anderson
2020-11-09 14:35       ` Sean Anderson
2020-11-09 14:35         ` Sean Anderson
2020-11-09 14:40       ` Andy Shevchenko
2020-11-09 14:40         ` Andy Shevchenko
2020-11-09 14:41         ` Andy Shevchenko
2020-11-09 14:41           ` Andy Shevchenko
2020-11-09 14:49           ` Sean Anderson
2020-11-09 14:49             ` Sean Anderson
2020-11-09 15:10             ` Andy Shevchenko
2020-11-09 15:10               ` Andy Shevchenko
2020-11-09 14:36     ` Andy Shevchenko
2020-11-09 14:36       ` Andy Shevchenko
2020-11-09 17:56       ` Serge Semin
2020-11-09 17:56         ` Serge Semin
2020-11-07  8:13 ` [PATCH 03/32] spi: dw: Fix driving MOSI low while recieving Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07 13:30   ` Sean Anderson
2020-11-07 13:30     ` Sean Anderson
2020-11-09 13:29   ` Mark Brown
2020-11-09 13:29     ` Mark Brown
2020-11-09 13:47     ` Sean Anderson
2020-11-09 13:47       ` Sean Anderson
2020-11-09 14:14       ` Mark Brown
2020-11-09 14:14         ` Mark Brown
2020-11-09 14:48         ` Serge Semin
2020-11-09 14:48           ` Serge Semin
2020-11-09 16:45           ` Mark Brown
2020-11-09 16:45             ` Mark Brown
2020-11-09 19:19         ` Serge Semin
2020-11-09 19:19           ` Serge Semin
2020-11-09 19:40           ` Sean Anderson
2020-11-09 19:40             ` Sean Anderson
2020-11-09 20:17             ` Serge Semin
2020-11-09 20:17               ` Serge Semin
2020-11-09 20:29               ` Mark Brown
2020-11-09 20:29                 ` Mark Brown
2020-11-09 20:20           ` Mark Brown
2020-11-09 20:20             ` Mark Brown
2020-11-09 21:05             ` Serge Semin
2020-11-09 21:05               ` Serge Semin
2020-11-10 13:43               ` Mark Brown
2020-11-10 13:43                 ` Mark Brown
2020-11-07  8:13 ` [PATCH 04/32] spi: dw: Introduce polling device tree property Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-09 16:04   ` Mark Brown
2020-11-09 16:04     ` Mark Brown
2020-11-09 19:59   ` Serge Semin
2020-11-09 19:59     ` Serge Semin
2020-11-13  9:22     ` Damien Le Moal
2020-11-13  9:22       ` Damien Le Moal
2020-11-15 16:01       ` Serge Semin
2020-11-15 16:01         ` Serge Semin
2020-11-16  7:47         ` Damien Le Moal
2020-11-16  7:47           ` Damien Le Moal
2020-11-16 12:33           ` Mark Brown
2020-11-16 12:33             ` Mark Brown
2020-11-16 21:55           ` Serge Semin
2020-11-16 21:55             ` Serge Semin
2020-11-17 14:44             ` Damien Le Moal
2020-11-17 14:44               ` Damien Le Moal
2020-11-17 18:26               ` Serge Semin
2020-11-17 18:26                 ` Serge Semin
2020-11-18  4:41                 ` Damien Le Moal
2020-11-18  4:41                   ` Damien Le Moal
2020-11-18 15:16                   ` Serge Semin
2020-11-18 15:16                     ` Serge Semin
2020-11-19  5:12                     ` Damien Le Moal
2020-11-19  5:12                       ` Damien Le Moal
2020-11-19  8:51                       ` Serge Semin
2020-11-19  8:51                         ` Serge Semin
2020-11-19  8:57                         ` Damien Le Moal
2020-11-19  8:57                           ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 05/32] spi: dw: Introduce DW_SPI_CAP_POLL_NODELAY Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-09 14:03   ` Mark Brown
2020-11-09 14:03     ` Mark Brown
2020-11-09 20:45   ` Serge Semin
2020-11-09 20:45     ` Serge Semin
2020-11-07  8:13 ` [PATCH 06/32] spi: dw: Add support for the Kendryte K210 SoC Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07 13:31   ` Sean Anderson
2020-11-07 13:31     ` Sean Anderson
2020-11-07 13:42     ` Damien Le Moal
2020-11-07 13:42       ` Damien Le Moal
2020-11-07 13:52       ` Sean Anderson
2020-11-07 13:52         ` Sean Anderson
2020-11-09 14:15         ` Mark Brown
2020-11-09 14:15           ` Mark Brown
2020-11-13  8:00     ` Damien Le Moal
2020-11-13  8:00       ` Damien Le Moal
2020-11-09 21:21   ` Serge Semin
2020-11-09 21:21     ` Serge Semin
2020-11-09 21:39     ` Damien Le Moal
2020-11-09 21:39       ` Damien Le Moal
2020-11-09 21:55       ` Rob Herring
2020-11-09 21:55         ` Rob Herring
2020-11-09 22:00         ` Damien Le Moal
2020-11-09 22:00           ` Damien Le Moal
2020-11-09 23:07           ` Rob Herring
2020-11-09 23:07             ` Rob Herring
2020-11-10  0:35             ` Damien Le Moal
2020-11-10  0:35               ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 07/32] dt-bindings: Update DW SPI device tree bindings Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 08/32] riscv: Fix kernel time_init() Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-12  7:21   ` Atish Patra
2020-11-12  7:21     ` Atish Patra
2020-11-13  7:31   ` Stephen Boyd
2020-11-13  7:31     ` Stephen Boyd
2020-11-13  7:40     ` Damien Le Moal
2020-11-13  7:40       ` Damien Le Moal
2020-11-13  7:53       ` Stephen Boyd
2020-11-13  7:53         ` Stephen Boyd
2020-11-13  7:57         ` Damien Le Moal
2020-11-13  7:57           ` Damien Le Moal
2020-11-13  8:11           ` Stephen Boyd
2020-11-13  8:11             ` Stephen Boyd
2020-11-13  8:23             ` Damien Le Moal
2020-11-13  8:23               ` Damien Le Moal
2020-11-16  7:06               ` Stephen Boyd
2020-11-16  7:06                 ` Stephen Boyd
2020-11-16  7:18                 ` Damien Le Moal
2020-11-16  7:18                   ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 09/32] riscv: Fix SiFive gpio probe Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-10 14:39   ` Linus Walleij
2020-11-10 14:39     ` Linus Walleij
2020-11-11  7:00     ` Damien Le Moal
2020-11-11  7:00       ` Damien Le Moal
2020-11-11  8:54       ` Linus Walleij
2020-11-11  8:54         ` Linus Walleij
2020-11-11  8:56         ` Damien Le Moal
2020-11-11  8:56           ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 10/32] riscv: Fix sifive serial driver Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07  8:13 ` [PATCH 11/32] riscv: Enable interrupts during syscalls with M-Mode Damien Le Moal
2020-11-07  8:13   ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 12/32] riscv: Automatically select sysctl config options Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 13/32] riscv: Fix builtin DTB handling Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-15  4:17   ` kernel test robot
2020-11-15  4:17     ` kernel test robot
2020-11-15  4:17     ` kernel test robot
2020-11-07  8:14 ` [PATCH 14/32] dt-bindings: Define all Kendryte K210 clock IDs Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:33   ` Sean Anderson
2020-11-07 13:33     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 15/32] dt-bindings: Define Kendryte K210 sysctl registers Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:34   ` Sean Anderson
2020-11-07 13:34     ` Sean Anderson
2020-11-09 21:59   ` Rob Herring
2020-11-09 21:59     ` Rob Herring
2020-11-09 22:10     ` Sean Anderson
2020-11-09 22:10       ` Sean Anderson
2020-11-09 23:01       ` Rob Herring
2020-11-09 23:01         ` Rob Herring
2020-11-07  8:14 ` [PATCH 16/32] dt-bindings: Define Kendryte K210 pin functions Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:38   ` Sean Anderson
2020-11-07 13:38     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 17/32] dt-bindings: Define Kendryte K210 reset signals Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:38   ` Sean Anderson
2020-11-07 13:38     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 18/32] riscv: Add Kendryte K210 SoC clock driver Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:48   ` Sean Anderson
2020-11-07 13:48     ` Sean Anderson
2020-11-13  8:14     ` Damien Le Moal
2020-11-13  8:14       ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 19/32] riscv: Add Kendryte K210 SoC reset controller Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 13:58   ` Sean Anderson
2020-11-07 13:58     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 20/32] riscv: Add Kendryte K210 FPIOA pinctrl driver Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-09 18:48   ` kernel test robot
2020-11-09 18:48     ` kernel test robot
2020-11-09 18:48     ` kernel test robot
2020-11-15  0:28   ` kernel test robot
2020-11-15  0:28     ` kernel test robot
2020-11-15  0:28     ` kernel test robot
2020-11-24  8:43   ` Linus Walleij
2020-11-24  8:43     ` Linus Walleij
2020-11-24  8:53     ` Damien Le Moal
2020-11-24  8:53       ` Damien Le Moal
2020-11-29 21:33       ` Linus Walleij
2020-11-29 21:33         ` Linus Walleij
2020-11-30  3:13         ` Damien Le Moal
2020-11-30  3:13           ` Damien Le Moal
2020-11-30  7:05           ` Serge Semin
2020-11-30  7:05             ` Serge Semin
2020-11-30  7:27             ` Damien Le Moal
2020-11-30  7:27               ` Damien Le Moal
2020-11-24  8:56     ` Damien Le Moal
2020-11-24  8:56       ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 21/32] dt-bindings: Add Kendryte and Canaan vendor prefix Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:03   ` Sean Anderson
2020-11-07 14:03     ` Sean Anderson
2020-11-13  8:17     ` Damien Le Moal
2020-11-13  8:17       ` Damien Le Moal
2020-11-09 22:01   ` Rob Herring
2020-11-09 22:01     ` Rob Herring
2020-11-09 22:04     ` Damien Le Moal
2020-11-09 22:04       ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 22/32] dt-binding: Document kendryte,k210-sysctl bindings Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:05   ` Sean Anderson
2020-11-07 14:05     ` Sean Anderson
2020-11-09 15:32   ` Rob Herring
2020-11-09 15:32     ` Rob Herring
2020-11-07  8:14 ` [PATCH 23/32] dt-binding: Document kendryte,k210-clk bindings Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:05   ` Sean Anderson
2020-11-07 14:05     ` Sean Anderson
2020-11-09 21:58   ` Rob Herring
2020-11-09 21:58     ` Rob Herring
2020-11-07  8:14 ` [PATCH 24/32] dt-bindings: Document kendryte,k210-fpioa bindings Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:06   ` Sean Anderson
2020-11-07 14:06     ` Sean Anderson
2020-11-09 15:32   ` Rob Herring
2020-11-09 15:32     ` Rob Herring
2020-11-09 15:36   ` Rob Herring
2020-11-09 15:36     ` Rob Herring
2020-11-09 15:45     ` Sean Anderson
2020-11-09 15:45       ` Sean Anderson
2020-11-11 14:32       ` Rob Herring
2020-11-11 14:32         ` Rob Herring
2020-11-11 15:06         ` Damien Le Moal
2020-11-11 15:06           ` Damien Le Moal
2020-11-12 11:03           ` Damien Le Moal
2020-11-12 11:03             ` Damien Le Moal
2020-11-19 10:57       ` Geert Uytterhoeven
2020-11-19 10:57         ` Geert Uytterhoeven
2020-11-19 11:22         ` Damien Le Moal
2020-11-19 11:22           ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 25/32] dt-bindings: Document kendryte,k210-rst bindings Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:07   ` Sean Anderson
2020-11-07 14:07     ` Sean Anderson
2020-11-09 15:37   ` Rob Herring
2020-11-09 15:37     ` Rob Herring
2020-11-09 15:41   ` Rob Herring
2020-11-09 15:41     ` Rob Herring
2020-11-07  8:14 ` [PATCH 26/32] riscv: Update Kendryte K210 device tree Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:08   ` Sean Anderson
2020-11-07 14:08     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 27/32] riscv: Add SiPeed MAIX BiT board " Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:13   ` Sean Anderson
2020-11-07 14:13     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 28/32] riscv: Add SiPeed MAIX DOCK " Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 29/32] riscv: Add SiPeed MAIX GO " Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 30/32] riscv: Add SiPeed MAIXDUINO " Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07 14:14   ` Sean Anderson
2020-11-07 14:14     ` Sean Anderson
2020-11-07  8:14 ` [PATCH 31/32] riscv: Add Kendryte KD233 " Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-07  8:14 ` [PATCH 32/32] riscv: Update Kendryte K210 defconfig Damien Le Moal
2020-11-07  8:14   ` Damien Le Moal
2020-11-09 12:51 ` [PATCH 00/32] RISC-V Kendryte K210 support improvments Mark Brown
2020-11-09 12:51   ` Mark Brown
2020-11-09 12:55   ` Damien Le Moal
2020-11-09 12:55     ` Damien Le Moal

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.