14cdc2ec1Saddy ke /* 24cdc2ec1Saddy ke * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd 34cdc2ec1Saddy ke * 44cdc2ec1Saddy ke * This program is free software; you can redistribute it and/or modify 54cdc2ec1Saddy ke * it under the terms of the GNU General Public License as published by 64cdc2ec1Saddy ke * the Free Software Foundation; either version 2 of the License, or 74cdc2ec1Saddy ke * (at your option) any later version. 84cdc2ec1Saddy ke */ 94cdc2ec1Saddy ke 104cdc2ec1Saddy ke #include <linux/module.h> 114cdc2ec1Saddy ke #include <linux/platform_device.h> 124cdc2ec1Saddy ke #include <linux/clk.h> 134cdc2ec1Saddy ke #include <linux/mmc/host.h> 144cdc2ec1Saddy ke #include <linux/mmc/dw_mmc.h> 154cdc2ec1Saddy ke #include <linux/of_address.h> 16cbb79e43SAlexandru M Stan #include <linux/slab.h> 174cdc2ec1Saddy ke 184cdc2ec1Saddy ke #include "dw_mmc.h" 194cdc2ec1Saddy ke #include "dw_mmc-pltfm.h" 204cdc2ec1Saddy ke 214cdc2ec1Saddy ke #define RK3288_CLKGEN_DIV 2 224cdc2ec1Saddy ke 23cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data { 24cbb79e43SAlexandru M Stan struct clk *drv_clk; 25cbb79e43SAlexandru M Stan struct clk *sample_clk; 26cbb79e43SAlexandru M Stan int default_sample_phase; 27cbb79e43SAlexandru M Stan }; 28cbb79e43SAlexandru M Stan 294cdc2ec1Saddy ke static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr) 304cdc2ec1Saddy ke { 314cdc2ec1Saddy ke *cmdr |= SDMMC_CMD_USE_HOLD_REG; 324cdc2ec1Saddy ke } 334cdc2ec1Saddy ke 344cdc2ec1Saddy ke static int dw_mci_rk3288_setup_clock(struct dw_mci *host) 354cdc2ec1Saddy ke { 364cdc2ec1Saddy ke host->bus_hz /= RK3288_CLKGEN_DIV; 374cdc2ec1Saddy ke 384cdc2ec1Saddy ke return 0; 394cdc2ec1Saddy ke } 404cdc2ec1Saddy ke 414cdc2ec1Saddy ke static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) 424cdc2ec1Saddy ke { 43cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv = host->priv; 444cdc2ec1Saddy ke int ret; 454cdc2ec1Saddy ke unsigned int cclkin; 464cdc2ec1Saddy ke u32 bus_hz; 474cdc2ec1Saddy ke 48e7791079SDoug Anderson if (ios->clock == 0) 49e7791079SDoug Anderson return; 50e7791079SDoug Anderson 514cdc2ec1Saddy ke /* 524cdc2ec1Saddy ke * cclkin: source clock of mmc controller 534cdc2ec1Saddy ke * bus_hz: card interface clock generated by CLKGEN 544cdc2ec1Saddy ke * bus_hz = cclkin / RK3288_CLKGEN_DIV 554cdc2ec1Saddy ke * ios->clock = (div == 0) ? bus_hz : (bus_hz / (2 * div)) 564cdc2ec1Saddy ke * 574cdc2ec1Saddy ke * Note: div can only be 0 or 1 584cdc2ec1Saddy ke * if DDR50 8bit mode(only emmc work in 8bit mode), 594cdc2ec1Saddy ke * div must be set 1 604cdc2ec1Saddy ke */ 614cdc2ec1Saddy ke if (ios->bus_width == MMC_BUS_WIDTH_8 && 624cdc2ec1Saddy ke ios->timing == MMC_TIMING_MMC_DDR52) 634cdc2ec1Saddy ke cclkin = 2 * ios->clock * RK3288_CLKGEN_DIV; 644cdc2ec1Saddy ke else 654cdc2ec1Saddy ke cclkin = ios->clock * RK3288_CLKGEN_DIV; 664cdc2ec1Saddy ke 674cdc2ec1Saddy ke ret = clk_set_rate(host->ciu_clk, cclkin); 684cdc2ec1Saddy ke if (ret) 694cdc2ec1Saddy ke dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock); 704cdc2ec1Saddy ke 714cdc2ec1Saddy ke bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV; 724cdc2ec1Saddy ke if (bus_hz != host->bus_hz) { 734cdc2ec1Saddy ke host->bus_hz = bus_hz; 744cdc2ec1Saddy ke /* force dw_mci_setup_bus() */ 754cdc2ec1Saddy ke host->current_speed = 0; 764cdc2ec1Saddy ke } 77cbb79e43SAlexandru M Stan 78cbb79e43SAlexandru M Stan /* Make sure we use phases which we can enumerate with */ 79cbb79e43SAlexandru M Stan if (!IS_ERR(priv->sample_clk)) 80cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, priv->default_sample_phase); 81cbb79e43SAlexandru M Stan } 82cbb79e43SAlexandru M Stan 83cbb79e43SAlexandru M Stan #define NUM_PHASES 360 84cbb79e43SAlexandru M Stan #define TUNING_ITERATION_TO_PHASE(i) (DIV_ROUND_UP((i) * 360, NUM_PHASES)) 85cbb79e43SAlexandru M Stan 86cbb79e43SAlexandru M Stan static int dw_mci_rk3288_execute_tuning(struct dw_mci_slot *slot) 87cbb79e43SAlexandru M Stan { 88cbb79e43SAlexandru M Stan struct dw_mci *host = slot->host; 89cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv = host->priv; 90cbb79e43SAlexandru M Stan struct mmc_host *mmc = slot->mmc; 91cbb79e43SAlexandru M Stan int ret = 0; 92cbb79e43SAlexandru M Stan int i; 93cbb79e43SAlexandru M Stan bool v, prev_v = 0, first_v; 94cbb79e43SAlexandru M Stan struct range_t { 95cbb79e43SAlexandru M Stan int start; 96cbb79e43SAlexandru M Stan int end; /* inclusive */ 97cbb79e43SAlexandru M Stan }; 98cbb79e43SAlexandru M Stan struct range_t *ranges; 99cbb79e43SAlexandru M Stan unsigned int range_count = 0; 100cbb79e43SAlexandru M Stan int longest_range_len = -1; 101cbb79e43SAlexandru M Stan int longest_range = -1; 102cbb79e43SAlexandru M Stan int middle_phase; 103cbb79e43SAlexandru M Stan 104cbb79e43SAlexandru M Stan if (IS_ERR(priv->sample_clk)) { 105cbb79e43SAlexandru M Stan dev_err(host->dev, "Tuning clock (sample_clk) not defined.\n"); 106cbb79e43SAlexandru M Stan return -EIO; 107cbb79e43SAlexandru M Stan } 108cbb79e43SAlexandru M Stan 109cbb79e43SAlexandru M Stan ranges = kmalloc_array(NUM_PHASES / 2 + 1, sizeof(*ranges), GFP_KERNEL); 110cbb79e43SAlexandru M Stan if (!ranges) 111cbb79e43SAlexandru M Stan return -ENOMEM; 112cbb79e43SAlexandru M Stan 113cbb79e43SAlexandru M Stan /* Try each phase and extract good ranges */ 114cbb79e43SAlexandru M Stan for (i = 0; i < NUM_PHASES; ) { 115cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, TUNING_ITERATION_TO_PHASE(i)); 116cbb79e43SAlexandru M Stan 117cbb79e43SAlexandru M Stan v = !mmc_send_tuning(mmc); 118cbb79e43SAlexandru M Stan 119cbb79e43SAlexandru M Stan if (i == 0) 120cbb79e43SAlexandru M Stan first_v = v; 121cbb79e43SAlexandru M Stan 122cbb79e43SAlexandru M Stan if ((!prev_v) && v) { 123cbb79e43SAlexandru M Stan range_count++; 124cbb79e43SAlexandru M Stan ranges[range_count-1].start = i; 125cbb79e43SAlexandru M Stan } 126cbb79e43SAlexandru M Stan if (v) { 127cbb79e43SAlexandru M Stan ranges[range_count-1].end = i; 128cbb79e43SAlexandru M Stan i++; 129cbb79e43SAlexandru M Stan } else if (i == NUM_PHASES - 1) { 130cbb79e43SAlexandru M Stan /* No extra skipping rules if we're at the end */ 131cbb79e43SAlexandru M Stan i++; 132cbb79e43SAlexandru M Stan } else { 133cbb79e43SAlexandru M Stan /* 134cbb79e43SAlexandru M Stan * No need to check too close to an invalid 135cbb79e43SAlexandru M Stan * one since testing bad phases is slow. Skip 136cbb79e43SAlexandru M Stan * 20 degrees. 137cbb79e43SAlexandru M Stan */ 138cbb79e43SAlexandru M Stan i += DIV_ROUND_UP(20 * NUM_PHASES, 360); 139cbb79e43SAlexandru M Stan 140cbb79e43SAlexandru M Stan /* Always test the last one */ 141cbb79e43SAlexandru M Stan if (i >= NUM_PHASES) 142cbb79e43SAlexandru M Stan i = NUM_PHASES - 1; 143cbb79e43SAlexandru M Stan } 144cbb79e43SAlexandru M Stan 145cbb79e43SAlexandru M Stan prev_v = v; 146cbb79e43SAlexandru M Stan } 147cbb79e43SAlexandru M Stan 148cbb79e43SAlexandru M Stan if (range_count == 0) { 149cbb79e43SAlexandru M Stan dev_warn(host->dev, "All phases bad!"); 150cbb79e43SAlexandru M Stan ret = -EIO; 151cbb79e43SAlexandru M Stan goto free; 152cbb79e43SAlexandru M Stan } 153cbb79e43SAlexandru M Stan 154cbb79e43SAlexandru M Stan /* wrap around case, merge the end points */ 155cbb79e43SAlexandru M Stan if ((range_count > 1) && first_v && v) { 156cbb79e43SAlexandru M Stan ranges[0].start = ranges[range_count-1].start; 157cbb79e43SAlexandru M Stan range_count--; 158cbb79e43SAlexandru M Stan } 159cbb79e43SAlexandru M Stan 160cbb79e43SAlexandru M Stan if (ranges[0].start == 0 && ranges[0].end == NUM_PHASES - 1) { 161cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, priv->default_sample_phase); 162cbb79e43SAlexandru M Stan dev_info(host->dev, "All phases work, using default phase %d.", 163cbb79e43SAlexandru M Stan priv->default_sample_phase); 164cbb79e43SAlexandru M Stan goto free; 165cbb79e43SAlexandru M Stan } 166cbb79e43SAlexandru M Stan 167cbb79e43SAlexandru M Stan /* Find the longest range */ 168cbb79e43SAlexandru M Stan for (i = 0; i < range_count; i++) { 169cbb79e43SAlexandru M Stan int len = (ranges[i].end - ranges[i].start + 1); 170cbb79e43SAlexandru M Stan 171cbb79e43SAlexandru M Stan if (len < 0) 172cbb79e43SAlexandru M Stan len += NUM_PHASES; 173cbb79e43SAlexandru M Stan 174cbb79e43SAlexandru M Stan if (longest_range_len < len) { 175cbb79e43SAlexandru M Stan longest_range_len = len; 176cbb79e43SAlexandru M Stan longest_range = i; 177cbb79e43SAlexandru M Stan } 178cbb79e43SAlexandru M Stan 179cbb79e43SAlexandru M Stan dev_dbg(host->dev, "Good phase range %d-%d (%d len)\n", 180cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(ranges[i].start), 181cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(ranges[i].end), 182cbb79e43SAlexandru M Stan len 183cbb79e43SAlexandru M Stan ); 184cbb79e43SAlexandru M Stan } 185cbb79e43SAlexandru M Stan 186cbb79e43SAlexandru M Stan dev_dbg(host->dev, "Best phase range %d-%d (%d len)\n", 187cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(ranges[longest_range].start), 188cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(ranges[longest_range].end), 189cbb79e43SAlexandru M Stan longest_range_len 190cbb79e43SAlexandru M Stan ); 191cbb79e43SAlexandru M Stan 192cbb79e43SAlexandru M Stan middle_phase = ranges[longest_range].start + longest_range_len / 2; 193cbb79e43SAlexandru M Stan middle_phase %= NUM_PHASES; 194cbb79e43SAlexandru M Stan dev_info(host->dev, "Successfully tuned phase to %d\n", 195cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(middle_phase)); 196cbb79e43SAlexandru M Stan 197cbb79e43SAlexandru M Stan clk_set_phase(priv->sample_clk, 198cbb79e43SAlexandru M Stan TUNING_ITERATION_TO_PHASE(middle_phase)); 199cbb79e43SAlexandru M Stan 200cbb79e43SAlexandru M Stan free: 201cbb79e43SAlexandru M Stan kfree(ranges); 202cbb79e43SAlexandru M Stan return ret; 203cbb79e43SAlexandru M Stan } 204cbb79e43SAlexandru M Stan 205cbb79e43SAlexandru M Stan static int dw_mci_rk3288_parse_dt(struct dw_mci *host) 206cbb79e43SAlexandru M Stan { 207cbb79e43SAlexandru M Stan struct device_node *np = host->dev->of_node; 208cbb79e43SAlexandru M Stan struct dw_mci_rockchip_priv_data *priv; 209cbb79e43SAlexandru M Stan 210cbb79e43SAlexandru M Stan priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL); 211cbb79e43SAlexandru M Stan if (!priv) 212cbb79e43SAlexandru M Stan return -ENOMEM; 213cbb79e43SAlexandru M Stan 214cbb79e43SAlexandru M Stan if (of_property_read_u32(np, "rockchip,default-sample-phase", 215cbb79e43SAlexandru M Stan &priv->default_sample_phase)) 216cbb79e43SAlexandru M Stan priv->default_sample_phase = 0; 217cbb79e43SAlexandru M Stan 218cbb79e43SAlexandru M Stan priv->drv_clk = devm_clk_get(host->dev, "ciu-drive"); 219cbb79e43SAlexandru M Stan if (IS_ERR(priv->drv_clk)) 220cbb79e43SAlexandru M Stan dev_dbg(host->dev, "ciu_drv not available\n"); 221cbb79e43SAlexandru M Stan 222cbb79e43SAlexandru M Stan priv->sample_clk = devm_clk_get(host->dev, "ciu-sample"); 223cbb79e43SAlexandru M Stan if (IS_ERR(priv->sample_clk)) 224cbb79e43SAlexandru M Stan dev_dbg(host->dev, "ciu_sample not available\n"); 225cbb79e43SAlexandru M Stan 226cbb79e43SAlexandru M Stan host->priv = priv; 227cbb79e43SAlexandru M Stan 228cbb79e43SAlexandru M Stan return 0; 2294cdc2ec1Saddy ke } 2304cdc2ec1Saddy ke 23176756234SAddy Ke static int dw_mci_rockchip_init(struct dw_mci *host) 23276756234SAddy Ke { 23376756234SAddy Ke /* It is slot 8 on Rockchip SoCs */ 23476756234SAddy Ke host->sdio_id0 = 8; 23576756234SAddy Ke 23657e10486SAddy Ke /* It needs this quirk on all Rockchip SoCs */ 23757e10486SAddy Ke host->pdata->quirks |= DW_MCI_QUIRK_BROKEN_DTO; 23857e10486SAddy Ke 23976756234SAddy Ke return 0; 24076756234SAddy Ke } 24176756234SAddy Ke 2426d53200bSaddy ke /* Common capabilities of RK3288 SoC */ 2436d53200bSaddy ke static unsigned long dw_mci_rk3288_dwmmc_caps[4] = { 2446d53200bSaddy ke MMC_CAP_RUNTIME_RESUME, /* emmc */ 2456d53200bSaddy ke MMC_CAP_RUNTIME_RESUME, /* sdmmc */ 2466d53200bSaddy ke MMC_CAP_RUNTIME_RESUME, /* sdio0 */ 2476d53200bSaddy ke MMC_CAP_RUNTIME_RESUME, /* sdio1 */ 2486d53200bSaddy ke }; 2494cdc2ec1Saddy ke static const struct dw_mci_drv_data rk2928_drv_data = { 2504cdc2ec1Saddy ke .prepare_command = dw_mci_rockchip_prepare_command, 25176756234SAddy Ke .init = dw_mci_rockchip_init, 2524cdc2ec1Saddy ke }; 2534cdc2ec1Saddy ke 2544cdc2ec1Saddy ke static const struct dw_mci_drv_data rk3288_drv_data = { 2556d53200bSaddy ke .caps = dw_mci_rk3288_dwmmc_caps, 2564cdc2ec1Saddy ke .prepare_command = dw_mci_rockchip_prepare_command, 2574cdc2ec1Saddy ke .set_ios = dw_mci_rk3288_set_ios, 258cbb79e43SAlexandru M Stan .execute_tuning = dw_mci_rk3288_execute_tuning, 259cbb79e43SAlexandru M Stan .parse_dt = dw_mci_rk3288_parse_dt, 2604cdc2ec1Saddy ke .setup_clock = dw_mci_rk3288_setup_clock, 26176756234SAddy Ke .init = dw_mci_rockchip_init, 2624cdc2ec1Saddy ke }; 2634cdc2ec1Saddy ke 2644cdc2ec1Saddy ke static const struct of_device_id dw_mci_rockchip_match[] = { 2654cdc2ec1Saddy ke { .compatible = "rockchip,rk2928-dw-mshc", 2664cdc2ec1Saddy ke .data = &rk2928_drv_data }, 2674cdc2ec1Saddy ke { .compatible = "rockchip,rk3288-dw-mshc", 2684cdc2ec1Saddy ke .data = &rk3288_drv_data }, 2694cdc2ec1Saddy ke {}, 2704cdc2ec1Saddy ke }; 2714cdc2ec1Saddy ke MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match); 2724cdc2ec1Saddy ke 2734cdc2ec1Saddy ke static int dw_mci_rockchip_probe(struct platform_device *pdev) 2744cdc2ec1Saddy ke { 2754cdc2ec1Saddy ke const struct dw_mci_drv_data *drv_data; 2764cdc2ec1Saddy ke const struct of_device_id *match; 2774cdc2ec1Saddy ke 2784cdc2ec1Saddy ke if (!pdev->dev.of_node) 2794cdc2ec1Saddy ke return -ENODEV; 2804cdc2ec1Saddy ke 2814cdc2ec1Saddy ke match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node); 2824cdc2ec1Saddy ke drv_data = match->data; 2834cdc2ec1Saddy ke 2844cdc2ec1Saddy ke return dw_mci_pltfm_register(pdev, drv_data); 2854cdc2ec1Saddy ke } 2864cdc2ec1Saddy ke 2874cdc2ec1Saddy ke #ifdef CONFIG_PM_SLEEP 2884cdc2ec1Saddy ke static int dw_mci_rockchip_suspend(struct device *dev) 2894cdc2ec1Saddy ke { 2904cdc2ec1Saddy ke struct dw_mci *host = dev_get_drvdata(dev); 2914cdc2ec1Saddy ke 2924cdc2ec1Saddy ke return dw_mci_suspend(host); 2934cdc2ec1Saddy ke } 2944cdc2ec1Saddy ke 2954cdc2ec1Saddy ke static int dw_mci_rockchip_resume(struct device *dev) 2964cdc2ec1Saddy ke { 2974cdc2ec1Saddy ke struct dw_mci *host = dev_get_drvdata(dev); 2984cdc2ec1Saddy ke 2994cdc2ec1Saddy ke return dw_mci_resume(host); 3004cdc2ec1Saddy ke } 3014cdc2ec1Saddy ke #endif /* CONFIG_PM_SLEEP */ 3024cdc2ec1Saddy ke 3034cdc2ec1Saddy ke static SIMPLE_DEV_PM_OPS(dw_mci_rockchip_pmops, 3044cdc2ec1Saddy ke dw_mci_rockchip_suspend, 3054cdc2ec1Saddy ke dw_mci_rockchip_resume); 3064cdc2ec1Saddy ke 3074cdc2ec1Saddy ke static struct platform_driver dw_mci_rockchip_pltfm_driver = { 3084cdc2ec1Saddy ke .probe = dw_mci_rockchip_probe, 30996083379SDmitry Torokhov .remove = dw_mci_pltfm_remove, 3104cdc2ec1Saddy ke .driver = { 3114cdc2ec1Saddy ke .name = "dwmmc_rockchip", 3124cdc2ec1Saddy ke .of_match_table = dw_mci_rockchip_match, 3134cdc2ec1Saddy ke .pm = &dw_mci_rockchip_pmops, 3144cdc2ec1Saddy ke }, 3154cdc2ec1Saddy ke }; 3164cdc2ec1Saddy ke 3174cdc2ec1Saddy ke module_platform_driver(dw_mci_rockchip_pltfm_driver); 3184cdc2ec1Saddy ke 3194cdc2ec1Saddy ke MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>"); 3204cdc2ec1Saddy ke MODULE_DESCRIPTION("Rockchip Specific DW-MSHC Driver Extension"); 321a7ca2b16SZhangfei Gao MODULE_ALIAS("platform:dwmmc_rockchip"); 3224cdc2ec1Saddy ke MODULE_LICENSE("GPL v2"); 323