0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #include <linux/clk.h>
0015 #include <linux/delay.h>
0016 #include <linux/highmem.h>
0017 #include <linux/module.h>
0018 #include <linux/interrupt.h>
0019 #include <linux/irq.h>
0020 #include <linux/of.h>
0021 #include <linux/platform_device.h>
0022 #include <linux/pm.h>
0023 #include <linux/slab.h>
0024 #include <linux/mmc/host.h>
0025 #include <linux/io.h>
0026 #include "sdhci.h"
0027 #include "sdhci-pltfm.h"
0028 #include <linux/platform_data/sdhci-pic32.h>
0029
0030 #define SDH_SHARED_BUS_CTRL 0x000000E0
0031 #define SDH_SHARED_BUS_NR_CLK_PINS_MASK 0x7
0032 #define SDH_SHARED_BUS_NR_IRQ_PINS_MASK 0x30
0033 #define SDH_SHARED_BUS_CLK_PINS 0x10
0034 #define SDH_SHARED_BUS_IRQ_PINS 0x14
0035 #define SDH_CAPS_SDH_SLOT_TYPE_MASK 0xC0000000
0036 #define SDH_SLOT_TYPE_REMOVABLE 0x0
0037 #define SDH_SLOT_TYPE_EMBEDDED 0x1
0038 #define SDH_SLOT_TYPE_SHARED_BUS 0x2
0039 #define SDHCI_CTRL_CDSSEL 0x80
0040 #define SDHCI_CTRL_CDTLVL 0x40
0041
0042 #define ADMA_FIFO_RD_THSHLD 512
0043 #define ADMA_FIFO_WR_THSHLD 512
0044
0045 struct pic32_sdhci_priv {
0046 struct platform_device *pdev;
0047 struct clk *sys_clk;
0048 struct clk *base_clk;
0049 };
0050
0051 static unsigned int pic32_sdhci_get_max_clock(struct sdhci_host *host)
0052 {
0053 struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);
0054
0055 return clk_get_rate(sdhci_pdata->base_clk);
0056 }
0057
0058 static void pic32_sdhci_set_bus_width(struct sdhci_host *host, int width)
0059 {
0060 u8 ctrl;
0061
0062 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
0063 if (width == MMC_BUS_WIDTH_8) {
0064 ctrl &= ~SDHCI_CTRL_4BITBUS;
0065 if (host->version >= SDHCI_SPEC_300)
0066 ctrl |= SDHCI_CTRL_8BITBUS;
0067 } else {
0068 if (host->version >= SDHCI_SPEC_300)
0069 ctrl &= ~SDHCI_CTRL_8BITBUS;
0070 if (width == MMC_BUS_WIDTH_4)
0071 ctrl |= SDHCI_CTRL_4BITBUS;
0072 else
0073 ctrl &= ~SDHCI_CTRL_4BITBUS;
0074 }
0075
0076
0077 ctrl &= ~SDHCI_CTRL_CDTLVL;
0078 ctrl |= SDHCI_CTRL_CDSSEL;
0079 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
0080 }
0081
0082 static unsigned int pic32_sdhci_get_ro(struct sdhci_host *host)
0083 {
0084
0085
0086
0087
0088 return 0;
0089 }
0090
0091 static const struct sdhci_ops pic32_sdhci_ops = {
0092 .get_max_clock = pic32_sdhci_get_max_clock,
0093 .set_clock = sdhci_set_clock,
0094 .set_bus_width = pic32_sdhci_set_bus_width,
0095 .reset = sdhci_reset,
0096 .set_uhs_signaling = sdhci_set_uhs_signaling,
0097 .get_ro = pic32_sdhci_get_ro,
0098 };
0099
0100 static const struct sdhci_pltfm_data sdhci_pic32_pdata = {
0101 .ops = &pic32_sdhci_ops,
0102 .quirks = SDHCI_QUIRK_NO_HISPD_BIT,
0103 .quirks2 = SDHCI_QUIRK2_NO_1_8_V,
0104 };
0105
0106 static void pic32_sdhci_shared_bus(struct platform_device *pdev)
0107 {
0108 struct sdhci_host *host = platform_get_drvdata(pdev);
0109 u32 bus = readl(host->ioaddr + SDH_SHARED_BUS_CTRL);
0110 u32 clk_pins = (bus & SDH_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
0111 u32 irq_pins = (bus & SDH_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;
0112
0113
0114 if (clk_pins & 1)
0115 bus |= (1 << SDH_SHARED_BUS_CLK_PINS);
0116
0117
0118 if (irq_pins & 1)
0119 bus |= (1 << SDH_SHARED_BUS_IRQ_PINS);
0120
0121 writel(bus, host->ioaddr + SDH_SHARED_BUS_CTRL);
0122 }
0123
0124 static void pic32_sdhci_probe_platform(struct platform_device *pdev,
0125 struct pic32_sdhci_priv *pdata)
0126 {
0127 u32 caps_slot_type;
0128 struct sdhci_host *host = platform_get_drvdata(pdev);
0129
0130
0131 host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
0132 caps_slot_type = (host->caps & SDH_CAPS_SDH_SLOT_TYPE_MASK) >> 30;
0133 if (caps_slot_type == SDH_SLOT_TYPE_SHARED_BUS)
0134 pic32_sdhci_shared_bus(pdev);
0135 }
0136
0137 static int pic32_sdhci_probe(struct platform_device *pdev)
0138 {
0139 struct sdhci_host *host;
0140 struct sdhci_pltfm_host *pltfm_host;
0141 struct pic32_sdhci_priv *sdhci_pdata;
0142 struct pic32_sdhci_platform_data *plat_data;
0143 int ret;
0144
0145 host = sdhci_pltfm_init(pdev, &sdhci_pic32_pdata,
0146 sizeof(struct pic32_sdhci_priv));
0147 if (IS_ERR(host)) {
0148 ret = PTR_ERR(host);
0149 goto err;
0150 }
0151
0152 pltfm_host = sdhci_priv(host);
0153 sdhci_pdata = sdhci_pltfm_priv(pltfm_host);
0154
0155 plat_data = pdev->dev.platform_data;
0156 if (plat_data && plat_data->setup_dma) {
0157 ret = plat_data->setup_dma(ADMA_FIFO_RD_THSHLD,
0158 ADMA_FIFO_WR_THSHLD);
0159 if (ret)
0160 goto err_host;
0161 }
0162
0163 sdhci_pdata->sys_clk = devm_clk_get(&pdev->dev, "sys_clk");
0164 if (IS_ERR(sdhci_pdata->sys_clk)) {
0165 ret = PTR_ERR(sdhci_pdata->sys_clk);
0166 dev_err(&pdev->dev, "Error getting clock\n");
0167 goto err_host;
0168 }
0169
0170 ret = clk_prepare_enable(sdhci_pdata->sys_clk);
0171 if (ret) {
0172 dev_err(&pdev->dev, "Error enabling clock\n");
0173 goto err_host;
0174 }
0175
0176 sdhci_pdata->base_clk = devm_clk_get(&pdev->dev, "base_clk");
0177 if (IS_ERR(sdhci_pdata->base_clk)) {
0178 ret = PTR_ERR(sdhci_pdata->base_clk);
0179 dev_err(&pdev->dev, "Error getting clock\n");
0180 goto err_sys_clk;
0181 }
0182
0183 ret = clk_prepare_enable(sdhci_pdata->base_clk);
0184 if (ret) {
0185 dev_err(&pdev->dev, "Error enabling clock\n");
0186 goto err_base_clk;
0187 }
0188
0189 ret = mmc_of_parse(host->mmc);
0190 if (ret)
0191 goto err_base_clk;
0192
0193 pic32_sdhci_probe_platform(pdev, sdhci_pdata);
0194
0195 ret = sdhci_add_host(host);
0196 if (ret)
0197 goto err_base_clk;
0198
0199 dev_info(&pdev->dev, "Successfully added sdhci host\n");
0200 return 0;
0201
0202 err_base_clk:
0203 clk_disable_unprepare(sdhci_pdata->base_clk);
0204 err_sys_clk:
0205 clk_disable_unprepare(sdhci_pdata->sys_clk);
0206 err_host:
0207 sdhci_pltfm_free(pdev);
0208 err:
0209 dev_err(&pdev->dev, "pic32-sdhci probe failed: %d\n", ret);
0210 return ret;
0211 }
0212
0213 static int pic32_sdhci_remove(struct platform_device *pdev)
0214 {
0215 struct sdhci_host *host = platform_get_drvdata(pdev);
0216 struct pic32_sdhci_priv *sdhci_pdata = sdhci_priv(host);
0217 u32 scratch;
0218
0219 scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
0220 sdhci_remove_host(host, scratch == (u32)~0);
0221 clk_disable_unprepare(sdhci_pdata->base_clk);
0222 clk_disable_unprepare(sdhci_pdata->sys_clk);
0223 sdhci_pltfm_free(pdev);
0224
0225 return 0;
0226 }
0227
0228 static const struct of_device_id pic32_sdhci_id_table[] = {
0229 { .compatible = "microchip,pic32mzda-sdhci" },
0230 {}
0231 };
0232 MODULE_DEVICE_TABLE(of, pic32_sdhci_id_table);
0233
0234 static struct platform_driver pic32_sdhci_driver = {
0235 .driver = {
0236 .name = "pic32-sdhci",
0237 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0238 .of_match_table = of_match_ptr(pic32_sdhci_id_table),
0239 },
0240 .probe = pic32_sdhci_probe,
0241 .remove = pic32_sdhci_remove,
0242 };
0243
0244 module_platform_driver(pic32_sdhci_driver);
0245
0246 MODULE_DESCRIPTION("Microchip PIC32 SDHCI driver");
0247 MODULE_AUTHOR("Pistirica Sorin Andrei & Sandeep Sheriker");
0248 MODULE_LICENSE("GPL v2");