diff mbox series

[v4,06/17] spi: dw: Add device tree properties for fields in CTRL1

Message ID 20200211060425.1619471-7-seanga2@gmail.com
State Superseded
Headers show
Series riscv: Add Sipeed Maix support | expand

Commit Message

Sean Anderson Feb. 11, 2020, 6:04 a.m. UTC
Some devices have different layouts for the fields in CTRL1 (e.g. the
Kendryte K210). Allow this layout to be configurable from the device tree.
The documentation has been taken from Linux.

Signed-off-by: Sean Anderson <seanga2 at gmail.com>
---

Changes in v4:
- New

 .../spi/snps,dw-apb-ssi.txt                   | 43 +++++++++++++++++++
 drivers/spi/designware_spi.c                  | 40 ++++++++++-------
 2 files changed, 68 insertions(+), 15 deletions(-)
 create mode 100644 doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt

Comments

Simon Glass Feb. 11, 2020, 5:14 p.m. UTC | #1
On Mon, 10 Feb 2020 at 23:05, Sean Anderson <seanga2 at gmail.com> wrote:
>
> Some devices have different layouts for the fields in CTRL1 (e.g. the
> Kendryte K210). Allow this layout to be configurable from the device tree.
> The documentation has been taken from Linux.
>
> Signed-off-by: Sean Anderson <seanga2 at gmail.com>
> ---
>
> Changes in v4:
> - New
>
>  .../spi/snps,dw-apb-ssi.txt                   | 43 +++++++++++++++++++
>  drivers/spi/designware_spi.c                  | 40 ++++++++++-------
>  2 files changed, 68 insertions(+), 15 deletions(-)
>  create mode 100644 doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
>

Reviewed-by: Simon Glass <sjg at chromium.org>
Rick Chen Feb. 18, 2020, 6:05 a.m. UTC | #2
Hi Sean

> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Sean Anderson
> Sent: Tuesday, February 11, 2020 2:04 PM
> To: u-boot at lists.denx.de
> Cc: Rick Chen; Eugeniy Paltsev
> Subject: [PATCH v4 06/17] spi: dw: Add device tree properties for fields in CTRL1
>
> Some devices have different layouts for the fields in CTRL1 (e.g. the Kendryte K210). Allow this layout to be configurable from the device tree.

The description of CTRL1 here don't match with the below content of CTRL0.
Is it a typo ?

Thanks
Rick

> The documentation has been taken from Linux.
>
> Signed-off-by: Sean Anderson <seanga2 at gmail.com>
> ---
>
> Changes in v4:
> - New
>
>  .../spi/snps,dw-apb-ssi.txt                   | 43 +++++++++++++++++++
>  drivers/spi/designware_spi.c                  | 40 ++++++++++-------
>  2 files changed, 68 insertions(+), 15 deletions(-)  create mode 100644 doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
>
> diff --git a/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt b/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
> new file mode 100644
> index 0000000000..4b6152f6b7
> --- /dev/null
> +++ b/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
> @@ -0,0 +1,43 @@
> +Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
> +
> +Required properties:
> +- compatible : "snps,dw-apb-ssi"
> +- reg : The register base for the controller. For "mscc,<soc>-spi", a
> +second
> +  register set is required (named ICPU_CFG:SPI_MST)
> +- #address-cells : <1>, as required by generic SPI binding.
> +- #size-cells : <0>, also as required by generic SPI binding.
> +- clocks : phandles for the clocks, see the description of clock-names below.
> +   The phandle for the "ssi_clk" is required. The phandle for the "pclk" clock
> +   is optional. If a single clock is specified but no clock-name, it is the
> +   "ssi_clk" clock. If both clocks are listed, the "ssi_clk" must be first.
> +
> +Optional properties:
> +- clock-names : Contains the names of the clocks:
> +    "ssi_clk", for the core clock used to generate the external SPI clock.
> +    "pclk", the interface clock, required for register access.
> +- cs-gpios : Specifies the gpio pins to be used for chipselects.
> +- num-cs : The number of chipselects. If omitted, this will default to 4.
> +- reg-io-width : The I/O register width (in bytes) implemented by this
> +  device.  Supported values are 2 or 4 (the default).
> +- snps,dfs-offset The offset in bits of the DFS field in CTRL0,
> +defaulting to 0
> +- snps,frf-offset The offset in bits of the FRF field in CTRL0,
> +defaulting to 4
> +- snps,tmod-offset The offset in bits of the tmode field in CTRL0,
> +defaulting
> +  to 6
> +- snps,mode-offset The offset in bits of the work mode field in CTRL0,
> +  defaulting to 8
> +
> +Child nodes as per the generic SPI binding.
> +
> +Example:
> +
> +       spi at fff00000 {
> +               compatible = "snps,dw-apb-ssi";
> +               reg = <0xfff00000 0x1000>;
> +               interrupts = <0 154 4>;
> +               #address-cells = <1>;
> +               #size-cells = <0>;
> +               clocks = <&spi_m_clk>;
> +               num-cs = <2>;
> +               cs-gpios = <&gpio0 13 0>,
> +                          <&gpio0 14 0>;
> +       };
> diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 66ff8eeccd..04cc873754 100644
> --- a/drivers/spi/designware_spi.c
> +++ b/drivers/spi/designware_spi.c
> @@ -3,6 +3,7 @@
>   * Designware master SPI core controller driver
>   *
>   * Copyright (C) 2014 Stefan Roese <sr at denx.de>
> + * Copyright (C) 2020 Sean Anderson <seanga2 at gmail.com>
>   *
>   * Very loosely based on the Linux driver:
>   * drivers/spi/spi-dw.c, which is:
> @@ -50,20 +51,14 @@
>  #define DW_SPI_DR                      0x60
>
>  /* Bit fields in CTRLR0 */
> -#define SPI_DFS_OFFSET                 0
> -
> -#define SPI_FRF_OFFSET                 4
>  #define SPI_FRF_SPI                    0x0
>  #define SPI_FRF_SSP                    0x1
>  #define SPI_FRF_MICROWIRE              0x2
>  #define SPI_FRF_RESV                   0x3
>
> -#define SPI_MODE_OFFSET                        6
> -#define SPI_SCPH_OFFSET                        6
> -#define SPI_SCOL_OFFSET                        7
> +#define SPI_MODE_SCPH                  0x1
> +#define SPI_MODE_SCOL                  0x2
>
> -#define SPI_TMOD_OFFSET                        8
> -#define SPI_TMOD_MASK                  (0x3 << SPI_TMOD_OFFSET)
>  #define        SPI_TMOD_TR                     0x0             /* xmit & recv */
>  #define SPI_TMOD_TO                    0x1             /* xmit only */
>  #define SPI_TMOD_RO                    0x2             /* recv only */
> @@ -88,6 +83,12 @@
>  struct dw_spi_platdata {
>         s32 frequency;          /* Default clock frequency, -1 for none */
>         void __iomem *regs;
> +
> +       /* Offsets in CTRL0 */
> +       u8 dfs_off;
> +       u8 frf_off;
> +       u8 tmod_off;
> +       u8 mode_off;
>  };
>
>  struct dw_spi_priv {
> @@ -114,6 +115,15 @@ struct dw_spi_priv {
>         struct reset_ctl_bulk   resets;
>  };
>
> +static inline u32 GEN_CTRL0(struct dw_spi_priv *priv,
> +                           struct dw_spi_platdata *plat)
> +{
> +       return ((priv->bits_per_word - 1) << plat->dfs_off |
> +             (priv->type << plat->frf_off) |
> +             (priv->mode << plat->mode_off) |
> +             (priv->tmode << plat->tmod_off)); }
> +
>  static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset)  {
>         return __raw_readl(priv->regs + offset); @@ -159,6 +169,10 @@ static int dw_spi_ofdata_to_platdata(struct udevice *bus)
>         /* Use 500KHz as a suitable default */
>         plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
>                                                500000);
> +       plat->dfs_off = dev_read_u32_default(bus, "snps,dfs-offset", 0);
> +       plat->frf_off = dev_read_u32_default(bus, "snps,frf-offset", 4);
> +       plat->mode_off = dev_read_u32_default(bus, "snps,mode-offset", 6);
> +       plat->tmod_off = dev_read_u32_default(bus, "snps,tmod-offset", 8);
>         debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs,
>               plat->frequency);
>
> @@ -387,6 +401,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>                        const void *dout, void *din, unsigned long flags)  {
>         struct udevice *bus = dev->parent;
> +       struct dw_spi_platdata *plat = dev_get_platdata(bus);
>         struct dw_spi_priv *priv = dev_get_priv(bus);
>         const u8 *tx = dout;
>         u8 *rx = din;
> @@ -405,10 +420,6 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>         if (flags & SPI_XFER_BEGIN)
>                 external_cs_manage(dev, false);
>
> -       cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) |
> -               (priv->mode << SPI_MODE_OFFSET) |
> -               (priv->tmode << SPI_TMOD_OFFSET);
> -
>         if (rx && tx)
>                 priv->tmode = SPI_TMOD_TR;
>         else if (rx)
> @@ -420,8 +431,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>                  */
>                 priv->tmode = SPI_TMOD_TR;
>
> -       cr0 &= ~SPI_TMOD_MASK;
> -       cr0 |= (priv->tmode << SPI_TMOD_OFFSET);
> +       cr0 = GEN_CTRL0(priv, plat);
>
>         priv->len = bitlen >> 3;
>         debug("%s: rx=%p tx=%p len=%d [bytes]\n", __func__, rx, tx, priv->len); @@ -475,7 +485,7 @@ static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
>
>  static int dw_spi_set_speed(struct udevice *bus, uint speed)  {
> -       struct dw_spi_platdata *plat = bus->platdata;
> +       struct dw_spi_platdata *plat = dev_get_platdata(bus);
>         struct dw_spi_priv *priv = dev_get_priv(bus);
>         u16 clk_div;
>
> --
> 2.25.0
>
Sean Anderson Feb. 18, 2020, 6:50 a.m. UTC | #3
On 2/18/20 1:05 AM, Rick Chen wrote:
> Hi Sean
> 
>> From: U-Boot [mailto:u-boot-bounces at lists.denx.de] On Behalf Of Sean Anderson
>> Sent: Tuesday, February 11, 2020 2:04 PM
>> To: u-boot at lists.denx.de
>> Cc: Rick Chen; Eugeniy Paltsev
>> Subject: [PATCH v4 06/17] spi: dw: Add device tree properties for fields in CTRL1
>>
>> Some devices have different layouts for the fields in CTRL1 (e.g. the Kendryte K210). Allow this layout to be configurable from the device tree.
> 
> The description of CTRL1 here don't match with the below content of CTRL0.
> Is it a typo ?

Yes. I will fix the message in the next revision.

--Sean
diff mbox series

Patch

diff --git a/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt b/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
new file mode 100644
index 0000000000..4b6152f6b7
--- /dev/null
+++ b/doc/device-tree-bindings/spi/snps,dw-apb-ssi.txt
@@ -0,0 +1,43 @@ 
+Synopsys DesignWare AMBA 2.0 Synchronous Serial Interface.
+
+Required properties:
+- compatible : "snps,dw-apb-ssi"
+- reg : The register base for the controller. For "mscc,<soc>-spi", a second
+  register set is required (named ICPU_CFG:SPI_MST)
+- #address-cells : <1>, as required by generic SPI binding.
+- #size-cells : <0>, also as required by generic SPI binding.
+- clocks : phandles for the clocks, see the description of clock-names below.
+   The phandle for the "ssi_clk" is required. The phandle for the "pclk" clock
+   is optional. If a single clock is specified but no clock-name, it is the
+   "ssi_clk" clock. If both clocks are listed, the "ssi_clk" must be first.
+
+Optional properties:
+- clock-names : Contains the names of the clocks:
+    "ssi_clk", for the core clock used to generate the external SPI clock.
+    "pclk", the interface clock, required for register access.
+- cs-gpios : Specifies the gpio pins to be used for chipselects.
+- num-cs : The number of chipselects. If omitted, this will default to 4.
+- reg-io-width : The I/O register width (in bytes) implemented by this
+  device.  Supported values are 2 or 4 (the default).
+- snps,dfs-offset The offset in bits of the DFS field in CTRL0, defaulting to 0
+- snps,frf-offset The offset in bits of the FRF field in CTRL0, defaulting to 4
+- snps,tmod-offset The offset in bits of the tmode field in CTRL0, defaulting
+  to 6
+- snps,mode-offset The offset in bits of the work mode field in CTRL0,
+  defaulting to 8
+
+Child nodes as per the generic SPI binding.
+
+Example:
+
+	spi at fff00000 {
+		compatible = "snps,dw-apb-ssi";
+		reg = <0xfff00000 0x1000>;
+		interrupts = <0 154 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&spi_m_clk>;
+		num-cs = <2>;
+		cs-gpios = <&gpio0 13 0>,
+			   <&gpio0 14 0>;
+	};
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 66ff8eeccd..04cc873754 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -3,6 +3,7 @@ 
  * Designware master SPI core controller driver
  *
  * Copyright (C) 2014 Stefan Roese <sr at denx.de>
+ * Copyright (C) 2020 Sean Anderson <seanga2 at gmail.com>
  *
  * Very loosely based on the Linux driver:
  * drivers/spi/spi-dw.c, which is:
@@ -50,20 +51,14 @@ 
 #define DW_SPI_DR			0x60
 
 /* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
 #define SPI_FRF_SPI			0x0
 #define SPI_FRF_SSP			0x1
 #define SPI_FRF_MICROWIRE		0x2
 #define SPI_FRF_RESV			0x3
 
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
+#define SPI_MODE_SCPH			0x1
+#define SPI_MODE_SCOL			0x2
 
-#define SPI_TMOD_OFFSET			8
-#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
 #define	SPI_TMOD_TR			0x0		/* xmit & recv */
 #define SPI_TMOD_TO			0x1		/* xmit only */
 #define SPI_TMOD_RO			0x2		/* recv only */
@@ -88,6 +83,12 @@ 
 struct dw_spi_platdata {
 	s32 frequency;		/* Default clock frequency, -1 for none */
 	void __iomem *regs;
+
+	/* Offsets in CTRL0 */
+	u8 dfs_off;
+	u8 frf_off;
+	u8 tmod_off;
+	u8 mode_off;
 };
 
 struct dw_spi_priv {
@@ -114,6 +115,15 @@  struct dw_spi_priv {
 	struct reset_ctl_bulk	resets;
 };
 
+static inline u32 GEN_CTRL0(struct dw_spi_priv *priv,
+			    struct dw_spi_platdata *plat)
+{
+	return ((priv->bits_per_word - 1) << plat->dfs_off |
+	      (priv->type << plat->frf_off) |
+	      (priv->mode << plat->mode_off) |
+	      (priv->tmode << plat->tmod_off));
+}
+
 static inline u32 dw_read(struct dw_spi_priv *priv, u32 offset)
 {
 	return __raw_readl(priv->regs + offset);
@@ -159,6 +169,10 @@  static int dw_spi_ofdata_to_platdata(struct udevice *bus)
 	/* Use 500KHz as a suitable default */
 	plat->frequency = dev_read_u32_default(bus, "spi-max-frequency",
 					       500000);
+	plat->dfs_off = dev_read_u32_default(bus, "snps,dfs-offset", 0);
+	plat->frf_off = dev_read_u32_default(bus, "snps,frf-offset", 4);
+	plat->mode_off = dev_read_u32_default(bus, "snps,mode-offset", 6);
+	plat->tmod_off = dev_read_u32_default(bus, "snps,tmod-offset", 8);
 	debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs,
 	      plat->frequency);
 
@@ -387,6 +401,7 @@  static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		       const void *dout, void *din, unsigned long flags)
 {
 	struct udevice *bus = dev->parent;
+	struct dw_spi_platdata *plat = dev_get_platdata(bus);
 	struct dw_spi_priv *priv = dev_get_priv(bus);
 	const u8 *tx = dout;
 	u8 *rx = din;
@@ -405,10 +420,6 @@  static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
 	if (flags & SPI_XFER_BEGIN)
 		external_cs_manage(dev, false);
 
-	cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) |
-		(priv->mode << SPI_MODE_OFFSET) |
-		(priv->tmode << SPI_TMOD_OFFSET);
-
 	if (rx && tx)
 		priv->tmode = SPI_TMOD_TR;
 	else if (rx)
@@ -420,8 +431,7 @@  static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
 		 */
 		priv->tmode = SPI_TMOD_TR;
 
-	cr0 &= ~SPI_TMOD_MASK;
-	cr0 |= (priv->tmode << SPI_TMOD_OFFSET);
+	cr0 = GEN_CTRL0(priv, plat);
 
 	priv->len = bitlen >> 3;
 	debug("%s: rx=%p tx=%p len=%d [bytes]\n", __func__, rx, tx, priv->len);
@@ -475,7 +485,7 @@  static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen,
 
 static int dw_spi_set_speed(struct udevice *bus, uint speed)
 {
-	struct dw_spi_platdata *plat = bus->platdata;
+	struct dw_spi_platdata *plat = dev_get_platdata(bus);
 	struct dw_spi_priv *priv = dev_get_priv(bus);
 	u16 clk_div;