xref: /openbmc/linux/drivers/mmc/host/sdhci-dove.c (revision 584259d4)
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