182c29810SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2985b1aa0SMike Rapoport /*
3985b1aa0SMike Rapoport * sdhci-dove.c Support for SDHCI on Marvell's Dove SoC
4985b1aa0SMike Rapoport *
5985b1aa0SMike Rapoport * Author: Saeed Bishara <saeed@marvell.com>
6985b1aa0SMike Rapoport * Mike Rapoport <mike@compulab.co.il>
7985b1aa0SMike Rapoport * Based on sdhci-cns3xxx.c
8985b1aa0SMike Rapoport */
9985b1aa0SMike Rapoport
1030b87c60SSebastian Hesselbarth #include <linux/clk.h>
1130b87c60SSebastian Hesselbarth #include <linux/err.h>
12f8ec589bSRussell King #include <linux/io.h>
13985b1aa0SMike Rapoport #include <linux/mmc/host.h>
14f8ec589bSRussell King #include <linux/module.h>
154ee7ed0dSSebastian Hesselbarth #include <linux/of.h>
16985b1aa0SMike Rapoport
17985b1aa0SMike Rapoport #include "sdhci-pltfm.h"
18985b1aa0SMike Rapoport
sdhci_dove_readw(struct sdhci_host * host,int reg)19985b1aa0SMike Rapoport static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
20985b1aa0SMike Rapoport {
21985b1aa0SMike Rapoport u16 ret;
22985b1aa0SMike Rapoport
23985b1aa0SMike Rapoport switch (reg) {
24985b1aa0SMike Rapoport case SDHCI_HOST_VERSION:
25985b1aa0SMike Rapoport case SDHCI_SLOT_INT_STATUS:
26985b1aa0SMike Rapoport /* those registers don't exist */
27985b1aa0SMike Rapoport return 0;
28985b1aa0SMike Rapoport default:
29985b1aa0SMike Rapoport ret = readw(host->ioaddr + reg);
30985b1aa0SMike Rapoport }
31985b1aa0SMike Rapoport return ret;
32985b1aa0SMike Rapoport }
33985b1aa0SMike Rapoport
sdhci_dove_readl(struct sdhci_host * host,int reg)34985b1aa0SMike Rapoport static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
35985b1aa0SMike Rapoport {
36985b1aa0SMike Rapoport u32 ret;
37985b1aa0SMike Rapoport
38f8ec589bSRussell King ret = readl(host->ioaddr + reg);
39f8ec589bSRussell King
40985b1aa0SMike Rapoport switch (reg) {
41985b1aa0SMike Rapoport case SDHCI_CAPABILITIES:
42985b1aa0SMike Rapoport /* Mask the support for 3.0V */
43985b1aa0SMike Rapoport ret &= ~SDHCI_CAN_VDD_300;
44985b1aa0SMike Rapoport break;
45985b1aa0SMike Rapoport }
46985b1aa0SMike Rapoport return ret;
47985b1aa0SMike Rapoport }
48985b1aa0SMike Rapoport
49c915568dSLars-Peter Clausen static const struct sdhci_ops sdhci_dove_ops = {
50985b1aa0SMike Rapoport .read_w = sdhci_dove_readw,
51985b1aa0SMike Rapoport .read_l = sdhci_dove_readl,
521771059cSRussell King .set_clock = sdhci_set_clock,
532317f56cSRussell King .set_bus_width = sdhci_set_bus_width,
5403231f9bSRussell King .reset = sdhci_reset,
5596d7b78cSRussell King .set_uhs_signaling = sdhci_set_uhs_signaling,
56985b1aa0SMike Rapoport };
57985b1aa0SMike Rapoport
581db5eebfSLars-Peter Clausen static const struct sdhci_pltfm_data sdhci_dove_pdata = {
59985b1aa0SMike Rapoport .ops = &sdhci_dove_ops,
60985b1aa0SMike Rapoport .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
61985b1aa0SMike Rapoport SDHCI_QUIRK_NO_BUSY_IRQ |
62985b1aa0SMike Rapoport SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
63a9ca1d54SSebastian Hesselbarth SDHCI_QUIRK_FORCE_DMA |
64a9ca1d54SSebastian Hesselbarth SDHCI_QUIRK_NO_HISPD_BIT,
65985b1aa0SMike Rapoport };
6685d6509dSShawn Guo
sdhci_dove_probe(struct platform_device * pdev)67c3be1efdSBill Pemberton static int sdhci_dove_probe(struct platform_device *pdev)
6885d6509dSShawn Guo {
6930b87c60SSebastian Hesselbarth struct sdhci_host *host;
7030b87c60SSebastian Hesselbarth struct sdhci_pltfm_host *pltfm_host;
7130b87c60SSebastian Hesselbarth int ret;
7230b87c60SSebastian Hesselbarth
730e748234SChristian Daudt host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
74c5ee2490SSebastian Hesselbarth if (IS_ERR(host))
75c5ee2490SSebastian Hesselbarth return PTR_ERR(host);
76ee3298a2SRussell King - ARM Linux
7730b87c60SSebastian Hesselbarth pltfm_host = sdhci_priv(host);
78*584259d4SAdrian Hunter pltfm_host->clk = devm_clk_get_enabled(&pdev->dev, NULL);
79c430689fSRussell King
80c5ee2490SSebastian Hesselbarth ret = mmc_of_parse(host->mmc);
81c5ee2490SSebastian Hesselbarth if (ret)
82c5ee2490SSebastian Hesselbarth goto err_sdhci_add;
83c430689fSRussell King
84c430689fSRussell King ret = sdhci_add_host(host);
85c430689fSRussell King if (ret)
86c430689fSRussell King goto err_sdhci_add;
87c430689fSRussell King
8830b87c60SSebastian Hesselbarth return 0;
8930b87c60SSebastian Hesselbarth
90c430689fSRussell King err_sdhci_add:
91c430689fSRussell King sdhci_pltfm_free(pdev);
9230b87c60SSebastian Hesselbarth return ret;
9385d6509dSShawn Guo }
9485d6509dSShawn Guo
95498d83e7SBill Pemberton static const struct of_device_id sdhci_dove_of_match_table[] = {
964ee7ed0dSSebastian Hesselbarth { .compatible = "marvell,dove-sdhci", },
974ee7ed0dSSebastian Hesselbarth {}
984ee7ed0dSSebastian Hesselbarth };
994ee7ed0dSSebastian Hesselbarth MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table);
1004ee7ed0dSSebastian Hesselbarth
10185d6509dSShawn Guo static struct platform_driver sdhci_dove_driver = {
10285d6509dSShawn Guo .driver = {
10385d6509dSShawn Guo .name = "sdhci-dove",
10421b2cec6SDouglas Anderson .probe_type = PROBE_PREFER_ASYNCHRONOUS,
105fa243f64SUlf Hansson .pm = &sdhci_pltfm_pmops,
1065941fd07SSachin Kamat .of_match_table = sdhci_dove_of_match_table,
10785d6509dSShawn Guo },
10885d6509dSShawn Guo .probe = sdhci_dove_probe,
109*584259d4SAdrian Hunter .remove_new = sdhci_pltfm_remove,
11085d6509dSShawn Guo };
11185d6509dSShawn Guo
112d1f81a64SAxel Lin module_platform_driver(sdhci_dove_driver);
11385d6509dSShawn Guo
11485d6509dSShawn Guo MODULE_DESCRIPTION("SDHCI driver for Dove");
11585d6509dSShawn Guo MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
11685d6509dSShawn Guo "Mike Rapoport <mike@compulab.co.il>");
11785d6509dSShawn Guo MODULE_LICENSE("GPL v2");
118