This patch series is adding support for additional
Marvell HW overlay build on top of Cadence xSPI IP
It includes:
- Clock and PHY configuration
- ACPI support
- Additional MRVL HW overlay to support tranfer operations
Piyush Malgujar (1):
driver: spi: cadence: Add ACPI support
Witold Sadowski (4):
spi: cadence: Add new bindings documentation for Cadence XSPI
spi: cadence: Add Marvell IP modification changes
spi: cadence: Force single modebyte
cadence-xspi: Add xfer capabilities
.../devicetree/bindings/spi/cdns,xspi.yaml | 84 ++-
drivers/spi/spi-cadence-xspi.c | 675 +++++++++++++++++-
2 files changed, 738 insertions(+), 21 deletions(-)
--
2.17.1
This patch series is adding support for second version of Marvell HW
overlay for Cadence xSPI IP block.
Overlay extends xSPI features, with clock configuration, interrupt
masking and full-duplex, variable length SPI operations.
All that functionalites allows xSPI block to operate not only with
memory devices, but also with simple SPI devices, or TPM devices.
Piyush Malgujar (1):
spi: cadence: Allow to read basic xSPI configuration from ACPI
Witold Sadowski (4):
spi: cadence: Ensure data lines set to low during dummy-cycle period
spi: cadence: Add MRVL overlay bindings documentation for Cadence XSPI
spi: cadence: Add Marvell xSPI IP overlay changes
spi: cadence: Add MRVL overlay xfer operation support
.../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++-
drivers/spi/spi-cadence-xspi.c | 691 +++++++++++++++++-
2 files changed, 762 insertions(+), 21 deletions(-)
--
2.43.0
From: Piyush Malgujar <[email protected]>
These changes enables to read the configs from ACPI tables as required
for successful probing in ACPI uefi environment.
In case of ACPI disabled/dts based environment, it will continue to
read configs from dts as before
Signed-off-by: Piyush Malgujar <[email protected]>
Signed-off-by: Witold Sadowski <[email protected]>
---
drivers/spi/spi-cadence-xspi.c | 97 +++++++++++++++++++++++++++++++---
1 file changed, 90 insertions(+), 7 deletions(-)
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index 5d36f9177f3c..e4ebfad8a1cb 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -2,6 +2,7 @@
// Cadence XSPI flash controller driver
// Copyright (C) 2020-21 Cadence
+#include <linux/acpi.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/err.h>
@@ -14,6 +15,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/spi/spi.h>
#include <linux/spi/spi-mem.h>
#include <linux/bitfield.h>
@@ -700,6 +702,67 @@ static int cdns_xspi_mem_op(struct cdns_xspi_dev *cdns_xspi,
(dir != SPI_MEM_NO_DATA));
}
+#ifdef CONFIG_ACPI
+static bool cdns_xspi_supports_op(struct spi_mem *mem,
+ const struct spi_mem_op *op)
+{
+ struct spi_device *spi = mem->spi;
+ const union acpi_object *obj;
+ struct acpi_device *adev;
+
+ adev = ACPI_COMPANION(&spi->dev);
+
+ if (!acpi_dev_get_property(adev, "spi-tx-bus-width", ACPI_TYPE_INTEGER,
+ &obj)) {
+ switch (obj->integer.value) {
+ case 1:
+ break;
+ case 2:
+ spi->mode |= SPI_TX_DUAL;
+ break;
+ case 4:
+ spi->mode |= SPI_TX_QUAD;
+ break;
+ case 8:
+ spi->mode |= SPI_TX_OCTAL;
+ break;
+ default:
+ dev_warn(&spi->dev,
+ "spi-tx-bus-width %lld not supported\n",
+ obj->integer.value);
+ break;
+ }
+ }
+
+ if (!acpi_dev_get_property(adev, "spi-rx-bus-width", ACPI_TYPE_INTEGER,
+ &obj)) {
+ switch (obj->integer.value) {
+ case 1:
+ break;
+ case 2:
+ spi->mode |= SPI_RX_DUAL;
+ break;
+ case 4:
+ spi->mode |= SPI_RX_QUAD;
+ break;
+ case 8:
+ spi->mode |= SPI_RX_OCTAL;
+ break;
+ default:
+ dev_warn(&spi->dev,
+ "spi-rx-bus-width %lld not supported\n",
+ obj->integer.value);
+ break;
+ }
+ }
+
+ if (!spi_mem_default_supports_op(mem, op))
+ return false;
+
+ return true;
+}
+#endif
+
static int cdns_xspi_mem_op_execute(struct spi_mem *mem,
const struct spi_mem_op *op)
{
@@ -723,6 +786,9 @@ static int cdns_xspi_adjust_mem_op_size(struct spi_mem *mem, struct spi_mem_op *
}
static const struct spi_controller_mem_ops cadence_xspi_mem_ops = {
+#ifdef CONFIG_ACPI
+ .supports_op = cdns_xspi_supports_op,
+#endif
.exec_op = cdns_xspi_mem_op_execute,
.adjust_op_size = cdns_xspi_adjust_mem_op_size,
};
@@ -774,21 +840,20 @@ static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev)
static int cdns_xspi_of_get_plat_data(struct platform_device *pdev)
{
- struct device_node *node_prop = pdev->dev.of_node;
- struct device_node *node_child;
+ struct fwnode_handle *fwnode_child;
unsigned int cs;
- for_each_child_of_node(node_prop, node_child) {
- if (!of_device_is_available(node_child))
+ device_for_each_child_node(&pdev->dev, fwnode_child) {
+ if (!fwnode_device_is_available(fwnode_child))
continue;
- if (of_property_read_u32(node_child, "reg", &cs)) {
+ if (fwnode_property_read_u32(fwnode_child, "reg", &cs)) {
dev_err(&pdev->dev, "Couldn't get memory chip select\n");
- of_node_put(node_child);
+ fwnode_handle_put(fwnode_child);
return -ENXIO;
} else if (cs >= CDNS_XSPI_MAX_BANKS) {
dev_err(&pdev->dev, "reg (cs) parameter value too large\n");
- of_node_put(node_child);
+ fwnode_handle_put(fwnode_child);
return -ENXIO;
}
}
@@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cdns_xspi_acpi_match[] = {
+ {
+ .id = "cdns,xspi-nor",
+ .driver_data = (kernel_ulong_t) &cdns_driver_data,
+ },
+ {
+ .id = "mrvl,xspi-nor",
+ .driver_data = (kernel_ulong_t) &mrvl_driver_data,
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, cdns_xspi_acpi_match);
+#endif
+
static const struct of_device_id cdns_xspi_of_match[] = {
{
.compatible = "cdns,xspi-nor",
@@ -942,6 +1022,9 @@ static struct platform_driver cdns_xspi_platform_driver = {
.driver = {
.name = CDNS_XSPI_NAME,
.of_match_table = cdns_xspi_of_match,
+#ifdef CONFIG_ACPI
+ .acpi_match_table = cdns_xspi_acpi_match,
+#endif
},
};
--
2.43.0
Add new bindings for v2 Marvell xSPI overlay:
mrvl,xspi-nor compatible string
New compatible string to distinguish between orginal and modified xSPI
block
PHY configuration registers
Allow to change orginal xSPI PHY configuration values. If not set, and
Marvell overlay is enabled, safe defaults will be written into xSPI PHY
Optional base for xfer register set
Additional reg field to allocate xSPI Marvell overlay XFER block
Signed-off-by: Witold Sadowski <[email protected]>
---
.../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
1 file changed, 91 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
index eb0f92468185..0e608245b136 100644
--- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
+++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
@@ -20,23 +20,82 @@ allOf:
properties:
compatible:
- const: cdns,xspi-nor
+ oneOf:
+ - description: Vanilla Cadence xSPI controller
+ items:
+ - const: cdns,xspi-nor
+ - description: Cadence xSPI controller with v2 Marvell overlay
+ items:
+ - const: mrvl,xspi-nor
+
reg:
+ minItems: 3
items:
- description: address and length of the controller register set
- description: address and length of the Slave DMA data port
- description: address and length of the auxiliary registers
+ - description: address and length of the xfer registers
reg-names:
+ minItems: 3
items:
- const: io
- const: sdma
- const: aux
+ - const: xferbase
interrupts:
maxItems: 1
+ cdns,dll-phy-control:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x707
+
+ cdns,rfile-phy-control:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x40000
+
+ cdns,rfile-phy-tsel:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+
+ cdns,phy-dq-timing:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x101
+
+ cdns,phy-dqs-timing:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x700404
+
+ cdns,phy-gate-lpbk-ctrl:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x200030
+
+ cdns,phy-dll-master-ctrl:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x00800000
+
+ cdns,phy-dll-slave-ctrl:
+ description: |
+ PHY config register. Valid only for cdns,mrvl-xspi-nor
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0x0000ff01
+
required:
- compatible
- reg
@@ -68,6 +127,37 @@ examples:
reg = <0>;
};
+ flash@1 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <75000000>;
+ reg = <1>;
+ };
+ };
+ };
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ mrvl_xspi: spi@d0010000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mrvl,xspi-nor";
+ reg = <0x0 0xa0010000 0x0 0x1040>,
+ <0x0 0xb0000000 0x0 0x1000>,
+ <0x0 0xa0020000 0x0 0x100>,
+ <0x0 0xa0090000 0x0 0x100>;
+ reg-names = "io", "sdma", "aux", "xferbase";
+ interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <75000000>;
+ reg = <0>;
+ };
+
flash@1 {
compatible = "jedec,spi-nor";
spi-max-frequency = <75000000>;
--
2.43.0
Add support for basic v2 Marvell overlay block. Support for basic
operation is added here: clock configuration, PHY configuration,
interrupt configuration(enabling)
Clock divider block is build on top of Cadence xSPI IP, and divides
external 800MHz clock. It allows only for a few different clock speeds
starting from 6.25MHz up to 200MHz.
PHY configuration can be read from device-tree, if parameter is not
present - safe defaults will be used..
In addition to handle interrupt propoerly driver must clear MSI-X
interrupt bit, in addition to clearing xSPI interrupt bit. Interrupt
masking must be disabled.
Signed-off-by: Witold Sadowski <[email protected]>
---
drivers/spi/spi-cadence-xspi.c | 326 ++++++++++++++++++++++++++++++++-
1 file changed, 318 insertions(+), 8 deletions(-)
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index cdce2e280f66..5d36f9177f3c 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -193,6 +193,44 @@
((op)->data.dir == SPI_MEM_DATA_IN) ? \
CDNS_XSPI_STIG_CMD_DIR_READ : CDNS_XSPI_STIG_CMD_DIR_WRITE))
+/*PHY default values*/
+#define REGS_DLL_PHY_CTRL 0x00000707
+#define CTB_RFILE_PHY_CTRL 0x00004000
+#define RFILE_PHY_TSEL 0x00000000
+#define RFILE_PHY_DQ_TIMING 0x00000101
+#define RFILE_PHY_DQS_TIMING 0x00700404
+#define RFILE_PHY_GATE_LPBK_CTRL 0x00200030
+#define RFILE_PHY_DLL_MASTER_CTRL 0x00800000
+#define RFILE_PHY_DLL_SLAVE_CTRL 0x0000ff01
+
+/*PHY config rtegisters*/
+#define CDNS_XSPI_RF_MINICTRL_REGS_DLL_PHY_CTRL 0x1034
+#define CDNS_XSPI_PHY_CTB_RFILE_PHY_CTRL 0x0080
+#define CDNS_XSPI_PHY_CTB_RFILE_PHY_TSEL 0x0084
+#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQ_TIMING 0x0000
+#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQS_TIMING 0x0004
+#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_GATE_LPBK_CTRL 0x0008
+#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DLL_MASTER_CTRL 0x000c
+#define CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DLL_SLAVE_CTRL 0x0010
+#define CDNS_XSPI_DATASLICE_RFILE_PHY_DLL_OBS_REG_0 0x001c
+
+#define CDNS_XSPI_DLL_RST_N BIT(24)
+#define CDNS_XSPI_DLL_LOCK BIT(0)
+
+/* Marvell clock config register */
+#define CDNS_MRVL_XSPI_CLK_CTRL_AUX_REG 0x2020
+#define CDNS_MRVL_XSPI_CLK_ENABLE BIT(0)
+#define CDNS_MRVL_XSPI_CLK_DIV GENMASK(4, 1)
+#define CDNS_MRVL_XSPI_IRQ_ENABLE BIT(6)
+
+/* Marvell MSI-X clear interrupt register */
+#define CDNS_MRVL_XSPI_SPIX_INTR_AUX 0x2000
+#define CDNS_MRVL_MSIX_CLEAR_IRQ 0x01
+
+/* Marvell clock macros */
+#define CDNS_MRVL_XSPI_CLOCK_IO_HZ 800000000
+#define CDNS_MRVL_XSPI_CLOCK_DIVIDED(div) ((CDNS_MRVL_XSPI_CLOCK_IO_HZ) / (div))
+
enum cdns_xspi_stig_instr_type {
CDNS_XSPI_STIG_INSTR_TYPE_0,
CDNS_XSPI_STIG_INSTR_TYPE_1,
@@ -212,6 +250,7 @@ enum cdns_xspi_stig_cmd_dir {
struct cdns_xspi_dev {
struct platform_device *pdev;
struct device *dev;
+ bool mrvl_hw_overlay;
void __iomem *iobase;
void __iomem *auxbase;
@@ -232,6 +271,170 @@ struct cdns_xspi_dev {
u8 hw_num_banks;
};
+struct cdns_xspi_driver_data {
+ bool mrvl_hw_overlay;
+};
+
+static struct cdns_xspi_driver_data mrvl_driver_data = {
+ .mrvl_hw_overlay = true,
+};
+
+static struct cdns_xspi_driver_data cdns_driver_data = {
+ .mrvl_hw_overlay = false,
+};
+
+#define MRVL_DEFAULT_CLK 25000000
+
+const int cdns_mrvl_xspi_clk_div_list[] = {
+ 4, //0x0 = Divide by 4. SPI clock is 200 MHz.
+ 6, //0x1 = Divide by 6. SPI clock is 133.33 MHz.
+ 8, //0x2 = Divide by 8. SPI clock is 100 MHz.
+ 10, //0x3 = Divide by 10. SPI clock is 80 MHz.
+ 12, //0x4 = Divide by 12. SPI clock is 66.666 MHz.
+ 16, //0x5 = Divide by 16. SPI clock is 50 MHz.
+ 18, //0x6 = Divide by 18. SPI clock is 44.44 MHz.
+ 20, //0x7 = Divide by 20. SPI clock is 40 MHz.
+ 24, //0x8 = Divide by 24. SPI clock is 33.33 MHz.
+ 32, //0x9 = Divide by 32. SPI clock is 25 MHz.
+ 40, //0xA = Divide by 40. SPI clock is 20 MHz.
+ 50, //0xB = Divide by 50. SPI clock is 16 MHz.
+ 64, //0xC = Divide by 64. SPI clock is 12.5 MHz.
+ 128, //0xD = Divide by 128. SPI clock is 6.25 MHz.
+ -1 //End of list
+};
+
+static bool cdns_xspi_reset_dll(struct cdns_xspi_dev *cdns_xspi)
+{
+ u32 dll_cntrl = readl(cdns_xspi->iobase +
+ CDNS_XSPI_RF_MINICTRL_REGS_DLL_PHY_CTRL);
+ u32 dll_lock;
+
+ /*Reset DLL*/
+ dll_cntrl |= CDNS_XSPI_DLL_RST_N;
+ writel(dll_cntrl, cdns_xspi->iobase +
+ CDNS_XSPI_RF_MINICTRL_REGS_DLL_PHY_CTRL);
+
+ /*Wait for DLL lock*/
+ return readl_relaxed_poll_timeout(cdns_xspi->iobase +
+ CDNS_XSPI_INTR_STATUS_REG,
+ dll_lock, ((dll_lock & CDNS_XSPI_DLL_LOCK) == 1), 10, 10000);
+}
+
+static void cdns_configure_phy_register_io(struct cdns_xspi_dev *cdns_xspi,
+ const char *prop_name,
+ u64 default_value, u64 offset)
+{
+ struct device_node *node_prop = cdns_xspi->pdev->dev.of_node;
+ u64 phy_cfg;
+
+ if (of_property_read_u64(node_prop, prop_name, &phy_cfg))
+ phy_cfg = default_value;
+ writel(phy_cfg,
+ cdns_xspi->iobase + offset);
+}
+
+static void cdns_configure_phy_register_aux(struct cdns_xspi_dev *cdns_xspi,
+ const char *prop_name,
+ u64 default_value, u64 offset)
+{
+ struct device_node *node_prop = cdns_xspi->pdev->dev.of_node;
+ u64 phy_cfg;
+
+ if (of_property_read_u64(node_prop, "cdns,dll-phy-control", &phy_cfg))
+ phy_cfg = default_value;
+ writel(phy_cfg,
+ cdns_xspi->auxbase + offset);
+}
+
+//Static confiuration of PHY
+static bool cdns_xspi_configure_phy(struct cdns_xspi_dev *cdns_xspi)
+{
+ cdns_configure_phy_register_io(cdns_xspi,
+ "cdns,dll-phy-control",
+ REGS_DLL_PHY_CTRL,
+ CDNS_XSPI_RF_MINICTRL_REGS_DLL_PHY_CTRL);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,rfile-phy-control",
+ CTB_RFILE_PHY_CTRL,
+ CDNS_XSPI_PHY_CTB_RFILE_PHY_CTRL);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,rfile-phy-tsel",
+ RFILE_PHY_TSEL,
+ CDNS_XSPI_PHY_CTB_RFILE_PHY_TSEL);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,phy-dq-timing",
+ RFILE_PHY_DQ_TIMING,
+ CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQ_TIMING);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,phy-dqs-timing",
+ RFILE_PHY_DQS_TIMING,
+ CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DQS_TIMING);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,phy-gate-lpbk-ctrl",
+ RFILE_PHY_GATE_LPBK_CTRL,
+ CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_GATE_LPBK_CTRL);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,phy-dll-master-ctrl",
+ RFILE_PHY_DLL_MASTER_CTRL,
+ CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_GATE_LPBK_CTRL);
+ cdns_configure_phy_register_aux(cdns_xspi,
+ "cdns,phy-dll-slave-ctrl",
+ RFILE_PHY_DLL_SLAVE_CTRL,
+ CDNS_XSPI_PHY_DATASLICE_RFILE_PHY_DLL_SLAVE_CTRL);
+
+ return cdns_xspi_reset_dll(cdns_xspi);
+}
+
+// Find max avalible clock
+static bool cdns_mrvl_xspi_setup_clock(struct cdns_xspi_dev *cdns_xspi,
+ int requested_clk)
+{
+ int i = 0;
+ int clk_val;
+ u32 clk_reg;
+ bool update_clk = false;
+
+ while (cdns_mrvl_xspi_clk_div_list[i] > 0) {
+ clk_val = CDNS_MRVL_XSPI_CLOCK_DIVIDED(
+ cdns_mrvl_xspi_clk_div_list[i]);
+ if (clk_val <= requested_clk)
+ break;
+ i++;
+ }
+
+ if (cdns_mrvl_xspi_clk_div_list[i] == -1) {
+ dev_info(cdns_xspi->dev,
+ "Unable to find clk div for CLK: %d - using 6.25MHz\n",
+ requested_clk);
+ i = 0x0D;
+ } else {
+ dev_dbg(cdns_xspi->dev, "Found clk div: %d, clk val: %d\n",
+ cdns_mrvl_xspi_clk_div_list[i],
+ CDNS_MRVL_XSPI_CLOCK_DIVIDED(
+ cdns_mrvl_xspi_clk_div_list[i]));
+ }
+
+ clk_reg = readl(cdns_xspi->auxbase + CDNS_MRVL_XSPI_CLK_CTRL_AUX_REG);
+
+ if (FIELD_GET(CDNS_MRVL_XSPI_CLK_DIV, clk_reg) != i) {
+ clk_reg &= ~CDNS_MRVL_XSPI_CLK_ENABLE;
+ writel(clk_reg,
+ cdns_xspi->auxbase + CDNS_MRVL_XSPI_CLK_CTRL_AUX_REG);
+ clk_reg = FIELD_PREP(CDNS_MRVL_XSPI_CLK_DIV, i);
+ clk_reg &= ~CDNS_MRVL_XSPI_CLK_DIV;
+ clk_reg |= FIELD_PREP(CDNS_MRVL_XSPI_CLK_DIV, i);
+ clk_reg |= CDNS_MRVL_XSPI_CLK_ENABLE;
+ clk_reg |= CDNS_MRVL_XSPI_IRQ_ENABLE;
+ update_clk = true;
+ }
+
+ if (update_clk)
+ writel(clk_reg,
+ cdns_xspi->auxbase + CDNS_MRVL_XSPI_CLK_CTRL_AUX_REG);
+
+ return update_clk;
+}
+
static int cdns_xspi_wait_for_controller_idle(struct cdns_xspi_dev *cdns_xspi)
{
u32 ctrl_stat;
@@ -295,6 +498,10 @@ static void cdns_xspi_set_interrupts(struct cdns_xspi_dev *cdns_xspi,
bool enabled)
{
u32 intr_enable;
+ u32 irq_status;
+
+ irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+ writel(irq_status, cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
intr_enable = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_ENABLE_REG);
if (enabled)
@@ -319,6 +526,9 @@ static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
return -EIO;
}
+ writel(FIELD_PREP(CDNS_XSPI_CTRL_WORK_MODE, CDNS_XSPI_WORK_MODE_STIG),
+ cdns_xspi->iobase + CDNS_XSPI_CTRL_CONFIG_REG);
+
ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
cdns_xspi_set_interrupts(cdns_xspi, false);
@@ -326,6 +536,70 @@ static int cdns_xspi_controller_init(struct cdns_xspi_dev *cdns_xspi)
return 0;
}
+static void mrvl_ioreadq(void __iomem *addr, void *buf, int len)
+{
+ int i = 0;
+ int rcount = len / 8;
+ int rcount_nf = len % 8;
+ uint64_t tmp;
+ uint64_t *buf64 = (uint64_t *)buf;
+
+ if (((uint64_t)buf % 8) == 0) {
+ for (i = 0; i < rcount; i++)
+ *buf64++ = readq(addr);
+ } else {
+ for (i = 0; i < rcount; i++) {
+ tmp = readq(addr);
+ memcpy(buf+(i*8), &tmp, 8);
+ }
+ }
+
+ if (rcount_nf != 0) {
+ tmp = readq(addr);
+ memcpy(buf+(i*8), &tmp, rcount_nf);
+ }
+}
+
+static void mrvl_iowriteq(void __iomem *addr, const void *buf, int len)
+{
+ int i = 0;
+ int rcount = len / 8;
+ int rcount_nf = len % 8;
+ uint64_t tmp;
+ uint64_t *buf64 = (uint64_t *)buf;
+
+ if (((uint64_t)buf % 8) == 0) {
+ for (i = 0; i < rcount; i++)
+ writeq(*buf64++, addr);
+ } else {
+ for (i = 0; i < rcount; i++) {
+ memcpy(&tmp, buf+(i*8), 8);
+ writeq(tmp, addr);
+ }
+ }
+
+ if (rcount_nf != 0) {
+ memcpy(&tmp, buf+(i*8), rcount_nf);
+ writeq(tmp, addr);
+ }
+}
+
+static void cdns_xspi_sdma_memread(struct cdns_xspi_dev *cdns_xspi, int len)
+{
+ if (cdns_xspi->mrvl_hw_overlay)
+ mrvl_ioreadq(cdns_xspi->sdmabase, cdns_xspi->in_buffer, len);
+ else
+ ioread8_rep(cdns_xspi->sdmabase, cdns_xspi->in_buffer, len);
+}
+
+static void cdns_xspi_sdma_memwrite(struct cdns_xspi_dev *cdns_xspi, int len)
+{
+ if (cdns_xspi->mrvl_hw_overlay)
+ mrvl_iowriteq(cdns_xspi->sdmabase, cdns_xspi->out_buffer, len);
+ else
+ iowrite8_rep(cdns_xspi->sdmabase, cdns_xspi->out_buffer, len);
+}
+
static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
{
u32 sdma_size, sdma_trd_info;
@@ -337,13 +611,11 @@ static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
switch (sdma_dir) {
case CDNS_XSPI_SDMA_DIR_READ:
- ioread8_rep(cdns_xspi->sdmabase,
- cdns_xspi->in_buffer, sdma_size);
+ cdns_xspi_sdma_memread(cdns_xspi, sdma_size);
break;
case CDNS_XSPI_SDMA_DIR_WRITE:
- iowrite8_rep(cdns_xspi->sdmabase,
- cdns_xspi->out_buffer, sdma_size);
+ cdns_xspi_sdma_memwrite(cdns_xspi, sdma_size);
break;
}
}
@@ -421,6 +693,9 @@ static int cdns_xspi_mem_op(struct cdns_xspi_dev *cdns_xspi,
if (cdns_xspi->cur_cs != spi_get_chipselect(mem->spi, 0))
cdns_xspi->cur_cs = spi_get_chipselect(mem->spi, 0);
+ if (cdns_xspi->mrvl_hw_overlay)
+ cdns_mrvl_xspi_setup_clock(cdns_xspi, mem->spi->max_speed_hz);
+
return cdns_xspi_send_stig_command(cdns_xspi, op,
(dir != SPI_MEM_NO_DATA));
}
@@ -461,6 +736,10 @@ static irqreturn_t cdns_xspi_irq_handler(int this_irq, void *dev)
irq_status = readl(cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
writel(irq_status, cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG);
+ if (cdns_xspi->mrvl_hw_overlay)
+ writel(CDNS_MRVL_MSIX_CLEAR_IRQ,
+ cdns_xspi->auxbase + CDNS_MRVL_XSPI_SPIX_INTR_AUX);
+
if (irq_status &
(CDNS_XSPI_SDMA_ERROR | CDNS_XSPI_SDMA_TRIGGER |
CDNS_XSPI_STIG_DONE)) {
@@ -534,11 +813,23 @@ static void cdns_xspi_print_phy_config(struct cdns_xspi_dev *cdns_xspi)
readl(cdns_xspi->auxbase + CDNS_XSPI_CCP_PHY_DLL_SLAVE_CTRL));
}
+static int cdns_xspi_setup(struct spi_device *spi_dev)
+{
+ struct cdns_xspi_dev *cdns_xspi = spi_controller_get_devdata(
+ spi_dev->controller);
+
+ if (cdns_xspi->mrvl_hw_overlay)
+ cdns_mrvl_xspi_setup_clock(cdns_xspi, spi_dev->max_speed_hz);
+
+ return 0;
+}
+
static int cdns_xspi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct spi_controller *host = NULL;
struct cdns_xspi_dev *cdns_xspi = NULL;
+ const struct cdns_xspi_driver_data *drv_data;
struct resource *res;
int ret;
@@ -550,10 +841,16 @@ static int cdns_xspi_probe(struct platform_device *pdev)
SPI_RX_DUAL | SPI_RX_QUAD | SPI_TX_OCTAL | SPI_RX_OCTAL |
SPI_MODE_0 | SPI_MODE_3;
+ drv_data = of_device_get_match_data(dev);
+
host->mem_ops = &cadence_xspi_mem_ops;
host->dev.of_node = pdev->dev.of_node;
+ host->dev.fwnode = pdev->dev.fwnode;
host->bus_num = -1;
+ if (drv_data->mrvl_hw_overlay)
+ host->setup = cdns_xspi_setup;
+
platform_set_drvdata(pdev, host);
cdns_xspi = spi_controller_get_devdata(host);
@@ -565,23 +862,27 @@ static int cdns_xspi_probe(struct platform_device *pdev)
init_completion(&cdns_xspi->auto_cmd_complete);
init_completion(&cdns_xspi->sdma_complete);
+ cdns_xspi->mrvl_hw_overlay = drv_data->mrvl_hw_overlay;
+
ret = cdns_xspi_of_get_plat_data(pdev);
if (ret)
return -ENODEV;
- cdns_xspi->iobase = devm_platform_ioremap_resource_byname(pdev, "io");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ cdns_xspi->iobase = devm_ioremap_resource(dev, res);
if (IS_ERR(cdns_xspi->iobase)) {
dev_err(dev, "Failed to remap controller base address\n");
return PTR_ERR(cdns_xspi->iobase);
}
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sdma");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
cdns_xspi->sdmabase = devm_ioremap_resource(dev, res);
if (IS_ERR(cdns_xspi->sdmabase))
return PTR_ERR(cdns_xspi->sdmabase);
cdns_xspi->sdmasize = resource_size(res);
- cdns_xspi->auxbase = devm_platform_ioremap_resource_byname(pdev, "aux");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ cdns_xspi->auxbase = devm_ioremap_resource(dev, res);
if (IS_ERR(cdns_xspi->auxbase)) {
dev_err(dev, "Failed to remap AUX address\n");
return PTR_ERR(cdns_xspi->auxbase);
@@ -598,8 +899,12 @@ static int cdns_xspi_probe(struct platform_device *pdev)
return ret;
}
- cdns_xspi_print_phy_config(cdns_xspi);
+ if (drv_data->mrvl_hw_overlay) {
+ cdns_mrvl_xspi_setup_clock(cdns_xspi, MRVL_DEFAULT_CLK);
+ cdns_xspi_configure_phy(cdns_xspi);
+ }
+ cdns_xspi_print_phy_config(cdns_xspi);
ret = cdns_xspi_controller_init(cdns_xspi);
if (ret) {
dev_err(dev, "Failed to initialize controller\n");
@@ -622,6 +927,11 @@ static int cdns_xspi_probe(struct platform_device *pdev)
static const struct of_device_id cdns_xspi_of_match[] = {
{
.compatible = "cdns,xspi-nor",
+ .data = &cdns_driver_data,
+ },
+ {
+ .compatible = "mrvl,xspi-nor",
+ .data = &mrvl_driver_data,
},
{ /* end of table */}
};
--
2.43.0
MRVL Xfer overlay extend xSPI capabilities, to support non-memory SPI
operations. Marvell overlay combined with generic command allows to
create full-duplex SPI transactions. It also allows to create
transaction with undetermined transaction length - with cs_hold
parameter, and ability to extend CS signal assertion, even if xSPI block
requests CS signal de-assertion.
Signed-off-by: Witold Sadowski <[email protected]>
---
drivers/spi/spi-cadence-xspi.c | 248 +++++++++++++++++++++++++++++++++
1 file changed, 248 insertions(+)
diff --git a/drivers/spi/spi-cadence-xspi.c b/drivers/spi/spi-cadence-xspi.c
index e4ebfad8a1cb..1fc6760cfef7 100644
--- a/drivers/spi/spi-cadence-xspi.c
+++ b/drivers/spi/spi-cadence-xspi.c
@@ -219,20 +219,39 @@
#define CDNS_XSPI_DLL_RST_N BIT(24)
#define CDNS_XSPI_DLL_LOCK BIT(0)
+#define CDNS_XSPI_POLL_TIMEOUT_US 1000
+#define CDNS_XSPI_POLL_DELAY_US 10
+
/* Marvell clock config register */
#define CDNS_MRVL_XSPI_CLK_CTRL_AUX_REG 0x2020
#define CDNS_MRVL_XSPI_CLK_ENABLE BIT(0)
#define CDNS_MRVL_XSPI_CLK_DIV GENMASK(4, 1)
#define CDNS_MRVL_XSPI_IRQ_ENABLE BIT(6)
+
/* Marvell MSI-X clear interrupt register */
#define CDNS_MRVL_XSPI_SPIX_INTR_AUX 0x2000
#define CDNS_MRVL_MSIX_CLEAR_IRQ 0x01
+#define SPIX_XFER_FUNC_CTRL 0x210
+#define SPIX_XFER_FUNC_CTRL_READ_DATA(i) (0x000 + 8 * (i))
+
/* Marvell clock macros */
#define CDNS_MRVL_XSPI_CLOCK_IO_HZ 800000000
#define CDNS_MRVL_XSPI_CLOCK_DIVIDED(div) ((CDNS_MRVL_XSPI_CLOCK_IO_HZ) / (div))
+/* Marvell XFER registers */
+#define XFER_SOFT_RESET BIT(11)
+#define XFER_CS_N_HOLD GENMASK(9, 6)
+#define XFER_RECEIVE_ENABLE BIT(4)
+#define XFER_FUNC_ENABLE BIT(3)
+#define XFER_CLK_CAPTURE_POL BIT(2)
+#define XFER_CLK_DRIVE_POL BIT(1)
+#define XFER_FUNC_START BIT(0)
+
+#define XFER_QWORD_COUNT 32
+#define XFER_QWORD_BYTECOUNT 8
+
enum cdns_xspi_stig_instr_type {
CDNS_XSPI_STIG_INSTR_TYPE_0,
CDNS_XSPI_STIG_INSTR_TYPE_1,
@@ -257,6 +276,7 @@ struct cdns_xspi_dev {
void __iomem *iobase;
void __iomem *auxbase;
void __iomem *sdmabase;
+ void __iomem *xferbase;
int irq;
int cur_cs;
@@ -271,6 +291,9 @@ struct cdns_xspi_dev {
const void *out_buffer;
u8 hw_num_banks;
+
+ bool xfer_in_progress;
+ int current_xfer_qword;
};
struct cdns_xspi_driver_data {
@@ -889,6 +912,220 @@ static int cdns_xspi_setup(struct spi_device *spi_dev)
return 0;
}
+static int cdns_xspi_prepare_generic(int cs, const void *dout, int len, int glue, u32 *cmd_regs)
+{
+ u8 *data = (u8 *)dout;
+ int i;
+ int data_counter = 0;
+
+ memset(cmd_regs, 0x00, 6*4);
+
+ if (len > 7) {
+ for (i = (len >= 10 ? 2 : len - 8); i >= 0 ; i--)
+ cmd_regs[3] |= data[data_counter++] << (8*i);
+ }
+ if (len > 3) {
+ for (i = (len >= 7 ? 3 : len - 4); i >= 0; i--)
+ cmd_regs[2] |= data[data_counter++] << (8*i);
+ }
+ for (i = (len >= 3 ? 2 : len - 1); i >= 0 ; i--)
+ cmd_regs[1] |= data[data_counter++] << (8 + 8*i);
+
+ cmd_regs[1] |= 96;
+ cmd_regs[3] |= len << 24;
+ cmd_regs[4] |= cs << 12;
+
+ if (glue == 1)
+ cmd_regs[4] |= 1 << 28;
+
+ return 0;
+}
+
+static unsigned char reverse_bits(unsigned char num)
+{
+ unsigned int count = sizeof(num) * 8 - 1;
+ unsigned int reverse_num = num;
+
+ num >>= 1;
+ while (num) {
+ reverse_num <<= 1;
+ reverse_num |= num & 1;
+ num >>= 1;
+ count--;
+ }
+ reverse_num <<= count;
+ return reverse_num;
+}
+
+static void cdns_xspi_read_single_qword(struct cdns_xspi_dev *cdns_xspi, u8 **buffer)
+{
+ u64 d = readq(cdns_xspi->xferbase +
+ SPIX_XFER_FUNC_CTRL_READ_DATA(cdns_xspi->current_xfer_qword));
+ u8 *ptr = (u8 *)&d;
+ int k;
+
+ for (k = 0; k < 8; k++) {
+ u8 val = reverse_bits((ptr[k]));
+ **buffer = val;
+ *buffer = *buffer + 1;
+ }
+
+ cdns_xspi->current_xfer_qword++;
+ cdns_xspi->current_xfer_qword %= XFER_QWORD_COUNT;
+}
+
+static void cdns_xspi_finish_read(struct cdns_xspi_dev *cdns_xspi, u8 **buffer, u32 data_count)
+{
+ u64 d = readq(cdns_xspi->xferbase +
+ SPIX_XFER_FUNC_CTRL_READ_DATA(cdns_xspi->current_xfer_qword));
+ u8 *ptr = (u8 *)&d;
+ int k;
+
+ for (k = 0; k < data_count % XFER_QWORD_BYTECOUNT; k++) {
+ u8 val = reverse_bits((ptr[k]));
+ **buffer = val;
+ *buffer = *buffer + 1;
+ }
+
+ cdns_xspi->current_xfer_qword++;
+ cdns_xspi->current_xfer_qword %= XFER_QWORD_COUNT;
+}
+
+static int cdns_xspi_prepare_transfer(int cs, int dir, int len, u32 *cmd_regs)
+{
+ memset(cmd_regs, 0x00, 6*4);
+
+ cmd_regs[1] |= 127;
+ cmd_regs[2] |= len << 16;
+ cmd_regs[4] |= dir << 4; //dir = 0 read, dir =1 write
+ cmd_regs[4] |= cs << 12;
+
+ return 0;
+}
+
+static bool cdns_xspi_stig_ready(struct cdns_xspi_dev *cdns_xspi, bool sleep)
+{
+ u32 ctrl_stat;
+
+ return readl_relaxed_poll_timeout
+ (cdns_xspi->iobase + CDNS_XSPI_CTRL_STATUS_REG,
+ ctrl_stat,
+ ((ctrl_stat & BIT(3)) == 0),
+ sleep ? CDNS_XSPI_POLL_DELAY_US : 0,
+ sleep ? CDNS_XSPI_POLL_TIMEOUT_US : 0);
+}
+
+static bool cdns_xspi_sdma_ready(struct cdns_xspi_dev *cdns_xspi, bool sleep)
+{
+ u32 ctrl_stat;
+
+ return readl_relaxed_poll_timeout
+ (cdns_xspi->iobase + CDNS_XSPI_INTR_STATUS_REG,
+ ctrl_stat,
+ (ctrl_stat & CDNS_XSPI_SDMA_TRIGGER),
+ sleep ? CDNS_XSPI_POLL_DELAY_US : 0,
+ sleep ? CDNS_XSPI_POLL_TIMEOUT_US : 0);
+}
+
+static int cdns_xspi_transfer_one_message_b0(struct spi_controller *controller,
+ struct spi_message *m)
+{
+ struct cdns_xspi_dev *cdns_xspi = spi_controller_get_devdata(controller);
+ struct spi_device *spi = m->spi;
+ struct spi_transfer *t = NULL;
+
+ const int max_len = XFER_QWORD_BYTECOUNT * XFER_QWORD_COUNT;
+ int current_cycle_count;
+ int cs = spi_get_chipselect(spi, 0);
+ int cs_change = 0;
+
+ /* Enable xfer state machine */
+ if (!cdns_xspi->xfer_in_progress) {
+ u32 xfer_control = readl(cdns_xspi->xferbase + SPIX_XFER_FUNC_CTRL);
+
+ cdns_xspi->current_xfer_qword = 0;
+ cdns_xspi->xfer_in_progress = true;
+ xfer_control |= (XFER_RECEIVE_ENABLE |
+ XFER_CLK_CAPTURE_POL |
+ XFER_FUNC_START |
+ XFER_SOFT_RESET |
+ FIELD_PREP(XFER_CS_N_HOLD, (1 << cs)));
+ xfer_control &= ~(XFER_FUNC_ENABLE | XFER_CLK_DRIVE_POL);
+ writel(xfer_control, cdns_xspi->xferbase + SPIX_XFER_FUNC_CTRL);
+ }
+
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ u8 *txd = (u8 *) t->tx_buf;
+ u8 *rxd = (u8 *) t->rx_buf;
+ u8 data[10];
+ u32 cmd_regs[6];
+
+ if (!txd)
+ txd = data;
+
+ cdns_xspi->in_buffer = txd + 1;
+ cdns_xspi->out_buffer = txd + 1;
+
+ while (t->len) {
+
+ current_cycle_count = t->len > max_len ? max_len : t->len;
+
+ if (current_cycle_count < 10) {
+ cdns_xspi_prepare_generic(cs, txd, current_cycle_count,
+ false, cmd_regs);
+ cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
+ if (cdns_xspi_stig_ready(cdns_xspi, true))
+ return -EIO;
+ } else {
+ cdns_xspi_prepare_generic(cs, txd, 1, true, cmd_regs);
+ cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
+ cdns_xspi_prepare_transfer(cs, 1, current_cycle_count - 1,
+ cmd_regs);
+ cdns_xspi_trigger_command(cdns_xspi, cmd_regs);
+ if (cdns_xspi_sdma_ready(cdns_xspi, true))
+ return -EIO;
+ cdns_xspi_sdma_handle(cdns_xspi);
+ if (cdns_xspi_stig_ready(cdns_xspi, true))
+ return -EIO;
+
+ cdns_xspi->in_buffer += current_cycle_count;
+ cdns_xspi->out_buffer += current_cycle_count;
+ }
+
+ if (rxd) {
+ int j;
+
+ for (j = 0; j < current_cycle_count / 8; j++)
+ cdns_xspi_read_single_qword(cdns_xspi, &rxd);
+ cdns_xspi_finish_read(cdns_xspi, &rxd, current_cycle_count);
+ } else {
+ cdns_xspi->current_xfer_qword += current_cycle_count /
+ XFER_QWORD_BYTECOUNT;
+ if (current_cycle_count % XFER_QWORD_BYTECOUNT)
+ cdns_xspi->current_xfer_qword++;
+
+ cdns_xspi->current_xfer_qword %= XFER_QWORD_COUNT;
+ }
+ cs_change = t->cs_change;
+ t->len -= current_cycle_count;
+ }
+ }
+
+ if (!cs_change) {
+ u32 xfer_control = readl(cdns_xspi->xferbase + SPIX_XFER_FUNC_CTRL);
+
+ xfer_control &= ~(XFER_RECEIVE_ENABLE |
+ XFER_SOFT_RESET);
+ writel(xfer_control, cdns_xspi->xferbase + SPIX_XFER_FUNC_CTRL);
+ cdns_xspi->xfer_in_progress = false;
+ }
+
+ m->status = 0;
+ spi_finalize_current_message(controller);
+
+ return 0;
+}
+
static int cdns_xspi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -953,6 +1190,16 @@ static int cdns_xspi_probe(struct platform_device *pdev)
return PTR_ERR(cdns_xspi->auxbase);
}
+ if (drv_data->mrvl_hw_overlay) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ cdns_xspi->xferbase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(cdns_xspi->xferbase)) {
+ dev_info(dev, "XFER register base not found, set it\n");
+ // For compatibility with older firmware
+ cdns_xspi->xferbase = cdns_xspi->iobase + 0x8000;
+ }
+ }
+
cdns_xspi->irq = platform_get_irq(pdev, 0);
if (cdns_xspi->irq < 0)
return -ENXIO;
@@ -967,6 +1214,7 @@ static int cdns_xspi_probe(struct platform_device *pdev)
if (drv_data->mrvl_hw_overlay) {
cdns_mrvl_xspi_setup_clock(cdns_xspi, MRVL_DEFAULT_CLK);
cdns_xspi_configure_phy(cdns_xspi);
+ host->transfer_one_message = cdns_xspi_transfer_one_message_b0;
}
cdns_xspi_print_phy_config(cdns_xspi);
--
2.43.0
On Wed, Apr 17, 2024 at 06:13:49PM -0700, Witold Sadowski wrote:
> Add new bindings for v2 Marvell xSPI overlay:
> mrvl,xspi-nor compatible string
> New compatible string to distinguish between orginal and modified xSPI
> block
>
> PHY configuration registers
> Allow to change orginal xSPI PHY configuration values. If not set, and
> Marvell overlay is enabled, safe defaults will be written into xSPI PHY
>
> Optional base for xfer register set
> Additional reg field to allocate xSPI Marvell overlay XFER block
>
> Signed-off-by: Witold Sadowski <[email protected]>
> ---
> .../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
> 1 file changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> index eb0f92468185..0e608245b136 100644
> --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> @@ -20,23 +20,82 @@ allOf:
>
> properties:
> compatible:
> - const: cdns,xspi-nor
> + oneOf:
> + - description: Vanilla Cadence xSPI controller
> + items:
> + - const: cdns,xspi-nor
The "items: isn't required here is it? Can't you just have
oneOf:
- description: Vanilla Cadence xSPI controller
const: cdns,xspi-nor
- description: Cadence xSPI controller with v2 Marvell overlay
const: mrvl,xspi-nor
if you don't want to use an enum?
> + - description: Cadence xSPI controller with v2 Marvell overlay
> + items:
> + - const: mrvl,xspi-nor
"mrvl" is deprecated, please use "marvell". You're also missing a
soc-specific compatible here, I doubt there's only going to be one
device from marvell with an xspi controller ever.
> reg:
> + minItems: 3
> items:
> - description: address and length of the controller register set
> - description: address and length of the Slave DMA data port
> - description: address and length of the auxiliary registers
> + - description: address and length of the xfer registers
>
> reg-names:
> + minItems: 3
> items:
> - const: io
> - const: sdma
> - const: aux
> + - const: xferbase
Please constrain the 4th reg to only the marvell device.
>
> interrupts:
> maxItems: 1
>
> + cdns,dll-phy-control:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
Under what circumstances do you expect these things to change for a
particular SoC? If it's fixed per SoC, you could deduce it from the
compatible rather than needing properties.
None of these properties explain what they do and all appear to just
set register values directly, which is not generally something that we
permit in DT. Some explanation of how these values vary would help a
lot...
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x707
> +
> + cdns,rfile-phy-control:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
Please enforce constraints like which compatibles something is valid for
in the binding, not in free-form text.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x40000
> +
> + cdns,rfile-phy-tsel:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0
> +
> + cdns,phy-dq-timing:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x101
> +
> + cdns,phy-dqs-timing:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x700404
> +
> + cdns,phy-gate-lpbk-ctrl:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x200030
> +
> + cdns,phy-dll-master-ctrl:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x00800000
> +
> + cdns,phy-dll-slave-ctrl:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x0000ff01
> +
> required:
> - compatible
> - reg
> @@ -68,6 +127,37 @@ examples:
> reg = <0>;
> };
>
> + flash@1 {
> + compatible = "jedec,spi-nor";
> + spi-max-frequency = <75000000>;
> + reg = <1>;
> + };
> + };
> + };
> + - |
> + #include <dt-bindings/interrupt-controller/irq.h>
> + bus {
> + #address-cells = <2>;
> + #size-cells = <2>;
> +
> + mrvl_xspi: spi@d0010000 {
Drop the node label here, nothing ever refers to it.
Thanks,
Conor.
> + #address-cells = <1>;
> + #size-cells = <0>;
> + compatible = "mrvl,xspi-nor";
> + reg = <0x0 0xa0010000 0x0 0x1040>,
> + <0x0 0xb0000000 0x0 0x1000>,
> + <0x0 0xa0020000 0x0 0x100>,
> + <0x0 0xa0090000 0x0 0x100>;
> + reg-names = "io", "sdma", "aux", "xferbase";
> + interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
> + interrupt-parent = <&gic>;
> +
> + flash@0 {
> + compatible = "jedec,spi-nor";
> + spi-max-frequency = <75000000>;
> + reg = <0>;
> + };
> +
> flash@1 {
> compatible = "jedec,spi-nor";
> spi-max-frequency = <75000000>;
> --
> 2.43.0
>
On 18/04/2024 03:13, Witold Sadowski wrote:
> Add new bindings for v2 Marvell xSPI overlay:
> mrvl,xspi-nor compatible string
> New compatible string to distinguish between orginal and modified xSPI
> block
>
Do not attach (thread) your patchsets to some other threads (unrelated
or older versions). This buries them deep in the mailbox and might
interfere with applying entire sets.
> PHY configuration registers
> Allow to change orginal xSPI PHY configuration values. If not set, and
> Marvell overlay is enabled, safe defaults will be written into xSPI PHY
>
> Optional base for xfer register set
> Additional reg field to allocate xSPI Marvell overlay XFER block
>
> Signed-off-by: Witold Sadowski <[email protected]>
> ---
Please use subject prefixes matching the subsystem. You can get them for
example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
your patch is touching.
You already received *exactly* the same comment. Can you respond to
feedbacks and acknowledge that you will implement them?
Please provide changelog and explain what happened in between. There
were several comments already, so did you implement them? Were they ignored?
There was no single response from you.
> .../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
> 1 file changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> index eb0f92468185..0e608245b136 100644
> --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> @@ -20,23 +20,82 @@ allOf:
>
> properties:
> compatible:
> - const: cdns,xspi-nor
> + oneOf:
> + - description: Vanilla Cadence xSPI controller
> + items:
> + - const: cdns,xspi-nor
> + - description: Cadence xSPI controller with v2 Marvell overlay
> + items:
> + - const: mrvl,xspi-nor
> +
>
No need for two blank lines. BTW, that's just enum.
> reg:
> + minItems: 3
> items:
> - description: address and length of the controller register set
> - description: address and length of the Slave DMA data port
> - description: address and length of the auxiliary registers
> + - description: address and length of the xfer registers
>
> reg-names:
> + minItems: 3
> items:
> - const: io
> - const: sdma
> - const: aux
> + - const: xferbase
>
> interrupts:
> maxItems: 1
>
> + cdns,dll-phy-control:
> + description: |
Do not need '|' unless you need to preserve formatting.
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x707
> +
> + cdns,rfile-phy-control:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x40000
> +
> + cdns,rfile-phy-tsel:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0
> +
> + cdns,phy-dq-timing:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x101
> +
> + cdns,phy-dqs-timing:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x700404
> +
> + cdns,phy-gate-lpbk-ctrl:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x200030
> +
> + cdns,phy-dll-master-ctrl:
> + description: |
> + PHY config register. Valid only for cdns,mrvl-xspi-nor
> + $ref: /schemas/types.yaml#/definitions/uint32
> + default: 0x00800000
> +
> + cdns,phy-dll-slave-ctrl:
Please use some easier to read logical properties, not just register
values. Specifically, this is impossible to review whether any of these
are actually OS policy, instead of hardware configuration.
You also miss constraining these and reg per variant (but that was
mentioned by Conor, I think).
Best regards,
Krzysztof
On 18/04/2024 03:13, Witold Sadowski wrote:
> From: Piyush Malgujar <[email protected]>
>
> These changes enables to read the configs from ACPI tables as required
> for successful probing in ACPI uefi environment.
> In case of ACPI disabled/dts based environment, it will continue to
> read configs from dts as before
>
..
> }
> @@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device *pdev)
> return 0;
> }
>
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id cdns_xspi_acpi_match[] = {
> + {
> + .id = "cdns,xspi-nor",
> + .driver_data = (kernel_ulong_t) &cdns_driver_data,
> + },
> + {
> + .id = "mrvl,xspi-nor",
> + .driver_data = (kernel_ulong_t) &mrvl_driver_data,
UEFI provides compatibles for ACPI? I think that's first such format in
the kernel.
Best regards,
Krzysztof
Hi Witold,
kernel test robot noticed the following build warnings:
[auto build test WARNING on v6.9-rc4]
[also build test WARNING on linus/master next-20240418]
[cannot apply to broonie-spi/for-next]
[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#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Witold-Sadowski/spi-cadence-Ensure-data-lines-set-to-low-during-dummy-cycle-period/20240418-091647
base: v6.9-rc4
patch link: https://lore.kernel.org/r/20240418011353.1764672-4-wsadowski%40marvell.com
patch subject: [PATCH v3 3/5] spi: cadence: Add Marvell xSPI IP overlay changes
config: x86_64-randconfig-122-20240419 (https://download.01.org/0day-ci/archive/20240419/[email protected]/config)
compiler: gcc-13 (Ubuntu 13.2.0-4ubuntu3) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240419/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
sparse warnings: (new ones prefixed by >>)
>> drivers/spi/spi-cadence-xspi.c:288:11: sparse: sparse: symbol 'cdns_mrvl_xspi_clk_div_list' was not declared. Should it be static?
vim +/cdns_mrvl_xspi_clk_div_list +288 drivers/spi/spi-cadence-xspi.c
287
> 288 const int cdns_mrvl_xspi_clk_div_list[] = {
289 4, //0x0 = Divide by 4. SPI clock is 200 MHz.
290 6, //0x1 = Divide by 6. SPI clock is 133.33 MHz.
291 8, //0x2 = Divide by 8. SPI clock is 100 MHz.
292 10, //0x3 = Divide by 10. SPI clock is 80 MHz.
293 12, //0x4 = Divide by 12. SPI clock is 66.666 MHz.
294 16, //0x5 = Divide by 16. SPI clock is 50 MHz.
295 18, //0x6 = Divide by 18. SPI clock is 44.44 MHz.
296 20, //0x7 = Divide by 20. SPI clock is 40 MHz.
297 24, //0x8 = Divide by 24. SPI clock is 33.33 MHz.
298 32, //0x9 = Divide by 32. SPI clock is 25 MHz.
299 40, //0xA = Divide by 40. SPI clock is 20 MHz.
300 50, //0xB = Divide by 50. SPI clock is 16 MHz.
301 64, //0xC = Divide by 64. SPI clock is 12.5 MHz.
302 128, //0xD = Divide by 128. SPI clock is 6.25 MHz.
303 -1 //End of list
304 };
305
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
> On 18/04/2024 03:13, Witold Sadowski wrote:
> > From: Piyush Malgujar <[email protected]>
> >
> > These changes enables to read the configs from ACPI tables as required
> > for successful probing in ACPI uefi environment.
> > In case of ACPI disabled/dts based environment, it will continue to
> > read configs from dts as before
> >
>
> ...
>
> > }
> > @@ -924,6 +989,21 @@ static int cdns_xspi_probe(struct platform_device
> *pdev)
> > return 0;
> > }
> >
> > +#ifdef CONFIG_ACPI
> > +static const struct acpi_device_id cdns_xspi_acpi_match[] = {
> > + {
> > + .id = "cdns,xspi-nor",
> > + .driver_data = (kernel_ulong_t) &cdns_driver_data,
> > + },
> > + {
> > + .id = "mrvl,xspi-nor",
> > + .driver_data = (kernel_ulong_t) &mrvl_driver_data,
>
> UEFI provides compatibles for ACPI? I think that's first such format in
> the kernel.
Yes, that code is not doing what was expected.
Current usage scenario in ACPI mode is:
xSPI block with HID PRP0001, and additional compatible package set to
correct compatible string
With that approach only issue(in ACPI mode) is with matching device
with data field from of_device_id. It looks like there are functions
to match that when DTB is used, but in ACPI mode it fails.
I believe solution is to traverse dev->driver->of_match_table manually
To match device name with correct compatible data structure.
That will be included in next patchset.
>
> Best regards,
> Krzysztof
Regards
Witek
> ----------------------------------------------------------------------
> On 18/04/2024 03:13, Witold Sadowski wrote:
> > Add new bindings for v2 Marvell xSPI overlay:
> > mrvl,xspi-nor compatible string
> > New compatible string to distinguish between orginal and modified xSPI
> > block
> >
>
> Do not attach (thread) your patchsets to some other threads (unrelated or
> older versions). This buries them deep in the mailbox and might interfere
> with applying entire sets.
Ok.
>
> > PHY configuration registers
> > Allow to change orginal xSPI PHY configuration values. If not set, and
> > Marvell overlay is enabled, safe defaults will be written into xSPI
> > PHY
> >
> > Optional base for xfer register set
> > Additional reg field to allocate xSPI Marvell overlay XFER block
> >
> > Signed-off-by: Witold Sadowski <[email protected]>
> > ---
>
> Please use subject prefixes matching the subsystem. You can get them for
> example with `git log --oneline -- DIRECTORY_OR_FILE` on the directory
> your patch is touching.
>
> You already received *exactly* the same comment. Can you respond to
> feedbacks and acknowledge that you will implement them?
>
>
> Please provide changelog and explain what happened in between. There were
> several comments already, so did you implement them? Were they ignored?
>
> There was no single response from you.
Sorry for that. I will try to do better from now on.
>
> > .../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
> > 1 file changed, 91 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > index eb0f92468185..0e608245b136 100644
> > --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > @@ -20,23 +20,82 @@ allOf:
> >
> > properties:
> > compatible:
> > - const: cdns,xspi-nor
> > + oneOf:
> > + - description: Vanilla Cadence xSPI controller
> > + items:
> > + - const: cdns,xspi-nor
> > + - description: Cadence xSPI controller with v2 Marvell overlay
> > + items:
> > + - const: mrvl,xspi-nor
> > +
> >
>
> No need for two blank lines. BTW, that's just enum.
Ok, will change that.
>
>
> > reg:
> > + minItems: 3
> > items:
> > - description: address and length of the controller register set
> > - description: address and length of the Slave DMA data port
> > - description: address and length of the auxiliary registers
> > + - description: address and length of the xfer registers
> >
> > reg-names:
> > + minItems: 3
> > items:
> > - const: io
> > - const: sdma
> > - const: aux
> > + - const: xferbase
> >
> > interrupts:
> > maxItems: 1
> >
> > + cdns,dll-phy-control:
> > + description: |
>
> Do not need '|' unless you need to preserve formatting.
>
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x707
> > +
> > + cdns,rfile-phy-control:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x40000
> > +
> > + cdns,rfile-phy-tsel:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0
> > +
> > + cdns,phy-dq-timing:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x101
> > +
> > + cdns,phy-dqs-timing:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x700404
> > +
> > + cdns,phy-gate-lpbk-ctrl:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x200030
> > +
> > + cdns,phy-dll-master-ctrl:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x00800000
> > +
> > + cdns,phy-dll-slave-ctrl:
>
> Please use some easier to read logical properties, not just register
> values. Specifically, this is impossible to review whether any of these
> are actually OS policy, instead of hardware configuration.
>
> You also miss constraining these and reg per variant (but that was
> mentioned by Conor, I think).
All of that will be removed, PHY configuration is stable around whole
SPI frequency range. Internal SoC structure must be changed to change
That values, it will be easier to track that in the driver, based on
SoC version/overlay version(if ever that will be necessary)
>
> Best regards,
> Krzysztof
> ----------------------------------------------------------------------
> On Wed, Apr 17, 2024 at 06:13:49PM -0700, Witold Sadowski wrote:
> > Add new bindings for v2 Marvell xSPI overlay:
> > mrvl,xspi-nor compatible string
> > New compatible string to distinguish between orginal and modified xSPI
> > block
> >
> > PHY configuration registers
> > Allow to change orginal xSPI PHY configuration values. If not set, and
> > Marvell overlay is enabled, safe defaults will be written into xSPI
> > PHY
> >
> > Optional base for xfer register set
> > Additional reg field to allocate xSPI Marvell overlay XFER block
> >
> > Signed-off-by: Witold Sadowski <[email protected]>
> > ---
> > .../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
> > 1 file changed, 91 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > index eb0f92468185..0e608245b136 100644
> > --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > @@ -20,23 +20,82 @@ allOf:
> >
> > properties:
> > compatible:
> > - const: cdns,xspi-nor
> > + oneOf:
> > + - description: Vanilla Cadence xSPI controller
> > + items:
> > + - const: cdns,xspi-nor
>
> The "items: isn't required here is it? Can't you just have
> oneOf:
> - description: Vanilla Cadence xSPI controller
> const: cdns,xspi-nor
> - description: Cadence xSPI controller with v2 Marvell overlay
> const: mrvl,xspi-nor
> if you don't want to use an enum?
It works without items, but I will try also with enums.
>
> > + - description: Cadence xSPI controller with v2 Marvell overlay
> > + items:
> > + - const: mrvl,xspi-nor
>
>
> "mrvl" is deprecated, please use "marvell". You're also missing a soc-
> specific compatible here, I doubt there's only going to be one device from
> marvell with an xspi controller ever.
The intention is to add overlay on top of existing IP block to gain some
More features from it. So if there will be different SoC with same xSPI
IP, we can simply use that property, as internal SoC structure will be the same.
On the other hand, if there will be used different IP to handle SPI operations
It should use different driver. Also, I do not expect that new version of the
Overlay will be developed to handle different IP.
>
> > reg:
> > + minItems: 3
> > items:
> > - description: address and length of the controller register set
> > - description: address and length of the Slave DMA data port
> > - description: address and length of the auxiliary registers
> > + - description: address and length of the xfer registers
> >
> > reg-names:
> > + minItems: 3
> > items:
> > - const: io
> > - const: sdma
> > - const: aux
> > + - const: xferbase
>
> Please constrain the 4th reg to only the marvell device.
Ok.
>
> >
> > interrupts:
> > maxItems: 1
> >
> > + cdns,dll-phy-control:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
>
> Under what circumstances do you expect these things to change for a
> particular SoC? If it's fixed per SoC, you could deduce it from the
> compatible rather than needing properties.
>
> None of these properties explain what they do and all appear to just set
> register values directly, which is not generally something that we permit
> in DT. Some explanation of how these values vary would help a lot...
I will remove that PHY configuration block. That can be d in driver, based
on SoC version/HW overlay version.
I believe to change that values or some internal clock should be changed,
or whole internal structure, have to be changed. After few internal
discussions, I don't think only changing the SoC will be enough to change
that values.
>
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x707
> > +
> > + cdns,rfile-phy-control:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
>
> Please enforce constraints like which compatibles something is valid for
> in the binding, not in free-form text.
>
>
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x40000
> > +
> > + cdns,rfile-phy-tsel:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0
> > +
> > + cdns,phy-dq-timing:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x101
> > +
> > + cdns,phy-dqs-timing:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x700404
> > +
> > + cdns,phy-gate-lpbk-ctrl:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x200030
> > +
> > + cdns,phy-dll-master-ctrl:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x00800000
> > +
> > + cdns,phy-dll-slave-ctrl:
> > + description: |
> > + PHY config register. Valid only for cdns,mrvl-xspi-nor
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + default: 0x0000ff01
> > +
> > required:
> > - compatible
> > - reg
> > @@ -68,6 +127,37 @@ examples:
> > reg = <0>;
> > };
> >
> > + flash@1 {
> > + compatible = "jedec,spi-nor";
> > + spi-max-frequency = <75000000>;
> > + reg = <1>;
> > + };
> > + };
> > + };
> > + - |
> > + #include <dt-bindings/interrupt-controller/irq.h>
> > + bus {
> > + #address-cells = <2>;
> > + #size-cells = <2>;
> > +
> > + mrvl_xspi: spi@d0010000 {
>
> Drop the node label here, nothing ever refers to it.
Ok.
>
> Thanks,
> Conor.
>
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + compatible = "mrvl,xspi-nor";
> > + reg = <0x0 0xa0010000 0x0 0x1040>,
> > + <0x0 0xb0000000 0x0 0x1000>,
> > + <0x0 0xa0020000 0x0 0x100>,
> > + <0x0 0xa0090000 0x0 0x100>;
> > + reg-names = "io", "sdma", "aux", "xferbase";
> > + interrupts = <0 90 IRQ_TYPE_LEVEL_HIGH>;
> > + interrupt-parent = <&gic>;
> > +
> > + flash@0 {
> > + compatible = "jedec,spi-nor";
> > + spi-max-frequency = <75000000>;
> > + reg = <0>;
> > + };
> > +
> > flash@1 {
> > compatible = "jedec,spi-nor";
> > spi-max-frequency = <75000000>;
> > --
> > 2.43.0
> >
Regards
Witek
On Mon, Apr 29, 2024 at 02:47:23PM +0000, Witold Sadowski wrote:
> > ----------------------------------------------------------------------
> > On Wed, Apr 17, 2024 at 06:13:49PM -0700, Witold Sadowski wrote:
> > > Add new bindings for v2 Marvell xSPI overlay:
> > > mrvl,xspi-nor compatible string
> > > New compatible string to distinguish between orginal and modified xSPI
> > > block
> > >
> > > PHY configuration registers
> > > Allow to change orginal xSPI PHY configuration values. If not set, and
> > > Marvell overlay is enabled, safe defaults will be written into xSPI
> > > PHY
> > >
> > > Optional base for xfer register set
> > > Additional reg field to allocate xSPI Marvell overlay XFER block
> > >
> > > Signed-off-by: Witold Sadowski <[email protected]>
> > > ---
> > > .../devicetree/bindings/spi/cdns,xspi.yaml | 92 ++++++++++++++++++-
> > > 1 file changed, 91 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > index eb0f92468185..0e608245b136 100644
> > > --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > @@ -20,23 +20,82 @@ allOf:
> > >
> > > properties:
> > > compatible:
> > > - const: cdns,xspi-nor
> > > + oneOf:
> > > + - description: Vanilla Cadence xSPI controller
> > > + items:
> > > + - const: cdns,xspi-nor
> >
> > The "items: isn't required here is it? Can't you just have
> > oneOf:
> > - description: Vanilla Cadence xSPI controller
> > const: cdns,xspi-nor
> > - description: Cadence xSPI controller with v2 Marvell overlay
> > const: mrvl,xspi-nor
> > if you don't want to use an enum?
>
> It works without items, but I will try also with enums.
>
> >
> > > + - description: Cadence xSPI controller with v2 Marvell overlay
> > > + items:
> > > + - const: mrvl,xspi-nor
> >
> >
> > "mrvl" is deprecated, please use "marvell". You're also missing a soc-
> > specific compatible here, I doubt there's only going to be one device from
> > marvell with an xspi controller ever.
>
> The intention is to add overlay on top of existing IP block to gain some
> More features from it. So if there will be different SoC with same xSPI
> IP, we can simply use that property, as internal SoC structure will be the same.
> On the other hand, if there will be used different IP to handle SPI operations
> It should use different driver. Also, I do not expect that new version of the
> Overlay will be developed to handle different IP.
I'm struggling to understand what you mean here by "overlay". Ordinarily
I'd expect someone to meant a dt-overlay, but you're talking about IP
blocks, so this sounds like hardware modifications.
I am also a bit confused by the claim that the "internal SoC structure
will be the same". Usually different SoCs have different internal
structures, even when they re-use IP cores. If they have the same internal
structure then they're not really different SoCs, just different
packages! I think what you're saying here is that you intend using the
"mrvl,xspi-nor" compatible for multiple SoCs that all contain the same
modified versions of the Cadence IP, not different packages for the same
SoC?
Confusing wording aside, using the same generic compatible for different
SoCs is what I trying to avoid. I don't mind there being a fallback
compatible that's generic, but I want to see specific compatibles here
for the individual SoCs.
If you did actually mean that only the packaging is different between
the devices, then I don't think you need specific compatibles for each
different package, but you should have one for the SoC itself IMO.
Cheers,
Conor.
> On Mon, Apr 29, 2024 at 02:47:23PM +0000, Witold Sadowski wrote:
> > > --------------------------------------------------------------------
> > > -- On Wed, Apr 17, 2024 at 06:13:49PM -0700, Witold Sadowski wrote:
> > > > Add new bindings for v2 Marvell xSPI overlay:
> > > > mrvl,xspi-nor compatible string
> > > > New compatible string to distinguish between orginal and modified
> > > > xSPI block
> > > >
> > > > PHY configuration registers
> > > > Allow to change orginal xSPI PHY configuration values. If not set,
> > > > and Marvell overlay is enabled, safe defaults will be written into
> > > > xSPI PHY
> > > >
> > > > Optional base for xfer register set Additional reg field to
> > > > allocate xSPI Marvell overlay XFER block
> > > >
> > > > Signed-off-by: Witold Sadowski <[email protected]>
> > > > ---
> > > > .../devicetree/bindings/spi/cdns,xspi.yaml | 92
> ++++++++++++++++++-
> > > > 1 file changed, 91 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > > b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > > index eb0f92468185..0e608245b136 100644
> > > > --- a/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > > +++ b/Documentation/devicetree/bindings/spi/cdns,xspi.yaml
> > > > @@ -20,23 +20,82 @@ allOf:
> > > >
> > > > properties:
> > > > compatible:
> > > > - const: cdns,xspi-nor
> > > > + oneOf:
> > > > + - description: Vanilla Cadence xSPI controller
> > > > + items:
> > > > + - const: cdns,xspi-nor
> > >
> > > The "items: isn't required here is it? Can't you just have
> > > oneOf:
> > > - description: Vanilla Cadence xSPI controller
> > > const: cdns,xspi-nor
> > > - description: Cadence xSPI controller with v2 Marvell overlay
> > > const: mrvl,xspi-nor
> > > if you don't want to use an enum?
> >
> > It works without items, but I will try also with enums.
> >
> > >
> > > > + - description: Cadence xSPI controller with v2 Marvell
> overlay
> > > > + items:
> > > > + - const: mrvl,xspi-nor
> > >
> > >
> > > "mrvl" is deprecated, please use "marvell". You're also missing a
> > > soc- specific compatible here, I doubt there's only going to be one
> > > device from marvell with an xspi controller ever.
> >
> > The intention is to add overlay on top of existing IP block to gain
> > some More features from it. So if there will be different SoC with
> > same xSPI IP, we can simply use that property, as internal SoC structure
> will be the same.
> > On the other hand, if there will be used different IP to handle SPI
> > operations It should use different driver. Also, I do not expect that
> > new version of the Overlay will be developed to handle different IP.
>
> I'm struggling to understand what you mean here by "overlay". Ordinarily
> I'd expect someone to meant a dt-overlay, but you're talking about IP
> blocks, so this sounds like hardware modifications.
> I am also a bit confused by the claim that the "internal SoC structure
> will be the same". Usually different SoCs have different internal
> structures, even when they re-use IP cores. If they have the same internal
> structure then they're not really different SoCs, just different packages!
> I think what you're saying here is that you intend using the "mrvl,xspi-
> nor" compatible for multiple SoCs that all contain the same modified
> versions of the Cadence IP, not different packages for the same SoC?
Yes, by HW overlay I meant actual HW modification. I called it overlay,
as it is not modifying xSPI block itself, but it is rather build around
it. As I don't have better word for it now, I will continue to use it.
With that approach we can still have full functionality of xSPI block
(like memory transfers), and additional features(like SPI full-duplex
operations).
Regarding "internal SoC structure" - I meant physical parameters of silicon,
Signal propagation times inside block etc. That won't be changed if we have
Two different SoC, bud made in same technology.
>
> Confusing wording aside, using the same generic compatible for different
> SoCs is what I trying to avoid. I don't mind there being a fallback
> compatible that's generic, but I want to see specific compatibles here for
> the individual SoCs.
>
> If you did actually mean that only the packaging is different between the
> devices, then I don't think you need specific compatibles for each
> different package, but you should have one for the SoC itself IMO.
We can have SoC A, B with common xSPI block, and both of them can share
Same dtb node with compatible property "marvell,cn10k,xspi-nor" for
example. I don't think it will be beneficial to have different compatible
name for each different SoC, for example "marvell,t98,xspi-nor", if all
other parts will be the same. Or am I not correct?
>
> Cheers,
> Conor.
Regards
Witek
On 30/04/2024 00:59, Witold Sadowski wrote:
>
>>
>> Confusing wording aside, using the same generic compatible for different
>> SoCs is what I trying to avoid. I don't mind there being a fallback
>> compatible that's generic, but I want to see specific compatibles here for
>> the individual SoCs.
>>
>> If you did actually mean that only the packaging is different between the
>> devices, then I don't think you need specific compatibles for each
>> different package, but you should have one for the SoC itself IMO.
>
> We can have SoC A, B with common xSPI block, and both of them can share
> Same dtb node with compatible property "marvell,cn10k,xspi-nor" for
> example. I don't think it will be beneficial to have different compatible
> name for each different SoC, for example "marvell,t98,xspi-nor", if all
> other parts will be the same. Or am I not correct?
Please see writing bindings (or any presentation for DTS and bindings):
you are expected to have SoC specific compatibles for every block in the
SoC. There are many examples in recent bindings, so take a look there.
Best regards,
Krzysztof
On 29/04/2024 16:30, Witold Sadowski wrote:
>>>
>>> +#ifdef CONFIG_ACPI
>>> +static const struct acpi_device_id cdns_xspi_acpi_match[] = {
>>> + {
>>> + .id = "cdns,xspi-nor",
>>> + .driver_data = (kernel_ulong_t) &cdns_driver_data,
>>> + },
>>> + {
>>> + .id = "mrvl,xspi-nor",
>>> + .driver_data = (kernel_ulong_t) &mrvl_driver_data,
>>
>> UEFI provides compatibles for ACPI? I think that's first such format in
>> the kernel.
>
> Yes, that code is not doing what was expected.
> Current usage scenario in ACPI mode is:
> xSPI block with HID PRP0001, and additional compatible package set to
> correct compatible string
> With that approach only issue(in ACPI mode) is with matching device
> with data field from of_device_id. It looks like there are functions
> to match that when DTB is used, but in ACPI mode it fails.
> I believe solution is to traverse dev->driver->of_match_table manually
> To match device name with correct compatible data structure.
> That will be included in next patchset.
PRP0001 should be handled by regular of_device_id table, of course
assuming your kernel has build-in CONFIG_OF.
Best regards,
Krzysztof
> On 29/04/2024 16:30, Witold Sadowski wrote:
> >>>
> >>> +#ifdef CONFIG_ACPI
> >>> +static const struct acpi_device_id cdns_xspi_acpi_match[] = {
> >>> + {
> >>> + .id = "cdns,xspi-nor",
> >>> + .driver_data = (kernel_ulong_t) &cdns_driver_data,
> >>> + },
> >>> + {
> >>> + .id = "mrvl,xspi-nor",
> >>> + .driver_data = (kernel_ulong_t) &mrvl_driver_data,
> >>
> >> UEFI provides compatibles for ACPI? I think that's first such format
> >> in the kernel.
> >
> > Yes, that code is not doing what was expected.
> > Current usage scenario in ACPI mode is:
> > xSPI block with HID PRP0001, and additional compatible package set to
> > correct compatible string With that approach only issue(in ACPI mode)
> > is with matching device with data field from of_device_id. It looks
> > like there are functions to match that when DTB is used, but in ACPI
> > mode it fails.
> > I believe solution is to traverse dev->driver->of_match_table manually
> > To match device name with correct compatible data structure.
> > That will be included in next patchset.
>
> PRP0001 should be handled by regular of_device_id table, of course
> assuming your kernel has build-in CONFIG_OF.
And it is correctly matched by id, but functions to retrieve data fails.
I'm referring to of_device_get_match_data - there is no of node in
ACPI case.
I have come up with solution, as I wasn't able to find similar function that
will work with ACPI and dtb on the same time:
static const void * cdns_xspi_get_data(struct device *dev)
{
const struct of_device_id *matches = dev->driver->of_match_table;
for (; matches->name[0] || matches->type[0] || matches->compatible[0];
matches++) {
if (device_is_compatible(dev, matches->compatible))
return matches->data;
}
return NULL;
}
Is there a better way to handle that?
>
> Best regards,
> Krzysztof
On Wed, May 08, 2024 at 08:04:49AM +0000, Witold Sadowski wrote:
>
> I have come up with solution, as I wasn't able to find similar function that
> will work with ACPI and dtb on the same time:
The usual thing would just be to try both an ACPI match and an OF match.
> On Wed, May 08, 2024 at 08:04:49AM +0000, Witold Sadowski wrote:
>
> >
> > I have come up with solution, as I wasn't able to find similar
> > function that will work with ACPI and dtb on the same time:
>
> The usual thing would just be to try both an ACPI match and an OF match.
Ok, thanks. I thought it can be done in single step.