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 */