aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoraddy ke <addy.ke@rock-chips.com>2014-08-19 00:36:14 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2014-09-09 07:59:16 -0400
commit4cdc2ec1da322776215c4d6bca0717a7a103a4dd (patch)
tree1761d2c46974933b3a604f37308e23f75da7c856
parentda29fe2bf573f0ae56fdc2e790387cb73fc8c6f8 (diff)
mmc: dw_mmc: move rockchip related code to a separate file
To support HS200 and UHS-1, we need add a big hunk of code, as shown in the following patches. So a separate file for rockchip SOCs is suitable. Signed-off-by: Addy Ke <addy.ke@rock-chips.com> Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Tested-by: Doug Anderson <dianders@chromium.org> Reviewed-by: Doug Anderson <dianders@chromium.org> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/Kconfig9
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c57
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c136
4 files changed, 146 insertions, 57 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index a43295c49a44..13860656104b 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -638,6 +638,15 @@ config MMC_DW_PCI
638 638
639 If unsure, say N. 639 If unsure, say N.
640 640
641config MMC_DW_ROCKCHIP
642 tristate "Rockchip specific extensions for Synopsys DW Memory Card Interface"
643 depends on MMC_DW && ARCH_ROCKCHIP
644 select MMC_DW_PLTFM
645 help
646 This selects support for Rockchip SoC specific extensions to the
647 Synopsys DesignWare Memory Card Interface driver. Select this option
648 for platforms based on RK3066, RK3188 and RK3288 SoC's.
649
641config MMC_SH_MMCIF 650config MMC_SH_MMCIF
642 tristate "SuperH Internal MMCIF support" 651 tristate "SuperH Internal MMCIF support"
643 depends on MMC_BLOCK && HAS_DMA 652 depends on MMC_BLOCK && HAS_DMA
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 2d223463e6c5..b09ecfb88269 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o
46obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o 46obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o
47obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o 47obj-$(CONFIG_MMC_DW_K3) += dw_mmc-k3.o
48obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o 48obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o
49obj-$(CONFIG_MMC_DW_ROCKCHIP) += dw_mmc-rockchip.o
49obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o 50obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o
50obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o 51obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
51obj-$(CONFIG_MMC_VUB300) += vub300.o 52obj-$(CONFIG_MMC_VUB300) += vub300.o
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 1cd02828e5a3..8b6572162ed9 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -26,64 +26,11 @@
26#include "dw_mmc.h" 26#include "dw_mmc.h"
27#include "dw_mmc-pltfm.h" 27#include "dw_mmc-pltfm.h"
28 28
29#define RK3288_CLKGEN_DIV 2
30
31static void dw_mci_pltfm_prepare_command(struct dw_mci *host, u32 *cmdr) 29static void dw_mci_pltfm_prepare_command(struct dw_mci *host, u32 *cmdr)
32{ 30{
33 *cmdr |= SDMMC_CMD_USE_HOLD_REG; 31 *cmdr |= SDMMC_CMD_USE_HOLD_REG;
34} 32}
35 33
36static int dw_mci_rk3288_setup_clock(struct dw_mci *host)
37{
38 host->bus_hz /= RK3288_CLKGEN_DIV;
39
40 return 0;
41}
42
43static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
44{
45 int ret;
46 unsigned int cclkin;
47 u32 bus_hz;
48
49 /*
50 * cclkin: source clock of mmc controller.
51 * bus_hz: card interface clock generated by CLKGEN.
52 * bus_hz = cclkin / RK3288_CLKGEN_DIV;
53 * ios->clock = (div == 0) ? bus_hz : (bus_hz / (2 * div))
54 *
55 * Note: div can only be 0 or 1
56 * if DDR50 8bit mode(only emmc work in 8bit mode),
57 * div must be set 1
58 */
59 if ((ios->bus_width == MMC_BUS_WIDTH_8) &&
60 (ios->timing == MMC_TIMING_MMC_DDR52))
61 cclkin = 2 * ios->clock * RK3288_CLKGEN_DIV;
62 else
63 cclkin = ios->clock * RK3288_CLKGEN_DIV;
64
65 ret = clk_set_rate(host->ciu_clk, cclkin);
66 if (ret)
67 dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);
68
69 bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV;
70 if (bus_hz != host->bus_hz) {
71 host->bus_hz = bus_hz;
72 /* force dw_mci_setup_bus() */
73 host->current_speed = 0;
74 }
75}
76
77static const struct dw_mci_drv_data rk2928_drv_data = {
78 .prepare_command = dw_mci_pltfm_prepare_command,
79};
80
81static const struct dw_mci_drv_data rk3288_drv_data = {
82 .prepare_command = dw_mci_pltfm_prepare_command,
83 .set_ios = dw_mci_rk3288_set_ios,
84 .setup_clock = dw_mci_rk3288_setup_clock,
85};
86
87static const struct dw_mci_drv_data socfpga_drv_data = { 34static const struct dw_mci_drv_data socfpga_drv_data = {
88 .prepare_command = dw_mci_pltfm_prepare_command, 35 .prepare_command = dw_mci_pltfm_prepare_command,
89}; 36};
@@ -141,10 +88,6 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_pmops);
141 88
142static const struct of_device_id dw_mci_pltfm_match[] = { 89static const struct of_device_id dw_mci_pltfm_match[] = {
143 { .compatible = "snps,dw-mshc", }, 90 { .compatible = "snps,dw-mshc", },
144 { .compatible = "rockchip,rk2928-dw-mshc",
145 .data = &rk2928_drv_data },
146 { .compatible = "rockchip,rk3288-dw-mshc",
147 .data = &rk3288_drv_data },
148 { .compatible = "altr,socfpga-dw-mshc", 91 { .compatible = "altr,socfpga-dw-mshc",
149 .data = &socfpga_drv_data }, 92 .data = &socfpga_drv_data },
150 {}, 93 {},
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
new file mode 100644
index 000000000000..f0c2cb1a210d
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -0,0 +1,136 @@
1/*
2 * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <linux/module.h>
11#include <linux/platform_device.h>
12#include <linux/clk.h>
13#include <linux/mmc/host.h>
14#include <linux/mmc/dw_mmc.h>
15#include <linux/of_address.h>
16
17#include "dw_mmc.h"
18#include "dw_mmc-pltfm.h"
19
20#define RK3288_CLKGEN_DIV 2
21
22static void dw_mci_rockchip_prepare_command(struct dw_mci *host, u32 *cmdr)
23{
24 *cmdr |= SDMMC_CMD_USE_HOLD_REG;
25}
26
27static int dw_mci_rk3288_setup_clock(struct dw_mci *host)
28{
29 host->bus_hz /= RK3288_CLKGEN_DIV;
30
31 return 0;
32}
33
34static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios)
35{
36 int ret;
37 unsigned int cclkin;
38 u32 bus_hz;
39
40 /*
41 * cclkin: source clock of mmc controller
42 * bus_hz: card interface clock generated by CLKGEN
43 * bus_hz = cclkin / RK3288_CLKGEN_DIV
44 * ios->clock = (div == 0) ? bus_hz : (bus_hz / (2 * div))
45 *
46 * Note: div can only be 0 or 1
47 * if DDR50 8bit mode(only emmc work in 8bit mode),
48 * div must be set 1
49 */
50 if (ios->bus_width == MMC_BUS_WIDTH_8 &&
51 ios->timing == MMC_TIMING_MMC_DDR52)
52 cclkin = 2 * ios->clock * RK3288_CLKGEN_DIV;
53 else
54 cclkin = ios->clock * RK3288_CLKGEN_DIV;
55
56 ret = clk_set_rate(host->ciu_clk, cclkin);
57 if (ret)
58 dev_warn(host->dev, "failed to set rate %uHz\n", ios->clock);
59
60 bus_hz = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV;
61 if (bus_hz != host->bus_hz) {
62 host->bus_hz = bus_hz;
63 /* force dw_mci_setup_bus() */
64 host->current_speed = 0;
65 }
66}
67
68static const struct dw_mci_drv_data rk2928_drv_data = {
69 .prepare_command = dw_mci_rockchip_prepare_command,
70};
71
72static const struct dw_mci_drv_data rk3288_drv_data = {
73 .prepare_command = dw_mci_rockchip_prepare_command,
74 .set_ios = dw_mci_rk3288_set_ios,
75 .setup_clock = dw_mci_rk3288_setup_clock,
76};
77
78static const struct of_device_id dw_mci_rockchip_match[] = {
79 { .compatible = "rockchip,rk2928-dw-mshc",
80 .data = &rk2928_drv_data },
81 { .compatible = "rockchip,rk3288-dw-mshc",
82 .data = &rk3288_drv_data },
83 {},
84};
85MODULE_DEVICE_TABLE(of, dw_mci_rockchip_match);
86
87static int dw_mci_rockchip_probe(struct platform_device *pdev)
88{
89 const struct dw_mci_drv_data *drv_data;
90 const struct of_device_id *match;
91
92 if (!pdev->dev.of_node)
93 return -ENODEV;
94
95 match = of_match_node(dw_mci_rockchip_match, pdev->dev.of_node);
96 drv_data = match->data;
97
98 return dw_mci_pltfm_register(pdev, drv_data);
99}
100
101#ifdef CONFIG_PM_SLEEP
102static int dw_mci_rockchip_suspend(struct device *dev)
103{
104 struct dw_mci *host = dev_get_drvdata(dev);
105
106 return dw_mci_suspend(host);
107}
108
109static int dw_mci_rockchip_resume(struct device *dev)
110{
111 struct dw_mci *host = dev_get_drvdata(dev);
112
113 return dw_mci_resume(host);
114}
115#endif /* CONFIG_PM_SLEEP */
116
117static SIMPLE_DEV_PM_OPS(dw_mci_rockchip_pmops,
118 dw_mci_rockchip_suspend,
119 dw_mci_rockchip_resume);
120
121static struct platform_driver dw_mci_rockchip_pltfm_driver = {
122 .probe = dw_mci_rockchip_probe,
123 .remove = __exit_p(dw_mci_pltfm_remove),
124 .driver = {
125 .name = "dwmmc_rockchip",
126 .of_match_table = dw_mci_rockchip_match,
127 .pm = &dw_mci_rockchip_pmops,
128 },
129};
130
131module_platform_driver(dw_mci_rockchip_pltfm_driver);
132
133MODULE_AUTHOR("Addy Ke <addy.ke@rock-chips.com>");
134MODULE_DESCRIPTION("Rockchip Specific DW-MSHC Driver Extension");
135MODULE_ALIAS("platform:dwmmc-rockchip");
136MODULE_LICENSE("GPL v2");