Skip to contentSkip to conversation

mmc: sdhci: Add size for caller in init+register

PATCH New Christian Daudt 3 participants 8 messages May 29, 2013 – Jun 4, 2013

Subsystems (10)
lore
Share & tools
lore
#0 lore raw

PATCH v4 1/3 mmc: sdhci: Add size for caller in init+register

Add a param to allow users of sdhci_pltfm to allocate private space in calls to sdhci_pltfm_init+sdhci_pltfm_register. This is implemented in the same way as sdhci does for its users.
None of the users have been migrated yet and are passing in zero to
retain their private allocation.

- todo: migrate clients to using allocation this way
- todo: remove priv variable once migration is complete

Also removed unused variable in sdhci_pltfm_init fn

drivers/mmc/host/sdhci-bcm2835.c +1 -1
index d49bc95..0584a1c 100644
@@ -148,7 +148,7 @@ static int bcm2835_sdhci_probe(struct platform_device *pdev)
 	struct sdhci_pltfm_host *pltfm_host;
 	int ret;
 
-	host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata);
+	host = sdhci_pltfm_init(pdev, &bcm2835_sdhci_pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
drivers/mmc/host/sdhci-cns3xxx.c +1 -1
index 8ebb6b6..f2cc266 100644
@@ -96,7 +96,7 @@ static const struct sdhci_pltfm_data sdhci_cns3xxx_pdata = {
 
 static int sdhci_cns3xxx_probe(struct platform_device *pdev)
 {
-	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata);
+	return sdhci_pltfm_register(pdev, &sdhci_cns3xxx_pdata, 0);
 }
 
 static int sdhci_cns3xxx_remove(struct platform_device *pdev)
drivers/mmc/host/sdhci-dove.c +1 -1
index 15e7803..8424839 100644
@@ -130,7 +130,7 @@ static int sdhci_dove_probe(struct platform_device *pdev)
 		gpio_direction_input(priv->gpio_cd);
 	}
 
-	host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata);
+	host = sdhci_pltfm_init(pdev, &sdhci_dove_pdata, 0);
 	if (IS_ERR(host)) {
 		ret = PTR_ERR(host);
 		goto err_sdhci_pltfm_init;
drivers/mmc/host/sdhci-esdhc-imx.c +1 -1
index 67d6dde..9a1e6fa 100644
@@ -470,7 +470,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
 	int err;
 	struct pltfm_imx_data *imx_data;
 
-	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata);
+	host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
drivers/mmc/host/sdhci-of-esdhc.c +1 -1
index 5e68adc..37e668f 100644
@@ -262,7 +262,7 @@ static const struct sdhci_pltfm_data sdhci_esdhc_pdata = {
 
 static int sdhci_esdhc_probe(struct platform_device *pdev)
 {
-	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata);
+	return sdhci_pltfm_register(pdev, &sdhci_esdhc_pdata, 0);
 }
 
 static int sdhci_esdhc_remove(struct platform_device *pdev)
drivers/mmc/host/sdhci-of-hlwd.c +1 -1
index 200a6a9..57c514a 100644
@@ -68,7 +68,7 @@ static const struct sdhci_pltfm_data sdhci_hlwd_pdata = {
 
 static int sdhci_hlwd_probe(struct platform_device *pdev)
 {
-	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata);
+	return sdhci_pltfm_register(pdev, &sdhci_hlwd_pdata, 0);
 }
 
 static int sdhci_hlwd_remove(struct platform_device *pdev)
drivers/mmc/host/sdhci-pltfm.c +9 -8
index cd0f1f6..38e38a5 100644
@@ -115,10 +115,10 @@ void sdhci_get_of_property(struct platform_device *pdev) {}
 EXPORT_SYMBOL_GPL(sdhci_get_of_property);
 
 struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
-				    const struct sdhci_pltfm_data *pdata)
+				    const struct sdhci_pltfm_data *pdata,
+				    size_t priv_size)
 {
 	struct sdhci_host *host;
-	struct sdhci_pltfm_host *pltfm_host;
 	struct device_node *np = pdev->dev.of_node;
 	struct resource *iomem;
 	int ret;
@@ -134,17 +134,17 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
 
 	/* Some PCI-based MFD need the parent here */
 	if (pdev->dev.parent != &platform_bus && !np)
-		host = sdhci_alloc_host(pdev->dev.parent, sizeof(*pltfm_host));
+		host = sdhci_alloc_host(pdev->dev.parent,
+			sizeof(struct sdhci_pltfm_host) + priv_size);
 	else
-		host = sdhci_alloc_host(&pdev->dev, sizeof(*pltfm_host));
+		host = sdhci_alloc_host(&pdev->dev,
+			sizeof(struct sdhci_pltfm_host) + priv_size);
 
 	if (IS_ERR(host)) {
 		ret = PTR_ERR(host);
 		goto err;
 	}
 
-	pltfm_host = sdhci_priv(host);
-
 	host->hw_name = dev_name(&pdev->dev);
 	if (pdata && pdata->ops)
 		host->ops = pdata->ops;
@@ -202,12 +202,13 @@ void sdhci_pltfm_free(struct platform_device *pdev)
 EXPORT_SYMBOL_GPL(sdhci_pltfm_free);
 
 int sdhci_pltfm_register(struct platform_device *pdev,
-			 const struct sdhci_pltfm_data *pdata)
+			const struct sdhci_pltfm_data *pdata,
+			size_t priv_size)
 {
 	struct sdhci_host *host;
 	int ret = 0;
 
-	host = sdhci_pltfm_init(pdev, pdata);
+	host = sdhci_pltfm_init(pdev, pdata, priv_size);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 
drivers/mmc/host/sdhci-pltfm.h +11 -2
index 1210ed1..ed4a85d 100644
@@ -27,6 +27,8 @@ struct sdhci_pltfm_host {
 	/* migrate from sdhci_of_host */
 	unsigned int clock;
 	u16 xfer_mode_shadow;
+
+	unsigned long private[0] ____cacheline_aligned;
 };
 
 #ifdef CONFIG_MMC_SDHCI_BIG_ENDIAN_32BIT_BYTE_SWAPPER
@@ -91,15 +93,22 @@ static inline void sdhci_be32bs_writeb(struct sdhci_host *host, u8 val, int reg)
 extern void sdhci_get_of_property(struct platform_device *pdev);
 
 extern struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
-					  const struct sdhci_pltfm_data *pdata);
+					  const struct sdhci_pltfm_data *pdata,
+					  size_t priv_size);
 extern void sdhci_pltfm_free(struct platform_device *pdev);
 
 extern int sdhci_pltfm_register(struct platform_device *pdev,
-				const struct sdhci_pltfm_data *pdata);
+				const struct sdhci_pltfm_data *pdata,
+				size_t priv_size);
 extern int sdhci_pltfm_unregister(struct platform_device *pdev);
 
 extern unsigned int sdhci_pltfm_clk_get_max_clock(struct sdhci_host *host);
 
+static inline void *sdhci_pltfm_priv(struct sdhci_pltfm_host *host)
+{
+	return (void *)host->private;
+}
+
 #ifdef CONFIG_PM
 extern const struct dev_pm_ops sdhci_pltfm_pmops;
 #define SDHCI_PLTFM_PMOPS (&sdhci_pltfm_pmops)
drivers/mmc/host/sdhci-pxav2.c +1 -1
index 6a3f702..1cf093f 100644
@@ -175,7 +175,7 @@ static int sdhci_pxav2_probe(struct platform_device *pdev)
 	if (!pxa)
 		return -ENOMEM;
 
-	host = sdhci_pltfm_init(pdev, NULL);
+	host = sdhci_pltfm_init(pdev, NULL, 0);
 	if (IS_ERR(host)) {
 		kfree(pxa);
 		return PTR_ERR(host);
drivers/mmc/host/sdhci-pxav3.c +1 -1
index 1ae358e..9124104 100644
@@ -230,7 +230,7 @@ static int sdhci_pxav3_probe(struct platform_device *pdev)
 	if (!pxa)
 		return -ENOMEM;
 
-	host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata);
+	host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0);
 	if (IS_ERR(host)) {
 		kfree(pxa);
 		return PTR_ERR(host);
drivers/mmc/host/sdhci-tegra.c +1 -1
index e0dba74..c8b0582 100644
@@ -231,7 +231,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
 		return -EINVAL;
 	soc_data = match->data;
 
-	host = sdhci_pltfm_init(pdev, soc_data->pdata);
+	host = sdhci_pltfm_init(pdev, soc_data->pdata, 0);
 	if (IS_ERR(host))
 		return PTR_ERR(host);
 	pltfm_host = sdhci_priv(host);
Signature · 1 line
1.7.10.4
#1 lore raw

PATCH v4 1/3 mmc: sdhci: Add size for caller in init+register

Hi Chris,
Can you pls take this patch and the one named "[PATCH V4 2/3] ARM:
mmc: bcm281xx SDHCI driver" into your tree ?

Thanks,
csd.

Quoted 14 lines · Christian Daudt

Add a param to allow users of sdhci_pltfm to allocate private space in calls to sdhci_pltfm_init+sdhci_pltfm_register. This is implemented in the same way as sdhci does for its users.
None of the users have been migrated yet and are passing in zero to
retain their private allocation.

- todo: migrate clients to using allocation this way
- todo: remove priv variable once migration is complete

Also removed unused variable in sdhci_pltfm_init fn

#2 lore raw

PATCH v4 2/3 ARM: mmc: bcm281xx SDHCI driver

In reply to Christian Daudt

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

Changes from V3:
- switch mdelay to usleep_range

Changes from V2:
- Structure cleanups
- init space from sdhci_pltfm_init
- replace spinlock_irqsave with mutex on sd_card_emulate
- Reduce init_74_clocks delay and document it

Changes from V1:
- split DT into separate patch
- use gpio_is_valid instead of direct test
- switch pr_debug calls to dev_dbg
- use of_property_read_bool

arch/arm/configs/bcm_defconfig +7 -0
index e3bf2d6..65edf6d 100644
@@ -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
drivers/mmc/host/Kconfig +11 -0
index 9ab8f8d..2455a35 100644
@@ -249,6 +249,17 @@ config MMC_SDHCI_S3C_DMA
 
 	  YMMV.
 
+config MMC_SDHCI_BCM_KONA
+	tristate "SDHCI support on Broadcom KONA platform"
+	depends on ARCH_BCM
+	select 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
drivers/mmc/host/Makefile +1 -0
index cd32280..cd4c845 100644
@@ -60,6 +60,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)
drivers/mmc/host/sdhci-bcm-kona.c new file +443 -0

443 lines not on this page · raw message

Signature · 1 line
1.7.10.4
#3 lore raw

PATCH v4 2/3 ARM: mmc: bcm281xx SDHCI driver

Hi Christian,

Quoted 64 lines · Christian Daudt
drivers/mmc/host/sdhci-bcm-kona.c new file +64 -0
+	/* if device is eMMC, emulate card insert right here */
+	if (kona_dev->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 (gpio_is_valid(kona_dev->cd_gpio)) {
+		ret = devm_gpio_request(dev, kona_dev->cd_gpio, "sdio cd");
+		if (ret < 0) {
+			dev_err(mmc_dev(host->mmc),
+				"Unable to request GPIO pin %d\n",
+				kona_dev->cd_gpio);
+			goto err_remove_host;
+		}
+
+		gpio_direction_input(kona_dev->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->cd_gpio,
+				(SD_DETECT_GPIO_DEBOUNCE_128MS * 1000));
+		if (ret < 0) {
+			dev_err(mmc_dev(host->mmc),
+				"%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->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(mmc_dev(host->mmc),
+				"Failed irq %d request for gpio=%d ret=%d\n",
+				gpio_to_irq(kona_dev->cd_gpio),
+				kona_dev->cd_gpio, ret);
+			goto err_remove_host;
+		}
+		if (gpio_is_valid(kona_dev->wp_gpio)) {
+			ret = devm_gpio_request(dev,

drivers/mmc/host/sdhci-bcm-kona.c line 384

Quoted 10 lines
drivers/mmc/host/sdhci-bcm-kona.c new file +10 -0
+				kona_dev->wp_gpio, "sdio wp");
+			if (ret < 0) {
+				dev_err(&pdev->dev,
+					"Unable to request WP pin %d\n",
+					kona_dev->wp_gpio);
+				kona_dev->wp_gpio = -1;
+			} else {
+				gpio_direction_input(kona_dev->wp_gpio);
+			}
+		}

Could you investigate replacing this section of code with a call to mmc_of_parse(), please? It should be able to replace your parsing and handling of bus-width, cd-gpios, wp-gpios, and non-removable (other than the initialization quirks specific to your hardware).

I'd like to avoid every driver having its own DT parsing. Thanks,

- Chris.

Signature · 2 lines
Chris Ball   <[email protected]>   <http://printf.net/>
One Laptop Per Child
#4 lore raw

PATCH v4 2/3 ARM: mmc: bcm281xx SDHCI driver

Hi Chris,

Quoted 10 lines · Chris Ball

Could you investigate replacing this section of code with a call to mmc_of_parse(), please? It should be able to replace your parsing and handling of bus-width, cd-gpios, wp-gpios, and non-removable (other than the initialization quirks specific to your hardware).

I'd like to avoid every driver having its own DT parsing. Thanks,

- Chris.

I looked into it and it can replace just about everything that our own dt parsing code is doing. The only problem is with cd_gpio. If I call mmc_of_parse, then it will install its own irq handler for cd gpio, and our driver needs a different handler. the mmc irq handler can call a card_event callback, but that is already pointing to sdhci_card_event. So the only way I can use mmc_of_parse that I can see is by adding a flag to it to skip cd_gpio parsing which only this driver will then set to true. Any other ideas ?

Thanks,
csd

#5 lore raw

PATCH v4 2/3 ARM: mmc: bcm281xx SDHCI driver

Quoted 8 lines · Christian Daudt

I looked into it and it can replace just about everything that our own dt parsing code is doing. The only problem is with cd_gpio. If I call mmc_of_parse, then it will install its own irq handler for cd gpio, and our driver needs a different handler. the mmc irq handler can call a card_event callback, but that is already pointing to sdhci_card_event. So the only way I can use mmc_of_parse that I can see is by adding a flag to it to skip cd_gpio parsing which only this driver will then set to true. Any other ideas ?

Can't you add a callback handler into sdhci_card_event that can call a platform specific function?

Arnd

#6 lore raw

PATCH v4 2/3 ARM: mmc: bcm281xx SDHCI driver

Quoted 9 lines · Arnd Bergmann
Quoted 8 lines · Christian Daudt

I looked into it and it can replace just about everything that our own dt parsing code is doing. The only problem is with cd_gpio. If I call mmc_of_parse, then it will install its own irq handler for cd gpio, and our driver needs a different handler. the mmc irq handler can call a card_event callback, but that is already pointing to sdhci_card_event. So the only way I can use mmc_of_parse that I can see is by adding a flag to it to skip cd_gpio parsing which only this driver will then set to true. Any other ideas ?

Quoted 4 lines

Can't you add a callback handler into sdhci_card_event that can call a platform specific function?

I can add another layer of callbacks. I have to first check if I can rework our driver to fit into this callback model. I'll update this when I've tried it.

thanks,
csd

#7 lore raw

PATCH v4 3/3 ARM: mmc: bcm281xx SDHCI driver (dt mods)

In reply to Christian Daudt

Add SDHCI bindings for the Broadcom 281xx SoCs.

Changes from V2:
- Documentation cleanups

Changes from V1:
- split original patch into 2, one for driver and this one for dt

Documentation/devicetree/bindings/mmc/bcm,kona-sdhci.txt new file +16 -0
new file mode 100644
index 0000000..094ae01
@@ -0,0 +1,16 @@
+Broadcom BCM281xx SDHCI
+
+This file documents differences between the core properties in mmc.txt
+and the properties present in the bcm281xx SDHCI
+
+Required properties:
+- compatible : Should be "bcm,kona-sdhci"
+
+Example:
+
+sdio2: sdio at 0x3f1a0000 {
+	compatible = "bcm,kona-sdhci";
+	reg = <0x3f1a0000 0x10000>;
+	interrupts = <0x0 74 0x4>;
+};
+
arch/arm/boot/dts/bcm11351-brt.dts +17 -0
index 248067c..9ae3404 100644
@@ -27,4 +27,21 @@
 		status = "okay";
 	};
 
+	sdio0: sdio at 0x3f180000 {
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+	sdio1: sdio at 0x3f190000 {
+		non-removable;
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+	sdio3: sdio at 0x3f1b0000 {
+		max-frequency = <48000000>;
+		status = "okay";
+	};
+
+
 };
arch/arm/boot/dts/bcm11351.dtsi +28 -0
index 41b2c6c..39de6e2 100644
@@ -60,4 +60,32 @@
 		clock-frequency = <32768>;
 	};
 
+	sdio0: sdio at 0x3f180000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f180000 0x10000>;
+		interrupts = <0x0 77 0x4>;
+		status = "disabled";
+	};
+
+	sdio1: sdio at 0x3f190000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f190000 0x10000>;
+		interrupts = <0x0 76 0x4>;
+		status = "disabled";
+	};
+
+	sdio2: sdio at 0x3f1a0000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f1a0000 0x10000>;
+		interrupts = <0x0 74 0x4>;
+		status = "disabled";
+	};
+
+	sdio3: sdio at 0x3f1b0000 {
+		compatible = "bcm,kona-sdhci";
+		reg = <0x3f1b0000 0x10000>;
+		interrupts = <0x0 73 0x4>;
+		status = "disabled";
+	};
+
 };
Signature · 1 line
1.7.10.4