Skip to content

Commit 20b1597

Browse files
Anton Vorontsovtorvalds
authored andcommitted
sdhci-pltfm: add support for CNS3xxx SoC devices
There's nothing special, just SoC-specific ops and quirks. Signed-off-by: Anton Vorontsov <[email protected]> Cc: Ben Dooks <[email protected]> Cc: Richard R?jfors <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 845e3f4 commit 20b1597

File tree

5 files changed

+114
-0
lines changed

5 files changed

+114
-0
lines changed

drivers/mmc/host/Kconfig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,15 @@ config MMC_SDHCI_PLTFM
121121

122122
If unsure, say N.
123123

124+
config MMC_SDHCI_CNS3XXX
125+
bool "SDHCI support on the Cavium Networks CNS3xxx SoC"
126+
depends on ARCH_CNS3XXX
127+
depends on MMC_SDHCI_PLTFM
128+
help
129+
This selects the SDHCI support for CNS3xxx System-on-Chip devices.
130+
131+
If unsure, say N.
132+
124133
config MMC_SDHCI_S3C
125134
tristate "SDHCI support on Samsung S3C SoC"
126135
depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)

drivers/mmc/host/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
3939

4040
obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o
4141
sdhci-platform-y := sdhci-pltfm.o
42+
sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
4243

4344
obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o
4445
sdhci-of-y := sdhci-of-core.o

drivers/mmc/host/sdhci-cns3xxx.c

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* SDHCI support for CNS3xxx SoC
3+
*
4+
* Copyright 2008 Cavium Networks
5+
* Copyright 2010 MontaVista Software, LLC.
6+
*
7+
* Authors: Scott Shu
8+
* Anton Vorontsov <[email protected]>
9+
*
10+
* This program is free software; you can redistribute it and/or modify
11+
* it under the terms of the GNU General Public License version 2 as
12+
* published by the Free Software Foundation.
13+
*/
14+
15+
#include <linux/delay.h>
16+
#include <linux/device.h>
17+
#include <linux/mmc/host.h>
18+
#include <linux/sdhci-pltfm.h>
19+
#include <mach/cns3xxx.h>
20+
#include "sdhci.h"
21+
#include "sdhci-pltfm.h"
22+
23+
static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host)
24+
{
25+
return 150000000;
26+
}
27+
28+
static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock)
29+
{
30+
struct device *dev = mmc_dev(host->mmc);
31+
int div = 1;
32+
u16 clk;
33+
unsigned long timeout;
34+
35+
if (clock == host->clock)
36+
return;
37+
38+
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
39+
40+
if (clock == 0)
41+
goto out;
42+
43+
while (host->max_clk / div > clock) {
44+
/*
45+
* On CNS3xxx divider grows linearly up to 4, and then
46+
* exponentially up to 256.
47+
*/
48+
if (div < 4)
49+
div += 1;
50+
else if (div < 256)
51+
div *= 2;
52+
else
53+
break;
54+
}
55+
56+
dev_dbg(dev, "desired SD clock: %d, actual: %d\n",
57+
clock, host->max_clk / div);
58+
59+
/* Divide by 3 is special. */
60+
if (div != 3)
61+
div >>= 1;
62+
63+
clk = div << SDHCI_DIVIDER_SHIFT;
64+
clk |= SDHCI_CLOCK_INT_EN;
65+
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
66+
67+
timeout = 20;
68+
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
69+
& SDHCI_CLOCK_INT_STABLE)) {
70+
if (timeout == 0) {
71+
dev_warn(dev, "clock is unstable");
72+
break;
73+
}
74+
timeout--;
75+
mdelay(1);
76+
}
77+
78+
clk |= SDHCI_CLOCK_CARD_EN;
79+
sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
80+
out:
81+
host->clock = clock;
82+
}
83+
84+
static struct sdhci_ops sdhci_cns3xxx_ops = {
85+
.get_max_clock = sdhci_cns3xxx_get_max_clk,
86+
.set_clock = sdhci_cns3xxx_set_clock,
87+
};
88+
89+
struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
90+
.ops = &sdhci_cns3xxx_ops,
91+
.quirks = SDHCI_QUIRK_BROKEN_DMA |
92+
SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
93+
SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
94+
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
95+
SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
96+
SDHCI_QUIRK_NONSTANDARD_CLOCK,
97+
};

drivers/mmc/host/sdhci-pltfm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,9 @@ static int __devexit sdhci_pltfm_remove(struct platform_device *pdev)
158158

159159
static const struct platform_device_id sdhci_pltfm_ids[] = {
160160
{ "sdhci", },
161+
#ifdef CONFIG_MMC_SDHCI_CNS3XXX
162+
{ "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata },
163+
#endif
161164
{ },
162165
};
163166
MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids);

drivers/mmc/host/sdhci-pltfm.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,8 @@
1111
#ifndef _DRIVERS_MMC_SDHCI_PLTFM_H
1212
#define _DRIVERS_MMC_SDHCI_PLTFM_H
1313

14+
#include <linux/sdhci-pltfm.h>
15+
16+
extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
17+
1418
#endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */

0 commit comments

Comments
 (0)