2022-02-16 13:31:47

by André Almeida

[permalink] [raw]
Subject: [PATCH v3 0/3] spi: amd: Add support for new controller version

Hi Mark,

This v3 has a small change at 3/3 for making it work at COMPILE_TEST.
Could you please replace the patch that you had applied on your tree?
Thanks and sorry for the trouble.

This series do some cleanup and add support for new controller version,
AMDI0062.

Change from v2:
- Keep ACPI_PTR() for ACPI dependent variable, making it suitable for
compiling test.

Change from v1:
- Replace `if (version == 2)` with a more extensible switch case.

André Almeida (3):
spi: amd: Use iopoll for busy waiting
spi: amd: Remove needless rom_addr variable
spi: amd: Add support for version AMDI0062

drivers/spi/spi-amd.c | 87 +++++++++++++++++++++++++++++++++++--------
1 file changed, 71 insertions(+), 16 deletions(-)

--
2.35.1


2022-02-16 13:33:19

by André Almeida

[permalink] [raw]
Subject: [PATCH v3 1/3] spi: amd: Use iopoll for busy waiting

Instead of implementing a custom IO busy wait function, just use
readl_poll_timeout().

Signed-off-by: André Almeida <[email protected]>
---
drivers/spi/spi-amd.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 4b3ac7aceaf6..899b8d90ff61 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
+#include <linux/iopoll.h>

#define AMD_SPI_CTRL0_REG 0x00
#define AMD_SPI_EXEC_CMD BIT(16)
@@ -103,16 +104,10 @@ static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count)

static int amd_spi_busy_wait(struct amd_spi *amd_spi)
{
- int timeout = 100000;
+ u32 val;

- /* poll for SPI bus to become idle */
- while (amd_spi_readreg32(amd_spi, AMD_SPI_CTRL0_REG) & AMD_SPI_BUSY) {
- usleep_range(10, 20);
- if (timeout-- < 0)
- return -ETIMEDOUT;
- }
-
- return 0;
+ return readl_poll_timeout(amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG,
+ val, !(val & AMD_SPI_BUSY), 20, 2000000);
}

static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
--
2.35.1

2022-02-16 13:36:12

by André Almeida

[permalink] [raw]
Subject: [PATCH v3 2/3] spi: amd: Remove needless rom_addr variable

rom_addr is not used in the code, so we can just drop it from struct
amd_spi.

Signed-off-by: André Almeida <[email protected]>
---
drivers/spi/spi-amd.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 899b8d90ff61..417ce14a21c6 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -38,7 +38,6 @@
struct amd_spi {
void __iomem *io_remap_addr;
unsigned long io_base_addr;
- u32 rom_addr;
};

static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
--
2.35.1

2022-02-16 16:24:24

by André Almeida

[permalink] [raw]
Subject: [PATCH v3 3/3] spi: amd: Add support for version AMDI0062

Add support for the AMD SPI controller version AMDI0062. Do this in a
modular way where's easy to add new versions.

Signed-off-by: André Almeida <[email protected]>
---
drivers/spi/spi-amd.c | 79 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 70 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 417ce14a21c6..cba6a4486c24 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -19,6 +19,10 @@
#define AMD_SPI_FIFO_CLEAR BIT(20)
#define AMD_SPI_BUSY BIT(31)

+#define AMD_SPI_OPCODE_REG 0x45
+#define AMD_SPI_CMD_TRIGGER_REG 0x47
+#define AMD_SPI_TRIGGER_CMD BIT(7)
+
#define AMD_SPI_OPCODE_MASK 0xFF

#define AMD_SPI_ALT_CS_REG 0x1D
@@ -35,9 +39,15 @@
#define AMD_SPI_XFER_TX 1
#define AMD_SPI_XFER_RX 2

+enum amd_spi_versions {
+ AMD_SPI_V1 = 1, /* AMDI0061 */
+ AMD_SPI_V2, /* AMDI0062 */
+};
+
struct amd_spi {
void __iomem *io_remap_addr;
unsigned long io_base_addr;
+ enum amd_spi_versions version;
};

static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
@@ -81,14 +91,29 @@ static void amd_spi_select_chip(struct amd_spi *amd_spi, u8 cs)
amd_spi_setclear_reg8(amd_spi, AMD_SPI_ALT_CS_REG, cs, AMD_SPI_ALT_CS_MASK);
}

+static inline void amd_spi_clear_chip(struct amd_spi *amd_spi, u8 chip_select)
+{
+ amd_spi_writereg8(amd_spi, AMD_SPI_ALT_CS_REG, chip_select & ~AMD_SPI_ALT_CS_MASK);
+}
+
static void amd_spi_clear_fifo_ptr(struct amd_spi *amd_spi)
{
amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_FIFO_CLEAR, AMD_SPI_FIFO_CLEAR);
}

-static void amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)
+static int amd_spi_set_opcode(struct amd_spi *amd_spi, u8 cmd_opcode)
{
- amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode, AMD_SPI_OPCODE_MASK);
+ switch (amd_spi->version) {
+ case AMD_SPI_V1:
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, cmd_opcode,
+ AMD_SPI_OPCODE_MASK);
+ return 0;
+ case AMD_SPI_V2:
+ amd_spi_writereg8(amd_spi, AMD_SPI_OPCODE_REG, cmd_opcode);
+ return 0;
+ default:
+ return -ENODEV;
+ }
}

static inline void amd_spi_set_rx_count(struct amd_spi *amd_spi, u8 rx_count)
@@ -104,9 +129,21 @@ static inline void amd_spi_set_tx_count(struct amd_spi *amd_spi, u8 tx_count)
static int amd_spi_busy_wait(struct amd_spi *amd_spi)
{
u32 val;
+ int reg;
+
+ switch (amd_spi->version) {
+ case AMD_SPI_V1:
+ reg = AMD_SPI_CTRL0_REG;
+ break;
+ case AMD_SPI_V2:
+ reg = AMD_SPI_STATUS_REG;
+ break;
+ default:
+ return -ENODEV;
+ }

- return readl_poll_timeout(amd_spi->io_remap_addr + AMD_SPI_CTRL0_REG,
- val, !(val & AMD_SPI_BUSY), 20, 2000000);
+ return readl_poll_timeout(amd_spi->io_remap_addr + reg, val,
+ !(val & AMD_SPI_BUSY), 20, 2000000);
}

static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
@@ -117,10 +154,20 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
if (ret)
return ret;

- /* Set ExecuteOpCode bit in the CTRL0 register */
- amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD, AMD_SPI_EXEC_CMD);
-
- return 0;
+ switch (amd_spi->version) {
+ case AMD_SPI_V1:
+ /* Set ExecuteOpCode bit in the CTRL0 register */
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_CTRL0_REG, AMD_SPI_EXEC_CMD,
+ AMD_SPI_EXEC_CMD);
+ return 0;
+ case AMD_SPI_V2:
+ /* Trigger the command execution */
+ amd_spi_setclear_reg8(amd_spi, AMD_SPI_CMD_TRIGGER_REG,
+ AMD_SPI_TRIGGER_CMD, AMD_SPI_TRIGGER_CMD);
+ return 0;
+ default:
+ return -ENODEV;
+ }
}

static int amd_spi_master_setup(struct spi_device *spi)
@@ -190,6 +237,17 @@ static inline int amd_spi_fifo_xfer(struct amd_spi *amd_spi,
message->actual_length = tx_len + rx_len + 1;
/* complete the transaction */
message->status = 0;
+
+ switch (amd_spi->version) {
+ case AMD_SPI_V1:
+ break;
+ case AMD_SPI_V2:
+ amd_spi_clear_chip(amd_spi, message->spi->chip_select);
+ break;
+ default:
+ return -ENODEV;
+ }
+
spi_finalize_current_message(master);

return 0;
@@ -235,6 +293,8 @@ static int amd_spi_probe(struct platform_device *pdev)
}
dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr);

+ amd_spi->version = (enum amd_spi_versions) device_get_match_data(dev);
+
/* Initialize the spi_master fields */
master->bus_num = 0;
master->num_chipselect = 4;
@@ -260,7 +320,8 @@ static int amd_spi_probe(struct platform_device *pdev)

#ifdef CONFIG_ACPI
static const struct acpi_device_id spi_acpi_match[] = {
- { "AMDI0061", 0 },
+ { "AMDI0061", AMD_SPI_V1 },
+ { "AMDI0062", AMD_SPI_V2 },
{},
};
MODULE_DEVICE_TABLE(acpi, spi_acpi_match);
--
2.35.1