Unverified Commit b0b71a6f authored by Mark Brown's avatar Mark Brown
Browse files

Merge series "spi: Adding support for Microchip Sparx5 SoC" from Lars Povlsen...

Merge series "spi: Adding support for Microchip Sparx5 SoC" from Lars Povlsen <lars.povlsen@microchip.com>:

The series add support for the Sparx5 SoC SPI controller in the
spi-dw-mmio.c spi driver.

v5 changes:
- rx-sample-delay-ns documentation changes from Rob Herring:
 - Drop superfluous type $ref
 - Add default value = 0

v4 changes:
- Changed snps,rx-sample-delay-ns to snps,rx-sample-delay-ns
  suggested by Rob Herring (rockchip also has this property).
- Added support for controller-level rx-sample-delay-ns value as
  well as per SPI slave value (rockchip has controller-level property).
- Dropped internal mux in favor of suggested spi-mux to
  control bus inteface selection.

v3 changes:
- Added mux support for controlling SPI bus interface. This is new mux
  driver, bindings and added to sparx5 base DT.
- Removed "microchip,spi-interface2" property in favour of
  "mux-controls" property in SPI controller (sparx5 only).
- Changed dw_spi_sparx5_set_cs() to use the mux control instead of
  directly acessing "mux" register. Associated code/defines moved to mux
  driver.
- Changed dw_spi_sparx5_set_cs() to match other similar functions in
  signature and avoid explicit CS toggling.
- Spun off duplicated NAND device DT chunks into separate DT file.

v2 changes:
- Moved all RX sample delay into spi-dw-core.c, using
  the "snps,rx-sample-delay-ns" device property.
- Integrated Sparx5 support directly in spi-dw-mmio.c
- Changed SPI2 configuration to per-slave "microchip,spi-interface2"
  property.
- Added bindings to existing snps,dw-apb-ssi.yaml file
- Dropped patches for polled mode and SPI memory operations.

Lars Povlsen (6):
  spi: dw: Add support for RX sample delay register
  spi: dw: Add Microchip Sparx5 support
  arm64: dts: sparx5: Add SPI controller and associated mmio-mux
  dt-bindings: snps,dw-apb-ssi: Add sparx5 support, plus
    rx-sample-delay-ns property
  arm64: dts: sparx5: Add spi-nor support
  arm64: dts: sparx5: Add spi-nand devices

 .../bindings/spi/snps,dw-apb-ssi.yaml         | 21 ++++++
 arch/arm64/boot/dts/microchip/sparx5.dtsi     | 47 ++++++++++++-
 .../arm64/boot/dts/microchip/sparx5_nand.dtsi | 31 ++++++++
 .../boot/dts/microchip/sparx5_pcb125.dts      | 30 ++++++++
 .../boot/dts/microchip/sparx5_pcb134.dts      |  1 +
 .../dts/microchip/sparx5_pcb134_board.dtsi    | 16 +++++
 .../boot/dts/microchip/sparx5_pcb135.dts      |  1 +
 .../dts/microchip/sparx5_pcb135_board.dtsi    | 16 +++++
 drivers/spi/spi-dw-core.c                     | 26 +++++++
 drivers/spi/spi-dw-mmio.c                     | 70 ++++++++++++++++++-
 drivers/spi/spi-dw.h                          |  3 +
 11 files changed, 260 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm64/boot/dts/microchip/sparx5_nand.dtsi

--
2.27.0

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
parents a59b2c7c 5ce78f44
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ properties:
              - mscc,ocelot-spi
              - mscc,jaguar2-spi
          - const: snps,dw-apb-ssi
      - description: Microchip Sparx5 SoC SPI Controller
        const: microchip,sparx5-spi
      - description: Amazon Alpine SPI Controller
        const: amazon,alpine-dw-apb-ssi
      - description: Renesas RZ/N1 SPI Controller
@@ -93,6 +95,12 @@ properties:
      - const: tx
      - const: rx

  rx-sample-delay-ns:
    default: 0
    description: Default value of the rx-sample-delay-ns property.
      This value will be used if the property is not explicitly defined
      for a SPI slave device. See below.

patternProperties:
  "^.*@[0-9a-f]+$":
    type: object
@@ -107,6 +115,13 @@ patternProperties:
      spi-tx-bus-width:
        const: 1

      rx-sample-delay-ns:
        description: SPI Rx sample delay offset, unit is nanoseconds.
          The delay from the default sample time before the actual
          sample of the rxd input signal occurs. The "rx_sample_delay"
          is an optional feature of the designware controller, and the
          upper limit is also subject to controller configuration.

unevaluatedProperties: false

required:
@@ -129,5 +144,11 @@ examples:
      num-cs = <2>;
      cs-gpios = <&gpio0 13 0>,
                 <&gpio0 14 0>;
      rx-sample-delay-ns = <3>;
      spi-flash@1 {
        compatible = "spi-nand";
        reg = <1>;
        rx-sample-delay-ns = <7>;
      };
    };
...
+26 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/of.h>

#include "spi-dw.h"

@@ -26,6 +27,8 @@ struct chip_data {

	u16 clk_div;		/* baud rate divider */
	u32 speed_hz;		/* baud rate */

	u32 rx_sample_dly;	/* RX sample delay */
};

#ifdef CONFIG_DEBUG_FS
@@ -52,6 +55,7 @@ static const struct debugfs_reg32 dw_spi_dbgfs_regs[] = {
	DW_SPI_DBGFS_REG("DMACR", DW_SPI_DMACR),
	DW_SPI_DBGFS_REG("DMATDLR", DW_SPI_DMATDLR),
	DW_SPI_DBGFS_REG("DMARDLR", DW_SPI_DMARDLR),
	DW_SPI_DBGFS_REG("RX_SAMPLE_DLY", DW_SPI_RX_SAMPLE_DLY),
};

static int dw_spi_debugfs_init(struct dw_spi *dws)
@@ -328,6 +332,12 @@ static int dw_spi_transfer_one(struct spi_controller *master,
	if (master->can_dma && master->can_dma(master, spi, transfer))
		dws->dma_mapped = master->cur_msg_mapped;

	/* Update RX sample delay if required */
	if (dws->cur_rx_sample_dly != chip->rx_sample_dly) {
		dw_writel(dws, DW_SPI_RX_SAMPLE_DLY, chip->rx_sample_dly);
		dws->cur_rx_sample_dly = chip->rx_sample_dly;
	}

	/* For poll mode just disable all interrupts */
	spi_mask_intr(dws, 0xff);

@@ -380,10 +390,22 @@ static int dw_spi_setup(struct spi_device *spi)
	/* Only alloc on first setup */
	chip = spi_get_ctldata(spi);
	if (!chip) {
		struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
		u32 rx_sample_dly_ns;

		chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL);
		if (!chip)
			return -ENOMEM;
		spi_set_ctldata(spi, chip);
		/* Get specific / default rx-sample-delay */
		if (device_property_read_u32(&spi->dev,
					     "rx-sample-delay-ns",
					     &rx_sample_dly_ns) != 0)
			/* Use default controller value */
			rx_sample_dly_ns = dws->def_rx_sample_dly_ns;
		chip->rx_sample_dly = DIV_ROUND_CLOSEST(rx_sample_dly_ns,
							NSEC_PER_SEC /
							dws->max_freq);
	}

	chip->tmode = SPI_TMOD_TR;
@@ -472,6 +494,10 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
	if (dws->set_cs)
		master->set_cs = dws->set_cs;

	/* Get default rx sample delay */
	device_property_read_u32(dev, "rx-sample-delay-ns",
				 &dws->def_rx_sample_dly_ns);

	/* Basic HW init */
	spi_hw_init(dev, dws);

+69 −1
Original line number Diff line number Diff line
@@ -45,6 +45,9 @@ struct dw_spi_mmio {
#define MSCC_SPI_MST_SW_MODE_SW_PIN_CTRL_MODE	BIT(13)
#define MSCC_SPI_MST_SW_MODE_SW_SPI_CS(x)	(x << 5)

#define SPARX5_FORCE_ENA			0xa4
#define SPARX5_FORCE_VAL			0xa8

/*
 * For Keem Bay, CTRLR0[31] is used to select controller mode.
 * 0: SSI is slave
@@ -54,7 +57,7 @@ struct dw_spi_mmio {

struct dw_spi_mscc {
	struct regmap       *syscon;
	void __iomem        *spi_mst;
	void __iomem        *spi_mst; /* Not sparx5 */
};

/*
@@ -134,6 +137,70 @@ static int dw_spi_mscc_jaguar2_init(struct platform_device *pdev,
				JAGUAR2_IF_SI_OWNER_OFFSET);
}

/*
 * The Designware SPI controller (referred to as master in the
 * documentation) automatically deasserts chip select when the tx fifo
 * is empty. The chip selects then needs to be driven by a CS override
 * register. enable is an active low signal.
 */
static void dw_spi_sparx5_set_cs(struct spi_device *spi, bool enable)
{
	struct dw_spi *dws = spi_master_get_devdata(spi->master);
	struct dw_spi_mmio *dwsmmio = container_of(dws, struct dw_spi_mmio, dws);
	struct dw_spi_mscc *dwsmscc = dwsmmio->priv;
	u8 cs = spi->chip_select;

	if (!enable) {
		/* CS override drive enable */
		regmap_write(dwsmscc->syscon, SPARX5_FORCE_ENA, 1);
		/* Now set CSx enabled */
		regmap_write(dwsmscc->syscon, SPARX5_FORCE_VAL, ~BIT(cs));
		/* Allow settle */
		usleep_range(1, 5);
	} else {
		/* CS value */
		regmap_write(dwsmscc->syscon, SPARX5_FORCE_VAL, ~0);
		/* Allow settle */
		usleep_range(1, 5);
		/* CS override drive disable */
		regmap_write(dwsmscc->syscon, SPARX5_FORCE_ENA, 0);
	}

	dw_spi_set_cs(spi, enable);
}

static int dw_spi_mscc_sparx5_init(struct platform_device *pdev,
				   struct dw_spi_mmio *dwsmmio)
{
	const char *syscon_name = "microchip,sparx5-cpu-syscon";
	struct device *dev = &pdev->dev;
	struct dw_spi_mscc *dwsmscc;

	if (!IS_ENABLED(CONFIG_SPI_MUX)) {
		dev_err(dev, "This driver needs CONFIG_SPI_MUX\n");
		return -EOPNOTSUPP;
	}

	dwsmscc = devm_kzalloc(dev, sizeof(*dwsmscc), GFP_KERNEL);
	if (!dwsmscc)
		return -ENOMEM;

	dwsmscc->syscon =
		syscon_regmap_lookup_by_compatible(syscon_name);
	if (IS_ERR(dwsmscc->syscon)) {
		dev_err(dev, "No syscon map %s\n", syscon_name);
		return PTR_ERR(dwsmscc->syscon);
	}

	dwsmmio->dws.set_cs = dw_spi_sparx5_set_cs;
	dwsmmio->priv = dwsmscc;

	/* Register hook to configure CTRLR0 */
	dwsmmio->dws.update_cr0 = dw_spi_update_cr0;

	return 0;
}

static int dw_spi_alpine_init(struct platform_device *pdev,
			      struct dw_spi_mmio *dwsmmio)
{
@@ -297,6 +364,7 @@ static const struct of_device_id dw_spi_mmio_of_match[] = {
	{ .compatible = "renesas,rzn1-spi", .data = dw_spi_dw_apb_init},
	{ .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},
	{ /* end of table */}
};
MODULE_DEVICE_TABLE(of, dw_spi_mmio_of_match);
+3 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#define DW_SPI_IDR			0x58
#define DW_SPI_VERSION			0x5c
#define DW_SPI_DR			0x60
#define DW_SPI_RX_SAMPLE_DLY		0xf0
#define DW_SPI_CS_OVERRIDE		0xf4

/* Bit fields in CTRLR0 */
@@ -140,6 +141,8 @@ struct dw_spi {
	u8			n_bytes;	/* current is a 1/2 bytes op */
	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
	u32			current_freq;	/* frequency in hz */
	u32			cur_rx_sample_dly;
	u32			def_rx_sample_dly_ns;

	/* DMA info */
	struct dma_chan		*txchan;