2 * OpenFirmware bindings for Secure Digital Host Controller Interface.
4 * Copyright (c) 2007 Freescale Semiconductor, Inc.
5 * Copyright (c) 2009 MontaVista Software, Inc.
7 * Authors: Xiaobo Xie <X.Xie@freescale.com>
8 * Anton Vorontsov <avorontsov@ru.mvista.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
16 #include <linux/module.h>
17 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/delay.h>
22 #include <linux/of_platform.h>
23 #include <linux/mmc/host.h>
24 #include <asm/machdep.h>
27 struct sdhci_of_data
{
32 struct sdhci_of_host
{
38 * Ops and quirks for the Freescale eSDHC controller.
41 #define ESDHC_DMA_SYSCTL 0x40c
42 #define ESDHC_DMA_SNOOP 0x00000040
44 #define ESDHC_SYSTEM_CONTROL 0x2c
45 #define ESDHC_CLOCK_MASK 0x0000fff0
46 #define ESDHC_PREDIV_SHIFT 8
47 #define ESDHC_DIVIDER_SHIFT 4
48 #define ESDHC_CLOCK_PEREN 0x00000004
49 #define ESDHC_CLOCK_HCKEN 0x00000002
50 #define ESDHC_CLOCK_IPGEN 0x00000001
52 #define ESDHC_HOST_CONTROL_RES 0x05
54 static u32
esdhc_readl(struct sdhci_host
*host
, int reg
)
56 return in_be32(host
->ioaddr
+ reg
);
59 static u16
esdhc_readw(struct sdhci_host
*host
, int reg
)
63 if (unlikely(reg
== SDHCI_HOST_VERSION
))
64 ret
= in_be16(host
->ioaddr
+ reg
);
66 ret
= in_be16(host
->ioaddr
+ (reg
^ 0x2));
70 static u8
esdhc_readb(struct sdhci_host
*host
, int reg
)
72 return in_8(host
->ioaddr
+ (reg
^ 0x3));
75 static void esdhc_writel(struct sdhci_host
*host
, u32 val
, int reg
)
77 out_be32(host
->ioaddr
+ reg
, val
);
80 static void esdhc_writew(struct sdhci_host
*host
, u16 val
, int reg
)
82 struct sdhci_of_host
*of_host
= sdhci_priv(host
);
83 int base
= reg
& ~0x3;
84 int shift
= (reg
& 0x2) * 8;
87 case SDHCI_TRANSFER_MODE
:
89 * Postpone this write, we must do it together with a
90 * command write that is down below.
92 of_host
->xfer_mode_shadow
= val
;
95 esdhc_writel(host
, val
<< 16 | of_host
->xfer_mode_shadow
,
98 case SDHCI_BLOCK_SIZE
:
100 * Two last DMA bits are reserved, and first one is used for
101 * non-standard blksz of 4096 bytes that we don't support
102 * yet. So clear the DMA boundary bits.
104 val
&= ~SDHCI_MAKE_BLKSZ(0x7, 0);
107 clrsetbits_be32(host
->ioaddr
+ base
, 0xffff << shift
, val
<< shift
);
110 static void esdhc_writeb(struct sdhci_host
*host
, u8 val
, int reg
)
112 int base
= reg
& ~0x3;
113 int shift
= (reg
& 0x3) * 8;
115 /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */
116 if (reg
== SDHCI_HOST_CONTROL
)
117 val
&= ~ESDHC_HOST_CONTROL_RES
;
119 clrsetbits_be32(host
->ioaddr
+ base
, 0xff << shift
, val
<< shift
);
122 static void esdhc_set_clock(struct sdhci_host
*host
, unsigned int clock
)
127 clrbits32(host
->ioaddr
+ ESDHC_SYSTEM_CONTROL
, ESDHC_CLOCK_IPGEN
|
128 ESDHC_CLOCK_HCKEN
| ESDHC_CLOCK_PEREN
| ESDHC_CLOCK_MASK
);
133 while (host
->max_clk
/ pre_div
/ 16 > clock
&& pre_div
< 256)
136 while (host
->max_clk
/ pre_div
/ div
> clock
&& div
< 16)
139 dev_dbg(mmc_dev(host
->mmc
), "desired SD clock: %d, actual: %d\n",
140 clock
, host
->max_clk
/ pre_div
/ div
);
145 setbits32(host
->ioaddr
+ ESDHC_SYSTEM_CONTROL
, ESDHC_CLOCK_IPGEN
|
146 ESDHC_CLOCK_HCKEN
| ESDHC_CLOCK_PEREN
|
147 div
<< ESDHC_DIVIDER_SHIFT
| pre_div
<< ESDHC_PREDIV_SHIFT
);
153 static int esdhc_enable_dma(struct sdhci_host
*host
)
155 setbits32(host
->ioaddr
+ ESDHC_DMA_SYSCTL
, ESDHC_DMA_SNOOP
);
159 static unsigned int esdhc_get_max_clock(struct sdhci_host
*host
)
161 struct sdhci_of_host
*of_host
= sdhci_priv(host
);
163 return of_host
->clock
;
166 static unsigned int esdhc_get_min_clock(struct sdhci_host
*host
)
168 struct sdhci_of_host
*of_host
= sdhci_priv(host
);
170 return of_host
->clock
/ 256 / 16;
173 static struct sdhci_of_data sdhci_esdhc
= {
174 .quirks
= SDHCI_QUIRK_FORCE_BLK_SZ_2048
|
175 SDHCI_QUIRK_BROKEN_CARD_DETECTION
|
176 SDHCI_QUIRK_NO_BUSY_IRQ
|
177 SDHCI_QUIRK_NONSTANDARD_CLOCK
|
178 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
|
179 SDHCI_QUIRK_PIO_NEEDS_DELAY
|
180 SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET
|
181 SDHCI_QUIRK_NO_CARD_NO_RESET
,
183 .readl
= esdhc_readl
,
184 .readw
= esdhc_readw
,
185 .readb
= esdhc_readb
,
186 .writel
= esdhc_writel
,
187 .writew
= esdhc_writew
,
188 .writeb
= esdhc_writeb
,
189 .set_clock
= esdhc_set_clock
,
190 .enable_dma
= esdhc_enable_dma
,
191 .get_max_clock
= esdhc_get_max_clock
,
192 .get_min_clock
= esdhc_get_min_clock
,
198 static int sdhci_of_suspend(struct of_device
*ofdev
, pm_message_t state
)
200 struct sdhci_host
*host
= dev_get_drvdata(&ofdev
->dev
);
202 return mmc_suspend_host(host
->mmc
, state
);
205 static int sdhci_of_resume(struct of_device
*ofdev
)
207 struct sdhci_host
*host
= dev_get_drvdata(&ofdev
->dev
);
209 return mmc_resume_host(host
->mmc
);
214 #define sdhci_of_suspend NULL
215 #define sdhci_of_resume NULL
219 static bool __devinit
sdhci_of_wp_inverted(struct device_node
*np
)
221 if (of_get_property(np
, "sdhci,wp-inverted", NULL
))
224 /* Old device trees don't have the wp-inverted property. */
225 return machine_is(mpc837x_rdb
) || machine_is(mpc837x_mds
);
228 static int __devinit
sdhci_of_probe(struct of_device
*ofdev
,
229 const struct of_device_id
*match
)
231 struct device_node
*np
= ofdev
->node
;
232 struct sdhci_of_data
*sdhci_of_data
= match
->data
;
233 struct sdhci_host
*host
;
234 struct sdhci_of_host
*of_host
;
239 if (!of_device_is_available(np
))
242 host
= sdhci_alloc_host(&ofdev
->dev
, sizeof(*of_host
));
246 of_host
= sdhci_priv(host
);
247 dev_set_drvdata(&ofdev
->dev
, host
);
249 host
->ioaddr
= of_iomap(np
, 0);
255 host
->irq
= irq_of_parse_and_map(np
, 0);
261 host
->hw_name
= dev_name(&ofdev
->dev
);
263 host
->quirks
= sdhci_of_data
->quirks
;
264 host
->ops
= &sdhci_of_data
->ops
;
267 if (of_get_property(np
, "sdhci,1-bit-only", NULL
))
268 host
->quirks
|= SDHCI_QUIRK_FORCE_1_BIT_DATA
;
270 if (sdhci_of_wp_inverted(np
))
271 host
->quirks
|= SDHCI_QUIRK_INVERTED_WRITE_PROTECT
;
273 clk
= of_get_property(np
, "clock-frequency", &size
);
274 if (clk
&& size
== sizeof(*clk
) && *clk
)
275 of_host
->clock
= *clk
;
277 ret
= sdhci_add_host(host
);
284 irq_dispose_mapping(host
->irq
);
286 iounmap(host
->ioaddr
);
288 sdhci_free_host(host
);
292 static int __devexit
sdhci_of_remove(struct of_device
*ofdev
)
294 struct sdhci_host
*host
= dev_get_drvdata(&ofdev
->dev
);
296 sdhci_remove_host(host
, 0);
297 sdhci_free_host(host
);
298 irq_dispose_mapping(host
->irq
);
299 iounmap(host
->ioaddr
);
303 static const struct of_device_id sdhci_of_match
[] = {
304 { .compatible
= "fsl,mpc8379-esdhc", .data
= &sdhci_esdhc
, },
305 { .compatible
= "fsl,mpc8536-esdhc", .data
= &sdhci_esdhc
, },
306 { .compatible
= "fsl,esdhc", .data
= &sdhci_esdhc
, },
307 { .compatible
= "generic-sdhci", },
310 MODULE_DEVICE_TABLE(of
, sdhci_of_match
);
312 static struct of_platform_driver sdhci_of_driver
= {
313 .driver
.name
= "sdhci-of",
314 .match_table
= sdhci_of_match
,
315 .probe
= sdhci_of_probe
,
316 .remove
= __devexit_p(sdhci_of_remove
),
317 .suspend
= sdhci_of_suspend
,
318 .resume
= sdhci_of_resume
,
321 static int __init
sdhci_of_init(void)
323 return of_register_platform_driver(&sdhci_of_driver
);
325 module_init(sdhci_of_init
);
327 static void __exit
sdhci_of_exit(void)
329 of_unregister_platform_driver(&sdhci_of_driver
);
331 module_exit(sdhci_of_exit
);
333 MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver");
334 MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, "
335 "Anton Vorontsov <avorontsov@ru.mvista.com>");
336 MODULE_LICENSE("GPL");