From: Lucas Tanure <tanureal@opensource.cirrus.com>
To: Mark Brown <broonie@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
"Rafael J . Wysocki" <rafael@kernel.org>,
Sanjay R Mehta <sanju.mehta@amd.com>,
Nehal Bakulchandra Shah <Nehal-Bakulchandra.shah@amd.com>
Cc: <linux-kernel@vger.kernel.org>, <linux-spi@vger.kernel.org>,
<patches@opensource.cirrus.com>,
Lucas Tanure <tanureal@opensource.cirrus.com>
Subject: [PATCH 10/10] spi: amd: Configure the SPI speed
Date: Wed, 8 Sep 2021 12:36:35 +0100 [thread overview]
Message-ID: <20210908113635.788578-1-tanureal@opensource.cirrus.com> (raw)
Add support for configuring the speed of the bus per
device as the fastest clock that is less or equal to
the device max_speed_hz
Signed-off-by: Lucas Tanure <tanureal@opensource.cirrus.com>
---
drivers/spi/spi-amd.c | 105 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 104 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c
index 788a5c42d811..0dde1ce757f2 100644
--- a/drivers/spi/spi-amd.c
+++ b/drivers/spi/spi-amd.c
@@ -19,7 +19,11 @@
#define AMD_SPI_EXEC_CMD BIT(16)
#define AMD_SPI_FIFO_CLEAR BIT(20)
#define AMD_SPI_BUSY BIT(31)
-#define AMD_SPI_ENABLE_REG 0x20
+#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_DUMMY_CYCL_REG 0x32
#define AMD_SPI_OPCODE_REG 0x45
@@ -34,6 +38,11 @@
#define AMD_SPI_TX_COUNT_REG 0x48
#define AMD_SPI_RX_COUNT_REG 0x4B
#define AMD_SPI_STATUS_REG 0x4C
+#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_SPD6_SHIFT 0
+#define AMD_SPI_SPD6_MASK GENMASK(5, AMD_SPI_SPD6_SHIFT)
#define AMD_SPI_FIFO_SIZE 70
#define AMD_SPI_MEM_SIZE 200
@@ -42,6 +51,33 @@
#define AMD_SPI_XFER_TX 1
#define AMD_SPI_XFER_RX 2
+#define AMD_SPI_MAX_HZ 100000000
+#define AMD_SPI_MIN_HZ 800000
+
+static bool speed_dev;
+module_param(speed_dev, 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
+};
+
+struct amd_spi_freq {
+ u32 speed_hz;
+ u32 ena;
+ u32 spd7;
+ bool use_spi100_eng;
+};
+
struct amd_spi {
void __iomem *io_remap_addr;
unsigned long io_base_addr;
@@ -50,6 +86,7 @@ struct amd_spi {
const struct amd_spi_devtype_data *devtype_data;
struct spi_device *spi_dev;
struct spi_master *master;
+ u32 speed_hz;
};
struct amd_spi_devtype_data {
@@ -191,11 +228,63 @@ static int amd_spi_execute_opcode_v2(struct amd_spi *amd_spi)
return 0;
}
+static const struct amd_spi_freq amd_spi_freq[] = {
+ { AMD_SPI_MAX_HZ, F_100MHz, 0, true},
+ { 66660000, F_66_66MHz, 0, false},
+ { 50000000, SPI_SPD7, F_50MHz, false},
+ { 33330000, F_33_33MHz, 0, false},
+ { 22220000, F_22_22MHz, 0, false},
+ { 16660000, F_16_66MHz, 0, false},
+ { 4000000, SPI_SPD7, F_4MHz, false},
+ { 3170000, SPI_SPD7, F_3_17MHz, false},
+ { AMD_SPI_MIN_HZ, F_800KHz, 0, false},
+};
+
+static int amd_set_spi_freq(struct amd_spi *amd_spi, u32 speed_hz)
+{
+ int i;
+ bool use_spi100_eng = false;
+ u32 spd7 = 0, ena;
+
+ 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;
+
+ use_spi100_eng = amd_spi_freq[i].use_spi100_eng;
+ spd7 = (amd_spi_freq[i].spd7 << AMD_SPI_SPD7_SHIFT) & AMD_SPI_SPD7_MASK;
+ ena = (amd_spi_freq[i].ena << AMD_SPI_ALT_SPD_SHIFT) & AMD_SPI_ALT_SPD_MASK;
+
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG, ena, AMD_SPI_ALT_SPD_MASK);
+ break;
+ }
+ }
+
+ if (spd7)
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_SPEED_REG, spd7, AMD_SPI_SPD7_MASK);
+
+ if (use_spi100_eng)
+ amd_spi_setclear_reg32(amd_spi, AMD_SPI_ENA_REG,
+ AMD_SPI_SPI100_MASK < AMD_SPI_SPI100_SHIFT,
+ AMD_SPI_SPI100_MASK);
+
+ return 0;
+}
+
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 (speed_dev)
+ amd_set_spi_freq(amd_spi, spi->max_speed_hz);
return 0;
}
@@ -322,6 +411,17 @@ static int amd_spi_transfer_one_message(struct spi_controller *ctrl, struct spi_
return ret;
}
+static int amd_spi_prepare_message(struct spi_controller *ctlr, struct spi_message *msg)
+{
+ struct amd_spi *amd_spi = spi_controller_get_devdata(ctlr);
+ struct spi_device *spi = msg->spi;
+
+ if (speed_dev)
+ amd_set_spi_freq(amd_spi, spi->max_speed_hz);
+
+ return 0;
+}
+
static size_t amd_spi_max_transfer_size(struct spi_device *spi)
{
return AMD_SPI_FIFO_SIZE;
@@ -360,10 +460,13 @@ static int amd_spi_probe(struct platform_device *pdev)
master->bus_num = 0;
master->num_chipselect = 4;
master->mode_bits = 0;
+ master->max_speed_hz = AMD_SPI_MAX_HZ;
+ master->min_speed_hz = AMD_SPI_MIN_HZ;
master->flags = SPI_CONTROLLER_HALF_DUPLEX | SPI_CONTROLLER_NO_TX_RX_CS;
master->setup = amd_spi_master_setup;
master->max_transfer_size = amd_spi_max_transfer_size;
master->max_message_size = amd_spi_max_transfer_size;
+ master->prepare_message = amd_spi_prepare_message;
master->transfer_one_message = amd_spi_transfer_one_message;
INIT_LIST_HEAD(&amd_spi->rbuf_head);
--
2.33.0
reply other threads:[~2021-09-08 11:36 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20210908113635.788578-1-tanureal@opensource.cirrus.com \
--to=tanureal@opensource.cirrus.com \
--cc=Nehal-Bakulchandra.shah@amd.com \
--cc=broonie@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=patches@opensource.cirrus.com \
--cc=rafael@kernel.org \
--cc=sanju.mehta@amd.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.