summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/spi/rk_spi.c36
-rw-r--r--drivers/spi/rk_spi.h9
2 files changed, 37 insertions, 8 deletions
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 3e44f1795e..0c627d963d 100644
--- a/drivers/spi/rk_spi.c
+++ b/drivers/spi/rk_spi.c
@@ -190,6 +190,26 @@ static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
return 0;
}
+static int rockchip_spi_calc_modclk(ulong max_freq)
+{
+ unsigned div;
+ const unsigned long gpll_hz = 594000000UL;
+
+ /*
+ * We need to find an input clock that provides at least twice
+ * the maximum frequency and can be generated from the assumed
+ * speed of GPLL (594MHz) using an integer divider.
+ *
+ * To give us more achievable bitrates at higher speeds (these
+ * are generated by dividing by an even 16-bit integer from
+ * this frequency), we try to have an input frequency of at
+ * least 4x our max_freq.
+ */
+
+ div = DIV_ROUND_UP(gpll_hz, max_freq * 4);
+ return gpll_hz / div;
+}
+
static int rockchip_spi_probe(struct udevice *bus)
{
struct rockchip_spi_platdata *plat = dev_get_platdata(bus);
@@ -207,11 +227,13 @@ static int rockchip_spi_probe(struct udevice *bus)
priv->last_transaction_us = timer_get_us();
priv->max_freq = plat->frequency;
- /*
- * Use 99 MHz as our clock since it divides nicely into 594 MHz which
- * is the assumed speed for CLK_GENERAL.
- */
- ret = clk_set_rate(&priv->clk, 99000000);
+ /* Clamp the value from the DTS against any hardware limits */
+ if (priv->max_freq > ROCKCHIP_SPI_MAX_RATE)
+ priv->max_freq = ROCKCHIP_SPI_MAX_RATE;
+
+ /* Find a module-input clock that fits with the max_freq setting */
+ ret = clk_set_rate(&priv->clk,
+ rockchip_spi_calc_modclk(priv->max_freq));
if (ret < 0) {
debug("%s: Failed to set clock: %d\n", __func__, ret);
return ret;
@@ -371,10 +393,10 @@ static int rockchip_spi_set_speed(struct udevice *bus, uint speed)
{
struct rockchip_spi_priv *priv = dev_get_priv(bus);
- if (speed > ROCKCHIP_SPI_MAX_RATE)
- return -EINVAL;
+ /* Clamp to the maximum frequency specified in the DTS */
if (speed > priv->max_freq)
speed = priv->max_freq;
+
priv->speed_hz = speed;
return 0;
diff --git a/drivers/spi/rk_spi.h b/drivers/spi/rk_spi.h
index f1ac81203f..02aa9d0436 100644
--- a/drivers/spi/rk_spi.h
+++ b/drivers/spi/rk_spi.h
@@ -119,6 +119,13 @@ enum {
};
#define ROCKCHIP_SPI_TIMEOUT_MS 1000
-#define ROCKCHIP_SPI_MAX_RATE 48000000
+
+/*
+ * We limit the maximum bitrate to 50MBit/s (50MHz) due to an assumed
+ * hardware limitation... the Linux kernel source has the following
+ * comment:
+ * "sclk_out: spi master internal logic in rk3x can support 50Mhz"
+ */
+#define ROCKCHIP_SPI_MAX_RATE 50000000
#endif /* __RK_SPI_H */