@@ -20,6 +20,9 @@
#include "dw_mmc-pltfm.h"
#define RK3288_CLKGEN_DIV 2
+#define RKMMC_RDYINT_GEN 0x120
+#define RKMMC_RDYINT_GEN_WORKING BIT(8)
+#define RKMMC_RDYINT_GEN_MAXVAL GENMASK(7, 0)
struct dw_mci_rockchip_priv_data {
struct clk *drv_clk;
@@ -28,6 +31,23 @@ struct dw_mci_rockchip_priv_data {
int num_phases;
};
+static int dw_mci_rockchip_prepare_hw_unbusy(struct dw_mci *host,
+ bool enable)
+{
+ u32 reg = readl(host->regs + RKMMC_RDYINT_GEN);
+
+ if (enable)
+ /* Self-clean when generating unbusy int */
+ reg |= RKMMC_RDYINT_GEN_WORKING;
+ else
+ /* Otherwise do it manually to avoid racing condition */
+ reg &= ~RKMMC_RDYINT_GEN_WORKING;
+
+ writel(reg, host->regs + RKMMC_RDYINT_GEN);
+
+ return 0;
+}
+
static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
{
struct dw_mci_rockchip_priv_data *priv = host->priv;
@@ -301,6 +321,15 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
"rockchip,rk3288-dw-mshc"))
host->bus_hz /= RK3288_CLKGEN_DIV;
+ /* Some Rockchip SoCs use hw unbusy int */
+ if (of_device_is_compatible(host->dev->of_node,
+ "rockchip,rk1808-dw-mshc")) {
+ host->hw_unbusy_int = 16;
+ writel(~(RKMMC_RDYINT_GEN_WORKING |
+ RKMMC_RDYINT_GEN_MAXVAL),
+ host->regs + RKMMC_RDYINT_GEN);
+ }
+
return 0;
}
@@ -322,6 +351,7 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
.set_ios = dw_mci_rk3288_set_ios,
.execute_tuning = dw_mci_rk3288_execute_tuning,
.parse_dt = dw_mci_rk3288_parse_dt,
+ .prepare_hw_unbusy = dw_mci_rockchip_prepare_hw_unbusy,
.init = dw_mci_rockchip_init,
};
The new register for controlling hardware unbusy interrupt is in 0x120. It looks like: |------------------------------------------------------------| |Bit | Attribute | Reset Value | Description | |------------------------------------------------------------| |31:25 | RO | 0x0 | reserved | |------------------------------------------------------------| |24 | RO | 0x0 | rdyint_cnt_finish | | | | |When high, it indicates| | | | |that the rdyint counter| | | | |is finished. | |------------------------------------------------------------| |23:16 | RO | 0x0 | rdyint_cnt_status | | | | |Couner status, reflect | | | | |internal counter value.| |------------------------------------------------------------| |15:9 | RO | 0x0 | reserved | |------------------------------------------------------------| |8 | RW | 0x0 | rdyint_gen_working | | | | |When set, IP starts to | | | | |count and generate one | | | | |rdyint trigger. After | | | | |the rdyint trigger is | | | | |generated, it will be | | | | |cleaned automatically. | | | | |Software should set it | | | | |again next time. | |------------------------------------------------------------| |7:0 | RW | 0xff | rdyint_gen_maxval | | | | |Max counter value for | | | | |the IP to count when | | | | |rdyint_gen_working is | | | | |set. This counter is | | | | |based on biu_clk. | |------------------------------------------------------------| Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com> --- drivers/mmc/host/dw_mmc-rockchip.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)