Unverified Commit 09fd04da authored by Mark Brown's avatar Mark Brown
Browse files

Add RZ/G3E xSPI support

Merge series from Biju Das <biju.das.jz@bp.renesas.com>:

The xSPI IP found on RZ/G3E SoC similar to RPC-IF interface, but it
can support writes on memory-mapped area. Even though the registers are
different, the rpcif driver code can be reused for xSPI by adding wrapper
functions.
parents 9fbae052 b0b8d3ae
Loading
Loading
Loading
Loading
+135 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/memory-controllers/renesas,rzg3e-xspi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Renesas Expanded Serial Peripheral Interface (xSPI)

maintainers:
  - Biju Das <biju.das.jz@bp.renesas.com>

description: |
  Renesas xSPI allows a SPI flash connected to the SoC to be accessed via
  the memory-mapping or the manual command mode.

  The flash chip itself should be represented by a subnode of the XSPI node.
  The flash interface is selected based on the "compatible" property of this
  subnode:
  -  "jedec,spi-nor";

allOf:
  - $ref: /schemas/spi/spi-controller.yaml#

properties:
  compatible:
    const: renesas,r9a09g047-xspi  # RZ/G3E

  reg:
    items:
      - description: xSPI registers
      - description: direct mapping area

  reg-names:
    items:
      - const: regs
      - const: dirmap

  interrupts:
    items:
      - description: Interrupt pulse signal by factors excluding errors
      - description: Interrupt pulse signal by error factors

  interrupt-names:
    items:
      - const: pulse
      - const: err_pulse

  clocks:
    items:
      - description: AHB clock
      - description: AXI clock
      - description: SPI clock
      - description: Double speed SPI clock

  clock-names:
    items:
      - const: ahb
      - const: axi
      - const: spi
      - const: spix2

  power-domains:
    maxItems: 1

  resets:
    items:
      - description: Hardware reset
      - description: AXI reset

  reset-names:
    items:
      - const: hresetn
      - const: aresetn

  renesas,xspi-cs-addr-sys:
    $ref: /schemas/types.yaml#/definitions/phandle
    description: |
      Phandle to the system controller (sys) that allows to configure
      xSPI CS0 and CS1 addresses.

patternProperties:
  "flash@[0-9a-f]+$":
    type: object
    additionalProperties: true

    properties:
      compatible:
        contains:
          const: jedec,spi-nor

required:
  - compatible
  - reg
  - reg-names
  - interrupts
  - interrupt-names
  - clocks
  - clock-names
  - power-domains
  - resets
  - reset-names
  - '#address-cells'
  - '#size-cells'

unevaluatedProperties: false

examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>
    #include <dt-bindings/clock/renesas,r9a09g047-cpg.h>

    spi@11030000 {
        compatible = "renesas,r9a09g047-xspi";
        reg = <0x11030000 0x10000>, <0x20000000 0x10000000>;
        reg-names = "regs", "dirmap";
        interrupts = <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
                     <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>;
        interrupt-names = "pulse", "err_pulse";
        clocks = <&cpg CPG_MOD 0x9f>, <&cpg CPG_MOD 0xa0>,
                 <&cpg CPG_CORE 9>, <&cpg CPG_MOD 0xa1>;
        clock-names = "ahb", "axi", "spi", "spix2";
        power-domains = <&cpg>;
        resets = <&cpg 0xa3>, <&cpg 0xa4>;
        reset-names = "hresetn", "aresetn";
        #address-cells = <1>;
        #size-cells = <0>;

        flash@0 {
          compatible = "jedec,spi-nor";
          reg = <0>;
          spi-max-frequency = <40000000>;
          spi-tx-bus-width = <1>;
          spi-rx-bus-width = <1>;
        };
    };
+147 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * R-Car RPC Interface Registers Definitions
 *
 * Copyright (C) 2025 Renesas Electronics Corporation
 */

#ifndef __RENESAS_RPC_IF_REGS_H__
#define __RENESAS_RPC_IF_REGS_H__

#include <linux/bits.h>

#define RPCIF_CMNCR		0x0000	/* R/W */
#define RPCIF_CMNCR_MD		BIT(31)
#define RPCIF_CMNCR_MOIIO3(val)	(((val) & 0x3) << 22)
#define RPCIF_CMNCR_MOIIO2(val)	(((val) & 0x3) << 20)
#define RPCIF_CMNCR_MOIIO1(val)	(((val) & 0x3) << 18)
#define RPCIF_CMNCR_MOIIO0(val)	(((val) & 0x3) << 16)
#define RPCIF_CMNCR_MOIIO(val)	(RPCIF_CMNCR_MOIIO0(val) | RPCIF_CMNCR_MOIIO1(val) | \
				 RPCIF_CMNCR_MOIIO2(val) | RPCIF_CMNCR_MOIIO3(val))
#define RPCIF_CMNCR_IO3FV(val)	(((val) & 0x3) << 14) /* documented for RZ/G2L */
#define RPCIF_CMNCR_IO2FV(val)	(((val) & 0x3) << 12) /* documented for RZ/G2L */
#define RPCIF_CMNCR_IO0FV(val)	(((val) & 0x3) << 8)
#define RPCIF_CMNCR_IOFV(val)	(RPCIF_CMNCR_IO0FV(val) | RPCIF_CMNCR_IO2FV(val) | \
				 RPCIF_CMNCR_IO3FV(val))
#define RPCIF_CMNCR_BSZ(val)	(((val) & 0x3) << 0)

#define RPCIF_SSLDR		0x0004	/* R/W */
#define RPCIF_SSLDR_SPNDL(d)	(((d) & 0x7) << 16)
#define RPCIF_SSLDR_SLNDL(d)	(((d) & 0x7) << 8)
#define RPCIF_SSLDR_SCKDL(d)	(((d) & 0x7) << 0)

#define RPCIF_DRCR		0x000C	/* R/W */
#define RPCIF_DRCR_SSLN		BIT(24)
#define RPCIF_DRCR_RBURST(v)	((((v) - 1) & 0x1F) << 16)
#define RPCIF_DRCR_RCF		BIT(9)
#define RPCIF_DRCR_RBE		BIT(8)
#define RPCIF_DRCR_SSLE		BIT(0)

#define RPCIF_DRCMR		0x0010	/* R/W */
#define RPCIF_DRCMR_CMD(c)	(((c) & 0xFF) << 16)
#define RPCIF_DRCMR_OCMD(c)	(((c) & 0xFF) << 0)

#define RPCIF_DREAR		0x0014	/* R/W */
#define RPCIF_DREAR_EAV(c)	(((c) & 0xF) << 16)
#define RPCIF_DREAR_EAC(c)	(((c) & 0x7) << 0)

#define RPCIF_DROPR		0x0018	/* R/W */

#define RPCIF_DRENR		0x001C	/* R/W */
#define RPCIF_DRENR_CDB(o)	(((u32)((o) & 0x3)) << 30)
#define RPCIF_DRENR_OCDB(o)	(((o) & 0x3) << 28)
#define RPCIF_DRENR_ADB(o)	(((o) & 0x3) << 24)
#define RPCIF_DRENR_OPDB(o)	(((o) & 0x3) << 20)
#define RPCIF_DRENR_DRDB(o)	(((o) & 0x3) << 16)
#define RPCIF_DRENR_DME		BIT(15)
#define RPCIF_DRENR_CDE		BIT(14)
#define RPCIF_DRENR_OCDE	BIT(12)
#define RPCIF_DRENR_ADE(v)	(((v) & 0xF) << 8)
#define RPCIF_DRENR_OPDE(v)	(((v) & 0xF) << 4)

#define RPCIF_SMCR		0x0020	/* R/W */
#define RPCIF_SMCR_SSLKP	BIT(8)
#define RPCIF_SMCR_SPIRE	BIT(2)
#define RPCIF_SMCR_SPIWE	BIT(1)
#define RPCIF_SMCR_SPIE		BIT(0)

#define RPCIF_SMCMR		0x0024	/* R/W */
#define RPCIF_SMCMR_CMD(c)	(((c) & 0xFF) << 16)
#define RPCIF_SMCMR_OCMD(c)	(((c) & 0xFF) << 0)

#define RPCIF_SMADR		0x0028	/* R/W */

#define RPCIF_SMOPR		0x002C	/* R/W */
#define RPCIF_SMOPR_OPD3(o)	(((o) & 0xFF) << 24)
#define RPCIF_SMOPR_OPD2(o)	(((o) & 0xFF) << 16)
#define RPCIF_SMOPR_OPD1(o)	(((o) & 0xFF) << 8)
#define RPCIF_SMOPR_OPD0(o)	(((o) & 0xFF) << 0)

#define RPCIF_SMENR		0x0030	/* R/W */
#define RPCIF_SMENR_CDB(o)	(((o) & 0x3) << 30)
#define RPCIF_SMENR_OCDB(o)	(((o) & 0x3) << 28)
#define RPCIF_SMENR_ADB(o)	(((o) & 0x3) << 24)
#define RPCIF_SMENR_OPDB(o)	(((o) & 0x3) << 20)
#define RPCIF_SMENR_SPIDB(o)	(((o) & 0x3) << 16)
#define RPCIF_SMENR_DME		BIT(15)
#define RPCIF_SMENR_CDE		BIT(14)
#define RPCIF_SMENR_OCDE	BIT(12)
#define RPCIF_SMENR_ADE(v)	(((v) & 0xF) << 8)
#define RPCIF_SMENR_OPDE(v)	(((v) & 0xF) << 4)
#define RPCIF_SMENR_SPIDE(v)	(((v) & 0xF) << 0)

#define RPCIF_SMRDR0		0x0038	/* R */
#define RPCIF_SMRDR1		0x003C	/* R */
#define RPCIF_SMWDR0		0x0040	/* W */
#define RPCIF_SMWDR1		0x0044	/* W */

#define RPCIF_CMNSR		0x0048	/* R */
#define RPCIF_CMNSR_SSLF	BIT(1)
#define RPCIF_CMNSR_TEND	BIT(0)

#define RPCIF_DRDMCR		0x0058	/* R/W */
#define RPCIF_DMDMCR_DMCYC(v)	((((v) - 1) & 0x1F) << 0)

#define RPCIF_DRDRENR		0x005C	/* R/W */
#define RPCIF_DRDRENR_HYPE(v)	(((v) & 0x7) << 12)
#define RPCIF_DRDRENR_ADDRE	BIT(8)
#define RPCIF_DRDRENR_OPDRE	BIT(4)
#define RPCIF_DRDRENR_DRDRE	BIT(0)

#define RPCIF_SMDMCR		0x0060	/* R/W */
#define RPCIF_SMDMCR_DMCYC(v)	((((v) - 1) & 0x1F) << 0)

#define RPCIF_SMDRENR		0x0064	/* R/W */
#define RPCIF_SMDRENR_HYPE(v)	(((v) & 0x7) << 12)
#define RPCIF_SMDRENR_ADDRE	BIT(8)
#define RPCIF_SMDRENR_OPDRE	BIT(4)
#define RPCIF_SMDRENR_SPIDRE	BIT(0)

#define RPCIF_PHYADD		0x0070	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */
#define RPCIF_PHYWR		0x0074	/* R/W available on R-Car E3/D3/V3M and RZ/G2{E,L} */

#define RPCIF_PHYCNT		0x007C	/* R/W */
#define RPCIF_PHYCNT_CAL	BIT(31)
#define RPCIF_PHYCNT_OCTA(v)	(((v) & 0x3) << 22)
#define RPCIF_PHYCNT_EXDS	BIT(21)
#define RPCIF_PHYCNT_OCT	BIT(20)
#define RPCIF_PHYCNT_DDRCAL	BIT(19)
#define RPCIF_PHYCNT_HS		BIT(18)
#define RPCIF_PHYCNT_CKSEL(v)	(((v) & 0x3) << 16) /* valid only for RZ/G2L */
#define RPCIF_PHYCNT_STRTIM(v)	(((v) & 0x7) << 15 | ((v) & 0x8) << 24) /* valid for R-Car and RZ/G2{E,H,M,N} */

#define RPCIF_PHYCNT_WBUF2	BIT(4)
#define RPCIF_PHYCNT_WBUF	BIT(2)
#define RPCIF_PHYCNT_PHYMEM(v)	(((v) & 0x3) << 0)
#define RPCIF_PHYCNT_PHYMEM_MASK GENMASK(1, 0)

#define RPCIF_PHYOFFSET1	0x0080	/* R/W */
#define RPCIF_PHYOFFSET1_DDRTMG(v) (((v) & 0x3) << 28)

#define RPCIF_PHYOFFSET2	0x0084	/* R/W */
#define RPCIF_PHYOFFSET2_OCTTMG(v) (((v) & 0x7) << 8)

#define RPCIF_PHYINT		0x0088	/* R/W */
#define RPCIF_PHYINT_WPVAL	BIT(1)

#endif /* __RENESAS_RPC_IF_REGS_H__ */
+523 −191

File changed.

Preview size limit exceeded, changes collapsed.

+105 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * RZ xSPI Interface Registers Definitions
 *
 * Copyright (C) 2025 Renesas Electronics Corporation
 */

#ifndef __RENESAS_XSPI_IF_REGS_H__
#define __RENESAS_XSPI_IF_REGS_H__

#include <linux/bits.h>

/* xSPI Wrapper Configuration Register */
#define XSPI_WRAPCFG		0x0000

/* xSPI Bridge Configuration Register */
#define XSPI_BMCFG		0x0008
#define XSPI_BMCFG_WRMD		BIT(0)
#define XSPI_BMCFG_MWRCOMB	BIT(7)
#define XSPI_BMCFG_MWRSIZE(val)	(((val) & 0xff) << 8)
#define XSPI_BMCFG_PREEN	BIT(16)

/* xSPI Command Map Configuration Register 0 CS0 */
#define XSPI_CMCFG0CS0		0x0010
#define XSPI_CMCFG0_FFMT(val)		(((val) & 0x03) << 0)
#define XSPI_CMCFG0_ADDSIZE(val)	(((val) & 0x03) << 2)

/* xSPI Command Map Configuration Register 1 CS0 */
#define XSPI_CMCFG1CS0		0x0014
#define XSPI_CMCFG1_RDCMD(val)	(((val) & 0xffff) << 0)
#define XSPI_CMCFG1_RDCMD_UPPER_BYTE(val)	(((val) & 0xff) << 8)
#define XSPI_CMCFG1_RDLATE(val)	(((val) & 0x1f) << 16)

/* xSPI Command Map Configuration Register 2 CS0 */
#define XSPI_CMCFG2CS0		0x0018
#define XSPI_CMCFG2_WRCMD(val)	(((val) & 0xffff) << 0)
#define XSPI_CMCFG2_WRCMD_UPPER(val)	(((val) & 0xff) << 8)
#define XSPI_CMCFG2_WRLATE(val)	(((val) & 0x1f) << 16)

/* xSPI Link I/O Configuration Register CS0 */
#define XSPI_LIOCFGCS0		0x0050
#define XSPI_LIOCFG_PRTMD(val)	(((val) & 0x3ff) << 0)
#define XSPI_LIOCFG_CSMIN(val)	(((val) & 0x0f) << 16)
#define XSPI_LIOCFG_CSASTEX	BIT(20)
#define XSPI_LIOCFG_CSNEGEX	BIT(21)

/* xSPI Bridge Map Control Register 0 */
#define XSPI_BMCTL0		0x0060
#define XSPI_BMCTL0_CS0ACC(val)	(((val) & 0x03) << 0)

/* xSPI Bridge Map Control Register 1 */
#define XSPI_BMCTL1		0x0064
#define XSPI_BMCTL1_MWRPUSH	BIT(8)

/* xSPI Command Manual Control Register 0 */
#define XSPI_CDCTL0		0x0070
#define XSPI_CDCTL0_TRREQ	BIT(0)
#define XSPI_CDCTL0_CSSEL	BIT(3)
#define XSPI_CDCTL0_TRNUM(val)	(((val) & 0x03) << 4)

/* xSPI Command Manual Type Buf */
#define XSPI_CDTBUF0		0x0080
#define XSPI_CDTBUF_CMDSIZE(val)	(((val) & 0x03) << 0)
#define XSPI_CDTBUF_ADDSIZE(val)	(((val) & 0x07) << 2)
#define XSPI_CDTBUF_DATASIZE(val)	(((val) & 0x0f) << 5)
#define XSPI_CDTBUF_LATE(val)		(((val) & 0x1f) << 9)
#define XSPI_CDTBUF_TRTYPE	BIT(15)
#define XSPI_CDTBUF_CMD(val)		(((val) & 0xffff) << 16)
#define XSPI_CDTBUF_CMD_FIELD(val)	(((val) & 0xff) << 24)

/* xSPI Command Manual Address Buff */
#define XSPI_CDABUF0		0x0084

/* xSPI Command Manual Data 0 Buf */
#define XSPI_CDD0BUF0		0x0088

/* xSPI Command Manual Data 1 Buf */
#define XSPI_CDD1BUF0		0x008c

/* xSPI Command Calibration Control Register 0 CS0 */
#define XSPI_CCCTL0CS0		0x0130
#define XSPI_CCCTL0_CAEN	BIT(0)

/* xSPI Interrupt Status Register */
#define XSPI_INTS		0x0190
#define XSPI_INTS_CMDCMP	BIT(0)

/* xSPI Interrupt Clear Register */
#define XSPI_INTC		0x0194
#define XSPI_INTC_CMDCMPC	BIT(0)

/* xSPI Interrupt Enable Register */
#define XSPI_INTE		0x0198
#define XSPI_INTE_CMDCMPE	BIT(0)

/* Maximum data size of MWRSIZE*/
#define MWRSIZE_MAX		64

/* xSPI Protocol mode */
#define PROTO_1S_2S_2S		0x48
#define PROTO_2S_2S_2S		0x49
#define PROTO_1S_4S_4S		0x090
#define PROTO_4S_4S_4S		0x092

#endif /* __RENESAS_XSPI_IF_REGS_H__ */
+15 −1
Original line number Diff line number Diff line
@@ -75,6 +75,19 @@ static bool rpcif_spi_mem_supports_op(struct spi_mem *mem,
	return true;
}

static ssize_t xspi_spi_mem_dirmap_write(struct spi_mem_dirmap_desc *desc,
					 u64 offs, size_t len, const void *buf)
{
	struct rpcif *rpc = spi_controller_get_devdata(desc->mem->spi->controller);

	if (offs + desc->info.offset + len > U32_MAX)
		return -EINVAL;

	rpcif_spi_mem_prepare(desc->mem->spi, &desc->info.op_tmpl, &offs, &len);

	return xspi_dirmap_write(rpc->dev, offs, len, buf);
}

static ssize_t rpcif_spi_mem_dirmap_read(struct spi_mem_dirmap_desc *desc,
					 u64 offs, size_t len, void *buf)
{
@@ -103,7 +116,7 @@ static int rpcif_spi_mem_dirmap_create(struct spi_mem_dirmap_desc *desc)
	if (!rpc->dirmap)
		return -EOPNOTSUPP;

	if (desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
	if (!rpc->xspi && desc->info.op_tmpl.data.dir != SPI_MEM_DATA_IN)
		return -EOPNOTSUPP;

	return 0;
@@ -125,6 +138,7 @@ static const struct spi_controller_mem_ops rpcif_spi_mem_ops = {
	.exec_op	= rpcif_spi_mem_exec_op,
	.dirmap_create	= rpcif_spi_mem_dirmap_create,
	.dirmap_read	= rpcif_spi_mem_dirmap_read,
	.dirmap_write	= xspi_spi_mem_dirmap_write,
};

static int rpcif_spi_probe(struct platform_device *pdev)
Loading