All of lore.kernel.org
 help / color / mirror / Atom feed
From: "André Almeida" <andrealmeid@collabora.com>
To: Sanjay R Mehta <sanju.mehta@amd.com>,
	Mark Brown <broonie@kernel.org>,
	linux-spi@vger.kernel.org, linux-kernel@vger.kernel.org,
	kernel@collabora.com, Stephen Rothwell <sfr@canb.auug.org.au>,
	krisman@collabora.com,
	Lucas Tanure <tanureal@opensource.cirrus.com>,
	Nehal Bakulchandra Shah <Nehal-Bakulchandra.shah@amd.com>,
	Charles Keepax <ckeepax@opensource.cirrus.com>
Cc: "André Almeida" <andrealmeid@collabora.com>
Subject: [PATCH] spi: amd: Configure device speed
Date: Thu, 17 Mar 2022 11:14:53 -0300	[thread overview]
Message-ID: <20220317141453.15868-1-andrealmeid@collabora.com> (raw)

Create mechanism to configure device clock frequency. For now, it can
only set the device to use the maximum speed.

Signed-off-by: André Almeida <andrealmeid@collabora.com>
---
 drivers/spi/spi-amd.c | 98 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index d909afac6e21..ce4cce50496b 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -35,6 +35,36 @@
 
 #define AMD_SPI_MEM_SIZE	200
 
+#define AMD_SPI_ENA_REG		0x20
+#define AMD_SPI_ALT_SPD_SHIFT	20
+#define AMD_SPI_ALT_SPD_MASK	GENMASK(23, AMD_SPI_ALT_SPD_SHIFT)
+#define AMD_SPI_SPI100_SHIFT	0
+#define AMD_SPI_SPI100_MASK	GENMASK(AMD_SPI_SPI100_SHIFT, AMD_SPI_SPI100_SHIFT)
+#define AMD_SPI_SPEED_REG	0x6C
+#define AMD_SPI_SPD7_SHIFT	8
+#define AMD_SPI_SPD7_MASK	GENMASK(13, AMD_SPI_SPD7_SHIFT)
+
+#define AMD_SPI_MAX_HZ		100000000
+#define AMD_SPI_MIN_HZ		800000
+
+/* Set device speed to the maximum frequency supported */
+static bool max_speed;
+module_param(max_speed, bool, 0644);
+
+enum amd_spi_speed {
+	F_66_66MHz,
+	F_33_33MHz,
+	F_22_22MHz,
+	F_16_66MHz,
+	F_100MHz,
+	F_800KHz,
+	SPI_SPD6,
+	SPI_SPD7,
+	F_50MHz = 0x4,
+	F_4MHz = 0x32,
+	F_3_17MHz = 0x3F
+};
+
 /* M_CMD OP codes for SPI */
 #define AMD_SPI_XFER_TX		1
 #define AMD_SPI_XFER_RX		2
@@ -48,6 +78,19 @@ struct amd_spi {
 	void __iomem *io_remap_addr;
 	unsigned long io_base_addr;
 	enum amd_spi_versions version;
+	unsigned int speed_hz;
+};
+
+/**
+ * struct amd_spi_freq - Matches device speed with values to write in regs
+ * @speed_hz: Device frequency
+ * @ena: Value to be written to "enable register"
+ * @spd7: Some frequencies requires to have a value written at SPISPEED register
+ */
+struct amd_spi_freq {
+	unsigned int speed_hz;
+	unsigned int enable_val;
+	unsigned int spd7_val;
 };
 
 static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx)
@@ -170,12 +213,67 @@ static int amd_spi_execute_opcode(struct amd_spi *amd_spi)
 	}
 }
 
+static const struct amd_spi_freq amd_spi_freq[] = {
+	{ AMD_SPI_MAX_HZ,   F_100MHz,         0},
+	{       66660000, F_66_66MHz,         0},
+	{       50000000,   SPI_SPD7,   F_50MHz},
+	{       33330000, F_33_33MHz,         0},
+	{       22220000, F_22_22MHz,         0},
+	{       16660000, F_16_66MHz,         0},
+	{        4000000,   SPI_SPD7,    F_4MHz},
+	{        3170000,   SPI_SPD7, F_3_17MHz},
+	{ AMD_SPI_MIN_HZ,   F_800KHz,         0},
+};
+
+static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz)
+{
+	unsigned int i, spd7_val, enable_val;
+
+	if (speed_hz == amd_spi->speed_hz)
+		return 0;
+
+	if (speed_hz < AMD_SPI_MIN_HZ)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(amd_spi_freq); i++) {
+		if (speed_hz >= amd_spi_freq[i].speed_hz) {
+			if (amd_spi->speed_hz == amd_spi_freq[i].speed_hz)
+				return 0;
+
+			amd_spi->speed_hz = amd_spi_freq[i].speed_hz;
+
+			enable_val = (amd_spi_freq[i].enable_val << AMD_SPI_ALT_SPD_SHIFT)
+				     & AMD_SPI_ALT_SPD_MASK;
+			amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, enable_val,
+					       AMD_SPI_ALT_SPD_MASK);
+
+			if (amd_spi->speed_hz == AMD_SPI_MAX_HZ)
+				amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, 1,
+						       AMD_SPI_SPI100_MASK);
+
+			if (amd_spi_freq[i].spd7_val) {
+				spd7_val = (amd_spi_freq[i].spd7_val << AMD_SPI_SPD7_SHIFT)
+					   & AMD_SPI_SPD7_MASK;
+				amd_spi_setclear_reg32(amd_spi, AMD_SPI_SPEED_REG, spd7_val,
+						       AMD_SPI_SPD7_MASK);
+			}
+
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+};
+
 static int amd_spi_master_setup(struct spi_device *spi)
 {
 	struct amd_spi *amd_spi = spi_master_get_devdata(spi->master);
 
 	amd_spi_clear_fifo_ptr(amd_spi);
 
+	if (max_speed)
+		amd_set_spi_freq(amd_spi, spi->max_speed_hz);
+
 	return 0;
 }
 
-- 
2.35.1


             reply	other threads:[~2022-03-17 14:15 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-17 14:14 André Almeida [this message]
2022-03-17 18:23 ` [PATCH] spi: amd: Configure device speed Mark Brown
2022-08-17 13:18 Shreeya Patel
2022-08-17 13:44 ` Mark Brown
2022-08-17 14:10   ` Shreeya Patel
2022-08-18 13:23     ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220317141453.15868-1-andrealmeid@collabora.com \
    --to=andrealmeid@collabora.com \
    --cc=Nehal-Bakulchandra.shah@amd.com \
    --cc=broonie@kernel.org \
    --cc=ckeepax@opensource.cirrus.com \
    --cc=kernel@collabora.com \
    --cc=krisman@collabora.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-spi@vger.kernel.org \
    --cc=sanju.mehta@amd.com \
    --cc=sfr@canb.auug.org.au \
    --cc=tanureal@opensource.cirrus.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.