linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ARM: mmc: bcm281xx SDHCI driver
@ 2013-05-09  5:55 Christian Daudt
  2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-11  4:28 ` Stephen Warren
  0 siblings, 2 replies; 8+ messages in thread
From: Christian Daudt @ 2013-05-09  5:55 UTC (permalink / raw)
  To: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc
  Cc: csd_b, Christian Daudt

Add SDHCI driver for the Broadcom 281xx SoCs. Also
add bindings for it into bcm281xx dts files.
Still missing:
 - power managemement

Signed-off-by: Christian Daudt <csd@broadcom.com>

diff --git a/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt b/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt
new file mode 100644
index 0000000..ad1c4bd
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt
@@ -0,0 +1,16 @@
+Broadcom BCM281xx SDHCI driver
+
+This file documents differences between the core properties in mmc.txt
+and the properties in the bcm281xx driver.
+
+Required properties:
+- compatible : Should be "bcm,kona-sdhci"
+
+Example:
+
+sdio2: sdio@0x3f1a0000 {
+	compatible = "bcm,kona-sdhci";
+	reg = <0x3f1a0000 0x10000>;
+	interrupts = <0x0 74 0x4>;
+};
+
diff --git a/arch/arm/boot/dts/bcm11351-brt.dts b/arch/arm/boot/dts/bcm11351-brt.dts
index 248067c..9ae3404 100644
--- a/arch/arm/boot/dts/bcm11351-brt.dts
+++ b/arch/arm/boot/dts/bcm11351-brt.dts
@@ -27,4 +27,21 @@
 		status = "okay";
 	};
 
+	sdio0: sdio@0x3f180000 {
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+	sdio1: sdio@0x3f190000 {
+		non-removable;
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+	sdio3: sdio@0x3f1b0000 {
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+
 };
diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
index ad13588..6606b41 100644
--- a/arch/arm/boot/dts/bcm11351.dtsi
+++ b/arch/arm/boot/dts/bcm11351.dtsi
@@ -47,4 +47,33 @@
 		    cache-unified;
 		    cache-level = <2>;
 	};
+
+	sdio0: sdio@0x3f180000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f180000 0x10000>;
+		interrupts = <0x0 77 0x4>;
+		status = "disabled";
+	};
+
+	sdio1: sdio@0x3f190000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f190000 0x10000>;
+		interrupts = <0x0 76 0x4>;
+		status = "disabled";
+	};
+
+	sdio2: sdio@0x3f1a0000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f1a0000 0x10000>;
+		interrupts = <0x0 74 0x4>;
+		status = "disabled";
+	};
+
+	sdio3: sdio@0x3f1b0000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f1b0000 0x10000>;
+		interrupts = <0x0 73 0x4>;
+		status = "disabled";
+	};
+
 };
diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
index e3bf2d6..65edf6d 100644
--- a/arch/arm/configs/bcm_defconfig
+++ b/arch/arm/configs/bcm_defconfig
@@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_BCM_KONA=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index d88219e..e067c5a 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
 
 	  YMMV.
 
+config MMC_SDHCI_BCM_KONA
+	tristate "SDHCI support on Broadcom KONA platform"
+	depends on ARCH_BCM && MMC_SDHCI_PLTFM
+	help
+	  This selects the Broadcom Kona Secure Digital Host Controller
+	  Interface(SDHCI) support.
+	  This is used in Broadcom mobile SoCs.
+
+	  If you have a controller with this interface, say Y or M here.
+
 config MMC_SDHCI_BCM2835
 	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
 	depends on ARCH_BCM2835
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c380e3c..a9f582b 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -59,6 +59,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
 obj-$(CONFIG_MMC_SDHCI_TEGRA)		+= sdhci-tegra.o
 obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
 obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
+obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
 
 ifeq ($(CONFIG_CB710_DEBUG),y)
diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
new file mode 100644
index 0000000..27188b9
--- /dev/null
+++ b/drivers/mmc/host/sdhci-bcm-kona.c
@@ -0,0 +1,486 @@
+/*
+ * Copyright (C) 2013 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/highmem.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/version.h>
+
+#include "sdhci-pltfm.h"
+#include "sdhci.h"
+
+#define SDHCI_SOFT_RESET			0x01000000
+#define KONA_SDHOST_CORECTRL			0x8000
+#define KONA_SDHOST_CD_PINCTRL			0x00000008
+#define KONA_SDHOST_STOP_HCLK			0x00000004
+#define KONA_SDHOST_RESET			0x00000002
+#define KONA_SDHOST_EN				0x00000001
+
+#define KONA_SDHOST_CORESTAT			0x8004
+#define KONA_SDHOST_WP				0x00000002
+#define KONA_SDHOST_CD_SW			0x00000001
+
+#define KONA_SDHOST_COREIMR			0x8008
+#define KONA_SDHOST_IP				0x00000001
+
+#define KONA_SDHOST_COREISR			0x800C
+#define KONA_SDHOST_COREIMSR			0x8010
+#define KONA_SDHOST_COREDBG1			0x8014
+#define KONA_SDHOST_COREGPO_MASK		0x8018
+
+#define SD_DETECT_GPIO_DEBOUNCE_128MS		128
+
+#define KONA_MMC_AUTOSUSPEND_DELAY		(50)
+
+struct sdhci_bcm_kona_cfg {
+	unsigned int	max_freq;
+	int		is_8bit;
+	int		irq;
+	int		cd_gpio;
+	int		wp_gpio;
+	int		non_removable;
+};
+
+struct sdhci_bcm_kona_dev {
+	struct sdhci_bcm_kona_cfg *cfg;
+	struct device *dev;
+	struct sdhci_host *host;
+	struct clk *peri_clk;
+	struct clk *sleep_clk;
+};
+
+
+static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
+{
+	unsigned int val;
+	unsigned long timeout;
+
+	/* This timeout should be sufficent for core to reset */
+	timeout = jiffies + msecs_to_jiffies(100);
+
+	/* reset the host using the top level reset */
+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
+	val |= KONA_SDHOST_RESET;
+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
+
+	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
+		if (time_is_before_jiffies(timeout)) {
+			pr_err("Error: sd host is stuck in reset!!!\n");
+			return -EFAULT;
+		}
+	}
+
+	/* bring the host out of reset */
+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
+	val &= ~KONA_SDHOST_RESET;
+
+	/*
+	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
+	 * Back-to-Back writes to same register needs delay when SD bus clock
+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
+	 * insert-removal.
+	 */
+	udelay(1000);
+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
+
+	return 0;
+}
+
+static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
+{
+	unsigned int val;
+
+	/* enable the interrupt from the IP core */
+	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
+	val |= KONA_SDHOST_IP;
+	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
+
+	/* Enable the AHB clock gating module to the host */
+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
+	val |= KONA_SDHOST_EN;
+
+	/*
+	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
+	 * Back-to-Back writes to same register needs delay when SD bus clock
+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
+	 * insert-removal.
+	 */
+	udelay(1000);
+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
+}
+
+/*
+ * Software emulation of the SD card insertion/removal. Set insert=1 for insert
+ * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
+ * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
+ * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
+ */
+static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
+{
+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
+	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
+	u32 val;
+	unsigned long flags;
+
+	/* this function can be called from various contexts including ISR */
+	spin_lock_irqsave(&host->lock, flags);
+	/* Ensure SD bus scanning to detect media change */
+	host->mmc->rescan_disable = 0;
+
+	/*
+	 * Back-to-Back register write needs a delay of min 10uS.
+	 * Back-to-Back writes to same register needs delay when SD bus clock
+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
+	 * insert-removal.
+	 * We keep 20uS
+	 */
+	udelay(20);
+	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
+
+	if (insert) {
+		if (kona_dev->cfg->wp_gpio >= 0) {
+			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
+
+			if (wp_status)
+				val |= KONA_SDHOST_WP;
+			else
+				val &= ~KONA_SDHOST_WP;
+		}
+
+		val |= KONA_SDHOST_CD_SW;
+		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
+	} else {
+		val &= ~KONA_SDHOST_CD_SW;
+		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
+	}
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	return 0;
+}
+
+/*
+ * SD card detection interrupt handler
+ */
+static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
+{
+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
+	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
+
+	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
+		pr_debug("card inserted\n");
+		sdhci_bcm_kona_sd_card_emulate(host, 1);
+	} else {
+		pr_debug("card removed\n");
+		sdhci_bcm_kona_sd_card_emulate(host, 0);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * Get the base clock. Use central clock source for now. Not sure if different
+ * clock speed to each dev is allowed
+ */
+static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host)
+{
+	struct sdhci_bcm_kona_dev *kona_dev;
+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
+	kona_dev = pltfm_priv->priv;
+
+	return kona_dev->cfg->max_freq;
+}
+
+static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host)
+{
+	return sdhci_bcm_kona_get_max_clk(host);
+}
+
+static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
+				u8 power_mode)
+{
+	if (power_mode == MMC_POWER_OFF)
+		return;
+	else
+		mdelay(10);
+}
+
+static struct sdhci_ops sdhci_bcm_kona_ops = {
+	.get_max_clock = sdhci_bcm_kona_get_max_clk,
+	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
+	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
+};
+
+static struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
+	.ops    = &sdhci_bcm_kona_ops,
+	.quirks = SDHCI_QUIRK_NO_CARD_NO_RESET |
+		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR |
+		SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE |
+		SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
+		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+};
+
+static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = {
+	{ .compatible = "bcm,kona-sdhci", .data = &sdhci_pltfm_data_kona },
+	{}
+};
+MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
+
+static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
+			struct platform_device *pdev)
+{
+	struct sdhci_bcm_kona_cfg *cfg;
+	struct device_node *np = pdev->dev.of_node;
+	u32 temp;
+
+	if (!np)
+		return NULL;
+
+	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
+	if (!cfg) {
+		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
+		return NULL;
+	}
+
+	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+	if (of_get_property(np, "non-removable", NULL))
+		cfg->non_removable = 1;
+
+	if (of_property_read_u32(np, "bus-width", &temp) == 0 && temp == 8)
+		cfg->is_8bit = 1;
+
+	if (of_property_read_u32(np, "max-frequency", &cfg->max_freq)) {
+		dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n");
+		return NULL;
+	}
+	return cfg;
+}
+
+static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct sdhci_bcm_kona_cfg *kona_cfg = NULL;
+	const struct sdhci_pltfm_data *plat_data;
+	struct sdhci_bcm_kona_dev *kona_dev = NULL;
+	struct sdhci_pltfm_host *pltfm_priv;
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host;
+	int ret;
+	unsigned int irq;
+	ret = 0;
+
+	match = of_match_device(sdhci_bcm_kona_of_match, &pdev->dev);
+	if (!match)
+		plat_data = &sdhci_pltfm_data_kona;
+	else
+		plat_data = match->data;
+
+	host = sdhci_pltfm_init(pdev, (struct sdhci_pltfm_data *)plat_data);
+	if (IS_ERR(host))
+		return PTR_ERR(host);
+
+	kona_cfg = dev->platform_data;
+	if (!kona_cfg)
+		kona_cfg = sdhci_bcm_kona_parse_dt(pdev);
+
+	if (!kona_cfg) {
+		ret = -ENXIO;
+		goto err_pltfm_free;
+	}
+
+	dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr);
+
+	pltfm_priv = sdhci_priv(host);
+
+	kona_dev = devm_kzalloc(dev, sizeof(*kona_dev), GFP_KERNEL);
+	if (!kona_dev) {
+		dev_err(dev, "Can't allocate kona_dev\n");
+		ret = -ENOMEM;
+		goto err_pltfm_free;
+	}
+	kona_dev->cfg = kona_cfg;
+	kona_dev->dev = dev;
+	pltfm_priv->priv = kona_dev;
+
+	dev_dbg(dev, "non-removable=%c\n",
+		 (kona_cfg->non_removable) ? 'Y' : 'N');
+	dev_dbg(dev, "cd_gpio %d, wp_gpio %d\n", kona_cfg->cd_gpio,
+		 kona_cfg->wp_gpio);
+
+	if (kona_cfg->non_removable) {
+		host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+	}
+
+	dev_dbg(dev, "is_8bit=%c\n", (kona_cfg->is_8bit) ? 'Y' : 'N');
+	if (kona_cfg->is_8bit)
+		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
+
+	ret = sdhci_bcm_kona_sd_reset(host);
+	if (ret)
+		goto err_pltfm_free;
+
+	sdhci_bcm_kona_sd_init(host);
+
+	ret = sdhci_add_host(host);
+	if (ret) {
+		dev_err(dev, "Failed sdhci_add_host\n");
+		goto err_reset;
+	}
+
+	/* if device is eMMC, emulate card insert right here */
+	if (kona_cfg->non_removable) {
+		ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
+		if (ret) {
+			dev_err(dev,
+				"unable to emulate card insertion\n");
+			goto err_remove_host;
+		}
+	} else if (kona_dev->cfg->cd_gpio >= 0) {
+		ret = devm_gpio_request(dev, kona_dev->cfg->cd_gpio, "sdio cd");
+		if (ret < 0) {
+			dev_err(kona_dev->dev,
+				"Unable to request GPIO pin %d\n",
+				kona_dev->cfg->cd_gpio);
+			goto err_remove_host;
+		}
+
+		gpio_direction_input(kona_dev->cfg->cd_gpio);
+
+		/* Set debounce for SD Card detect to maximum value (128ms)
+		 *
+		 * NOTE-1: If gpio_set_debounce() returns error we still
+		 * continue with the default debounce value set. Another reason
+		 * for doing this is that on rhea-ray boards the SD Detect GPIO
+		 * is on GPIO Expander and gpio_set_debounce() will return error
+		 * and if we return error from here, then probe() would fail and
+		 * SD detection would always fail.
+		 *
+		 * NOTE-2: We also give a msleep() of the "debounce" time here
+		 * so that we give enough time for the debounce to stabilize
+		 * before we read the gpio value in gpio_get_value_cansleep().
+		 */
+		ret = gpio_set_debounce(kona_dev->cfg->cd_gpio,
+				(SD_DETECT_GPIO_DEBOUNCE_128MS * 1000));
+		if (ret < 0) {
+			dev_err(kona_dev->dev,
+				"%s: gpio set debounce failed."
+				"default debounce value assumed\n", __func__);
+		}
+
+		/* Sleep for 128ms to allow debounce to stabilize */
+		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
+		/* request irq for cd_gpio after the gpio debounce is
+		 * stabilized, otherwise, some bogus gpio interrupts might be
+		 * triggered.
+		 */
+		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
+		ret = devm_request_threaded_irq(dev,
+				irq,
+				NULL,
+				sdhci_bcm_kona_pltfm_cd_interrupt,
+				IRQF_TRIGGER_FALLING|
+				IRQF_TRIGGER_RISING |
+				IRQF_ONESHOT |
+				IRQF_NO_SUSPEND, "sdio cd", host);
+		if (ret) {
+			dev_err(kona_dev->dev,
+				"Unable to request card detection irq=%d"
+				" for gpio=%d  ret=%d\n",
+				gpio_to_irq(kona_dev->cfg->cd_gpio),
+				kona_dev->cfg->cd_gpio, ret);
+			goto err_remove_host;
+		}
+		if (kona_dev->cfg->wp_gpio >= 0) {
+			ret = devm_gpio_request(dev,
+				kona_dev->cfg->wp_gpio, "sdio wp");
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"Unable to request WP pin %d\n",
+					kona_dev->cfg->wp_gpio);
+				kona_dev->cfg->wp_gpio = -1;
+			} else {
+				gpio_direction_input(kona_dev->cfg->wp_gpio);
+			}
+		}
+
+		/*
+		 * Since the card detection GPIO interrupt is configured to be
+		 * edge sensitive, check the initial GPIO value here, emulate
+		 * only if the card is present
+		 */
+		if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0)
+			sdhci_bcm_kona_sd_card_emulate(host, 1);
+	}
+
+	dev_dbg(dev, "initialized properly\n");
+	return 0;
+
+err_remove_host:
+	sdhci_remove_host(host, 0);
+
+err_reset:
+	sdhci_bcm_kona_sd_reset(host);
+
+err_pltfm_free:
+	sdhci_pltfm_free(pdev);
+
+	dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret);
+	return ret;
+}
+
+static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
+{
+	struct sdhci_host *host = platform_get_drvdata(pdev);
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_bcm_kona_dev *kona_dev = pltfm_host->priv;
+	int dead;
+	u32 scratch;
+
+	dead = 0;
+	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
+	if (scratch == (u32)-1)
+		dead = 1;
+	sdhci_remove_host(host, dead);
+
+	sdhci_free_host(host);
+
+	return 0;
+}
+
+static struct platform_driver sdhci_bcm_kona_driver = {
+	.driver		= {
+		.name	= "sdhci-kona",
+		.owner	= THIS_MODULE,
+		.pm	= SDHCI_PLTFM_PMOPS,
+		.of_match_table = of_match_ptr(sdhci_bcm_kona_of_match),
+	},
+	.probe		= sdhci_bcm_kona_probe,
+	.remove		= __exit_p(sdhci_bcm_kona_remove),
+};
+module_platform_driver(sdhci_bcm_kona_driver);
+
+MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform");
+MODULE_AUTHOR("Broadcom");
+MODULE_LICENSE("GPL v2");
+
-- 
1.7.10.4



^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-09  5:55 [PATCH] ARM: mmc: bcm281xx SDHCI driver Christian Daudt
@ 2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10  7:23   ` Christian Daudt
                     ` (2 more replies)
  2013-05-11  4:28 ` Stephen Warren
  1 sibling, 3 replies; 8+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-09  6:35 UTC (permalink / raw)
  To: Christian Daudt
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

On 22:55 Wed 08 May     , Christian Daudt wrote:
> Add SDHCI driver for the Broadcom 281xx SoCs. Also
> add bindings for it into bcm281xx dts files.
> Still missing:
>  - power managemement

split the dts/dtsi in an other patch
> 
> Signed-off-by: Christian Daudt <csd@broadcom.com>
> 
> diff --git a/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt b/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt
> new file mode 100644
> index 0000000..ad1c4bd
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt
> @@ -0,0 +1,16 @@
> +Broadcom BCM281xx SDHCI driver
> +
> +This file documents differences between the core properties in mmc.txt
> +and the properties in the bcm281xx driver.
> +
> +Required properties:
> +- compatible : Should be "bcm,kona-sdhci"
> +
> +Example:
> +
> +sdio2: sdio@0x3f1a0000 {
> +	compatible = "bcm,kona-sdhci";
> +	reg = <0x3f1a0000 0x10000>;
> +	interrupts = <0x0 74 0x4>;
> +};
> +
> diff --git a/arch/arm/boot/dts/bcm11351-brt.dts b/arch/arm/boot/dts/bcm11351-brt.dts
> index 248067c..9ae3404 100644
> --- a/arch/arm/boot/dts/bcm11351-brt.dts
> +++ b/arch/arm/boot/dts/bcm11351-brt.dts
> @@ -27,4 +27,21 @@
>  		status = "okay";
>  	};
>  
> +	sdio0: sdio@0x3f180000 {
> +		max-frequency = <48000000>;
> +		status = "okay";
> +	};
> +
> +	sdio1: sdio@0x3f190000 {
> +		non-removable;
> +		max-frequency = <48000000>;
> +		status = "okay";
> +	};
> +
> +	sdio3: sdio@0x3f1b0000 {
> +		max-frequency = <48000000>;
> +		status = "okay";
> +	};
> +
> +
>  };
> diff --git a/arch/arm/boot/dts/bcm11351.dtsi b/arch/arm/boot/dts/bcm11351.dtsi
> index ad13588..6606b41 100644
> --- a/arch/arm/boot/dts/bcm11351.dtsi
> +++ b/arch/arm/boot/dts/bcm11351.dtsi
> @@ -47,4 +47,33 @@
>  		    cache-unified;
>  		    cache-level = <2>;
>  	};
> +
> +	sdio0: sdio@0x3f180000 {
> +		compatible = "bcm,kona-sdhci";
> +		reg = <0x3f180000 0x10000>;
> +		interrupts = <0x0 77 0x4>;
> +		status = "disabled";
> +	};
> +
> +	sdio1: sdio@0x3f190000 {
> +		compatible = "bcm,kona-sdhci";
> +		reg = <0x3f190000 0x10000>;
> +		interrupts = <0x0 76 0x4>;
> +		status = "disabled";
> +	};
> +
> +	sdio2: sdio@0x3f1a0000 {
> +		compatible = "bcm,kona-sdhci";
> +		reg = <0x3f1a0000 0x10000>;
> +		interrupts = <0x0 74 0x4>;
> +		status = "disabled";
> +	};
> +
> +	sdio3: sdio@0x3f1b0000 {
> +		compatible = "bcm,kona-sdhci";
> +		reg = <0x3f1b0000 0x10000>;
> +		interrupts = <0x0 73 0x4>;
> +		status = "disabled";
> +	};
> +
>  };
> diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
> index e3bf2d6..65edf6d 100644
> --- a/arch/arm/configs/bcm_defconfig
> +++ b/arch/arm/configs/bcm_defconfig
> @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
>  CONFIG_LCD_CLASS_DEVICE=y
>  CONFIG_BACKLIGHT_CLASS_DEVICE=y
>  # CONFIG_USB_SUPPORT is not set
> +CONFIG_MMC=y
> +CONFIG_MMC_UNSAFE_RESUME=y
> +CONFIG_MMC_BLOCK_MINORS=32
> +CONFIG_MMC_TEST=y
> +CONFIG_MMC_SDHCI=y
> +CONFIG_MMC_SDHCI_PLTFM=y
> +CONFIG_MMC_SDHCI_BCM_KONA=y
>  CONFIG_NEW_LEDS=y
>  CONFIG_LEDS_CLASS=y
>  CONFIG_LEDS_TRIGGERS=y
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index d88219e..e067c5a 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
>  
>  	  YMMV.
>  
> +config MMC_SDHCI_BCM_KONA
> +	tristate "SDHCI support on Broadcom KONA platform"
> +	depends on ARCH_BCM && MMC_SDHCI_PLTFM
select MMC_SDHCI_PLTFM
will be better
> +	help
> +	  This selects the Broadcom Kona Secure Digital Host Controller
> +	  Interface(SDHCI) support.
> +	  This is used in Broadcom mobile SoCs.
> +
> +	  If you have a controller with this interface, say Y or M here.
> +
>  config MMC_SDHCI_BCM2835
>  	tristate "SDHCI platform support for the BCM2835 SD/MMC Controller"
>  	depends on ARCH_BCM2835
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c380e3c..a9f582b 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -59,6 +59,7 @@ obj-$(CONFIG_MMC_SDHCI_DOVE)		+= sdhci-dove.o
>  obj-$(CONFIG_MMC_SDHCI_TEGRA)		+= sdhci-tegra.o
>  obj-$(CONFIG_MMC_SDHCI_OF_ESDHC)	+= sdhci-of-esdhc.o
>  obj-$(CONFIG_MMC_SDHCI_OF_HLWD)		+= sdhci-of-hlwd.o
> +obj-$(CONFIG_MMC_SDHCI_BCM_KONA)	+= sdhci-bcm-kona.o
>  obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= sdhci-bcm2835.o
>  
>  ifeq ($(CONFIG_CB710_DEBUG),y)
> diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c
> new file mode 100644
> index 0000000..27188b9
> --- /dev/null
> +++ b/drivers/mmc/host/sdhci-bcm-kona.c
> @@ -0,0 +1,486 @@
> +/*
> + * Copyright (C) 2013 Broadcom Corporation
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/delay.h>
> +#include <linux/highmem.h>
> +#include <linux/platform_device.h>
> +#include <linux/mmc/host.h>
> +#include <linux/io.h>
> +#include <linux/gpio.h>
> +#include <linux/clk.h>
> +#include <linux/regulator/consumer.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/of_gpio.h>
> +#include <linux/version.h>
> +
> +#include "sdhci-pltfm.h"
> +#include "sdhci.h"
> +
> +#define SDHCI_SOFT_RESET			0x01000000
> +#define KONA_SDHOST_CORECTRL			0x8000
> +#define KONA_SDHOST_CD_PINCTRL			0x00000008
> +#define KONA_SDHOST_STOP_HCLK			0x00000004
> +#define KONA_SDHOST_RESET			0x00000002
> +#define KONA_SDHOST_EN				0x00000001
> +
> +#define KONA_SDHOST_CORESTAT			0x8004
> +#define KONA_SDHOST_WP				0x00000002
> +#define KONA_SDHOST_CD_SW			0x00000001
> +
> +#define KONA_SDHOST_COREIMR			0x8008
> +#define KONA_SDHOST_IP				0x00000001
> +
> +#define KONA_SDHOST_COREISR			0x800C
> +#define KONA_SDHOST_COREIMSR			0x8010
> +#define KONA_SDHOST_COREDBG1			0x8014
> +#define KONA_SDHOST_COREGPO_MASK		0x8018
> +
> +#define SD_DETECT_GPIO_DEBOUNCE_128MS		128
> +
> +#define KONA_MMC_AUTOSUSPEND_DELAY		(50)
> +
> +struct sdhci_bcm_kona_cfg {
> +	unsigned int	max_freq;
> +	int		is_8bit;
> +	int		irq;
> +	int		cd_gpio;
> +	int		wp_gpio;
> +	int		non_removable;
> +};
> +
> +struct sdhci_bcm_kona_dev {
> +	struct sdhci_bcm_kona_cfg *cfg;
> +	struct device *dev;
> +	struct sdhci_host *host;
> +	struct clk *peri_clk;
> +	struct clk *sleep_clk;
> +};
> +
> +
> +static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
> +{
> +	unsigned int val;
> +	unsigned long timeout;
> +
> +	/* This timeout should be sufficent for core to reset */
> +	timeout = jiffies + msecs_to_jiffies(100);
> +
> +	/* reset the host using the top level reset */
> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> +	val |= KONA_SDHOST_RESET;
> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> +
> +	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
> +		if (time_is_before_jiffies(timeout)) {
> +			pr_err("Error: sd host is stuck in reset!!!\n");
> +			return -EFAULT;
> +		}
> +	}
> +
> +	/* bring the host out of reset */
> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> +	val &= ~KONA_SDHOST_RESET;
> +
> +	/*
> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
> +	 * Back-to-Back writes to same register needs delay when SD bus clock
> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> +	 * insert-removal.
> +	 */
> +	udelay(1000);
really a udelay of 1ms
> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> +
> +	return 0;
> +}
> +
> +static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
> +{
> +	unsigned int val;
> +
> +	/* enable the interrupt from the IP core */
> +	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
> +	val |= KONA_SDHOST_IP;
> +	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
> +
> +	/* Enable the AHB clock gating module to the host */
> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> +	val |= KONA_SDHOST_EN;
> +
> +	/*
> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
> +	 * Back-to-Back writes to same register needs delay when SD bus clock
> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> +	 * insert-removal.
> +	 */
> +	udelay(1000);
ditto
> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> +}
> +
> +/*
> + * Software emulation of the SD card insertion/removal. Set insert=1 for insert
> + * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
> + * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
> + * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
> + */
> +static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
> +{
> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
> +	u32 val;
> +	unsigned long flags;
> +
> +	/* this function can be called from various contexts including ISR */
> +	spin_lock_irqsave(&host->lock, flags);
> +	/* Ensure SD bus scanning to detect media change */
> +	host->mmc->rescan_disable = 0;
> +
> +	/*
> +	 * Back-to-Back register write needs a delay of min 10uS.
> +	 * Back-to-Back writes to same register needs delay when SD bus clock
> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> +	 * insert-removal.
> +	 * We keep 20uS
> +	 */
> +	udelay(20);
> +	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
> +
> +	if (insert) {
> +		if (kona_dev->cfg->wp_gpio >= 0) {
gpio_is_valid
> +			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
> +
> +			if (wp_status)
> +				val |= KONA_SDHOST_WP;
> +			else
> +				val &= ~KONA_SDHOST_WP;
> +		}
> +
> +		val |= KONA_SDHOST_CD_SW;
> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
> +	} else {
> +		val &= ~KONA_SDHOST_CD_SW;
> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
> +	}
> +	spin_unlock_irqrestore(&host->lock, flags);
> +
> +	return 0;
> +}
> +
> +/*
> + * SD card detection interrupt handler
> + */
> +static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
> +{
> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
> +
> +	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
> +		pr_debug("card inserted\n");
dev_dbg
> +		sdhci_bcm_kona_sd_card_emulate(host, 1);
> +	} else {
> +		pr_debug("card removed\n");
ditto
> +		sdhci_bcm_kona_sd_card_emulate(host, 0);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * Get the base clock. Use central clock source for now. Not sure if different
> + * clock speed to each dev is allowed
> + */
> +static unsigned int sdhci_bcm_kona_get_max_clk(struct sdhci_host *host)
> +{
> +	struct sdhci_bcm_kona_dev *kona_dev;
> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
> +	kona_dev = pltfm_priv->priv;
> +
> +	return kona_dev->cfg->max_freq;
> +}
> +
> +static unsigned int sdhci_bcm_kona_get_timeout_clock(struct sdhci_host *host)
> +{
> +	return sdhci_bcm_kona_get_max_clk(host);
> +}
> +
> +static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
> +				u8 power_mode)
> +{
> +	if (power_mode == MMC_POWER_OFF)
> +		return;
> +	else
> +		mdelay(10);
> +}
> +
> +static struct sdhci_ops sdhci_bcm_kona_ops = {
> +	.get_max_clock = sdhci_bcm_kona_get_max_clk,
> +	.get_timeout_clock = sdhci_bcm_kona_get_timeout_clock,
> +	.platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
> +};
> +
> +static struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
> +	.ops    = &sdhci_bcm_kona_ops,
> +	.quirks = SDHCI_QUIRK_NO_CARD_NO_RESET |
> +		SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR |
> +		SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE |
> +		SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
> +		SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
> +};
> +
> +static const struct of_device_id sdhci_bcm_kona_of_match[] __initdata = {
> +	{ .compatible = "bcm,kona-sdhci", .data = &sdhci_pltfm_data_kona },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
> +
> +static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
> +			struct platform_device *pdev)
> +{
> +	struct sdhci_bcm_kona_cfg *cfg;
> +	struct device_node *np = pdev->dev.of_node;
> +	u32 temp;
> +
> +	if (!np)
> +		return NULL;
> +
> +	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
> +	if (!cfg) {
> +		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
> +		return NULL;
> +	}
> +
> +	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
> +	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
> +	if (of_get_property(np, "non-removable", NULL))
> +		cfg->non_removable = 1;
use of_property_read_bool
> +
> +	if (of_property_read_u32(np, "bus-width", &temp) == 0 && temp == 8)
> +		cfg->is_8bit = 1;
> +
> +	if (of_property_read_u32(np, "max-frequency", &cfg->max_freq)) {
> +		dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n");
> +		return NULL;
> +	}
> +	return cfg;
> +}
> +
> +static int __init sdhci_bcm_kona_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct sdhci_bcm_kona_cfg *kona_cfg = NULL;
> +	const struct sdhci_pltfm_data *plat_data;
> +	struct sdhci_bcm_kona_dev *kona_dev = NULL;
> +	struct sdhci_pltfm_host *pltfm_priv;
> +	struct device *dev = &pdev->dev;
> +	struct sdhci_host *host;
> +	int ret;
> +	unsigned int irq;
> +	ret = 0;
> +
> +	match = of_match_device(sdhci_bcm_kona_of_match, &pdev->dev);
> +	if (!match)
> +		plat_data = &sdhci_pltfm_data_kona;
> +	else
> +		plat_data = match->data;
> +
> +	host = sdhci_pltfm_init(pdev, (struct sdhci_pltfm_data *)plat_data);
> +	if (IS_ERR(host))
> +		return PTR_ERR(host);
> +
> +	kona_cfg = dev->platform_data;
> +	if (!kona_cfg)
> +		kona_cfg = sdhci_bcm_kona_parse_dt(pdev);
> +
> +	if (!kona_cfg) {
> +		ret = -ENXIO;
> +		goto err_pltfm_free;
> +	}
> +
> +	dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr);
> +
> +	pltfm_priv = sdhci_priv(host);
> +
> +	kona_dev = devm_kzalloc(dev, sizeof(*kona_dev), GFP_KERNEL);
> +	if (!kona_dev) {
> +		dev_err(dev, "Can't allocate kona_dev\n");
> +		ret = -ENOMEM;
> +		goto err_pltfm_free;
> +	}
> +	kona_dev->cfg = kona_cfg;
> +	kona_dev->dev = dev;
> +	pltfm_priv->priv = kona_dev;
> +
> +	dev_dbg(dev, "non-removable=%c\n",
> +		 (kona_cfg->non_removable) ? 'Y' : 'N');
> +	dev_dbg(dev, "cd_gpio %d, wp_gpio %d\n", kona_cfg->cd_gpio,
> +		 kona_cfg->wp_gpio);
> +
> +	if (kona_cfg->non_removable) {
> +		host->mmc->caps |= MMC_CAP_NONREMOVABLE;
> +		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
> +	}
> +
> +	dev_dbg(dev, "is_8bit=%c\n", (kona_cfg->is_8bit) ? 'Y' : 'N');
> +	if (kona_cfg->is_8bit)
> +		host->mmc->caps |= MMC_CAP_8_BIT_DATA;
> +
> +	ret = sdhci_bcm_kona_sd_reset(host);
> +	if (ret)
> +		goto err_pltfm_free;
> +
> +	sdhci_bcm_kona_sd_init(host);
> +
> +	ret = sdhci_add_host(host);
> +	if (ret) {
> +		dev_err(dev, "Failed sdhci_add_host\n");
> +		goto err_reset;
> +	}
> +
> +	/* if device is eMMC, emulate card insert right here */
> +	if (kona_cfg->non_removable) {
> +		ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
> +		if (ret) {
> +			dev_err(dev,
> +				"unable to emulate card insertion\n");
> +			goto err_remove_host;
> +		}
> +	} else if (kona_dev->cfg->cd_gpio >= 0) {
> +		ret = devm_gpio_request(dev, kona_dev->cfg->cd_gpio, "sdio cd");
> +		if (ret < 0) {
> +			dev_err(kona_dev->dev,
> +				"Unable to request GPIO pin %d\n",
> +				kona_dev->cfg->cd_gpio);
> +			goto err_remove_host;
> +		}
> +
> +		gpio_direction_input(kona_dev->cfg->cd_gpio);
> +
> +		/* Set debounce for SD Card detect to maximum value (128ms)
> +		 *
> +		 * NOTE-1: If gpio_set_debounce() returns error we still
> +		 * continue with the default debounce value set. Another reason
> +		 * for doing this is that on rhea-ray boards the SD Detect GPIO
> +		 * is on GPIO Expander and gpio_set_debounce() will return error
> +		 * and if we return error from here, then probe() would fail and
> +		 * SD detection would always fail.
> +		 *
> +		 * NOTE-2: We also give a msleep() of the "debounce" time here
> +		 * so that we give enough time for the debounce to stabilize
> +		 * before we read the gpio value in gpio_get_value_cansleep().
> +		 */
> +		ret = gpio_set_debounce(kona_dev->cfg->cd_gpio,
> +				(SD_DETECT_GPIO_DEBOUNCE_128MS * 1000));
> +		if (ret < 0) {
> +			dev_err(kona_dev->dev,
> +				"%s: gpio set debounce failed."
> +				"default debounce value assumed\n", __func__);
> +		}
> +
> +		/* Sleep for 128ms to allow debounce to stabilize */
> +		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
> +		/* request irq for cd_gpio after the gpio debounce is
> +		 * stabilized, otherwise, some bogus gpio interrupts might be
> +		 * triggered.
> +		 */
> +		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
> +		ret = devm_request_threaded_irq(dev,
> +				irq,
> +				NULL,
> +				sdhci_bcm_kona_pltfm_cd_interrupt,
> +				IRQF_TRIGGER_FALLING|
> +				IRQF_TRIGGER_RISING |
> +				IRQF_ONESHOT |
> +				IRQF_NO_SUSPEND, "sdio cd", host);
> +		if (ret) {
> +			dev_err(kona_dev->dev,
> +				"Unable to request card detection irq=%d"
> +				" for gpio=%d  ret=%d\n",
put the sting of the dev_err on one line so we can grep
> +				gpio_to_irq(kona_dev->cfg->cd_gpio),
> +				kona_dev->cfg->cd_gpio, ret);
> +			goto err_remove_host;
> +		}
> +		if (kona_dev->cfg->wp_gpio >= 0) {
> +			ret = devm_gpio_request(dev,
> +				kona_dev->cfg->wp_gpio, "sdio wp");
> +			if (ret < 0) {
> +				dev_err(&pdev->dev,
> +					"Unable to request WP pin %d\n",
> +					kona_dev->cfg->wp_gpio);
> +				kona_dev->cfg->wp_gpio = -1;
> +			} else {
> +				gpio_direction_input(kona_dev->cfg->wp_gpio);
> +			}
> +		}
> +
> +		/*
> +		 * Since the card detection GPIO interrupt is configured to be
> +		 * edge sensitive, check the initial GPIO value here, emulate
> +		 * only if the card is present
> +		 */
> +		if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0)
> +			sdhci_bcm_kona_sd_card_emulate(host, 1);
> +	}
> +
> +	dev_dbg(dev, "initialized properly\n");
> +	return 0;
> +
> +err_remove_host:
> +	sdhci_remove_host(host, 0);
> +
> +err_reset:
> +	sdhci_bcm_kona_sd_reset(host);
> +
> +err_pltfm_free:
> +	sdhci_pltfm_free(pdev);
> +
> +	dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret);
> +	return ret;
> +}
> +
> +static int __exit sdhci_bcm_kona_remove(struct platform_device *pdev)
> +{
> +	struct sdhci_host *host = platform_get_drvdata(pdev);
> +	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_host->priv;
> +	int dead;
> +	u32 scratch;
> +
> +	dead = 0;
> +	scratch = readl(host->ioaddr + SDHCI_INT_STATUS);
> +	if (scratch == (u32)-1)
> +		dead = 1;
> +	sdhci_remove_host(host, dead);
> +
> +	sdhci_free_host(host);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver sdhci_bcm_kona_driver = {
> +	.driver		= {
> +		.name	= "sdhci-kona",
> +		.owner	= THIS_MODULE,
> +		.pm	= SDHCI_PLTFM_PMOPS,
> +		.of_match_table = of_match_ptr(sdhci_bcm_kona_of_match),
> +	},
> +	.probe		= sdhci_bcm_kona_probe,
> +	.remove		= __exit_p(sdhci_bcm_kona_remove),
> +};
> +module_platform_driver(sdhci_bcm_kona_driver);
> +
> +MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform");
> +MODULE_AUTHOR("Broadcom");
> +MODULE_LICENSE("GPL v2");
> +
> -- 
> 1.7.10.4
> 
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-10  7:23   ` Christian Daudt
  2013-05-10  7:29   ` Christian Daudt
  2013-05-10  7:45   ` Christian Daudt
  2 siblings, 0 replies; 8+ messages in thread
From: Christian Daudt @ 2013-05-10  7:23 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

Thanks for the feedback.

On 13-05-08 11:35 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 22:55 Wed 08 May     , Christian Daudt wrote:
>> Add SDHCI driver for the Broadcom 281xx SoCs. Also
>> add bindings for it into bcm281xx dts files.
>> Still missing:
>>   - power managemement
> split the dts/dtsi in an other patch
ok.
>> Signed-off-by: Christian Daudt <csd@broadcom.com>
>>
>> diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
>> index e3bf2d6..65edf6d 100644
>> --- a/arch/arm/configs/bcm_defconfig
>> +++ b/arch/arm/configs/bcm_defconfig
>> @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
>>   CONFIG_LCD_CLASS_DEVICE=y
>>   CONFIG_BACKLIGHT_CLASS_DEVICE=y
>>   # CONFIG_USB_SUPPORT is not set
>> +CONFIG_MMC=y
>> +CONFIG_MMC_UNSAFE_RESUME=y
>> +CONFIG_MMC_BLOCK_MINORS=32
>> +CONFIG_MMC_TEST=y
>> +CONFIG_MMC_SDHCI=y
>> +CONFIG_MMC_SDHCI_PLTFM=y
>> +CONFIG_MMC_SDHCI_BCM_KONA=y
>>   CONFIG_NEW_LEDS=y
>>   CONFIG_LEDS_CLASS=y
>>   CONFIG_LEDS_TRIGGERS=y
>> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
>> index d88219e..e067c5a 100644
>> --- a/drivers/mmc/host/Kconfig
>> +++ b/drivers/mmc/host/Kconfig
>> @@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
>>   
>>   	  YMMV.
>>   
>> +config MMC_SDHCI_BCM_KONA
>> +	tristate "SDHCI support on Broadcom KONA platform"
>> +	depends on ARCH_BCM && MMC_SDHCI_PLTFM
> select MMC_SDHCI_PLTFM
> will be better
Ok - changed it. Why is the select is better than the depends ?
>> +
>> +static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +	unsigned long timeout;
>> +
>> +	/* This timeout should be sufficent for core to reset */
>> +	timeout = jiffies + msecs_to_jiffies(100);
>> +
>> +	/* reset the host using the top level reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_RESET;
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
>> +		if (time_is_before_jiffies(timeout)) {
>> +			pr_err("Error: sd host is stuck in reset!!!\n");
>> +			return -EFAULT;
>> +		}
>> +	}
>> +
>> +	/* bring the host out of reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val &= ~KONA_SDHOST_RESET;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> really a udelay of 1ms
I'm trying to clarify on whether this is really necessary but it does 
seem that this is the case. I'll send a follow-up patch if I manage to 
get confirmation on a smaller safe number.

>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	return 0;
>> +}
>> +
>> +static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +
>> +	/* enable the interrupt from the IP core */
>> +	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
>> +	val |= KONA_SDHOST_IP;
>> +	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
>> +
>> +	/* Enable the AHB clock gating module to the host */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_EN;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> ditto
see above
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +}
>> +
>> +/*
>> + * Software emulation of the SD card insertion/removal. Set insert=1 for insert
>> + * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
>> + * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
>> + * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
>> + */
>> +static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +	u32 val;
>> +	unsigned long flags;
>> +
>> +	/* this function can be called from various contexts including ISR */
>> +	spin_lock_irqsave(&host->lock, flags);
>> +	/* Ensure SD bus scanning to detect media change */
>> +	host->mmc->rescan_disable = 0;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of min 10uS.
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 * We keep 20uS
>> +	 */
>> +	udelay(20);
>> +	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
>> +
>> +	if (insert) {
>> +		if (kona_dev->cfg->wp_gpio >= 0) {
> gpio_is_valid
done
>> +			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
>> +
>> +			if (wp_status)
>> +				val |= KONA_SDHOST_WP;
>> +			else
>> +				val &= ~KONA_SDHOST_WP;
>> +		}
>> +
>> +		val |= KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	} else {
>> +		val &= ~KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	}
>> +	spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * SD card detection interrupt handler
>> + */
>> +static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +
>> +	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
>> +		pr_debug("card inserted\n");
> dev_dbg
done
>> +		sdhci_bcm_kona_sd_card_emulate(host, 1);
>> +	} else {
>> +		pr_debug("card removed\n");
> ditto
done
>> +static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
>> +			struct platform_device *pdev)
>> +{
>> +	struct sdhci_bcm_kona_cfg *cfg;
>> +	struct device_node *np = pdev->dev.of_node;
>> +	u32 temp;
>> +
>> +	if (!np)
>> +		return NULL;
>> +
>> +	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
>> +	if (!cfg) {
>> +		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
>> +		return NULL;
>> +	}
>> +
>> +	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
>> +	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
>> +	if (of_get_property(np, "non-removable", NULL))
>> +		cfg->non_removable = 1;
> use of_property_read_bool
done
>> +		/* Sleep for 128ms to allow debounce to stabilize */
>> +		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
>> +		/* request irq for cd_gpio after the gpio debounce is
>> +		 * stabilized, otherwise, some bogus gpio interrupts might be
>> +		 * triggered.
>> +		 */
>> +		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
>> +		ret = devm_request_threaded_irq(dev,
>> +				irq,
>> +				NULL,
>> +				sdhci_bcm_kona_pltfm_cd_interrupt,
>> +				IRQF_TRIGGER_FALLING|
>> +				IRQF_TRIGGER_RISING |
>> +				IRQF_ONESHOT |
>> +				IRQF_NO_SUSPEND, "sdio cd", host);
>> +		if (ret) {
>> +			dev_err(kona_dev->dev,
>> +				"Unable to request card detection irq=%d"
>> +				" for gpio=%d  ret=%d\n",
> put the sting of the dev_err on one line so we can grep
merged it into single line


  Thanks,
    csd



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10  7:23   ` Christian Daudt
@ 2013-05-10  7:29   ` Christian Daudt
  2013-05-10 10:26     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10 14:37     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10  7:45   ` Christian Daudt
  2 siblings, 2 replies; 8+ messages in thread
From: Christian Daudt @ 2013-05-10  7:29 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

Thanks for the feedback.

On 13-05-08 11:35 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 22:55 Wed 08 May     , Christian Daudt wrote:
>> Add SDHCI driver for the Broadcom 281xx SoCs. Also
>> add bindings for it into bcm281xx dts files.
>> Still missing:
>>   - power managemement
> split the dts/dtsi in an other patch
ok.
>> Signed-off-by: Christian Daudt <csd@broadcom.com>
>>
>> diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
>> index e3bf2d6..65edf6d 100644
>> --- a/arch/arm/configs/bcm_defconfig
>> +++ b/arch/arm/configs/bcm_defconfig
>> @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
>>   CONFIG_LCD_CLASS_DEVICE=y
>>   CONFIG_BACKLIGHT_CLASS_DEVICE=y
>>   # CONFIG_USB_SUPPORT is not set
>> +CONFIG_MMC=y
>> +CONFIG_MMC_UNSAFE_RESUME=y
>> +CONFIG_MMC_BLOCK_MINORS=32
>> +CONFIG_MMC_TEST=y
>> +CONFIG_MMC_SDHCI=y
>> +CONFIG_MMC_SDHCI_PLTFM=y
>> +CONFIG_MMC_SDHCI_BCM_KONA=y
>>   CONFIG_NEW_LEDS=y
>>   CONFIG_LEDS_CLASS=y
>>   CONFIG_LEDS_TRIGGERS=y
>> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
>> index d88219e..e067c5a 100644
>> --- a/drivers/mmc/host/Kconfig
>> +++ b/drivers/mmc/host/Kconfig
>> @@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
>>   
>>   	  YMMV.
>>   
>> +config MMC_SDHCI_BCM_KONA
>> +	tristate "SDHCI support on Broadcom KONA platform"
>> +	depends on ARCH_BCM && MMC_SDHCI_PLTFM
> select MMC_SDHCI_PLTFM
> will be better
Ok - changed it. Why is the select is better than the depends ?
>> +
>> +static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +	unsigned long timeout;
>> +
>> +	/* This timeout should be sufficent for core to reset */
>> +	timeout = jiffies + msecs_to_jiffies(100);
>> +
>> +	/* reset the host using the top level reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_RESET;
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
>> +		if (time_is_before_jiffies(timeout)) {
>> +			pr_err("Error: sd host is stuck in reset!!!\n");
>> +			return -EFAULT;
>> +		}
>> +	}
>> +
>> +	/* bring the host out of reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val &= ~KONA_SDHOST_RESET;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> really a udelay of 1ms
I'm trying to clarify on whether this is really necessary but it does 
seem that this is the case. I'll send a follow-up patch if I manage to 
get confirmation on a smaller safe number.

>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	return 0;
>> +}
>> +
>> +static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +
>> +	/* enable the interrupt from the IP core */
>> +	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
>> +	val |= KONA_SDHOST_IP;
>> +	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
>> +
>> +	/* Enable the AHB clock gating module to the host */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_EN;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> ditto
see above
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +}
>> +
>> +/*
>> + * Software emulation of the SD card insertion/removal. Set insert=1 for insert
>> + * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
>> + * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
>> + * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
>> + */
>> +static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +	u32 val;
>> +	unsigned long flags;
>> +
>> +	/* this function can be called from various contexts including ISR */
>> +	spin_lock_irqsave(&host->lock, flags);
>> +	/* Ensure SD bus scanning to detect media change */
>> +	host->mmc->rescan_disable = 0;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of min 10uS.
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 * We keep 20uS
>> +	 */
>> +	udelay(20);
>> +	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
>> +
>> +	if (insert) {
>> +		if (kona_dev->cfg->wp_gpio >= 0) {
> gpio_is_valid
done
>> +			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
>> +
>> +			if (wp_status)
>> +				val |= KONA_SDHOST_WP;
>> +			else
>> +				val &= ~KONA_SDHOST_WP;
>> +		}
>> +
>> +		val |= KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	} else {
>> +		val &= ~KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	}
>> +	spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * SD card detection interrupt handler
>> + */
>> +static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +
>> +	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
>> +		pr_debug("card inserted\n");
> dev_dbg
done
>> +		sdhci_bcm_kona_sd_card_emulate(host, 1);
>> +	} else {
>> +		pr_debug("card removed\n");
> ditto
done
>> +static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
>> +			struct platform_device *pdev)
>> +{
>> +	struct sdhci_bcm_kona_cfg *cfg;
>> +	struct device_node *np = pdev->dev.of_node;
>> +	u32 temp;
>> +
>> +	if (!np)
>> +		return NULL;
>> +
>> +	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
>> +	if (!cfg) {
>> +		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
>> +		return NULL;
>> +	}
>> +
>> +	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
>> +	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
>> +	if (of_get_property(np, "non-removable", NULL))
>> +		cfg->non_removable = 1;
> use of_property_read_bool
done
>> +		/* Sleep for 128ms to allow debounce to stabilize */
>> +		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
>> +		/* request irq for cd_gpio after the gpio debounce is
>> +		 * stabilized, otherwise, some bogus gpio interrupts might be
>> +		 * triggered.
>> +		 */
>> +		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
>> +		ret = devm_request_threaded_irq(dev,
>> +				irq,
>> +				NULL,
>> +				sdhci_bcm_kona_pltfm_cd_interrupt,
>> +				IRQF_TRIGGER_FALLING|
>> +				IRQF_TRIGGER_RISING |
>> +				IRQF_ONESHOT |
>> +				IRQF_NO_SUSPEND, "sdio cd", host);
>> +		if (ret) {
>> +			dev_err(kona_dev->dev,
>> +				"Unable to request card detection irq=%d"
>> +				" for gpio=%d  ret=%d\n",
> put the sting of the dev_err on one line so we can grep
merged it into single line


  Thanks,
    csd



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10  7:23   ` Christian Daudt
  2013-05-10  7:29   ` Christian Daudt
@ 2013-05-10  7:45   ` Christian Daudt
  2 siblings, 0 replies; 8+ messages in thread
From: Christian Daudt @ 2013-05-10  7:45 UTC (permalink / raw)
  To: Jean-Christophe PLAGNIOL-VILLARD
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

Thanks for the feedback.

On 13-05-08 11:35 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 22:55 Wed 08 May     , Christian Daudt wrote:
>> Add SDHCI driver for the Broadcom 281xx SoCs. Also
>> add bindings for it into bcm281xx dts files.
>> Still missing:
>>   - power managemement
> split the dts/dtsi in an other patch
ok.
>> Signed-off-by: Christian Daudt <csd@broadcom.com>
>>
>> diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
>> index e3bf2d6..65edf6d 100644
>> --- a/arch/arm/configs/bcm_defconfig
>> +++ b/arch/arm/configs/bcm_defconfig
>> @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
>>   CONFIG_LCD_CLASS_DEVICE=y
>>   CONFIG_BACKLIGHT_CLASS_DEVICE=y
>>   # CONFIG_USB_SUPPORT is not set
>> +CONFIG_MMC=y
>> +CONFIG_MMC_UNSAFE_RESUME=y
>> +CONFIG_MMC_BLOCK_MINORS=32
>> +CONFIG_MMC_TEST=y
>> +CONFIG_MMC_SDHCI=y
>> +CONFIG_MMC_SDHCI_PLTFM=y
>> +CONFIG_MMC_SDHCI_BCM_KONA=y
>>   CONFIG_NEW_LEDS=y
>>   CONFIG_LEDS_CLASS=y
>>   CONFIG_LEDS_TRIGGERS=y
>> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
>> index d88219e..e067c5a 100644
>> --- a/drivers/mmc/host/Kconfig
>> +++ b/drivers/mmc/host/Kconfig
>> @@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
>>
>>   	  YMMV.
>>
>> +config MMC_SDHCI_BCM_KONA
>> +	tristate "SDHCI support on Broadcom KONA platform"
>> +	depends on ARCH_BCM && MMC_SDHCI_PLTFM
> select MMC_SDHCI_PLTFM
> will be better
Ok - changed it. Why is the select is better than the depends ?
>> +
>> +static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +	unsigned long timeout;
>> +
>> +	/* This timeout should be sufficent for core to reset */
>> +	timeout = jiffies + msecs_to_jiffies(100);
>> +
>> +	/* reset the host using the top level reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_RESET;
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
>> +		if (time_is_before_jiffies(timeout)) {
>> +			pr_err("Error: sd host is stuck in reset!!!\n");
>> +			return -EFAULT;
>> +		}
>> +	}
>> +
>> +	/* bring the host out of reset */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val &= ~KONA_SDHOST_RESET;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> really a udelay of 1ms
I'm trying to clarify on whether this is really necessary but it does 
seem that this is the case. I'll send a follow-up patch if I manage to 
get confirmation on a smaller safe number.

>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +
>> +	return 0;
>> +}
>> +
>> +static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
>> +{
>> +	unsigned int val;
>> +
>> +	/* enable the interrupt from the IP core */
>> +	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
>> +	val |= KONA_SDHOST_IP;
>> +	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
>> +
>> +	/* Enable the AHB clock gating module to the host */
>> +	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
>> +	val |= KONA_SDHOST_EN;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 */
>> +	udelay(1000);
> ditto
see above
>> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
>> +}
>> +
>> +/*
>> + * Software emulation of the SD card insertion/removal. Set insert=1 for insert
>> + * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
>> + * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
>> + * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
>> + */
>> +static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +	u32 val;
>> +	unsigned long flags;
>> +
>> +	/* this function can be called from various contexts including ISR */
>> +	spin_lock_irqsave(&host->lock, flags);
>> +	/* Ensure SD bus scanning to detect media change */
>> +	host->mmc->rescan_disable = 0;
>> +
>> +	/*
>> +	 * Back-to-Back register write needs a delay of min 10uS.
>> +	 * Back-to-Back writes to same register needs delay when SD bus clock
>> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
>> +	 * insert-removal.
>> +	 * We keep 20uS
>> +	 */
>> +	udelay(20);
>> +	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
>> +
>> +	if (insert) {
>> +		if (kona_dev->cfg->wp_gpio >= 0) {
> gpio_is_valid
done
>> +			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
>> +
>> +			if (wp_status)
>> +				val |= KONA_SDHOST_WP;
>> +			else
>> +				val &= ~KONA_SDHOST_WP;
>> +		}
>> +
>> +		val |= KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	} else {
>> +		val &= ~KONA_SDHOST_CD_SW;
>> +		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
>> +	}
>> +	spin_unlock_irqrestore(&host->lock, flags);
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>> + * SD card detection interrupt handler
>> + */
>> +static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
>> +{
>> +	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
>> +	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
>> +
>> +	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
>> +		pr_debug("card inserted\n");
> dev_dbg
done
>> +		sdhci_bcm_kona_sd_card_emulate(host, 1);
>> +	} else {
>> +		pr_debug("card removed\n");
> ditto
done
>> +static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
>> +			struct platform_device *pdev)
>> +{
>> +	struct sdhci_bcm_kona_cfg *cfg;
>> +	struct device_node *np = pdev->dev.of_node;
>> +	u32 temp;
>> +
>> +	if (!np)
>> +		return NULL;
>> +
>> +	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
>> +	if (!cfg) {
>> +		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
>> +		return NULL;
>> +	}
>> +
>> +	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
>> +	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
>> +	if (of_get_property(np, "non-removable", NULL))
>> +		cfg->non_removable = 1;
> use of_property_read_bool
done
>> +		/* Sleep for 128ms to allow debounce to stabilize */
>> +		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
>> +		/* request irq for cd_gpio after the gpio debounce is
>> +		 * stabilized, otherwise, some bogus gpio interrupts might be
>> +		 * triggered.
>> +		 */
>> +		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
>> +		ret = devm_request_threaded_irq(dev,
>> +				irq,
>> +				NULL,
>> +				sdhci_bcm_kona_pltfm_cd_interrupt,
>> +				IRQF_TRIGGER_FALLING|
>> +				IRQF_TRIGGER_RISING |
>> +				IRQF_ONESHOT |
>> +				IRQF_NO_SUSPEND, "sdio cd", host);
>> +		if (ret) {
>> +			dev_err(kona_dev->dev,
>> +				"Unable to request card detection irq=%d"
>> +				" for gpio=%d  ret=%d\n",
> put the sting of the dev_err on one line so we can grep
merged it into single line


  Thanks,
    csd



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-10  7:29   ` Christian Daudt
@ 2013-05-10 10:26     ` Jean-Christophe PLAGNIOL-VILLARD
  2013-05-10 14:37     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 8+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-10 10:26 UTC (permalink / raw)
  To: Christian Daudt
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

On 00:29 Fri 10 May     , Christian Daudt wrote:
> Thanks for the feedback.
> 
> On 13-05-08 11:35 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >On 22:55 Wed 08 May     , Christian Daudt wrote:
> >>Add SDHCI driver for the Broadcom 281xx SoCs. Also
> >>add bindings for it into bcm281xx dts files.
> >>Still missing:
> >>  - power managemement
> >split the dts/dtsi in an other patch
> ok.
> >>Signed-off-by: Christian Daudt <csd@broadcom.com>
> >>
> >>diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
> >>index e3bf2d6..65edf6d 100644
> >>--- a/arch/arm/configs/bcm_defconfig
> >>+++ b/arch/arm/configs/bcm_defconfig
> >>@@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
> >>  CONFIG_LCD_CLASS_DEVICE=y
> >>  CONFIG_BACKLIGHT_CLASS_DEVICE=y
> >>  # CONFIG_USB_SUPPORT is not set
> >>+CONFIG_MMC=y
> >>+CONFIG_MMC_UNSAFE_RESUME=y
> >>+CONFIG_MMC_BLOCK_MINORS=32
> >>+CONFIG_MMC_TEST=y
> >>+CONFIG_MMC_SDHCI=y
> >>+CONFIG_MMC_SDHCI_PLTFM=y
> >>+CONFIG_MMC_SDHCI_BCM_KONA=y
> >>  CONFIG_NEW_LEDS=y
> >>  CONFIG_LEDS_CLASS=y
> >>  CONFIG_LEDS_TRIGGERS=y
> >>diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> >>index d88219e..e067c5a 100644
> >>--- a/drivers/mmc/host/Kconfig
> >>+++ b/drivers/mmc/host/Kconfig
> >>@@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
> >>  	  YMMV.
> >>+config MMC_SDHCI_BCM_KONA
> >>+	tristate "SDHCI support on Broadcom KONA platform"
> >>+	depends on ARCH_BCM && MMC_SDHCI_PLTFM
> >select MMC_SDHCI_PLTFM
> >will be better
> Ok - changed it. Why is the select is better than the depends ?
> >>+
> >>+static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
> >>+{
> >>+	unsigned int val;
> >>+	unsigned long timeout;
> >>+
> >>+	/* This timeout should be sufficent for core to reset */
> >>+	timeout = jiffies + msecs_to_jiffies(100);
> >>+
> >>+	/* reset the host using the top level reset */
> >>+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> >>+	val |= KONA_SDHOST_RESET;
> >>+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> >>+
> >>+	while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
> >>+		if (time_is_before_jiffies(timeout)) {
> >>+			pr_err("Error: sd host is stuck in reset!!!\n");
> >>+			return -EFAULT;
> >>+		}
> >>+	}
> >>+
> >>+	/* bring the host out of reset */
> >>+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> >>+	val &= ~KONA_SDHOST_RESET;
> >>+
> >>+	/*
> >>+	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
> >>+	 * Back-to-Back writes to same register needs delay when SD bus clock
> >>+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> >>+	 * insert-removal.
> >>+	 */
> >>+	udelay(1000);
> >really a udelay of 1ms
> I'm trying to clarify on whether this is really necessary but it
> does seem that this is the case. I'll send a follow-up patch if I
> manage to get confirmation on a smaller safe number.

a smaller delay will be better otherwise a msleep(1)

Best Regards,
J.
> 
> >>+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> >>+
> >>+	return 0;
> >>+}
> >>+
> >>+static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
> >>+{
> >>+	unsigned int val;
> >>+
> >>+	/* enable the interrupt from the IP core */
> >>+	val = sdhci_readl(host, KONA_SDHOST_COREIMR);
> >>+	val |= KONA_SDHOST_IP;
> >>+	sdhci_writel(host, val, KONA_SDHOST_COREIMR);
> >>+
> >>+	/* Enable the AHB clock gating module to the host */
> >>+	val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
> >>+	val |= KONA_SDHOST_EN;
> >>+
> >>+	/*
> >>+	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
> >>+	 * Back-to-Back writes to same register needs delay when SD bus clock
> >>+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> >>+	 * insert-removal.
> >>+	 */
> >>+	udelay(1000);
> >ditto
> see above
> >>+	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
> >>+}
> >>+
> >>+/*
> >>+ * Software emulation of the SD card insertion/removal. Set insert=1 for insert
> >>+ * and insert=0 for removal. The card detection is done by GPIO. For Broadcom
> >>+ * IP to function properly the bit 0 of CORESTAT register needs to be set/reset
> >>+ * to generate the CD IRQ handled in sdhci.c which schedules card_tasklet.
> >>+ */
> >>+static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
> >>+{
> >>+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
> >>+	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
> >>+	u32 val;
> >>+	unsigned long flags;
> >>+
> >>+	/* this function can be called from various contexts including ISR */
> >>+	spin_lock_irqsave(&host->lock, flags);
> >>+	/* Ensure SD bus scanning to detect media change */
> >>+	host->mmc->rescan_disable = 0;
> >>+
> >>+	/*
> >>+	 * Back-to-Back register write needs a delay of min 10uS.
> >>+	 * Back-to-Back writes to same register needs delay when SD bus clock
> >>+	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> >>+	 * insert-removal.
> >>+	 * We keep 20uS
> >>+	 */
> >>+	udelay(20);
> >>+	val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
> >>+
> >>+	if (insert) {
> >>+		if (kona_dev->cfg->wp_gpio >= 0) {
> >gpio_is_valid
> done
> >>+			int wp_status = gpio_get_value(kona_dev->cfg->wp_gpio);
> >>+
> >>+			if (wp_status)
> >>+				val |= KONA_SDHOST_WP;
> >>+			else
> >>+				val &= ~KONA_SDHOST_WP;
> >>+		}
> >>+
> >>+		val |= KONA_SDHOST_CD_SW;
> >>+		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
> >>+	} else {
> >>+		val &= ~KONA_SDHOST_CD_SW;
> >>+		sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
> >>+	}
> >>+	spin_unlock_irqrestore(&host->lock, flags);
> >>+
> >>+	return 0;
> >>+}
> >>+
> >>+/*
> >>+ * SD card detection interrupt handler
> >>+ */
> >>+static irqreturn_t sdhci_bcm_kona_pltfm_cd_interrupt(int irq, void *host)
> >>+{
> >>+	struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
> >>+	struct sdhci_bcm_kona_dev *kona_dev = pltfm_priv->priv;
> >>+
> >>+	if (gpio_get_value_cansleep(kona_dev->cfg->cd_gpio) == 0) {
> >>+		pr_debug("card inserted\n");
> >dev_dbg
> done
> >>+		sdhci_bcm_kona_sd_card_emulate(host, 1);
> >>+	} else {
> >>+		pr_debug("card removed\n");
> >ditto
> done
> >>+static struct sdhci_bcm_kona_cfg * __init sdhci_bcm_kona_parse_dt(
> >>+			struct platform_device *pdev)
> >>+{
> >>+	struct sdhci_bcm_kona_cfg *cfg;
> >>+	struct device_node *np = pdev->dev.of_node;
> >>+	u32 temp;
> >>+
> >>+	if (!np)
> >>+		return NULL;
> >>+
> >>+	cfg = devm_kzalloc(&pdev->dev, sizeof(*cfg), GFP_KERNEL);
> >>+	if (!cfg) {
> >>+		dev_err(&pdev->dev, "Can't allocate platform cfg\n");
> >>+		return NULL;
> >>+	}
> >>+
> >>+	cfg->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
> >>+	cfg->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
> >>+	if (of_get_property(np, "non-removable", NULL))
> >>+		cfg->non_removable = 1;
> >use of_property_read_bool
> done
> >>+		/* Sleep for 128ms to allow debounce to stabilize */
> >>+		msleep(SD_DETECT_GPIO_DEBOUNCE_128MS);
> >>+		/* request irq for cd_gpio after the gpio debounce is
> >>+		 * stabilized, otherwise, some bogus gpio interrupts might be
> >>+		 * triggered.
> >>+		 */
> >>+		irq = gpio_to_irq(kona_dev->cfg->cd_gpio);
> >>+		ret = devm_request_threaded_irq(dev,
> >>+				irq,
> >>+				NULL,
> >>+				sdhci_bcm_kona_pltfm_cd_interrupt,
> >>+				IRQF_TRIGGER_FALLING|
> >>+				IRQF_TRIGGER_RISING |
> >>+				IRQF_ONESHOT |
> >>+				IRQF_NO_SUSPEND, "sdio cd", host);
> >>+		if (ret) {
> >>+			dev_err(kona_dev->dev,
> >>+				"Unable to request card detection irq=%d"
> >>+				" for gpio=%d  ret=%d\n",
> >put the sting of the dev_err on one line so we can grep
> merged it into single line
> 
> 
>  Thanks,
>    csd
> 
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-10  7:29   ` Christian Daudt
  2013-05-10 10:26     ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-10 14:37     ` Jean-Christophe PLAGNIOL-VILLARD
  1 sibling, 0 replies; 8+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2013-05-10 14:37 UTC (permalink / raw)
  To: Christian Daudt
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Stephen Warren, Olof Johansson, Greg Kroah-Hartman, Wei WANG,
	Ludovic Desroches, Arnd Bergmann, Mike A. Chan,
	devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
	linux-mmc, csd_b

On 00:29 Fri 10 May     , Christian Daudt wrote:
> Thanks for the feedback.
> 
> On 13-05-08 11:35 PM, Jean-Christophe PLAGNIOL-VILLARD wrote:
> >On 22:55 Wed 08 May     , Christian Daudt wrote:
> >>Add SDHCI driver for the Broadcom 281xx SoCs. Also
> >>add bindings for it into bcm281xx dts files.
> >>Still missing:
> >>  - power managemement
> >split the dts/dtsi in an other patch
> ok.
> >>Signed-off-by: Christian Daudt <csd@broadcom.com>
> >>
> >>diff --git a/arch/arm/configs/bcm_defconfig b/arch/arm/configs/bcm_defconfig
> >>index e3bf2d6..65edf6d 100644
> >>--- a/arch/arm/configs/bcm_defconfig
> >>+++ b/arch/arm/configs/bcm_defconfig
> >>@@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
> >>  CONFIG_LCD_CLASS_DEVICE=y
> >>  CONFIG_BACKLIGHT_CLASS_DEVICE=y
> >>  # CONFIG_USB_SUPPORT is not set
> >>+CONFIG_MMC=y
> >>+CONFIG_MMC_UNSAFE_RESUME=y
> >>+CONFIG_MMC_BLOCK_MINORS=32
> >>+CONFIG_MMC_TEST=y
> >>+CONFIG_MMC_SDHCI=y
> >>+CONFIG_MMC_SDHCI_PLTFM=y
> >>+CONFIG_MMC_SDHCI_BCM_KONA=y
> >>  CONFIG_NEW_LEDS=y
> >>  CONFIG_LEDS_CLASS=y
> >>  CONFIG_LEDS_TRIGGERS=y
> >>diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> >>index d88219e..e067c5a 100644
> >>--- a/drivers/mmc/host/Kconfig
> >>+++ b/drivers/mmc/host/Kconfig
> >>@@ -238,6 +238,16 @@ config MMC_SDHCI_S3C_DMA
> >>  	  YMMV.
> >>+config MMC_SDHCI_BCM_KONA
> >>+	tristate "SDHCI support on Broadcom KONA platform"
> >>+	depends on ARCH_BCM && MMC_SDHCI_PLTFM
> >select MMC_SDHCI_PLTFM
> >will be better
> Ok - changed it. Why is the select is better than the depends ?

so you do not need to enable MMC_SDHCI_PLTFM

and you can drop one line in the savdefconfig

if tomorrow you need regulator select it so a old defconfig will continue to
work

Best Regards,
J.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] ARM: mmc: bcm281xx SDHCI driver
  2013-05-09  5:55 [PATCH] ARM: mmc: bcm281xx SDHCI driver Christian Daudt
  2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
@ 2013-05-11  4:28 ` Stephen Warren
  1 sibling, 0 replies; 8+ messages in thread
From: Stephen Warren @ 2013-05-11  4:28 UTC (permalink / raw)
  To: Christian Daudt
  Cc: Grant Likely, Rob Herring, Rob Landley, Russell King, Chris Ball,
	Olof Johansson, Greg Kroah-Hartman, Wei WANG, Ludovic Desroches,
	Arnd Bergmann, Mike A. Chan, devicetree-discuss, linux-doc,
	linux-kernel, linux-arm-kernel, linux-mmc, csd_b

On 05/08/2013 11:55 PM, Christian Daudt wrote:
> Add SDHCI driver for the Broadcom 281xx SoCs. Also
> add bindings for it into bcm281xx dts files.
> Still missing:
>  - power managemement

> diff --git a/drivers/mmc/host/sdhci-bcm-kona.c b/drivers/mmc/host/sdhci-bcm-kona.c

> +	/*
> +	 * Back-to-Back register write needs a delay of 1ms at bootup (min 10uS)
> +	 * Back-to-Back writes to same register needs delay when SD bus clock
> +	 * is very low w.r.t AHB clock, mainly during boot-time and during card
> +	 * insert-removal.
> +	 */
> +	udelay(1000);
> +	sdhci_writel(host, val, KONA_SDHOST_CORECTRL);

This sounds very similar to the workaround in
drivers/mmc/host/sdhci-bcm2835.c. Is this the same IP block supported by
that driver? Perhaps not, since bcm2835 apparently needs other WARs such
as always using 32-bit IO and hence needing custom read/write w/b
functions to do read-modify-write which isn't here?

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-05-11  4:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-09  5:55 [PATCH] ARM: mmc: bcm281xx SDHCI driver Christian Daudt
2013-05-09  6:35 ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-10  7:23   ` Christian Daudt
2013-05-10  7:29   ` Christian Daudt
2013-05-10 10:26     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-10 14:37     ` Jean-Christophe PLAGNIOL-VILLARD
2013-05-10  7:45   ` Christian Daudt
2013-05-11  4:28 ` Stephen Warren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).