aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c12
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.h3
-rw-r--r--drivers/mmc/host/dw_mmc.c47
-rw-r--r--drivers/mmc/host/dw_mmc.h24
-rw-r--r--include/linux/mmc/dw_mmc.h4
5 files changed, 86 insertions, 4 deletions
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index e17da912efff..c960ca7ffbe6 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -23,7 +23,8 @@
23 23
24#include "dw_mmc.h" 24#include "dw_mmc.h"
25 25
26int dw_mci_pltfm_register(struct platform_device *pdev) 26int dw_mci_pltfm_register(struct platform_device *pdev,
27 struct dw_mci_drv_data *drv_data)
27{ 28{
28 struct dw_mci *host; 29 struct dw_mci *host;
29 struct resource *regs; 30 struct resource *regs;
@@ -41,6 +42,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev)
41 if (host->irq < 0) 42 if (host->irq < 0)
42 return host->irq; 43 return host->irq;
43 44
45 host->drv_data = drv_data;
44 host->dev = &pdev->dev; 46 host->dev = &pdev->dev;
45 host->irq_flags = 0; 47 host->irq_flags = 0;
46 host->pdata = pdev->dev.platform_data; 48 host->pdata = pdev->dev.platform_data;
@@ -48,6 +50,12 @@ int dw_mci_pltfm_register(struct platform_device *pdev)
48 if (!host->regs) 50 if (!host->regs)
49 return -ENOMEM; 51 return -ENOMEM;
50 52
53 if (host->drv_data->init) {
54 ret = host->drv_data->init(host);
55 if (ret)
56 return ret;
57 }
58
51 platform_set_drvdata(pdev, host); 59 platform_set_drvdata(pdev, host);
52 ret = dw_mci_probe(host); 60 ret = dw_mci_probe(host);
53 return ret; 61 return ret;
@@ -56,7 +64,7 @@ EXPORT_SYMBOL_GPL(dw_mci_pltfm_register);
56 64
57static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev) 65static int __devinit dw_mci_pltfm_probe(struct platform_device *pdev)
58{ 66{
59 return dw_mci_pltfm_register(pdev); 67 return dw_mci_pltfm_register(pdev, NULL);
60} 68}
61 69
62static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev) 70static int __devexit dw_mci_pltfm_remove(struct platform_device *pdev)
diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h
index 6c065d9c2dd6..301f24541fc2 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.h
+++ b/drivers/mmc/host/dw_mmc-pltfm.h
@@ -12,7 +12,8 @@
12#ifndef _DW_MMC_PLTFM_H_ 12#ifndef _DW_MMC_PLTFM_H_
13#define _DW_MMC_PLTFM_H_ 13#define _DW_MMC_PLTFM_H_
14 14
15extern int dw_mci_pltfm_register(struct platform_device *pdev); 15extern int dw_mci_pltfm_register(struct platform_device *pdev,
16 struct dw_mci_drv_data *drv_data);
16extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev); 17extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
17extern const struct dev_pm_ops dw_mci_pltfm_pmops; 18extern const struct dev_pm_ops dw_mci_pltfm_pmops;
18 19
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index c792466fb8ac..9f8e487bfa97 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -231,6 +231,7 @@ static void dw_mci_set_timeout(struct dw_mci *host)
231static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) 231static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
232{ 232{
233 struct mmc_data *data; 233 struct mmc_data *data;
234 struct dw_mci_slot *slot = mmc_priv(mmc);
234 u32 cmdr; 235 u32 cmdr;
235 cmd->error = -EINPROGRESS; 236 cmd->error = -EINPROGRESS;
236 237
@@ -260,6 +261,9 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
260 cmdr |= SDMMC_CMD_DAT_WR; 261 cmdr |= SDMMC_CMD_DAT_WR;
261 } 262 }
262 263
264 if (slot->host->drv_data->prepare_command)
265 slot->host->drv_data->prepare_command(slot->host, &cmdr);
266
263 return cmdr; 267 return cmdr;
264} 268}
265 269
@@ -815,6 +819,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
815 slot->clock = ios->clock; 819 slot->clock = ios->clock;
816 } 820 }
817 821
822 if (slot->host->drv_data->set_ios)
823 slot->host->drv_data->set_ios(slot->host, ios);
824
818 switch (ios->power_mode) { 825 switch (ios->power_mode) {
819 case MMC_POWER_UP: 826 case MMC_POWER_UP:
820 set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); 827 set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags);
@@ -1820,6 +1827,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1820{ 1827{
1821 struct mmc_host *mmc; 1828 struct mmc_host *mmc;
1822 struct dw_mci_slot *slot; 1829 struct dw_mci_slot *slot;
1830 int ctrl_id, ret;
1823 u8 bus_width; 1831 u8 bus_width;
1824 1832
1825 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev); 1833 mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
@@ -1851,6 +1859,16 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1851 if (host->pdata->caps) 1859 if (host->pdata->caps)
1852 mmc->caps = host->pdata->caps; 1860 mmc->caps = host->pdata->caps;
1853 1861
1862 if (host->dev->of_node) {
1863 ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
1864 if (ctrl_id < 0)
1865 ctrl_id = 0;
1866 } else {
1867 ctrl_id = to_platform_device(host->dev)->id;
1868 }
1869 if (host->drv_data && host->drv_data->caps)
1870 mmc->caps |= host->drv_data->caps[ctrl_id];
1871
1854 if (host->pdata->caps2) 1872 if (host->pdata->caps2)
1855 mmc->caps2 = host->pdata->caps2; 1873 mmc->caps2 = host->pdata->caps2;
1856 1874
@@ -1861,6 +1879,14 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1861 else 1879 else
1862 bus_width = 1; 1880 bus_width = 1;
1863 1881
1882 if (host->drv_data->setup_bus) {
1883 struct device_node *slot_np;
1884 slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
1885 ret = host->drv_data->setup_bus(host, slot_np, bus_width);
1886 if (ret)
1887 goto err_setup_bus;
1888 }
1889
1864 switch (bus_width) { 1890 switch (bus_width) {
1865 case 8: 1891 case 8:
1866 mmc->caps |= MMC_CAP_8_BIT_DATA; 1892 mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -1927,6 +1953,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1927 queue_work(host->card_workqueue, &host->card_work); 1953 queue_work(host->card_workqueue, &host->card_work);
1928 1954
1929 return 0; 1955 return 0;
1956
1957err_setup_bus:
1958 mmc_free_host(mmc);
1959 return -EINVAL;
1930} 1960}
1931 1961
1932static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) 1962static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
@@ -2021,7 +2051,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
2021 struct dw_mci_board *pdata; 2051 struct dw_mci_board *pdata;
2022 struct device *dev = host->dev; 2052 struct device *dev = host->dev;
2023 struct device_node *np = dev->of_node; 2053 struct device_node *np = dev->of_node;
2024 int idx; 2054 int idx, ret;
2025 2055
2026 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 2056 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
2027 if (!pdata) { 2057 if (!pdata) {
@@ -2048,6 +2078,12 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
2048 2078
2049 of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms); 2079 of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
2050 2080
2081 if (host->drv_data->parse_dt) {
2082 ret = host->drv_data->parse_dt(host);
2083 if (ret)
2084 return ERR_PTR(ret);
2085 }
2086
2051 return pdata; 2087 return pdata;
2052} 2088}
2053 2089
@@ -2107,6 +2143,15 @@ int dw_mci_probe(struct dw_mci *host)
2107 else 2143 else
2108 host->bus_hz = clk_get_rate(host->ciu_clk); 2144 host->bus_hz = clk_get_rate(host->ciu_clk);
2109 2145
2146 if (host->drv_data->setup_clock) {
2147 ret = host->drv_data->setup_clock(host);
2148 if (ret) {
2149 dev_err(host->dev,
2150 "implementation specific clock setup failed\n");
2151 goto err_clk_ciu;
2152 }
2153 }
2154
2110 if (!host->bus_hz) { 2155 if (!host->bus_hz) {
2111 dev_err(host->dev, 2156 dev_err(host->dev,
2112 "Platform data must supply bus speed\n"); 2157 "Platform data must supply bus speed\n");
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 15c27e17c23f..53b8fd987e47 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -182,4 +182,28 @@ extern int dw_mci_suspend(struct dw_mci *host);
182extern int dw_mci_resume(struct dw_mci *host); 182extern int dw_mci_resume(struct dw_mci *host);
183#endif 183#endif
184 184
185/**
186 * dw_mci driver data - dw-mshc implementation specific driver data.
187 * @caps: mmc subsystem specified capabilities of the controller(s).
188 * @init: early implementation specific initialization.
189 * @setup_clock: implementation specific clock configuration.
190 * @prepare_command: handle CMD register extensions.
191 * @set_ios: handle bus specific extensions.
192 * @parse_dt: parse implementation specific device tree properties.
193 * @setup_bus: initialize io-interface
194 *
195 * Provide controller implementation specific extensions. The usage of this
196 * data structure is fully optional and usage of each member in this structure
197 * is optional as well.
198 */
199struct dw_mci_drv_data {
200 unsigned long *caps;
201 int (*init)(struct dw_mci *host);
202 int (*setup_clock)(struct dw_mci *host);
203 void (*prepare_command)(struct dw_mci *host, u32 *cmdr);
204 void (*set_ios)(struct dw_mci *host, struct mmc_ios *ios);
205 int (*parse_dt)(struct dw_mci *host);
206 int (*setup_bus)(struct dw_mci *host,
207 struct device_node *slot_np, u8 bus_width);
208};
185#endif /* _DW_MMC_H_ */ 209#endif /* _DW_MMC_H_ */
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index b72e4aa91c11..6cb043e48953 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -78,6 +78,8 @@ struct mmc_data;
78 * @data_offset: Set the offset of DATA register according to VERID. 78 * @data_offset: Set the offset of DATA register according to VERID.
79 * @dev: Device associated with the MMC controller. 79 * @dev: Device associated with the MMC controller.
80 * @pdata: Platform data associated with the MMC controller. 80 * @pdata: Platform data associated with the MMC controller.
81 * @drv_data: Driver specific data for identified variant of the controller
82 * @priv: Implementation defined private data.
81 * @biu_clk: Pointer to bus interface unit clock instance. 83 * @biu_clk: Pointer to bus interface unit clock instance.
82 * @ciu_clk: Pointer to card interface unit clock instance. 84 * @ciu_clk: Pointer to card interface unit clock instance.
83 * @slot: Slots sharing this MMC controller. 85 * @slot: Slots sharing this MMC controller.
@@ -160,6 +162,8 @@ struct dw_mci {
160 u16 data_offset; 162 u16 data_offset;
161 struct device *dev; 163 struct device *dev;
162 struct dw_mci_board *pdata; 164 struct dw_mci_board *pdata;
165 struct dw_mci_drv_data *drv_data;
166 void *priv;
163 struct clk *biu_clk; 167 struct clk *biu_clk;
164 struct clk *ciu_clk; 168 struct clk *ciu_clk;
165 struct dw_mci_slot *slot[MAX_MCI_SLOTS]; 169 struct dw_mci_slot *slot[MAX_MCI_SLOTS];