All of lore.kernel.org
 help / color / mirror / Atom feed
From: cbouatmailru@gmail.com (Anton Vorontsov)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 3/4] cns3xxx: Add support for SDHCI controllers
Date: Thu, 25 Mar 2010 23:10:53 +0300	[thread overview]
Message-ID: <20100325201053.GC8014@oksana.dev.rtsoft.ru> (raw)
In-Reply-To: <20100325200851.GA6470@oksana.dev.rtsoft.ru>

CNS3xxx chips have SDHCI-compatible SDIO/SD/MMC controller. This patch
adds the support using generic sdhci-pltfm driver.

Signed-off-by: Anton Vorontsov <avorontsov@mvista.com>
---

Depends on -mm tree.

 arch/arm/mach-cns3xxx/Makefile    |    2 +-
 arch/arm/mach-cns3xxx/cns3420vb.c |    2 +
 arch/arm/mach-cns3xxx/devices.c   |  145 +++++++++++++++++++++++++++++++++++++
 arch/arm/mach-cns3xxx/devices.h   |   19 +++++
 4 files changed, 167 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/mach-cns3xxx/devices.c
 create mode 100644 arch/arm/mach-cns3xxx/devices.h

diff --git a/arch/arm/mach-cns3xxx/Makefile b/arch/arm/mach-cns3xxx/Makefile
index 427507a..1a28e48 100644
--- a/arch/arm/mach-cns3xxx/Makefile
+++ b/arch/arm/mach-cns3xxx/Makefile
@@ -1,2 +1,2 @@
-obj-$(CONFIG_ARCH_CNS3XXX)		+= core.o pm.o
+obj-$(CONFIG_ARCH_CNS3XXX)		+= core.o pm.o devices.o
 obj-$(CONFIG_MACH_CNS3420VB)		+= cns3420vb.o
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index 924e4da..c292945 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -32,6 +32,7 @@
 #include <mach/cns3xxx.h>
 #include <mach/irqs.h>
 #include "core.h"
+#include "devices.h"
 
 /*
  * NOR Flash
@@ -111,6 +112,7 @@ static void __init cns3420_early_serial_setup(void)
  */
 static struct platform_device *cns3420_pdevs[] __initdata = {
 	&cns3420_nor_pdev,
+	&cns3xxx_sdhci_pdev,
 };
 
 static void __init cns3420_init(void)
diff --git a/arch/arm/mach-cns3xxx/devices.c b/arch/arm/mach-cns3xxx/devices.c
new file mode 100644
index 0000000..549ad0c
--- /dev/null
+++ b/arch/arm/mach-cns3xxx/devices.c
@@ -0,0 +1,145 @@
+/*
+ * CNS3xxx common devices
+ *
+ * Copyright 2008 Cavium Networks
+ *		  Scott Shu
+ * Copyright 2010 MontaVista Software, LLC.
+ *		  Anton Vorontsov <avorontsov@mvista.com>
+ *
+ * This file 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/init.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/sdhci-pltfm.h>
+#include "../../../drivers/mmc/host/sdhci.h"
+#include "devices.h"
+
+/*
+ * SDHCI
+ */
+static struct resource cns3xxx_sdhci_resources[] = {
+	[0] = {
+		.start = CNS3XXX_SDIO_BASE,
+		.end   = CNS3XXX_SDIO_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_CNS3XXX_SDIO,
+		.end   = IRQ_CNS3XXX_SDIO,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int cns3xxx_sdhci_init(struct sdhci_host *host)
+{
+	u32 __iomem *gpioa = __io(CNS3XXX_MISC_BASE_VIRT + 0x0014);
+	u32 gpioa_pins = __raw_readl(gpioa);
+
+	/* MMC/SD pins share with GPIOA */
+	gpioa_pins |= 0x1fff0004;
+	__raw_writel(gpioa_pins, gpioa);
+
+	cns3xxx_pwr_clk_en(CNS3XXX_PWR_CLK_EN(SDIO));
+	cns3xxx_pwr_soft_rst(CNS3XXX_PWR_SOFTWARE_RST(SDIO));
+
+	return 0;
+}
+
+static unsigned int cns3xxx_sdhci_get_max_clk(struct sdhci_host *host)
+{
+	return 150000000;
+}
+
+static unsigned int cns3xxx_sdhci_get_timeout_clk(struct sdhci_host *host)
+{
+	return cns3xxx_sdhci_get_max_clk(host) / 100000;
+}
+
+static void cns3xxx_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	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(mmc_dev(host->mmc), "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 = 10;
+	while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
+			& SDHCI_CLOCK_INT_STABLE)) {
+		if (timeout == 0)
+			return;
+		timeout--;
+		mdelay(1);
+	}
+
+	clk |= SDHCI_CLOCK_CARD_EN;
+	sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
+
+	host->timeout_clk = cns3xxx_sdhci_get_timeout_clk(host);
+out:
+	host->clock = clock;
+}
+
+static struct sdhci_ops cns3xxx_sdhci_ops = {
+	.get_max_clock		= cns3xxx_sdhci_get_max_clk,
+	.get_timeout_clock	= cns3xxx_sdhci_get_timeout_clk,
+	.set_clock		= cns3xxx_sdhci_set_clock,
+};
+
+static struct sdhci_pltfm_data cns3xxx_sdhci_pdata = {
+	.ops = &cns3xxx_sdhci_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,
+	.init = cns3xxx_sdhci_init,
+};
+
+struct platform_device cns3xxx_sdhci_pdev = {
+	.name		= "sdhci",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(cns3xxx_sdhci_resources),
+	.resource	= cns3xxx_sdhci_resources,
+	.dev		= {
+		.platform_data	= &cns3xxx_sdhci_pdata,
+	},
+};
diff --git a/arch/arm/mach-cns3xxx/devices.h b/arch/arm/mach-cns3xxx/devices.h
new file mode 100644
index 0000000..c5bf5cf
--- /dev/null
+++ b/arch/arm/mach-cns3xxx/devices.h
@@ -0,0 +1,19 @@
+/*
+ * CNS3xxx common devices
+ *
+ * Copyright 2008 Cavium Networks
+ *		  Scott Shu
+ * Copyright 2010 MontaVista Software, LLC.
+ *		  Anton Vorontsov <avorontsov@mvista.com>
+ *
+ * This file 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.
+ */
+
+#ifndef __CNS3XXX_DEVICES_H_
+#define __CNS3XXX_DEVICES_H_
+
+extern struct platform_device cns3xxx_sdhci_pdev;
+
+#endif /* __CNS3XXX_DEVICES_H_ */
-- 
1.7.0

  parent reply	other threads:[~2010-03-25 20:10 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-03-25 20:08 [PATCH 0/4] Support for Cavium Networks CNS3xxx machines Anton Vorontsov
2010-03-25 20:10 ` [PATCH 1/4] cns3xxx: Add basic support for Cavium Networks CNS3xxx processors Anton Vorontsov
2010-03-25 20:23   ` Russell King - ARM Linux
2010-03-26 13:22     ` Anton Vorontsov
2010-03-26 23:08       ` Russell King - ARM Linux
2010-03-25 22:03   ` Sergei Shtylyov
2010-03-25 20:10 ` [PATCH 2/4] cns3xxx: Add defconfig for CNS3420 validation board Anton Vorontsov
2010-03-25 20:10 ` Anton Vorontsov [this message]
2010-03-25 20:10 ` [PATCH 4/4] cns3xxx: Add support for AHCI controllers Anton Vorontsov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100325201053.GC8014@oksana.dev.rtsoft.ru \
    --to=cbouatmailru@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.