179c83065SKever Yang /* 279c83065SKever Yang * (C) Copyright 2016 Fuzhou Rockchip Electronics Co., Ltd 379c83065SKever Yang * 479c83065SKever Yang * Rockchip SD Host Controller Interface 579c83065SKever Yang * 679c83065SKever Yang * SPDX-License-Identifier: GPL-2.0+ 779c83065SKever Yang */ 879c83065SKever Yang 9dce4cf74SZiyuan Xu #include <asm/arch/hardware.h> 1079c83065SKever Yang #include <common.h> 1179c83065SKever Yang #include <dm.h> 12c2868212SKever Yang #include <dt-structs.h> 13*0e00a84cSMasahiro Yamada #include <linux/libfdt.h> 1479c83065SKever Yang #include <malloc.h> 15c2868212SKever Yang #include <mapmem.h> 1679c83065SKever Yang #include <sdhci.h> 1739fbb56fSKever Yang #include <clk.h> 182f972333SKever Yang #include <syscon.h> 192f972333SKever Yang #include <dm/ofnode.h> 202f972333SKever Yang #include <asm/arch/clock.h> 2179c83065SKever Yang 2239fbb56fSKever Yang DECLARE_GLOBAL_DATA_PTR; 2379c83065SKever Yang /* 400KHz is max freq for card ID etc. Use that as min */ 2479c83065SKever Yang #define EMMC_MIN_FREQ 400000 2579c83065SKever Yang 2679c83065SKever Yang struct rockchip_sdhc_plat { 27c2868212SKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA) 28c2868212SKever Yang struct dtd_rockchip_rk3399_sdhci_5_1 dtplat; 29c2868212SKever Yang #endif 3079c83065SKever Yang struct mmc_config cfg; 3179c83065SKever Yang struct mmc mmc; 3279c83065SKever Yang }; 3379c83065SKever Yang 34dce4cf74SZiyuan Xu struct rockchip_emmc_phy { 35dce4cf74SZiyuan Xu u32 emmcphy_con[7]; 36dce4cf74SZiyuan Xu u32 reserved; 37dce4cf74SZiyuan Xu u32 emmcphy_status; 38dce4cf74SZiyuan Xu }; 39dce4cf74SZiyuan Xu 4079c83065SKever Yang struct rockchip_sdhc { 4179c83065SKever Yang struct sdhci_host host; 4279c83065SKever Yang void *base; 43dce4cf74SZiyuan Xu struct rockchip_emmc_phy *phy; 44cc0bf5edSchenfen struct clk emmc_clk; 4579c83065SKever Yang }; 4679c83065SKever Yang 47dce4cf74SZiyuan Xu #define PHYCTRL_CALDONE_MASK 0x1 48dce4cf74SZiyuan Xu #define PHYCTRL_CALDONE_SHIFT 0x6 49dce4cf74SZiyuan Xu #define PHYCTRL_CALDONE_DONE 0x1 50dce4cf74SZiyuan Xu 51dce4cf74SZiyuan Xu #define PHYCTRL_DLLRDY_MASK 0x1 52dce4cf74SZiyuan Xu #define PHYCTRL_DLLRDY_SHIFT 0x5 53dce4cf74SZiyuan Xu #define PHYCTRL_DLLRDY_DONE 0x1 54dce4cf74SZiyuan Xu 55dce4cf74SZiyuan Xu #define PHYCTRL_FREQSEL_200M 0x0 56dce4cf74SZiyuan Xu #define PHYCTRL_FREQSEL_50M 0x1 57dce4cf74SZiyuan Xu #define PHYCTRL_FREQSEL_100M 0x2 58dce4cf74SZiyuan Xu #define PHYCTRL_FREQSEL_150M 0x3 59dce4cf74SZiyuan Xu 60dce4cf74SZiyuan Xu #define KHz (1000) 61dce4cf74SZiyuan Xu #define MHz (1000 * KHz) 62dce4cf74SZiyuan Xu 63dce4cf74SZiyuan Xu static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) 64dce4cf74SZiyuan Xu { 65dce4cf74SZiyuan Xu u32 caldone, dllrdy, freqsel; 66dce4cf74SZiyuan Xu uint start; 67dce4cf74SZiyuan Xu 68dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(7 << 4, 0), &phy->emmcphy_con[6]); 69dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(1 << 11, 1 << 11), &phy->emmcphy_con[0]); 70cc0bf5edSchenfen writel(RK_CLRSETBITS(0xf << 7, 6 << 7), &phy->emmcphy_con[0]); 71dce4cf74SZiyuan Xu 72dce4cf74SZiyuan Xu /* 73dce4cf74SZiyuan Xu * According to the user manual, calpad calibration 74dce4cf74SZiyuan Xu * cycle takes more than 2us without the minimal recommended 75dce4cf74SZiyuan Xu * value, so we may need a little margin here 76dce4cf74SZiyuan Xu */ 77dce4cf74SZiyuan Xu udelay(3); 78dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(1, 1), &phy->emmcphy_con[6]); 79dce4cf74SZiyuan Xu 80dce4cf74SZiyuan Xu /* 81dce4cf74SZiyuan Xu * According to the user manual, it asks driver to 8210f01e73SZiyuan Xu * wait 5us for calpad busy trimming. But it seems that 8310f01e73SZiyuan Xu * 5us of caldone isn't enough for all cases. 84dce4cf74SZiyuan Xu */ 8510f01e73SZiyuan Xu udelay(500); 86dce4cf74SZiyuan Xu caldone = readl(&phy->emmcphy_status); 87dce4cf74SZiyuan Xu caldone = (caldone >> PHYCTRL_CALDONE_SHIFT) & PHYCTRL_CALDONE_MASK; 88dce4cf74SZiyuan Xu if (caldone != PHYCTRL_CALDONE_DONE) { 89fafc4637SZiyuan Xu printf("%s: caldone timeout.\n", __func__); 90dce4cf74SZiyuan Xu return; 91dce4cf74SZiyuan Xu } 92dce4cf74SZiyuan Xu 93dce4cf74SZiyuan Xu /* Set the frequency of the DLL operation */ 94dce4cf74SZiyuan Xu if (clock < 75 * MHz) 95dce4cf74SZiyuan Xu freqsel = PHYCTRL_FREQSEL_50M; 96dce4cf74SZiyuan Xu else if (clock < 125 * MHz) 97dce4cf74SZiyuan Xu freqsel = PHYCTRL_FREQSEL_100M; 98dce4cf74SZiyuan Xu else if (clock < 175 * MHz) 99dce4cf74SZiyuan Xu freqsel = PHYCTRL_FREQSEL_150M; 100dce4cf74SZiyuan Xu else 101dce4cf74SZiyuan Xu freqsel = PHYCTRL_FREQSEL_200M; 102dce4cf74SZiyuan Xu 103dce4cf74SZiyuan Xu /* Set the frequency of the DLL operation */ 104dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(3 << 12, freqsel << 12), &phy->emmcphy_con[0]); 105dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(1 << 1, 1 << 1), &phy->emmcphy_con[6]); 106dce4cf74SZiyuan Xu 107dce4cf74SZiyuan Xu start = get_timer(0); 108dce4cf74SZiyuan Xu 109dce4cf74SZiyuan Xu do { 110dce4cf74SZiyuan Xu udelay(1); 111dce4cf74SZiyuan Xu dllrdy = readl(&phy->emmcphy_status); 112dce4cf74SZiyuan Xu dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; 113dce4cf74SZiyuan Xu if (dllrdy == PHYCTRL_DLLRDY_DONE) 114dce4cf74SZiyuan Xu break; 115dce4cf74SZiyuan Xu } while (get_timer(start) < 50000); 116dce4cf74SZiyuan Xu 117dce4cf74SZiyuan Xu if (dllrdy != PHYCTRL_DLLRDY_DONE) 118fafc4637SZiyuan Xu printf("%s: dllrdy timeout.\n", __func__); 119dce4cf74SZiyuan Xu } 120dce4cf74SZiyuan Xu 121dce4cf74SZiyuan Xu static void rk3399_emmc_phy_power_off(struct rockchip_emmc_phy *phy) 122dce4cf74SZiyuan Xu { 123dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(1, 0), &phy->emmcphy_con[6]); 124dce4cf74SZiyuan Xu writel(RK_CLRSETBITS(1 << 1, 0), &phy->emmcphy_con[6]); 125dce4cf74SZiyuan Xu } 126dce4cf74SZiyuan Xu 127cc0bf5edSchenfen static int rk3399_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 128cc0bf5edSchenfen { 129cc0bf5edSchenfen unsigned int div, clk = 0, timeout; 130cc0bf5edSchenfen unsigned int input_clk; 131cc0bf5edSchenfen struct rockchip_sdhc *priv = 132cc0bf5edSchenfen container_of(host, struct rockchip_sdhc, host); 133cc0bf5edSchenfen 134cc0bf5edSchenfen /* Wait max 20 ms */ 135cc0bf5edSchenfen timeout = 200; 136cc0bf5edSchenfen while (sdhci_readl(host, SDHCI_PRESENT_STATE) & 137cc0bf5edSchenfen (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) { 138cc0bf5edSchenfen if (timeout == 0) { 139cc0bf5edSchenfen printf("%s: Timeout to wait cmd & data inhibit\n", 140cc0bf5edSchenfen __func__); 141cc0bf5edSchenfen return -EBUSY; 142cc0bf5edSchenfen } 143cc0bf5edSchenfen 144cc0bf5edSchenfen timeout--; 145cc0bf5edSchenfen udelay(100); 146cc0bf5edSchenfen } 147cc0bf5edSchenfen sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); 148cc0bf5edSchenfen 149cc0bf5edSchenfen if (clock == 0) 150cc0bf5edSchenfen return 0; 151cc0bf5edSchenfen 152cc0bf5edSchenfen input_clk = clk_set_rate(&priv->emmc_clk, clock); 153cc0bf5edSchenfen if (IS_ERR_VALUE(input_clk)) 154cc0bf5edSchenfen input_clk = host->max_clk; 155cc0bf5edSchenfen 156cc0bf5edSchenfen if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { 157cc0bf5edSchenfen /* 158cc0bf5edSchenfen * Check if the Host Controller supports Programmable Clock 159cc0bf5edSchenfen * Mode. 160cc0bf5edSchenfen */ 161cc0bf5edSchenfen if (host->clk_mul) { 162cc0bf5edSchenfen for (div = 1; div <= 1024; div++) { 163cc0bf5edSchenfen if ((input_clk / div) <= clock) 164cc0bf5edSchenfen break; 165cc0bf5edSchenfen } 166cc0bf5edSchenfen 167cc0bf5edSchenfen /* 168cc0bf5edSchenfen * Set Programmable Clock Mode in the Clock 169cc0bf5edSchenfen * Control register. 170cc0bf5edSchenfen */ 171cc0bf5edSchenfen clk = SDHCI_PROG_CLOCK_MODE; 172cc0bf5edSchenfen div--; 173cc0bf5edSchenfen } else { 174cc0bf5edSchenfen /* Version 3.00 divisors must be a multiple of 2. */ 175cc0bf5edSchenfen if (input_clk <= clock) { 176cc0bf5edSchenfen div = 1; 177cc0bf5edSchenfen } else { 178cc0bf5edSchenfen for (div = 2; 179cc0bf5edSchenfen div < SDHCI_MAX_DIV_SPEC_300; 180cc0bf5edSchenfen div += 2) { 181cc0bf5edSchenfen if ((input_clk / div) <= clock) 182cc0bf5edSchenfen break; 183cc0bf5edSchenfen } 184cc0bf5edSchenfen } 185cc0bf5edSchenfen div >>= 1; 186cc0bf5edSchenfen } 187cc0bf5edSchenfen } else { 188cc0bf5edSchenfen /* Version 2.00 divisors must be a power of 2. */ 189cc0bf5edSchenfen for (div = 1; div < SDHCI_MAX_DIV_SPEC_200; div *= 2) { 190cc0bf5edSchenfen if ((input_clk / div) <= clock) 191cc0bf5edSchenfen break; 192cc0bf5edSchenfen } 193cc0bf5edSchenfen div >>= 1; 194cc0bf5edSchenfen } 195cc0bf5edSchenfen 196cc0bf5edSchenfen clk |= (div & SDHCI_DIV_MASK) << SDHCI_DIVIDER_SHIFT; 197cc0bf5edSchenfen clk |= ((div & SDHCI_DIV_HI_MASK) >> SDHCI_DIV_MASK_LEN) 198cc0bf5edSchenfen << SDHCI_DIVIDER_HI_SHIFT; 199cc0bf5edSchenfen clk |= SDHCI_CLOCK_INT_EN; 200cc0bf5edSchenfen sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 201cc0bf5edSchenfen 202cc0bf5edSchenfen /* Wait max 20 ms */ 203cc0bf5edSchenfen timeout = 20; 204cc0bf5edSchenfen while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) 205cc0bf5edSchenfen & SDHCI_CLOCK_INT_STABLE)) { 206cc0bf5edSchenfen if (timeout == 0) { 207cc0bf5edSchenfen printf("%s: Internal clock never stabilised.\n", 208cc0bf5edSchenfen __func__); 209cc0bf5edSchenfen return -EBUSY; 210cc0bf5edSchenfen } 211cc0bf5edSchenfen timeout--; 212cc0bf5edSchenfen udelay(1000); 213cc0bf5edSchenfen } 214cc0bf5edSchenfen clk |= SDHCI_CLOCK_CARD_EN; 215cc0bf5edSchenfen sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); 216cc0bf5edSchenfen host->clock = clock; 217cc0bf5edSchenfen 218cc0bf5edSchenfen return 0; 219cc0bf5edSchenfen } 220cc0bf5edSchenfen 221dce4cf74SZiyuan Xu static int arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 222dce4cf74SZiyuan Xu { 223dce4cf74SZiyuan Xu struct rockchip_sdhc *priv = 224dce4cf74SZiyuan Xu container_of(host, struct rockchip_sdhc, host); 225dce4cf74SZiyuan Xu int cycle_phy = host->clock != clock && 226dce4cf74SZiyuan Xu clock > EMMC_MIN_FREQ; 227dce4cf74SZiyuan Xu 228dce4cf74SZiyuan Xu if (cycle_phy) 229dce4cf74SZiyuan Xu rk3399_emmc_phy_power_off(priv->phy); 230dce4cf74SZiyuan Xu 231cc0bf5edSchenfen rk3399_sdhci_set_clock(host, clock); 232dce4cf74SZiyuan Xu 233dce4cf74SZiyuan Xu if (cycle_phy) 234dce4cf74SZiyuan Xu rk3399_emmc_phy_power_on(priv->phy, clock); 235dce4cf74SZiyuan Xu 236dce4cf74SZiyuan Xu return 0; 237dce4cf74SZiyuan Xu } 238dce4cf74SZiyuan Xu 239dce4cf74SZiyuan Xu static struct sdhci_ops arasan_sdhci_ops = { 240dce4cf74SZiyuan Xu .set_clock = arasan_sdhci_set_clock, 241dce4cf74SZiyuan Xu }; 242dce4cf74SZiyuan Xu 243dce4cf74SZiyuan Xu static int arasan_get_phy(struct udevice *dev) 244dce4cf74SZiyuan Xu { 245dce4cf74SZiyuan Xu struct rockchip_sdhc *priv = dev_get_priv(dev); 246dce4cf74SZiyuan Xu 247dce4cf74SZiyuan Xu #if CONFIG_IS_ENABLED(OF_PLATDATA) 248dce4cf74SZiyuan Xu priv->phy = (struct rockchip_emmc_phy *)0xff77f780; 249dce4cf74SZiyuan Xu #else 2502f972333SKever Yang ofnode phy_node; 2512f972333SKever Yang void *grf_base; 2522f972333SKever Yang u32 grf_phy_offset, phandle; 253dce4cf74SZiyuan Xu 2542f972333SKever Yang phandle = dev_read_u32_default(dev, "phys", 0); 2552f972333SKever Yang phy_node = ofnode_get_by_phandle(phandle); 2562f972333SKever Yang if (!ofnode_valid(phy_node)) { 257dce4cf74SZiyuan Xu debug("Not found emmc phy device\n"); 258dce4cf74SZiyuan Xu return -ENODEV; 259dce4cf74SZiyuan Xu } 260dce4cf74SZiyuan Xu 2612f972333SKever Yang grf_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); 2622f972333SKever Yang if (grf_base < 0) 2632f972333SKever Yang printf("%s Get syscon grf failed", __func__); 2642f972333SKever Yang grf_phy_offset = ofnode_read_u32_default(phy_node, "reg", 0); 265dce4cf74SZiyuan Xu 266dce4cf74SZiyuan Xu priv->phy = (struct rockchip_emmc_phy *)(grf_base + grf_phy_offset); 267dce4cf74SZiyuan Xu #endif 268dce4cf74SZiyuan Xu return 0; 269dce4cf74SZiyuan Xu } 270dce4cf74SZiyuan Xu 27179c83065SKever Yang static int arasan_sdhci_probe(struct udevice *dev) 27279c83065SKever Yang { 27379c83065SKever Yang struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); 27479c83065SKever Yang struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 27579c83065SKever Yang struct rockchip_sdhc *prv = dev_get_priv(dev); 27679c83065SKever Yang struct sdhci_host *host = &prv->host; 27739fbb56fSKever Yang int max_frequency, ret; 27839fbb56fSKever Yang struct clk clk; 27939fbb56fSKever Yang 280c2868212SKever Yang #if CONFIG_IS_ENABLED(OF_PLATDATA) 281c2868212SKever Yang struct dtd_rockchip_rk3399_sdhci_5_1 *dtplat = &plat->dtplat; 28239fbb56fSKever Yang 283c2868212SKever Yang host->name = dev->name; 284adcf6d06SKever Yang host->ioaddr = map_sysmem(dtplat->reg[0], dtplat->reg[1]); 2852a62bae8SZiyuan Xu host->host_caps |= MMC_MODE_8BIT; 286c2868212SKever Yang max_frequency = dtplat->max_frequency; 287c2868212SKever Yang ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &clk); 288c2868212SKever Yang #else 289fd1bf8dfSPhilipp Tomsich max_frequency = dev_read_u32_default(dev, "max-frequency", 0); 2902a62bae8SZiyuan Xu switch (dev_read_u32_default(dev, "bus-width", 4)) { 2912a62bae8SZiyuan Xu case 8: 2922a62bae8SZiyuan Xu host->host_caps |= MMC_MODE_8BIT; 2932a62bae8SZiyuan Xu break; 2942a62bae8SZiyuan Xu case 4: 2952a62bae8SZiyuan Xu host->host_caps |= MMC_MODE_4BIT; 2962a62bae8SZiyuan Xu break; 2972a62bae8SZiyuan Xu case 1: 2982a62bae8SZiyuan Xu break; 2992a62bae8SZiyuan Xu default: 3002a62bae8SZiyuan Xu printf("Invalid \"bus-width\" value\n"); 3012a62bae8SZiyuan Xu return -EINVAL; 3022a62bae8SZiyuan Xu } 30339fbb56fSKever Yang ret = clk_get_by_index(dev, 0, &clk); 304c2868212SKever Yang #endif 30539fbb56fSKever Yang if (!ret) { 30639fbb56fSKever Yang ret = clk_set_rate(&clk, max_frequency); 30739fbb56fSKever Yang if (IS_ERR_VALUE(ret)) 30839fbb56fSKever Yang printf("%s clk set rate fail!\n", __func__); 30939fbb56fSKever Yang } else { 31039fbb56fSKever Yang printf("%s fail to get clk\n", __func__); 31139fbb56fSKever Yang } 31279c83065SKever Yang 313cc0bf5edSchenfen prv->emmc_clk = clk; 314dce4cf74SZiyuan Xu ret = arasan_get_phy(dev); 315dce4cf74SZiyuan Xu if (ret) 316dce4cf74SZiyuan Xu return ret; 317dce4cf74SZiyuan Xu 318dce4cf74SZiyuan Xu host->ops = &arasan_sdhci_ops; 319dce4cf74SZiyuan Xu 32079c83065SKever Yang host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD; 3216d0e34bfSStefan Herbrechtsmeier host->max_clk = max_frequency; 32279c83065SKever Yang 323a59bd218SJason Zhu if (dev_read_bool(dev, "mmc-hs200-1_8v")) 324a59bd218SJason Zhu host->host_caps |= MMC_MODE_HS200; 325a59bd218SJason Zhu else if (dev_read_bool(dev, "mmc-hs400-1_8v")) 326a59bd218SJason Zhu host->host_caps |= MMC_MODE_HS400; 3276d0e34bfSStefan Herbrechtsmeier ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ); 32879c83065SKever Yang 32979c83065SKever Yang host->mmc = &plat->mmc; 33079c83065SKever Yang if (ret) 33179c83065SKever Yang return ret; 33279c83065SKever Yang host->mmc->priv = &prv->host; 33379c83065SKever Yang host->mmc->dev = dev; 33479c83065SKever Yang upriv->mmc = host->mmc; 33579c83065SKever Yang 33679c83065SKever Yang return sdhci_probe(dev); 33779c83065SKever Yang } 33879c83065SKever Yang 33979c83065SKever Yang static int arasan_sdhci_ofdata_to_platdata(struct udevice *dev) 34079c83065SKever Yang { 341c2868212SKever Yang #if !CONFIG_IS_ENABLED(OF_PLATDATA) 34279c83065SKever Yang struct sdhci_host *host = dev_get_priv(dev); 34379c83065SKever Yang 34479c83065SKever Yang host->name = dev->name; 3454ae650e5SPhilipp Tomsich host->ioaddr = dev_read_addr_ptr(dev); 346c2868212SKever Yang #endif 34779c83065SKever Yang 34879c83065SKever Yang return 0; 34979c83065SKever Yang } 35079c83065SKever Yang 35179c83065SKever Yang static int rockchip_sdhci_bind(struct udevice *dev) 35279c83065SKever Yang { 35379c83065SKever Yang struct rockchip_sdhc_plat *plat = dev_get_platdata(dev); 35479c83065SKever Yang 35524f5aec3SMasahiro Yamada return sdhci_bind(dev, &plat->mmc, &plat->cfg); 35679c83065SKever Yang } 35779c83065SKever Yang 35879c83065SKever Yang static const struct udevice_id arasan_sdhci_ids[] = { 35979c83065SKever Yang { .compatible = "arasan,sdhci-5.1" }, 36079c83065SKever Yang { } 36179c83065SKever Yang }; 36279c83065SKever Yang 36379c83065SKever Yang U_BOOT_DRIVER(arasan_sdhci_drv) = { 364c2868212SKever Yang .name = "rockchip_rk3399_sdhci_5_1", 36579c83065SKever Yang .id = UCLASS_MMC, 36679c83065SKever Yang .of_match = arasan_sdhci_ids, 36779c83065SKever Yang .ofdata_to_platdata = arasan_sdhci_ofdata_to_platdata, 36879c83065SKever Yang .ops = &sdhci_ops, 36979c83065SKever Yang .bind = rockchip_sdhci_bind, 37079c83065SKever Yang .probe = arasan_sdhci_probe, 37179c83065SKever Yang .priv_auto_alloc_size = sizeof(struct rockchip_sdhc), 37279c83065SKever Yang .platdata_auto_alloc_size = sizeof(struct rockchip_sdhc_plat), 37379c83065SKever Yang }; 374