[U-Boot,v4,3/7] rockchip: spi: rk_spi: dynamically select an module input rate

Submitted by Philipp Tomsich on April 20, 2017, 8:05 p.m.

Details

Message ID 1492718755-14331-4-git-send-email-philipp.tomsich@theobroma-systems.com
State Accepted
Headers show

Commit Message

Philipp Tomsich April 20, 2017, 8:05 p.m.
The original clock/bitrate selection code for the rk_spi driver was a
bit limited, as it always selected a 99MHz input clock rate (which
would allow for a maximum bitrate of 49.5MBit/s), but returned -EINVAL
if a bitrate higher than 48MHz was requested.

To give us better control over the bitrate (i.e. add more operating
points, especially at "higher" bitrate---such as above 9MBit/s), we
try to choose 4x the maximum frequency (clamped to 50MBit) from the
DTS instead of 99MHz... for most use-cases this will yield a frequency
of 198MHz, but is flexible to go beyond this in future configurations.

This also rewrites the check to allow frequencies of up to half the
SPI module rate as bitrates and then clamps to whatever the DTS allows
as a maximum (board-specific) frequency and does away with the -EINVAL
when trying to select a bitrate (for cases that exceeded the hard
limit) and instead consistently clamps to the lower of the hard limit,
the soft limit for the SPI bus (from the DTS) or the soft limit for
the SPI slave device.

This replaces
  "rockchip: spi: rk_spi: select 198MHz input to the SPI module for the RK3399"
  "rockchip: spi: rk_spi: improve clocking code for the RK3399"
from earlier versions of this series.

Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>

---

Changes in v4:
- rewrite to not introduce a chip-specific define, add a dynamic
  module input rate selection and unify the bitrate handling for hard
  and soft limits.
  (replaces 2 earlier commits mentioned in the commit message)

Changes in v3: None
Changes in v2: None

 drivers/spi/rk_spi.c | 36 +++++++++++++++++++++++++++++-------
 drivers/spi/rk_spi.h |  9 ++++++++-
 2 files changed, 37 insertions(+), 8 deletions(-)

Comments

Simon Glass April 20, 2017, 9:05 p.m.
On 20 April 2017 at 14:05, Philipp Tomsich
<philipp.tomsich@theobroma-systems.com> wrote:
> The original clock/bitrate selection code for the rk_spi driver was a
> bit limited, as it always selected a 99MHz input clock rate (which
> would allow for a maximum bitrate of 49.5MBit/s), but returned -EINVAL
> if a bitrate higher than 48MHz was requested.
>
> To give us better control over the bitrate (i.e. add more operating
> points, especially at "higher" bitrate---such as above 9MBit/s), we
> try to choose 4x the maximum frequency (clamped to 50MBit) from the
> DTS instead of 99MHz... for most use-cases this will yield a frequency
> of 198MHz, but is flexible to go beyond this in future configurations.
>
> This also rewrites the check to allow frequencies of up to half the
> SPI module rate as bitrates and then clamps to whatever the DTS allows
> as a maximum (board-specific) frequency and does away with the -EINVAL
> when trying to select a bitrate (for cases that exceeded the hard
> limit) and instead consistently clamps to the lower of the hard limit,
> the soft limit for the SPI bus (from the DTS) or the soft limit for
> the SPI slave device.
>
> This replaces
>   "rockchip: spi: rk_spi: select 198MHz input to the SPI module for the RK3399"
>   "rockchip: spi: rk_spi: improve clocking code for the RK3399"
> from earlier versions of this series.
>
> Signed-off-by: Philipp Tomsich <philipp.tomsich@theobroma-systems.com>
>
> ---
>
> Changes in v4:
> - rewrite to not introduce a chip-specific define, add a dynamic
>   module input rate selection and unify the bitrate handling for hard
>   and soft limits.
>   (replaces 2 earlier commits mentioned in the commit message)
>
> Changes in v3: None
> Changes in v2: None
>
>  drivers/spi/rk_spi.c | 36 +++++++++++++++++++++++++++++-------
>  drivers/spi/rk_spi.h |  9 ++++++++-
>  2 files changed, 37 insertions(+), 8 deletions(-)

Applied to u-boot-rockchip/next, thanks!

Patch hide | download patch | download mbox

diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
index 3e44f17..0c627d9 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 f1ac812..02aa9d0 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 */