blob: de9f9603dbdcb21e848ccee5fe9e0093cdeb0da7 [file] [log] [blame]
Mike Rapoport985b1aa2010-11-07 16:57:12 -05001/*
2 * sdhci-dove.c Support for SDHCI on Marvell's Dove SoC
3 *
4 * Author: Saeed Bishara <saeed@marvell.com>
5 * Mike Rapoport <mike@compulab.co.il>
6 * Based on sdhci-cns3xxx.c
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +020022#include <linux/clk.h>
23#include <linux/err.h>
Russell Kingf8ec5892012-11-22 23:55:51 +000024#include <linux/io.h>
Mike Rapoport985b1aa2010-11-07 16:57:12 -050025#include <linux/mmc/host.h>
Russell Kingf8ec5892012-11-22 23:55:51 +000026#include <linux/module.h>
Sebastian Hesselbarth4ee7ed02012-07-31 10:12:59 +020027#include <linux/of.h>
Mike Rapoport985b1aa2010-11-07 16:57:12 -050028
Mike Rapoport985b1aa2010-11-07 16:57:12 -050029#include "sdhci-pltfm.h"
30
31static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
32{
33 u16 ret;
34
35 switch (reg) {
36 case SDHCI_HOST_VERSION:
37 case SDHCI_SLOT_INT_STATUS:
38 /* those registers don't exist */
39 return 0;
40 default:
41 ret = readw(host->ioaddr + reg);
42 }
43 return ret;
44}
45
46static u32 sdhci_dove_readl(struct sdhci_host *host, int reg)
47{
48 u32 ret;
49
Russell Kingf8ec5892012-11-22 23:55:51 +000050 ret = readl(host->ioaddr + reg);
51
Mike Rapoport985b1aa2010-11-07 16:57:12 -050052 switch (reg) {
53 case SDHCI_CAPABILITIES:
Mike Rapoport985b1aa2010-11-07 16:57:12 -050054 /* Mask the support for 3.0V */
55 ret &= ~SDHCI_CAN_VDD_300;
56 break;
Mike Rapoport985b1aa2010-11-07 16:57:12 -050057 }
58 return ret;
59}
60
Lars-Peter Clausenc9155682013-03-13 19:26:05 +010061static const struct sdhci_ops sdhci_dove_ops = {
Mike Rapoport985b1aa2010-11-07 16:57:12 -050062 .read_w = sdhci_dove_readw,
63 .read_l = sdhci_dove_readl,
Russell King17710592014-04-25 12:58:55 +010064 .set_clock = sdhci_set_clock,
Russell King2317f562014-04-25 12:57:07 +010065 .set_bus_width = sdhci_set_bus_width,
Russell King03231f92014-04-25 12:57:12 +010066 .reset = sdhci_reset,
Russell King96d7b782014-04-25 12:59:26 +010067 .set_uhs_signaling = sdhci_set_uhs_signaling,
Mike Rapoport985b1aa2010-11-07 16:57:12 -050068};
69
Lars-Peter Clausen1db5eeb2013-03-13 19:26:03 +010070static const struct sdhci_pltfm_data sdhci_dove_pdata = {
Mike Rapoport985b1aa2010-11-07 16:57:12 -050071 .ops = &sdhci_dove_ops,
72 .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
73 SDHCI_QUIRK_NO_BUSY_IRQ |
74 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
Sebastian Hesselbartha9ca1d52012-07-21 19:26:19 -040075 SDHCI_QUIRK_FORCE_DMA |
76 SDHCI_QUIRK_NO_HISPD_BIT,
Mike Rapoport985b1aa2010-11-07 16:57:12 -050077};
Shawn Guo85d65092011-05-27 23:48:12 +080078
Bill Pembertonc3be1ef2012-11-19 13:23:06 -050079static int sdhci_dove_probe(struct platform_device *pdev)
Shawn Guo85d65092011-05-27 23:48:12 +080080{
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +020081 struct sdhci_host *host;
82 struct sdhci_pltfm_host *pltfm_host;
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +020083 int ret;
84
Christian Daudt0e748232013-05-29 13:50:05 -070085 host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
Sebastian Hesselbarthc5ee2492014-05-23 00:16:52 +020086 if (IS_ERR(host))
87 return PTR_ERR(host);
Russell King - ARM Linuxee3298a2012-10-29 21:43:07 +000088
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +020089 pltfm_host = sdhci_priv(host);
Kevin Hao35daeed2015-02-27 15:47:26 +080090 pltfm_host->clk = devm_clk_get(&pdev->dev, NULL);
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +020091
Kevin Hao35daeed2015-02-27 15:47:26 +080092 if (!IS_ERR(pltfm_host->clk))
93 clk_prepare_enable(pltfm_host->clk);
Russell Kingc4306892012-11-22 23:55:30 +000094
Sebastian Hesselbarthc5ee2492014-05-23 00:16:52 +020095 ret = mmc_of_parse(host->mmc);
96 if (ret)
97 goto err_sdhci_add;
Russell Kingc4306892012-11-22 23:55:30 +000098
99 ret = sdhci_add_host(host);
100 if (ret)
101 goto err_sdhci_add;
102
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +0200103 return 0;
104
Russell Kingc4306892012-11-22 23:55:30 +0000105err_sdhci_add:
Kevin Hao35daeed2015-02-27 15:47:26 +0800106 clk_disable_unprepare(pltfm_host->clk);
Russell Kingc4306892012-11-22 23:55:30 +0000107 sdhci_pltfm_free(pdev);
Sebastian Hesselbarth30b87c62012-07-05 12:14:01 +0200108 return ret;
Shawn Guo85d65092011-05-27 23:48:12 +0800109}
110
Bill Pemberton498d83e2012-11-19 13:24:22 -0500111static const struct of_device_id sdhci_dove_of_match_table[] = {
Sebastian Hesselbarth4ee7ed02012-07-31 10:12:59 +0200112 { .compatible = "marvell,dove-sdhci", },
113 {}
114};
115MODULE_DEVICE_TABLE(of, sdhci_dove_of_match_table);
116
Shawn Guo85d65092011-05-27 23:48:12 +0800117static struct platform_driver sdhci_dove_driver = {
118 .driver = {
119 .name = "sdhci-dove",
Ulf Hanssonfa243f62016-07-27 13:07:21 +0200120 .pm = &sdhci_pltfm_pmops,
Sachin Kamat5941fd02014-02-25 15:18:24 +0530121 .of_match_table = sdhci_dove_of_match_table,
Shawn Guo85d65092011-05-27 23:48:12 +0800122 },
123 .probe = sdhci_dove_probe,
Kevin Haocaebcae2015-02-27 15:47:31 +0800124 .remove = sdhci_pltfm_unregister,
Shawn Guo85d65092011-05-27 23:48:12 +0800125};
126
Axel Lind1f81a62011-11-26 12:55:43 +0800127module_platform_driver(sdhci_dove_driver);
Shawn Guo85d65092011-05-27 23:48:12 +0800128
129MODULE_DESCRIPTION("SDHCI driver for Dove");
130MODULE_AUTHOR("Saeed Bishara <saeed@marvell.com>, "
131 "Mike Rapoport <mike@compulab.co.il>");
132MODULE_LICENSE("GPL v2");