12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 24cdc2ec1Saddy ke /* 34cdc2ec1Saddy ke * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 44cdc2ec1Saddy ke */ 54cdc2ec1Saddy ke 64cdc2ec1Saddy ke #include <linux/module.h> 74cdc2ec1Saddy ke #include <linux/platform_device.h> 84cdc2ec1Saddy ke #include <linux/clk.h> 94cdc2ec1Saddy ke #include <linux/mmc/host.h> 104cdc2ec1Saddy ke #include <linux/of_address.h> 111f5c51d7SShawn Lin #include <linux/mmc/slot-gpio.h> 12f9014268SShawn Lin #include <linux/pm_runtime.h> 13cbb79e43SAlexandru M Stan #include <linux/slab.h> 144cdc2ec1Saddy ke 154cdc2ec1Saddy ke #include "dw_mmc.h" 164cdc2ec1Saddy ke #include "dw_mmc-pltfm.h" 174cdc2ec1Saddy ke 184cdc2ec1Saddy ke #define RK3288_CLKGEN_DIV 2 194cdc2ec1Saddy ke 2052c92286SPeter Geis static const unsigned int freqs[] = { 100000, 200000, 300000, 400000 }; 2152c92286SPeter Geis 22cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data { 23cbb79e43SAlexandru M Stan struct clk *drv_clk; 24cbb79e43SAlexandru M Stan struct clk *sample_clk; 25cbb79e43SAlexandru M Stan int default_sample_phase; 261a12a70fSShawn Lin int num_phases; 27cbb79e43SAlexandru M Stan }; 28cbb79e43SAlexandru M Stan 294cdc2ec1Saddy ke static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) 304cdc2ec1Saddy ke { 31cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv = host->priv; 324cdc2ec1Saddy ke int ret; 334cdc2ec1Saddy ke unsigned int cclkin; 344cdc2ec1Saddy ke u32 bus_hz; 354cdc2ec1Saddy ke 36e7791079SDoug Anderson if (ios->clock == 0) 37e7791079SDoug Anderson return; 38e7791079SDoug Anderson 394cdc2ec1Saddy ke /* 404cdc2ec1Saddy ke * cclkin: source clock of mmc controller 414cdc2ec1Saddy ke * bus_hz: card interface clock generated by CLKGEN 424cdc2ec1Saddy ke * bus_hz = cclkin / RK3288_CLKGEN_DIV 434cdc2ec1Saddy ke * ios->clock = (div == 0) ? bus_hz : (bus_hz / (2 * div)) 444cdc2ec1Saddy ke * 45d39b1b2aSShawn Lin * Note: div can only be 0 or 1, but div must be set to 1 for eMMC 46d39b1b2aSShawn Lin * DDR52 8-bit mode. 474cdc2ec1Saddy ke */ 484cdc2ec1Saddy ke if (ios->bus_width == MMC_BUS_WIDTH_8 && 494cdc2ec1Saddy ke ios->timing == MMC_TIMING_MMC_DDR52) 504cdc2ec1Saddy ke cclkin = 2 * ios->clock * RK3288_CLKGEN_DIV; 514cdc2ec1Saddy ke else 524cdc2ec1Saddy ke cclkin = ios->clock * RK3288_CLKGEN_DIV; 534cdc2ec1Saddy ke 544cdc2ec1Saddy ke ret = clk_set_rate(host->ciu_clk, cclkin); 554cdc2ec1Saddy ke if (ret) 5652c92286SPeter Geis dev_warn(host->dev, "failed to set rate %uHz err: %d\n", cclkin, ret); 574cdc2ec1Saddy ke 584cdc2ec1Saddy ke bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV; 594cdc2ec1Saddy ke if (bus_hz != host->bus_hz) { 604cdc2ec1Saddy ke host->bus_hz = bus_hz; 614cdc2ec1Saddy ke /* force dw_mci_setup_bus() */ 624cdc2ec1Saddy ke host->current_speed = 0; 634cdc2ec1Saddy ke } 64cbb79e43SAlexandru M Stan 65cbb79e43SAlexandru M Stan /* Make sure we use phases which we can enumerate with */ 66df4e1372SShawn Lin if (!IS_ERR(priv->sample_clk) && ios->timing <= MMC_TIMING_SD_HS) 67cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, priv->default_sample_phase); 68d4aa908cSDouglas Anderson 69d4aa908cSDouglas Anderson /* 70d4aa908cSDouglas Anderson * Set the drive phase offset based on speed mode to achieve hold times. 71d4aa908cSDouglas Anderson * 72d4aa908cSDouglas Anderson * NOTE: this is _not_ a value that is dynamically tuned and is also 73d4aa908cSDouglas Anderson * _not_ a value that will vary from board to board. It is a value 74d4aa908cSDouglas Anderson * that could vary between different SoC models if they had massively 75d4aa908cSDouglas Anderson * different output clock delays inside their dw_mmc IP block (delay_o), 76d4aa908cSDouglas Anderson * but since it's OK to overshoot a little we don't need to do complex 77d4aa908cSDouglas Anderson * calculations and can pick values that will just work for everyone. 78d4aa908cSDouglas Anderson * 79d4aa908cSDouglas Anderson * When picking values we'll stick with picking 0/90/180/270 since 80d4aa908cSDouglas Anderson * those can be made very accurately on all known Rockchip SoCs. 81d4aa908cSDouglas Anderson * 82d4aa908cSDouglas Anderson * Note that these values match values from the DesignWare Databook 83d4aa908cSDouglas Anderson * tables for the most part except for SDR12 and "ID mode". For those 84d4aa908cSDouglas Anderson * two modes the databook calculations assume a clock in of 50MHz. As 85d4aa908cSDouglas Anderson * seen above, we always use a clock in rate that is exactly the 86d4aa908cSDouglas Anderson * card's input clock (times RK3288_CLKGEN_DIV, but that gets divided 87d4aa908cSDouglas Anderson * back out before the controller sees it). 88d4aa908cSDouglas Anderson * 89d4aa908cSDouglas Anderson * From measurement of a single device, it appears that delay_o is 90d4aa908cSDouglas Anderson * about .5 ns. Since we try to leave a bit of margin, it's expected 91d4aa908cSDouglas Anderson * that numbers here will be fine even with much larger delay_o 92d4aa908cSDouglas Anderson * (the 1.4 ns assumed by the DesignWare Databook would result in the 93d4aa908cSDouglas Anderson * same results, for instance). 94d4aa908cSDouglas Anderson */ 95d4aa908cSDouglas Anderson if (!IS_ERR(priv->drv_clk)) { 96d4aa908cSDouglas Anderson int phase; 97d4aa908cSDouglas Anderson 98d4aa908cSDouglas Anderson /* 99d4aa908cSDouglas Anderson * In almost all cases a 90 degree phase offset will provide 100d4aa908cSDouglas Anderson * sufficient hold times across all valid input clock rates 101d4aa908cSDouglas Anderson * assuming delay_o is not absurd for a given SoC. We'll use 102d4aa908cSDouglas Anderson * that as a default. 103d4aa908cSDouglas Anderson */ 104d4aa908cSDouglas Anderson phase = 90; 105d4aa908cSDouglas Anderson 106d4aa908cSDouglas Anderson switch (ios->timing) { 107d4aa908cSDouglas Anderson case MMC_TIMING_MMC_DDR52: 108d4aa908cSDouglas Anderson /* 109d4aa908cSDouglas Anderson * Since clock in rate with MMC_DDR52 is doubled when 110d4aa908cSDouglas Anderson * bus width is 8 we need to double the phase offset 111d4aa908cSDouglas Anderson * to get the same timings. 112d4aa908cSDouglas Anderson */ 113d4aa908cSDouglas Anderson if (ios->bus_width == MMC_BUS_WIDTH_8) 114d4aa908cSDouglas Anderson phase = 180; 115d4aa908cSDouglas Anderson break; 116d4aa908cSDouglas Anderson case MMC_TIMING_UHS_SDR104: 117d4aa908cSDouglas Anderson case MMC_TIMING_MMC_HS200: 118d4aa908cSDouglas Anderson /* 119d4aa908cSDouglas Anderson * In the case of 150 MHz clock (typical max for 120d4aa908cSDouglas Anderson * Rockchip SoCs), 90 degree offset will add a delay 121d4aa908cSDouglas Anderson * of 1.67 ns. That will meet min hold time of .8 ns 122d4aa908cSDouglas Anderson * as long as clock output delay is < .87 ns. On 123d4aa908cSDouglas Anderson * SoCs measured this seems to be OK, but it doesn't 124d4aa908cSDouglas Anderson * hurt to give margin here, so we use 180. 125d4aa908cSDouglas Anderson */ 126d4aa908cSDouglas Anderson phase = 180; 127d4aa908cSDouglas Anderson break; 128d4aa908cSDouglas Anderson } 129d4aa908cSDouglas Anderson 130d4aa908cSDouglas Anderson clk_set_phase(priv->drv_clk, phase); 131d4aa908cSDouglas Anderson } 132cbb79e43SAlexandru M Stan } 133cbb79e43SAlexandru M Stan 1341a12a70fSShawn Lin #define TUNING_ITERATION_TO_PHASE(i, num_phases) \ 1351a12a70fSShawn Lin (DIV_ROUND_UP((i) * 360, num_phases)) 136cbb79e43SAlexandru M Stan 1379979dbe5SChaotian Jing static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot, u32 opcode) 138cbb79e43SAlexandru M Stan { 139cbb79e43SAlexandru M Stan struct dw_mci *host = slot->host; 140cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv = host->priv; 141cbb79e43SAlexandru M Stan struct mmc_host *mmc = slot->mmc; 142cbb79e43SAlexandru M Stan int ret = 0; 143cbb79e43SAlexandru M Stan int i; 144cbb79e43SAlexandru M Stan bool v, prev_v = 0, first_v; 145cbb79e43SAlexandru M Stan struct range_t { 146cbb79e43SAlexandru M Stan int start; 147cbb79e43SAlexandru M Stan int end; /* inclusive */ 148cbb79e43SAlexandru M Stan }; 149cbb79e43SAlexandru M Stan struct range_t *ranges; 150cbb79e43SAlexandru M Stan unsigned int range_count = 0; 151cbb79e43SAlexandru M Stan int longest_range_len = -1; 152cbb79e43SAlexandru M Stan int longest_range = -1; 153cbb79e43SAlexandru M Stan int middle_phase; 154cbb79e43SAlexandru M Stan 155cbb79e43SAlexandru M Stan if (IS_ERR(priv->sample_clk)) { 156cbb79e43SAlexandru M Stan dev_err(host->dev, "Tuning clock (sample_clk) not defined.\n"); 157cbb79e43SAlexandru M Stan return -EIO; 158cbb79e43SAlexandru M Stan } 159cbb79e43SAlexandru M Stan 1601a12a70fSShawn Lin ranges = kmalloc_array(priv->num_phases / 2 + 1, 1611a12a70fSShawn Lin sizeof(*ranges), GFP_KERNEL); 162cbb79e43SAlexandru M Stan if (!ranges) 163cbb79e43SAlexandru M Stan return -ENOMEM; 164cbb79e43SAlexandru M Stan 165cbb79e43SAlexandru M Stan /* Try each phase and extract good ranges */ 1661a12a70fSShawn Lin for (i = 0; i < priv->num_phases; ) { 1671a12a70fSShawn Lin clk_set_phase(priv->sample_clk, 1681a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(i, priv->num_phases)); 169cbb79e43SAlexandru M Stan 1709979dbe5SChaotian Jing v = !mmc_send_tuning(mmc, opcode, NULL); 171cbb79e43SAlexandru M Stan 172cbb79e43SAlexandru M Stan if (i == 0) 173cbb79e43SAlexandru M Stan first_v = v; 174cbb79e43SAlexandru M Stan 175cbb79e43SAlexandru M Stan if ((!prev_v) && v) { 176cbb79e43SAlexandru M Stan range_count++; 177cbb79e43SAlexandru M Stan ranges[range_count-1].start = i; 178cbb79e43SAlexandru M Stan } 179cbb79e43SAlexandru M Stan if (v) { 180cbb79e43SAlexandru M Stan ranges[range_count-1].end = i; 181cbb79e43SAlexandru M Stan i++; 1821a12a70fSShawn Lin } else if (i == priv->num_phases - 1) { 183cbb79e43SAlexandru M Stan /* No extra skipping rules if we're at the end */ 184cbb79e43SAlexandru M Stan i++; 185cbb79e43SAlexandru M Stan } else { 186cbb79e43SAlexandru M Stan /* 187cbb79e43SAlexandru M Stan * No need to check too close to an invalid 188cbb79e43SAlexandru M Stan * one since testing bad phases is slow. Skip 189cbb79e43SAlexandru M Stan * 20 degrees. 190cbb79e43SAlexandru M Stan */ 1911a12a70fSShawn Lin i += DIV_ROUND_UP(20 * priv->num_phases, 360); 192cbb79e43SAlexandru M Stan 193cbb79e43SAlexandru M Stan /* Always test the last one */ 1941a12a70fSShawn Lin if (i >= priv->num_phases) 1951a12a70fSShawn Lin i = priv->num_phases - 1; 196cbb79e43SAlexandru M Stan } 197cbb79e43SAlexandru M Stan 198cbb79e43SAlexandru M Stan prev_v = v; 199cbb79e43SAlexandru M Stan } 200cbb79e43SAlexandru M Stan 201cbb79e43SAlexandru M Stan if (range_count == 0) { 202cbb79e43SAlexandru M Stan dev_warn(host->dev, "All phases bad!"); 203cbb79e43SAlexandru M Stan ret = -EIO; 204cbb79e43SAlexandru M Stan goto free; 205cbb79e43SAlexandru M Stan } 206cbb79e43SAlexandru M Stan 207cbb79e43SAlexandru M Stan /* wrap around case, merge the end points */ 208cbb79e43SAlexandru M Stan if ((range_count > 1) && first_v && v) { 209cbb79e43SAlexandru M Stan ranges[0].start = ranges[range_count-1].start; 210cbb79e43SAlexandru M Stan range_count--; 211cbb79e43SAlexandru M Stan } 212cbb79e43SAlexandru M Stan 2131a12a70fSShawn Lin if (ranges[0].start == 0 && ranges[0].end == priv->num_phases - 1) { 214cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, priv->default_sample_phase); 215cbb79e43SAlexandru M Stan dev_info(host->dev, "All phases work, using default phase %d.", 216cbb79e43SAlexandru M Stan priv->default_sample_phase); 217cbb79e43SAlexandru M Stan goto free; 218cbb79e43SAlexandru M Stan } 219cbb79e43SAlexandru M Stan 220cbb79e43SAlexandru M Stan /* Find the longest range */ 221cbb79e43SAlexandru M Stan for (i = 0; i < range_count; i++) { 222cbb79e43SAlexandru M Stan int len = (ranges[i].end - ranges[i].start + 1); 223cbb79e43SAlexandru M Stan 224cbb79e43SAlexandru M Stan if (len < 0) 2251a12a70fSShawn Lin len += priv->num_phases; 226cbb79e43SAlexandru M Stan 227cbb79e43SAlexandru M Stan if (longest_range_len < len) { 228cbb79e43SAlexandru M Stan longest_range_len = len; 229cbb79e43SAlexandru M Stan longest_range = i; 230cbb79e43SAlexandru M Stan } 231cbb79e43SAlexandru M Stan 232cbb79e43SAlexandru M Stan dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n", 2331a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(ranges[i].start, 2341a12a70fSShawn Lin priv->num_phases), 2351a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(ranges[i].end, 2361a12a70fSShawn Lin priv->num_phases), 237cbb79e43SAlexandru M Stan len 238cbb79e43SAlexandru M Stan ); 239cbb79e43SAlexandru M Stan } 240cbb79e43SAlexandru M Stan 241cbb79e43SAlexandru M Stan dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n", 2421a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(ranges[longest_range].start, 2431a12a70fSShawn Lin priv->num_phases), 2441a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(ranges[longest_range].end, 2451a12a70fSShawn Lin priv->num_phases), 246cbb79e43SAlexandru M Stan longest_range_len 247cbb79e43SAlexandru M Stan ); 248cbb79e43SAlexandru M Stan 249cbb79e43SAlexandru M Stan middle_phase = ranges[longest_range].start + longest_range_len / 2; 2501a12a70fSShawn Lin middle_phase %= priv->num_phases; 251cbb79e43SAlexandru M Stan dev_info(host->dev, "Successfully tuned phase to %d\n", 2521a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(middle_phase, priv->num_phases)); 253cbb79e43SAlexandru M Stan 254cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, 2551a12a70fSShawn Lin TUNING_ITERATION_TO_PHASE(middle_phase, 2561a12a70fSShawn Lin priv->num_phases)); 257cbb79e43SAlexandru M Stan 258cbb79e43SAlexandru M Stan free: 259cbb79e43SAlexandru M Stan kfree(ranges); 260cbb79e43SAlexandru M Stan return ret; 261cbb79e43SAlexandru M Stan } 262cbb79e43SAlexandru M Stan 263cbb79e43SAlexandru M Stan static int dw_mci_rk3288_parse_dt(struct dw_mci *host) 264cbb79e43SAlexandru M Stan { 265cbb79e43SAlexandru M Stan struct device_node *np = host->dev->of_node; 266cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv; 267cbb79e43SAlexandru M Stan 268cbb79e43SAlexandru M Stan priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); 269cbb79e43SAlexandru M Stan if (!priv) 270cbb79e43SAlexandru M Stan return -ENOMEM; 271cbb79e43SAlexandru M Stan 2721a12a70fSShawn Lin if (of_property_read_u32(np, "rockchip,desired-num-phases", 2731a12a70fSShawn Lin &priv->num_phases)) 2741a12a70fSShawn Lin priv->num_phases = 360; 2751a12a70fSShawn Lin 276cbb79e43SAlexandru M Stan if (of_property_read_u32(np, "rockchip,default-sample-phase", 277cbb79e43SAlexandru M Stan &priv->default_sample_phase)) 278cbb79e43SAlexandru M Stan priv->default_sample_phase = 0; 279cbb79e43SAlexandru M Stan 280cbb79e43SAlexandru M Stan priv->drv_clk = devm_clk_get(host->dev, "ciu-drive"); 281cbb79e43SAlexandru M Stan if (IS_ERR(priv->drv_clk)) 282e988867fSJohn Keeping dev_dbg(host->dev, "ciu-drive not available\n"); 283cbb79e43SAlexandru M Stan 284cbb79e43SAlexandru M Stan priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); 285cbb79e43SAlexandru M Stan if (IS_ERR(priv->sample_clk)) 286e988867fSJohn Keeping dev_dbg(host->dev, "ciu-sample not available\n"); 287cbb79e43SAlexandru M Stan 288cbb79e43SAlexandru M Stan host->priv = priv; 289cbb79e43SAlexandru M Stan 290cbb79e43SAlexandru M Stan return 0; 2914cdc2ec1Saddy ke } 2924cdc2ec1Saddy ke 29376756234SAddy Ke static int dw_mci_rockchip_init(struct dw_mci *host) 29476756234SAddy Ke { 29552c92286SPeter Geis int ret, i; 29652c92286SPeter Geis 29776756234SAddy Ke /* It is slot 8 on Rockchip SoCs */ 29876756234SAddy Ke host->sdio_id0 = 8; 29976756234SAddy Ke 30052c92286SPeter Geis if (of_device_is_compatible(host->dev->of_node, "rockchip,rk3288-dw-mshc")) { 30119756760SShawn Lin host->bus_hz /= RK3288_CLKGEN_DIV; 30219756760SShawn Lin 30352c92286SPeter Geis /* clock driver will fail if the clock is less than the lowest source clock 30452c92286SPeter Geis * divided by the internal clock divider. Test for the lowest available 30552c92286SPeter Geis * clock and set the minimum freq to clock / clock divider. 30652c92286SPeter Geis */ 30752c92286SPeter Geis 30852c92286SPeter Geis for (i = 0; i < ARRAY_SIZE(freqs); i++) { 30952c92286SPeter Geis ret = clk_round_rate(host->ciu_clk, freqs[i] * RK3288_CLKGEN_DIV); 31052c92286SPeter Geis if (ret > 0) { 31152c92286SPeter Geis host->minimum_speed = ret / RK3288_CLKGEN_DIV; 31252c92286SPeter Geis break; 31352c92286SPeter Geis } 31452c92286SPeter Geis } 31552c92286SPeter Geis if (ret < 0) 31652c92286SPeter Geis dev_warn(host->dev, "no valid minimum freq: %d\n", ret); 31752c92286SPeter Geis } 31852c92286SPeter Geis 31976756234SAddy Ke return 0; 32076756234SAddy Ke } 32176756234SAddy Ke 3224cdc2ec1Saddy ke static const struct dw_mci_drv_data rk2928_drv_data = { 32376756234SAddy Ke .init = dw_mci_rockchip_init, 3244cdc2ec1Saddy ke }; 3254cdc2ec1Saddy ke 3264cdc2ec1Saddy ke static const struct dw_mci_drv_data rk3288_drv_data = { 3274bac670aSJohn Keeping .common_caps = MMC_CAP_CMD23, 3284cdc2ec1Saddy ke .set_ios = dw_mci_rk3288_set_ios, 329cbb79e43SAlexandru M Stan .execute_tuning = dw_mci_rk3288_execute_tuning, 330cbb79e43SAlexandru M Stan .parse_dt = dw_mci_rk3288_parse_dt, 33176756234SAddy Ke .init = dw_mci_rockchip_init, 3324cdc2ec1Saddy ke }; 3334cdc2ec1Saddy ke 3344cdc2ec1Saddy ke static const struct of_device_id dw_mci_rockchip_match[] = { 3354cdc2ec1Saddy ke { .compatible = "rockchip,rk2928-dw-mshc", 3364cdc2ec1Saddy ke .data = &rk2928_drv_data }, 3374cdc2ec1Saddy ke { .compatible = "rockchip,rk3288-dw-mshc", 3384cdc2ec1Saddy ke .data = &rk3288_drv_data }, 3394cdc2ec1Saddy ke {}, 3404cdc2ec1Saddy ke }; 3414cdc2ec1Saddy ke MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match); 3424cdc2ec1Saddy ke 3434cdc2ec1Saddy ke static int dw_mci_rockchip_probe(struct platform_device *pdev) 3444cdc2ec1Saddy ke { 3454cdc2ec1Saddy ke const struct dw_mci_drv_data *drv_data; 3464cdc2ec1Saddy ke const struct of_device_id *match; 347f9014268SShawn Lin int ret; 3484cdc2ec1Saddy ke 3494cdc2ec1Saddy ke if (!pdev->dev.of_node) 3504cdc2ec1Saddy ke return -ENODEV; 3514cdc2ec1Saddy ke 3524cdc2ec1Saddy ke match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node); 3534cdc2ec1Saddy ke drv_data = match->data; 3544cdc2ec1Saddy ke 355f9014268SShawn Lin pm_runtime_get_noresume(&pdev->dev); 356f9014268SShawn Lin pm_runtime_set_active(&pdev->dev); 357f9014268SShawn Lin pm_runtime_enable(&pdev->dev); 358f9014268SShawn Lin pm_runtime_set_autosuspend_delay(&pdev->dev, 50); 359f9014268SShawn Lin pm_runtime_use_autosuspend(&pdev->dev); 360f9014268SShawn Lin 361f9014268SShawn Lin ret = dw_mci_pltfm_register(pdev, drv_data); 362f9014268SShawn Lin if (ret) { 363f9014268SShawn Lin pm_runtime_disable(&pdev->dev); 364f9014268SShawn Lin pm_runtime_set_suspended(&pdev->dev); 365f9014268SShawn Lin pm_runtime_put_noidle(&pdev->dev); 366f9014268SShawn Lin return ret; 3674cdc2ec1Saddy ke } 3684cdc2ec1Saddy ke 369f9014268SShawn Lin pm_runtime_put_autosuspend(&pdev->dev); 370f9014268SShawn Lin 371f9014268SShawn Lin return 0; 372f9014268SShawn Lin } 373f9014268SShawn Lin 374f9014268SShawn Lin static int dw_mci_rockchip_remove(struct platform_device *pdev) 375f9014268SShawn Lin { 376f9014268SShawn Lin pm_runtime_get_sync(&pdev->dev); 377f9014268SShawn Lin pm_runtime_disable(&pdev->dev); 378f9014268SShawn Lin pm_runtime_put_noidle(&pdev->dev); 379f9014268SShawn Lin 380*397605c2SUwe Kleine-König dw_mci_pltfm_remove(pdev); 381*397605c2SUwe Kleine-König 382*397605c2SUwe Kleine-König return 0; 383f9014268SShawn Lin } 384f9014268SShawn Lin 385f9014268SShawn Lin static const struct dev_pm_ops dw_mci_rockchip_dev_pm_ops = { 386f9014268SShawn Lin SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, 387f9014268SShawn Lin pm_runtime_force_resume) 388f9014268SShawn Lin SET_RUNTIME_PM_OPS(dw_mci_runtime_suspend, 389f9014268SShawn Lin dw_mci_runtime_resume, 390f9014268SShawn Lin NULL) 391f9014268SShawn Lin }; 392f9014268SShawn Lin 3934cdc2ec1Saddy ke static struct platform_driver dw_mci_rockchip_pltfm_driver = { 3944cdc2ec1Saddy ke .probe = dw_mci_rockchip_probe, 395f9014268SShawn Lin .remove = dw_mci_rockchip_remove, 3964cdc2ec1Saddy ke .driver = { 3974cdc2ec1Saddy ke .name = "dwmmc_rockchip", 39821b2cec6SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS, 3994cdc2ec1Saddy ke .of_match_table = dw_mci_rockchip_match, 400f9014268SShawn Lin .pm = &dw_mci_rockchip_dev_pm_ops, 4014cdc2ec1Saddy ke }, 4024cdc2ec1Saddy ke }; 4034cdc2ec1Saddy ke 4044cdc2ec1Saddy ke module_platform_driver(dw_mci_rockchip_pltfm_driver); 4054cdc2ec1Saddy ke 4064cdc2ec1Saddy ke MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>"); 4074cdc2ec1Saddy ke MODULE_DESCRIPTION("Rockchip Specific DW-MSHC Driver Extension"); 408a7ca2b16SZhangfei Gao MODULE_ALIAS("platform:dwmmc_rockchip"); 4094cdc2ec1Saddy ke MODULE_LICENSE("GPL v2"); 410