From: Anton Vorontsov <avorontsov@xxxxxxxxxx> There's nothing special, just SoC-specific ops and quirks. Signed-off-by: Anton Vorontsov <avorontsov@xxxxxxxxxx> Cc: Ben Dooks <ben@xxxxxxxxxxxx> Cc: Richard Röjfors <richard.rojfors@xxxxxxxxxxxxxx> Cc: <linux-mmc@xxxxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- drivers/mmc/host/Kconfig | 9 ++ drivers/mmc/host/Makefile | 1 drivers/mmc/host/sdhci-cns3xxx.c | 97 +++++++++++++++++++++++++++++ drivers/mmc/host/sdhci-pltfm.c | 3 drivers/mmc/host/sdhci-pltfm.h | 4 + 5 files changed, 114 insertions(+) diff -puN drivers/mmc/host/Kconfig~sdhci-pltfm-add-support-for-cns3xxx-soc-devices drivers/mmc/host/Kconfig --- a/drivers/mmc/host/Kconfig~sdhci-pltfm-add-support-for-cns3xxx-soc-devices +++ a/drivers/mmc/host/Kconfig @@ -121,6 +121,15 @@ config MMC_SDHCI_PLTFM If unsure, say N. +config MMC_SDHCI_CNS3XXX + bool "SDHCI support on the Cavium Networks CNS3xxx SoC" + depends on ARCH_CNS3XXX + depends on MMC_SDHCI_PLTFM + help + This selects the SDHCI support for CNS3xxx System-on-Chip devices. + + If unsure, say N. + config MMC_SDHCI_S3C tristate "SDHCI support on Samsung S3C SoC" depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX) diff -puN drivers/mmc/host/Makefile~sdhci-pltfm-add-support-for-cns3xxx-soc-devices drivers/mmc/host/Makefile --- a/drivers/mmc/host/Makefile~sdhci-pltfm-add-support-for-cns3xxx-soc-devices +++ a/drivers/mmc/host/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o sdhci-platform-y := sdhci-pltfm.o +sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o sdhci-of-y := sdhci-of-core.o diff -puN /dev/null drivers/mmc/host/sdhci-cns3xxx.c --- /dev/null +++ a/drivers/mmc/host/sdhci-cns3xxx.c @@ -0,0 +1,97 @@ +/* + * SDHCI support for CNS3xxx SoC + * + * Copyright 2008 Cavium Networks + * Copyright 2010 MontaVista Software, LLC. + * + * Authors: Scott Shu + * Anton Vorontsov <avorontsov@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/mmc/host.h> +#include <linux/sdhci-pltfm.h> +#include <mach/cns3xxx.h> +#include "sdhci.h" +#include "sdhci-pltfm.h" + +static unsigned int sdhci_cns3xxx_get_max_clk(struct sdhci_host *host) +{ + return 150000000; +} + +static void sdhci_cns3xxx_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct device *dev = mmc_dev(host->mmc); + int div = 1; + u16 clk; + unsigned long timeout; + + if (clock == host->clock) + return; + + sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); + + if (clock == 0) + goto out; + + while (host->max_clk / div > clock) { + /* + * On CNS3xxx divider grows linearly up to 4, and then + * exponentially up to 256. + */ + if (div < 4) + div += 1; + else if (div < 256) + div *= 2; + else + break; + } + + dev_dbg(dev, "desired SD clock: %d, actual: %d\n", + clock, host->max_clk / div); + + /* Divide by 3 is special. */ + if (div != 3) + div >>= 1; + + clk = div << SDHCI_DIVIDER_SHIFT; + clk |= SDHCI_CLOCK_INT_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); + + timeout = 20; + while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) + & SDHCI_CLOCK_INT_STABLE)) { + if (timeout == 0) { + dev_warn(dev, "clock is unstable"); + break; + } + timeout--; + mdelay(1); + } + + clk |= SDHCI_CLOCK_CARD_EN; + sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); +out: + host->clock = clock; +} + +static struct sdhci_ops sdhci_cns3xxx_ops = { + .get_max_clock = sdhci_cns3xxx_get_max_clk, + .set_clock = sdhci_cns3xxx_set_clock, +}; + +struct sdhci_pltfm_data sdhci_cns3xxx_pdata = { + .ops = &sdhci_cns3xxx_ops, + .quirks = SDHCI_QUIRK_BROKEN_DMA | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_INVERTED_WRITE_PROTECT | + SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_NONSTANDARD_CLOCK, +}; diff -puN drivers/mmc/host/sdhci-pltfm.c~sdhci-pltfm-add-support-for-cns3xxx-soc-devices drivers/mmc/host/sdhci-pltfm.c --- a/drivers/mmc/host/sdhci-pltfm.c~sdhci-pltfm-add-support-for-cns3xxx-soc-devices +++ a/drivers/mmc/host/sdhci-pltfm.c @@ -158,6 +158,9 @@ static int __devexit sdhci_pltfm_remove( static const struct platform_device_id sdhci_pltfm_ids[] = { { "sdhci", }, +#ifdef CONFIG_MMC_SDHCI_CNS3XXX + { "sdhci-cns3xxx", (kernel_ulong_t)&sdhci_cns3xxx_pdata }, +#endif { }, }; MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); diff -puN drivers/mmc/host/sdhci-pltfm.h~sdhci-pltfm-add-support-for-cns3xxx-soc-devices drivers/mmc/host/sdhci-pltfm.h --- a/drivers/mmc/host/sdhci-pltfm.h~sdhci-pltfm-add-support-for-cns3xxx-soc-devices +++ a/drivers/mmc/host/sdhci-pltfm.h @@ -11,4 +11,8 @@ #ifndef _DRIVERS_MMC_SDHCI_PLTFM_H #define _DRIVERS_MMC_SDHCI_PLTFM_H +#include <linux/sdhci-pltfm.h> + +extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; + #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ _ -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html