1 /* 2 * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * Rockchip SD Host Controller Interface 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 */ 8 9 #include <asm/arch/hardware.h> 10 #include <common.h> 11 #include <dm.h> 12 #include <dt-structs.h> 13 #include <libfdt.h> 14 #include <malloc.h> 15 #include <mapmem.h> 16 #include <sdhci.h> 17 #include <clk.h> 18 #include <syscon.h> 19 #include <dm/ofnode.h> 20 #include <asm/arch/clock.h> 21 22 DECLARE_GLOBAL_DATA_PTR; 23 /* 400KHz is max freq for card ID etc. Use that as min */ 24 #define EMMC_MIN_FREQ 400000 25 26 struct rockchip_sdhc_plat { 27 #if CONFIG_IS_ENABLED(OF_PLATDATA) 28 struct dtd_rockchip_rk3399_sdhci_5_1 dtplat; 29 #endif 30 struct mmc_config cfg; 31 struct mmc mmc; 32 }; 33 34 struct rockchip_emmc_phy { 35 u32 emmcphy_con[7]; 36 u32 reserved; 37 u32 emmcphy_status; 38 }; 39 40 struct rockchip_sdhc { 41 struct sdhci_host host; 42 void *base; 43 struct rockchip_emmc_phy *phy; 44 }; 45 46 #define PHYCTRL_CALDONE_MASK 0x1 47 #define PHYCTRL_CALDONE_SHIFT 0x6 48 #define PHYCTRL_CALDONE_DONE 0x1 49 50 #define PHYCTRL_DLLRDY_MASK 0x1 51 #define PHYCTRL_DLLRDY_SHIFT 0x5 52 #define PHYCTRL_DLLRDY_DONE 0x1 53 54 #define PHYCTRL_FREQSEL_200M 0x0 55 #define PHYCTRL_FREQSEL_50M 0x1 56 #define PHYCTRL_FREQSEL_100M 0x2 57 #define PHYCTRL_FREQSEL_150M 0x3 58 59 #define KHz (1000) 60 #define MHz (1000 * KHz) 61 62 static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) 63 { 64 u32 caldone, dllrdy, freqsel; 65 uint start; 66 67 writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]); 68 writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]); 69 writel(RK_CLRSETBITS(0xf << 7, 4 << 7), &phy->emmcphy_con[0]); 70 71 /* 72 * According to the user manual, calpad calibration 73 * cycle takes more than 2us without the minimal recommended 74 * value, so we may need a little margin here 75 */ 76 udelay(3); 77 writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]); 78 79 /* 80 * According to the user manual, it asks driver to 81 * wait 5us for calpad busy trimming 82 */ 83 udelay(5); 84 caldone = readl(&phy->emmcphy_status); 85 caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK; 86 if (caldone != PHYCTRL_CALDONE_DONE) { 87 debug("%s: caldone timeout.\n", __func__); 88 return; 89 } 90 91 /* Set the frequency of the DLL operation */ 92 if (clock < 75 * MHz) 93 freqsel = PHYCTRL_FREQSEL_50M; 94 else if (clock < 125 * MHz) 95 freqsel = PHYCTRL_FREQSEL_100M; 96 else if (clock < 175 * MHz) 97 freqsel = PHYCTRL_FREQSEL_150M; 98 else 99 freqsel = PHYCTRL_FREQSEL_200M; 100 101 /* Set the frequency of the DLL operation */ 102 writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]); 103 writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]); 104 105 start = get_timer(0); 106 107 do { 108 udelay(1); 109 dllrdy = readl(&phy->emmcphy_status); 110 dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; 111 if (dllrdy == PHYCTRL_DLLRDY_DONE) 112 break; 113 } while (get_timer(start) < 50000); 114 115 if (dllrdy != PHYCTRL_DLLRDY_DONE) 116 debug("%s: dllrdy timeout.\n", __func__); 117 } 118 119 static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy) 120 { 121 writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]); 122 writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]); 123 } 124 125 static int arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 126 { 127 struct rockchip_sdhc *priv = 128 container_of(host, struct rockchip_sdhc, host); 129 int cycle_phy = host->clock != clock && 130 clock > EMMC_MIN_FREQ; 131 132 if (cycle_phy) 133 rk3399_emmc_phy_power_off(priv->phy); 134 135 sdhci_set_clock(host, clock); 136 137 if (cycle_phy) 138 rk3399_emmc_phy_power_on(priv->phy, clock); 139 140 return 0; 141 } 142 143 static struct sdhci_ops arasan_sdhci_ops = { 144 .set_clock = arasan_sdhci_set_clock, 145 }; 146 147 static int arasan_get_phy(struct udevice *dev) 148 { 149 struct rockchip_sdhc *priv = dev_get_priv(dev); 150 151 #if CONFIG_IS_ENABLED(OF_PLATDATA) 152 priv->phy = (struct rockchip_emmc_phy *)0xff77f780; 153 #else 154 ofnode phy_node; 155 void *grf_base; 156 u32 grf_phy_offset, phandle; 157 158 phandle = dev_read_u32_default(dev, "phys", 0); 159 phy_node = ofnode_get_by_phandle(phandle); 160 if (!ofnode_valid(phy_node)) { 161 debug("Not found emmc phy device\n"); 162 return -ENODEV; 163 } 164 165 grf_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 166 if (grf_base < 0) 167 printf("%s Get syscon grf failed", __func__); 168 grf_phy_offset = ofnode_read_u32_default(phy_node, "reg", 0); 169 170 priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset); 171 #endif 172 return 0; 173 } 174 175 static int arasan_sdhci_probe(struct udevice *dev) 176 { 177 struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 178 struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 179 struct rockchip_sdhc *prv = dev_get_priv(dev); 180 struct sdhci_host *host = &prv->host; 181 int max_frequency, ret; 182 struct clk clk; 183 184 #if CONFIG_IS_ENABLED(OF_PLATDATA) 185 struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat; 186 187 host->name = dev->name; 188 host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); 189 host->host_caps |= MMC_MODE_8BIT; 190 max_frequency = dtplat->max_frequency; 191 ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); 192 #else 193 max_frequency = dev_read_u32_default(dev, "max-frequency", 0); 194 switch (dev_read_u32_default(dev, "bus-width", 4)) { 195 case 8: 196 host->host_caps |= MMC_MODE_8BIT; 197 break; 198 case 4: 199 host->host_caps |= MMC_MODE_4BIT; 200 break; 201 case 1: 202 break; 203 default: 204 printf("Invalid \"bus-width\" value\n"); 205 return -EINVAL; 206 } 207 ret = clk_get_by_index(dev, 0, &clk); 208 #endif 209 if (!ret) { 210 ret = clk_set_rate(&clk, max_frequency); 211 if (IS_ERR_VALUE(ret)) 212 printf("%s clk set rate fail!\n", __func__); 213 } else { 214 printf("%s fail to get clk\n", __func__); 215 } 216 217 ret = arasan_get_phy(dev); 218 if (ret) 219 return ret; 220 221 host->ops = &arasan_sdhci_ops; 222 223 host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; 224 host->max_clk = max_frequency; 225 226 ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); 227 228 host->mmc = &plat->mmc; 229 if (ret) 230 return ret; 231 host->mmc->priv = &prv->host; 232 host->mmc->dev = dev; 233 upriv->mmc = host->mmc; 234 235 return sdhci_probe(dev); 236 } 237 238 static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 239 { 240 #if !CONFIG_IS_ENABLED(OF_PLATDATA) 241 struct sdhci_host *host = dev_get_priv(dev); 242 243 host->name = dev->name; 244 host->ioaddr = dev_read_addr_ptr(dev); 245 #endif 246 247 return 0; 248 } 249 250 static int rockchip_sdhci_bind(struct udevice *dev) 251 { 252 struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 253 254 return sdhci_bind(dev, &plat->mmc, &plat->cfg); 255 } 256 257 static const struct udevice_id arasan_sdhci_ids[] = { 258 { .compatible = "arasan,sdhci-5.1" }, 259 { } 260 }; 261 262 U_BOOT_DRIVER(arasan_sdhci_drv) = { 263 .name = "rockchip_rk3399_sdhci_5_1", 264 .id = UCLASS_MMC, 265 .of_match = arasan_sdhci_ids, 266 .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 267 .ops = &sdhci_ops, 268 .bind = rockchip_sdhci_bind, 269 .probe = arasan_sdhci_probe, 270 .priv_auto_alloc_size = sizeof(struct rockchip_sdhc), 271 .platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat), 272 }; 273