Hi Sean > From: U-Boot [mailto:u-boot-boun...@lists.denx.de] On Behalf Of Sean Anderson > Sent: Tuesday, February 11, 2020 2:04 PM > To: u-boot@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 <sean...@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@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 <s...@denx.de> > + * Copyright (C) 2020 Sean Anderson <sean...@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 >