aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/Kconfig8
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/sh_mobile_sdhi.c145
3 files changed, 154 insertions, 0 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 570be139f9df..96956b3cc178 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -35,6 +35,14 @@ config MFD_ASIC3
35 This driver supports the ASIC3 multifunction chip found on many 35 This driver supports the ASIC3 multifunction chip found on many
36 PDAs (mainly iPAQ and HTC based ones) 36 PDAs (mainly iPAQ and HTC based ones)
37 37
38config MFD_SH_MOBILE_SDHI
39 bool "Support for SuperH Mobile SDHI"
40 depends on SUPERH
41 select MFD_CORE
42 ---help---
43 This driver supports the SDHI hardware block found in many
44 SuperH Mobile SoCs.
45
38config MFD_DM355EVM_MSP 46config MFD_DM355EVM_MSP
39 bool "DaVinci DM355 EVM microcontroller" 47 bool "DaVinci DM355 EVM microcontroller"
40 depends on I2C && MACH_DAVINCI_DM355_EVM 48 depends on I2C && MACH_DAVINCI_DM355_EVM
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f3b277b90d40..d9522943d2fb 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -4,6 +4,7 @@
4 4
5obj-$(CONFIG_MFD_SM501) += sm501.o 5obj-$(CONFIG_MFD_SM501) += sm501.o
6obj-$(CONFIG_MFD_ASIC3) += asic3.o 6obj-$(CONFIG_MFD_ASIC3) += asic3.o
7obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o
7 8
8obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o 9obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
9obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o 10obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c
new file mode 100644
index 000000000000..56f72cc1d569
--- /dev/null
+++ b/drivers/mfd/sh_mobile_sdhi.c
@@ -0,0 +1,145 @@
1/*
2 * SuperH Mobile SDHI
3 *
4 * Copyright (C) 2009 Magnus Damm
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * Based on "Compaq ASIC3 support":
11 *
12 * Copyright 2001 Compaq Computer Corporation.
13 * Copyright 2004-2005 Phil Blundell
14 * Copyright 2007-2008 OpenedHand Ltd.
15 *
16 * Authors: Phil Blundell <pb@handhelds.org>,
17 * Samuel Ortiz <sameo@openedhand.com>
18 *
19 */
20
21#include <linux/kernel.h>
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24
25#include <linux/mfd/core.h>
26#include <linux/mfd/tmio.h>
27
28struct sh_mobile_sdhi {
29 struct clk *clk;
30 struct tmio_mmc_data mmc_data;
31 struct mfd_cell cell_mmc;
32};
33
34static struct resource sh_mobile_sdhi_resources[] = {
35 {
36 .start = 0x000,
37 .end = 0x1ff,
38 .flags = IORESOURCE_MEM,
39 },
40 {
41 .start = 0,
42 .end = 0,
43 .flags = IORESOURCE_IRQ,
44 },
45};
46
47static struct mfd_cell sh_mobile_sdhi_cell = {
48 .name = "tmio-mmc",
49 .num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources),
50 .resources = sh_mobile_sdhi_resources,
51};
52
53static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
54{
55 struct sh_mobile_sdhi *priv;
56 struct resource *mem;
57 char clk_name[8];
58 int ret, irq;
59
60 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
61 if (!mem)
62 dev_err(&pdev->dev, "missing MEM resource\n");
63
64 irq = platform_get_irq(pdev, 0);
65 if (irq < 0)
66 dev_err(&pdev->dev, "missing IRQ resource\n");
67
68 if (!mem || (irq < 0))
69 return -EINVAL;
70
71 priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
72 if (priv == NULL) {
73 dev_err(&pdev->dev, "kzalloc failed\n");
74 return -ENOMEM;
75 }
76
77 snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
78 priv->clk = clk_get(&pdev->dev, clk_name);
79 if (IS_ERR(priv->clk)) {
80 dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
81 ret = PTR_ERR(priv->clk);
82 kfree(priv);
83 return ret;
84 }
85
86 clk_enable(priv->clk);
87
88 /* FIXME: silly const unsigned int hclk */
89 *(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk);
90
91 memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
92 priv->cell_mmc.driver_data = &priv->mmc_data;
93 priv->cell_mmc.platform_data = &priv->cell_mmc;
94 priv->cell_mmc.data_size = sizeof(priv->cell_mmc);
95
96 platform_set_drvdata(pdev, priv);
97
98 ret = mfd_add_devices(&pdev->dev, pdev->id,
99 &priv->cell_mmc, 1, mem, irq);
100 if (ret) {
101 clk_disable(priv->clk);
102 clk_put(priv->clk);
103 kfree(priv);
104 }
105
106 return ret;
107}
108
109static int sh_mobile_sdhi_remove(struct platform_device *pdev)
110{
111 struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev);
112
113 mfd_remove_devices(&pdev->dev);
114 clk_disable(priv->clk);
115 clk_put(priv->clk);
116 kfree(priv);
117
118 return 0;
119}
120
121static struct platform_driver sh_mobile_sdhi_driver = {
122 .driver = {
123 .name = "sh_mobile_sdhi",
124 .owner = THIS_MODULE,
125 },
126 .probe = sh_mobile_sdhi_probe,
127 .remove = __devexit_p(sh_mobile_sdhi_remove),
128};
129
130static int __init sh_mobile_sdhi_init(void)
131{
132 return platform_driver_register(&sh_mobile_sdhi_driver);
133}
134
135static void __exit sh_mobile_sdhi_exit(void)
136{
137 platform_driver_unregister(&sh_mobile_sdhi_driver);
138}
139
140module_init(sh_mobile_sdhi_init);
141module_exit(sh_mobile_sdhi_exit);
142
143MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
144MODULE_AUTHOR("Magnus Damm");
145MODULE_LICENSE("GPL v2");