mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-02-15 04:42:02 +00:00
79 lines
2.7 KiB
Diff
79 lines
2.7 KiB
Diff
From 52c92286b71e28d88642a4a416f40fbdb6cbb46f Mon Sep 17 00:00:00 2001
|
|
From: Peter Geis <pgwipeout@gmail.com>
|
|
Date: Sat, 5 Mar 2022 16:58:35 -0500
|
|
Subject: [PATCH] mmc: dw-mmc-rockchip: Fix handling invalid clock rates
|
|
|
|
The Rockchip rk356x ciu clock cannot be set as low as the dw-mmc
|
|
hardware supports. This leads to a situation during card initialization
|
|
where the clock is set lower than the clock driver can support. The
|
|
dw-mmc-rockchip driver spews errors when this happens.
|
|
For normal operation this only happens a few times during boot, but when
|
|
cd-broken is enabled (in cases such as the SoQuartz module) this fires
|
|
multiple times each poll cycle.
|
|
|
|
Fix this by testing the lowest possible frequency that the clock driver
|
|
can support which is within the mmc specification. Divide that rate by
|
|
the internal divider and set f_min to this.
|
|
|
|
Signed-off-by: Peter Geis <pgwipeout@gmail.com>
|
|
Link: https://lore.kernel.org/r/20220305215835.2210388-3-pgwipeout@gmail.com
|
|
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
|
---
|
|
drivers/mmc/host/dw_mmc-rockchip.c | 27 +++++++++++++++++++++++----
|
|
1 file changed, 23 insertions(+), 4 deletions(-)
|
|
|
|
--- a/drivers/mmc/host/dw_mmc-rockchip.c
|
|
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
|
|
@@ -15,7 +15,9 @@
|
|
#include "dw_mmc.h"
|
|
#include "dw_mmc-pltfm.h"
|
|
|
|
-#define RK3288_CLKGEN_DIV 2
|
|
+#define RK3288_CLKGEN_DIV 2
|
|
+
|
|
+static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 };
|
|
|
|
struct dw_mci_rockchip_priv_data {
|
|
struct clk *drv_clk;
|
|
@@ -51,7 +53,7 @@ static void dw_mci_rk3288_set_ios(struct
|
|
|
|
ret = clk_set_rate(host->ciu_clk, cclkin);
|
|
if (ret)
|
|
- dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);
|
|
+ dev_warn(host->dev, "failed to set rate %uHz err: %d\n", cclkin, ret);
|
|
|
|
bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV;
|
|
if (bus_hz != host->bus_hz) {
|
|
@@ -290,13 +292,30 @@ static int dw_mci_rk3288_parse_dt(struct
|
|
|
|
static int dw_mci_rockchip_init(struct dw_mci *host)
|
|
{
|
|
+ int ret, i;
|
|
+
|
|
/* It is slot 8 on Rockchip SoCs */
|
|
host->sdio_id0 = 8;
|
|
|
|
- if (of_device_is_compatible(host->dev->of_node,
|
|
- "rockchip,rk3288-dw-mshc"))
|
|
+ if (of_device_is_compatible(host->dev->of_node, "rockchip,rk3288-dw-mshc")) {
|
|
host->bus_hz /= RK3288_CLKGEN_DIV;
|
|
|
|
+ /* clock driver will fail if the clock is less than the lowest source clock
|
|
+ * divided by the internal clock divider. Test for the lowest available
|
|
+ * clock and set the minimum freq to clock / clock divider.
|
|
+ */
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(freqs); i++) {
|
|
+ ret = clk_round_rate(host->ciu_clk, freqs[i] * RK3288_CLKGEN_DIV);
|
|
+ if (ret > 0) {
|
|
+ host->minimum_speed = ret / RK3288_CLKGEN_DIV;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (ret < 0)
|
|
+ dev_warn(host->dev, "no valid minimum freq: %d\n", ret);
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|