Skip to contentSkip to conversation

mmc: support sdhci-mmp2

PATCH New Zhangfei Gao 4 participants 10 messages May 25, 2011 – Jun 8, 2011

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

PATCH v2 1/3 mmc: support sdhci-mmp2

Instead of sharing sdhci-pxa.c, use sdhci-mmp2.c specificlly for mmp2. sdhci-pxa.c is used to share among pxa serious, like pxa910, mmp2, etc. The platfrom difference are put under arch/arm, while is not easy to track.

---
 arch/arm/plat-pxa/include/plat/sdhci.h |   43 ++++-
 drivers/mmc/host/Kconfig               |   11 +-
 drivers/mmc/host/Makefile              |    2 +-
 drivers/mmc/host/sdhci-mmp2.c          |  303 ++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci-pxa.c           |  303 --------------------------------
 5 files changed, 349 insertions(+), 313 deletions(-)
 create mode 100644 drivers/mmc/host/sdhci-mmp2.c
 delete mode 100644 drivers/mmc/host/sdhci-pxa.c
arch/arm/plat-pxa/include/plat/sdhci.h +39 -4
index 1ab332e..c23b6b5 100644
@@ -13,23 +13,58 @@
 #ifndef __PLAT_PXA_SDHCI_H
 #define __PLAT_PXA_SDHCI_H
 
+#include <linux/mmc/sdhci.h>
+#include <linux/platform_device.h>
+
 /* pxa specific flag */
 /* Require clock free running */
 #define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
-
+/* card alwayes wired to host, like on-chip emmc */
+#define PXA_FLAG_CARD_PERMANENT	(1<<1)
 /* Board design supports 8-bit data on SD/SDIO BUS */
 #define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
+/* card not use wp, such as micro sd card */
+#define PXA_FLAG_CARD_NO_WP	(1<<3)
 
+struct sdhci_pxa;
 /*
  * struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
- * @max_speed: the maximum speed supported
- * @quirks: quirks of specific device
  * @flags: flags for platform requirement
+ * @clk_delay_cycles:
+ *	mmp2: each step is roughly 100ps, 5bits width
+ *	pxa910: each step is 1ns, 4bits width
+ * @clk_delay_sel: select clk_delay, used on pxa910
+ *	0: choose feedback clk
+ *	1: choose feedback clk + delay value
+ *	2: choose internal clk
+ * @ext_cd_gpio: gpio pin used for external CD line
+ * @ext_cd_gpio_invert: invert values for external CD gpio line
+ * @clk_delay_enable: enable clk_delay or not, used on pxa910
+ * @max_speed: the maximum speed supported
+ * @host_caps: Standard MMC host capabilities bit field.
+ * @quirks: quirks of platfrom
+ * @pm_caps: pm_caps of platfrom
  */
 struct sdhci_pxa_platdata {
+	unsigned int	flags;
+	unsigned int	clk_delay_cycles;
+	unsigned int	clk_delay_sel;
+	unsigned int	ext_cd_gpio;
+	bool		ext_cd_gpio_invert;
+	bool		clk_delay_enable;
 	unsigned int	max_speed;
+	unsigned int	host_caps;
 	unsigned int	quirks;
-	unsigned int	flags;
+	unsigned int	pm_caps;
+};
+
+struct sdhci_pxa {
+	struct sdhci_pxa_platdata	*pdata;
+	struct clk			*clk;
+	struct sdhci_ops		*ops;
+
+	u8	clk_enable;
+	u8	power_mode;
 };
 
 #endif /* __PLAT_PXA_SDHCI_H */
drivers/mmc/host/Kconfig +6 -5
index 862235e..513df18 100644
@@ -181,14 +181,15 @@ config MMC_SDHCI_S3C
 
 	  If unsure, say N.
 
-config MMC_SDHCI_PXA
-	tristate "Marvell PXA168/PXA910/MMP2 SD Host Controller support"
-	depends on ARCH_PXA || ARCH_MMP
+config MMC_SDHCI_MMP2
+	tristate "Marvell MMP2 SD Host Controller support"
+	depends on ARCH_MMP
 	select MMC_SDHCI
+	select MMC_SDHCI_PLTFM
 	select MMC_SDHCI_IO_ACCESSORS
 	help
-	  This selects the Marvell(R) PXA168/PXA910/MMP2 SD Host Controller.
-	  If you have a PXA168/PXA910/MMP2 platform with SD Host Controller
+	  This selects the Marvell(R) MMP2 SD Host Controller.
+	  If you have a MMP2 platform with SD Host Controller
 	  and a card slot, say Y or M here.
 
 	  If unsure, say N.
drivers/mmc/host/Makefile +1 -1
index 4933004..f8650e0 100644
@@ -9,7 +9,7 @@ obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
 obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
-obj-$(CONFIG_MMC_SDHCI_PXA)	+= sdhci-pxa.o
+obj-$(CONFIG_MMC_SDHCI_MMP2)	+= sdhci-mmp2.o
 obj-$(CONFIG_MMC_SDHCI_S3C)	+= sdhci-s3c.o
 obj-$(CONFIG_MMC_SDHCI_SPEAR)	+= sdhci-spear.o
 obj-$(CONFIG_MMC_WBSD)		+= wbsd.o
drivers/mmc/host/sdhci-mmp2.c new file +303 -0

303 lines not on this page · raw message

drivers/mmc/host/sdhci-pxa.c deleted +0 -303

303 lines not on this page · raw message

Signature · 1 line
1.7.0.4
#1 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 5 lines · Zhangfei Gao

Instead of sharing sdhci-pxa.c, use sdhci-mmp2.c specificlly for mmp2. sdhci-pxa.c is used to share among pxa serious, like pxa910, mmp2, etc. The platfrom difference are put under arch/arm, while is not easy to track.

Quoted 9 lines
---
 arch/arm/plat-pxa/include/plat/sdhci.h |   43 ++++-
 drivers/mmc/host/Kconfig               |   11 +-
 drivers/mmc/host/Makefile              |    2 +-
 drivers/mmc/host/sdhci-mmp2.c          |  303 ++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci-pxa.c           |  303 --------------------------------
 5 files changed, 349 insertions(+), 313 deletions(-)
 create mode 100644 drivers/mmc/host/sdhci-mmp2.c
 delete mode 100644 drivers/mmc/host/sdhci-pxa.c

Yes, looks good for the most part. I was rather confused by the fact that the old and new file are both 303 lines, so I assumed they would be identical, when they are really completely different.

There is a little room for simplification, I think:

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+	/* Micro SD does not support write-protect feature */
+	return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

drivers/mmc/host/sdhci-mmp2.c line 91

Quoted 8 lines
drivers/mmc/host/sdhci-mmp2.c new file +8 -0
+static void mmp2_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_pxa *pxa = pltfm_host->priv;
+
+	if (clock)
+		mmp2_soc_set_timing(host, pxa->pdata);
+}

The mmp2_soc_set_timing() function is only called here, so you can easily merge the two into one, starting with

	if (!clock)
		return;

drivers/mmc/host/sdhci-mmp2.c line 139

Quoted 9 lines
drivers/mmc/host/sdhci-mmp2.c new file +9 -0
+static int __devinit sdhci_mmp2_probe(struct platform_device *pdev)
+{
+	struct sdhci_pltfm_host *pltfm_host;
+	struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct sdhci_host *host = NULL;
+	struct sdhci_pxa *pxa = NULL;
+	int ret;
+	struct clk *clk;

The probe and release functions for mmp2 and pxa910 are almost identical. I'd suggest you leave them in sdhci-pxa.c as a library, and export them using EXPORT_SYMBOL_GPL. Then you can call them from the respective probe functions, e.g.

static struct sdhci_mmp2_ops = {
.set_clock = mmp2_set_clock,
.set_uhs_signaling = mmp2_set_uhs_signaling, .get_ro = mmp2_get_ro,
};
static int __devinit sdhci_mmp2_probe(struct platform_device *pdev)

{
	 unsigned int quirks = SDHCI_QUIRK_BROKEN_ADMA
		| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
		| SDHCI_QUIRK_32BIT_DMA_ADDR
		| SDHCI_QUIRK_32BIT_DMA_SIZE
		| SDHCI_QUIRK_32BIT_ADMA_SIZE
		| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;

	return sdhci_pxa_probe(pdev, quirks, sdhci_mmp2_ops);
}

drivers/mmc/host/sdhci-mmp2.c line 150

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +10 -0
+	pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+	if (!pxa) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL);
+	if (!pxa->ops) {
+		ret = -ENOMEM;
+		goto out;
+	}

I think you really shouldn't allocate the sdhci_ops dynamically. In fact, it would be much better if we were able to mark them as const in all drivers.

Quoted 9 lines
drivers/mmc/host/sdhci-mmp2.c new file +9 -0
+
+#ifdef CONFIG_PM
+static int sdhci_mmp2_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct sdhci_host *host = platform_get_drvdata(dev);
+
+	return sdhci_suspend_host(host, state);
+}
+

drivers/mmc/host/sdhci-mmp2.c line 272

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +10 -0
+static int sdhci_mmp2_resume(struct platform_device *dev)
+{
+	struct sdhci_host *host = platform_get_drvdata(dev);
+
+	return sdhci_resume_host(host);
+}
+#else
+#define sdhci_mmp2_suspend	NULL
+#define sdhci_mmp2_resume	NULL
+#endif

Similarly, I think it would be good if sdhci-pltfm.c would simply export these functions so you could refer to them in your driver. There is no need to have identical copies in each variant.

Arnd

#2 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 22 lines · Arnd Bergmann
Quoted 6 lines · Zhangfei Gao

? ? ? Instead of sharing sdhci-pxa.c, use sdhci-mmp2.c specificlly for mmp2. ? ? ? sdhci-pxa.c is used to share among pxa serious, like pxa910, mmp2, etc. ? ? ? The platfrom difference are put under arch/arm, while is not easy to track.

---

Quoted 8 lines
?arch/arm/plat-pxa/include/plat/sdhci.h | ? 43 ++++-
?drivers/mmc/host/Kconfig ? ? ? ? ? ? ? | ? 11 +-
?drivers/mmc/host/Makefile ? ? ? ? ? ? ?| ? ?2 +-
?drivers/mmc/host/sdhci-mmp2.c ? ? ? ? ?| ?303 ++++++++++++++++++++++++++++++++
?drivers/mmc/host/sdhci-pxa.c ? ? ? ? ? | ?303 --------------------------------

?5 files changed, 349 insertions(+), 313 deletions(-) ?create mode 100644 drivers/mmc/host/sdhci-mmp2.c ?delete mode 100644 drivers/mmc/host/sdhci-pxa.c

Yes, looks good for the most part. I was rather confused by the fact that the old and new file are both 303 lines, so I assumed they would be identical, when they are really completely different.

There is a little room for simplification, I think:

Quoted 8 lines

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+ ? ? /* Micro SD does not support write-protect feature */
+ ? ? return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

Quoted 13 lines

drivers/mmc/host/sdhci-mmp2.c line 91

Quoted 9 lines
drivers/mmc/host/sdhci-mmp2.c new file +8 -0
+static void mmp2_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ ? ? struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ ? ? struct sdhci_pxa *pxa = pltfm_host->priv;
+
+ ? ? if (clock)
+ ? ? ? ? ? ? mmp2_soc_set_timing(host, pxa->pdata);
+}

The mmp2_soc_set_timing() function is only called here, so you can easily merge the two into one, starting with

Quoted 2 lines

? ? ? ?if (!clock)
? ? ? ? ? ? ? ?return;

OK, thanks,

Quoted 44 lines

Review

Quoted 10 lines
(quoted diff) +9 -0
+static int __devinit sdhci_mmp2_probe(struct platform_device *pdev)
+{
+ ? ? struct sdhci_pltfm_host *pltfm_host;
+ ? ? struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+ ? ? struct device *dev = &pdev->dev;
+ ? ? struct sdhci_host *host = NULL;
+ ? ? struct sdhci_pxa *pxa = NULL;
+ ? ? int ret;
+ ? ? struct clk *clk;

The probe and release functions for mmp2 and pxa910 are almost identical. I'd suggest you leave them in sdhci-pxa.c as a library, and export them using EXPORT_SYMBOL_GPL. Then you can call them from the respective probe functions, e.g.

static struct sdhci_mmp2_ops = {
? ? ? ?.set_clock = mmp2_set_clock,
? ? ? ?.set_uhs_signaling = mmp2_set_uhs_signaling,
? ? ? ?.get_ro = mmp2_get_ro,
};
static int __devinit sdhci_mmp2_probe(struct platform_device *pdev) {
? ? ? ? unsigned int quirks = SDHCI_QUIRK_BROKEN_ADMA

? ? ? ? ? ? ? ?| SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
? ? ? ? ? ? ? ?| SDHCI_QUIRK_32BIT_DMA_ADDR
? ? ? ? ? ? ? ?| SDHCI_QUIRK_32BIT_DMA_SIZE
? ? ? ? ? ? ? ?| SDHCI_QUIRK_32BIT_ADMA_SIZE
? ? ? ? ? ? ? ?| SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;

? ? ? ?return sdhci_pxa_probe(pdev, quirks, sdhci_mmp2_ops); }

Quoted 10 lines

+ ? ? pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+ ? ? if (!pxa) {
+ ? ? ? ? ? ? ret = -ENOMEM;
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL);
+ ? ? if (!pxa->ops) {
+ ? ? ? ? ? ? ret = -ENOMEM;
+ ? ? ? ? ? ? goto out;
+ ? ? }

Quoted 3 lines

I think you really shouldn't allocate the sdhci_ops dynamically. In fact, it would be much better if we were able to mark them as const in all drivers.

We found some issues when supporting multi-slot, each slot may have different ops.
So use the method of allocating the sdhci_ops dynamically instead of using static ops.
For example, emmc has 74_clocks call back, while mmc and sdio slot does not have such ops.
If not dynamically allocate sdhci_ops, all slot ops may become same, and 74_clocks may be called for every slot.
Also, some board may have get_ro, while other board may not, so transfer the ops via flags.

Not sure whether it is worthy to add additional common files to share probe and remove function.
Also the init the ops part are different.

Quoted 16 lines
Quoted 16 lines
drivers/mmc/host/sdhci-mmp2.c new file +15 -0
+
+#ifdef CONFIG_PM
+static int sdhci_mmp2_suspend(struct platform_device *dev, pm_message_t state)
+{
+ ? ? struct sdhci_host *host = platform_get_drvdata(dev);
+
+ ? ? return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_mmp2_resume(struct platform_device *dev)
+{
+ ? ? struct sdhci_host *host = platform_get_drvdata(dev);
+
+ ? ? return sdhci_resume_host(host);
+}
Quoted 9 lines

drivers/mmc/host/sdhci-mmp2.c line 272

Quoted 4 lines
drivers/mmc/host/sdhci-mmp2.c new file +4 -0
+#else
+#define sdhci_mmp2_suspend ? NULL
+#define sdhci_mmp2_resume ? ?NULL
+#endif

Similarly, I think it would be good if sdhci-pltfm.c would simply export these functions so you could refer to them in your driver. There is no need to have identical copies in each variant.

There are some additional code for suspend and resume, so sdhci_pltfm_suspend may not enough.
For example, when enable wifi host sleep feature, additional register have to be configured.

Quoted 6 lines

? ? ? ?Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at ?http://vger.kernel.org/majordomo-info.html

#3 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 103 lines · zhangfei gao
Quoted 22 lines · Arnd Bergmann
Quoted 5 lines · Zhangfei Gao

Instead of sharing sdhci-pxa.c, use sdhci-mmp2.c specificlly for mmp2. sdhci-pxa.c is used to share among pxa serious, like pxa910, mmp2, etc. The platfrom difference are put under arch/arm, while is not easy to track.

Quoted 9 lines
---
 arch/arm/plat-pxa/include/plat/sdhci.h |   43 ++++-
 drivers/mmc/host/Kconfig               |   11 +-
 drivers/mmc/host/Makefile              |    2 +-
 drivers/mmc/host/sdhci-mmp2.c          |  303 ++++++++++++++++++++++++++++++++
 drivers/mmc/host/sdhci-pxa.c           |  303 --------------------------------
 5 files changed, 349 insertions(+), 313 deletions(-)
 create mode 100644 drivers/mmc/host/sdhci-mmp2.c
 delete mode 100644 drivers/mmc/host/sdhci-pxa.c

Yes, looks good for the most part. I was rather confused by the fact that the old and new file are both 303 lines, so I assumed they would be identical, when they are really completely different.

There is a little room for simplification, I think:

Quoted 8 lines

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+     /* Micro SD does not support write-protect feature */
+     return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

Quoted 13 lines

drivers/mmc/host/sdhci-mmp2.c line 91

Quoted 9 lines
drivers/mmc/host/sdhci-mmp2.c new file +8 -0
+static void mmp2_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+     struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+     struct sdhci_pxa *pxa = pltfm_host->priv;
+
+     if (clock)
+             mmp2_soc_set_timing(host, pxa->pdata);
+}

The mmp2_soc_set_timing() function is only called here, so you can easily merge the two into one, starting with

Quoted 2 lines
       if (!clock)
               return;

OK, thanks,

Quoted 44 lines

drivers/mmc/host/sdhci-mmp2.c line 139

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +9 -0
+static int __devinit sdhci_mmp2_probe(struct platform_device *pdev)
+{
+     struct sdhci_pltfm_host *pltfm_host;
+     struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
+     struct device *dev = &pdev->dev;
+     struct sdhci_host *host = NULL;
+     struct sdhci_pxa *pxa = NULL;
+     int ret;
+     struct clk *clk;

The probe and release functions for mmp2 and pxa910 are almost identical. I'd suggest you leave them in sdhci-pxa.c as a library, and export them using EXPORT_SYMBOL_GPL. Then you can call them from the respective probe functions, e.g.

static struct sdhci_mmp2_ops = {
.set_clock = mmp2_set_clock,
.set_uhs_signaling = mmp2_set_uhs_signaling, .get_ro = mmp2_get_ro,
};
static int __devinit sdhci_mmp2_probe(struct platform_device *pdev)

{
        unsigned int quirks = SDHCI_QUIRK_BROKEN_ADMA
               | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
               | SDHCI_QUIRK_32BIT_DMA_ADDR
               | SDHCI_QUIRK_32BIT_DMA_SIZE
               | SDHCI_QUIRK_32BIT_ADMA_SIZE
               | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC;

       return sdhci_pxa_probe(pdev, quirks, sdhci_mmp2_ops);
}

drivers/mmc/host/sdhci-mmp2.c line 150

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +10 -0
+     pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+     if (!pxa) {
+             ret = -ENOMEM;
+             goto out;
+     }
+     pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL);
+     if (!pxa->ops) {
+             ret = -ENOMEM;
+             goto out;
+     }
Quoted 3 lines

I think you really shouldn't allocate the sdhci_ops dynamically. In fact, it would be much better if we were able to mark them as const in all drivers.

Quoted 10 lines

We found some issues when supporting multi-slot, each slot may have different ops.
So use the method of allocating the sdhci_ops dynamically instead of using static ops.
For example, emmc has 74_clocks call back, while mmc and sdio slot does not have such ops.
If not dynamically allocate sdhci_ops, all slot ops may become same, and 74_clocks may be called for every slot.
Also, some board may have get_ro, while other board may not, so transfer the ops via flags.

74 clock code causes no harm for SD/eMMC/SDIO. You can
save 74 clocks if that really is important for SDIO. I do not know what a SD slot is. You cannot make any assumptions about what card the user will put into a slot.

Quoted 42 lines

Not sure whether it is worthy to add additional common files to share probe and remove function.
Also the init the ops part are different.

Quoted 16 lines
Quoted 16 lines
drivers/mmc/host/sdhci-mmp2.c new file +15 -0
+
+#ifdef CONFIG_PM
+static int sdhci_mmp2_suspend(struct platform_device *dev, pm_message_t state)
+{
+     struct sdhci_host *host = platform_get_drvdata(dev);
+
+     return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_mmp2_resume(struct platform_device *dev)
+{
+     struct sdhci_host *host = platform_get_drvdata(dev);
+
+     return sdhci_resume_host(host);
+}
Quoted 9 lines

drivers/mmc/host/sdhci-mmp2.c line 272

Quoted 4 lines
drivers/mmc/host/sdhci-mmp2.c new file +4 -0
+#else
+#define sdhci_mmp2_suspend   NULL
+#define sdhci_mmp2_resume    NULL
+#endif

Similarly, I think it would be good if sdhci-pltfm.c would simply export these functions so you could refer to them in your driver. There is no need to have identical copies in each variant.

There are some additional code for suspend and resume, so sdhci_pltfm_suspend may not enough.
For example, when enable wifi host sleep feature, additional register have to be configured.

Quoted 6 lines

Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

#4 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

In reply to zhangfei gao
Quoted 11 lines · On Monday 30 May 2011 07:42:04 zhangfei gao wrote:
Quoted 9 lines · Arnd Bergmann

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines · Zhangfei Gao
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+     /* Micro SD does not support write-protect feature */
+     return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Quoted 6 lines

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

Ok, I see.

Quoted 26 lines
Quoted 11 lines

drivers/mmc/host/sdhci-mmp2.c line 150

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +10 -0
+     pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+     if (!pxa) {
+             ret = -ENOMEM;
+             goto out;
+     }
+     pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL);
+     if (!pxa->ops) {
+             ret = -ENOMEM;
+             goto out;
+     }
Quoted 3 lines

I think you really shouldn't allocate the sdhci_ops dynamically. In fact, it would be much better if we were able to mark them as const in all drivers.

We found some issues when supporting multi-slot, each slot may have different ops.
So use the method of allocating the sdhci_ops dynamically instead of using static ops.
For example, emmc has 74_clocks call back, while mmc and sdio slot does not have such ops.
If not dynamically allocate sdhci_ops, all slot ops may become same, and 74_clocks may be called for every slot.
Also, some board may have get_ro, while other board may not, so transfer the ops via flags.

Quoted 3 lines

Not sure whether it is worthy to add additional common files to share probe and remove function.
Also the init the ops part are different.

IMHO, we should try much harder to keep the ops constant. For the two examples you gave, I would probably put a flag into private data for the get_ro operation to signify that it's never read-only, and provide a second set of operations for emmc, so that in the probe function you check the type of device and then set the appropriate one.

You could also do the same for all three cases:

	if (emmc)
		host->ops = &sdhci_mmp2_emmc_ops;
	else if (!has_ro_switch)
		host->ops = &sdhci_mmp2_rw_ops;
	else
		host->ops = &sdhci_mmp2_default_ops;
Quoted 25 lines
Quoted 15 lines
Quoted 15 lines
drivers/mmc/host/sdhci-mmp2.c new file +15 -0
+
+#ifdef CONFIG_PM
+static int sdhci_mmp2_suspend(struct platform_device *dev, pm_message_t state)
+{
+     struct sdhci_host *host = platform_get_drvdata(dev);
+
+     return sdhci_suspend_host(host, state);
+}
+
+static int sdhci_mmp2_resume(struct platform_device *dev)
+{
+     struct sdhci_host *host = platform_get_drvdata(dev);
+
+     return sdhci_resume_host(host);
+}
Quoted 9 lines

drivers/mmc/host/sdhci-mmp2.c line 272

Quoted 4 lines
drivers/mmc/host/sdhci-mmp2.c new file +4 -0
+#else
+#define sdhci_mmp2_suspend   NULL
+#define sdhci_mmp2_resume    NULL
+#endif

Similarly, I think it would be good if sdhci-pltfm.c would simply export these functions so you could refer to them in your driver. There is no need to have identical copies in each variant.

Quoted 4 lines

There are some additional code for suspend and resume, so sdhci_pltfm_suspend may not enough.
For example, when enable wifi host sleep feature, additional register have to be configured.

Well, not all drivers would have to use the common functions, but right now there are a number of identical copies, so it's certainly worth sharing.

Note that this comment wasn't directed at your patch as much as at the overall design of the sdhci sub-drivers.

Arnd

#5 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 57 lines · Arnd Bergmann
Quoted 11 lines · On Monday 30 May 2011 07:42:04 zhangfei gao wrote:
Quoted 9 lines · Arnd Bergmann

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines · Zhangfei Gao
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+ ? ? /* Micro SD does not support write-protect feature */
+ ? ? return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Quoted 6 lines

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

Ok, I see.

Quoted 26 lines
Quoted 11 lines
Quoted 10 lines

+ ? ? pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
+ ? ? if (!pxa) {
+ ? ? ? ? ? ? ret = -ENOMEM;
+ ? ? ? ? ? ? goto out;
+ ? ? }
+ ? ? pxa->ops = kzalloc(sizeof(struct sdhci_ops), GFP_KERNEL);
+ ? ? if (!pxa->ops) {
+ ? ? ? ? ? ? ret = -ENOMEM;
+ ? ? ? ? ? ? goto out;
+ ? ? }

Quoted 3 lines

I think you really shouldn't allocate the sdhci_ops dynamically. In fact, it would be much better if we were able to mark them as const in all drivers.

We found some issues when supporting multi-slot, each slot may have different ops.
So use the method of allocating the sdhci_ops dynamically instead of using static ops.
For example, emmc has 74_clocks call back, while mmc and sdio slot does not have such ops.
If not dynamically allocate sdhci_ops, all slot ops may become same, and 74_clocks may be called for every slot.
Also, some board may have get_ro, while other board may not, so transfer the ops via flags.

Quoted 3 lines

Not sure whether it is worthy to add additional common files to share probe and remove function.
Also the init the ops part are different.

IMHO, we should try much harder to keep the ops constant. For the two examples you gave, I would probably put a flag into private data for the get_ro operation to signify that it's never read-only, and provide a second set of operations for emmc, so that in the probe function you check the type of device and then set the appropriate one.

Quoted 8 lines

You could also do the same for all three cases:

? ? ? ?if (emmc)
? ? ? ? ? ? ? ?host->ops = &sdhci_mmp2_emmc_ops; ? ? ? ?else if (!has_ro_switch)
? ? ? ? ? ? ? ?host->ops = &sdhci_mmp2_rw_ops; ? ? ? ?else
? ? ? ? ? ? ? ?host->ops = &sdhci_mmp2_default_ops;

Thanks, will take this method to make the ops constant.

Quoted 26 lines
Quoted 26 lines
Quoted 25 lines
Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +9 -0
+
+#ifdef CONFIG_PM
+static int sdhci_mmp2_suspend(struct platform_device *dev, pm_message_t state)
+{
+ ? ? struct sdhci_host *host = platform_get_drvdata(dev);
+
+ ? ? return sdhci_suspend_host(host, state);
+}
+

drivers/mmc/host/sdhci-mmp2.c line 272

Quoted 10 lines
drivers/mmc/host/sdhci-mmp2.c new file +10 -0
+static int sdhci_mmp2_resume(struct platform_device *dev)
+{
+ ? ? struct sdhci_host *host = platform_get_drvdata(dev);
+
+ ? ? return sdhci_resume_host(host);
+}
+#else
+#define sdhci_mmp2_suspend ? NULL
+#define sdhci_mmp2_resume ? ?NULL
+#endif

Similarly, I think it would be good if sdhci-pltfm.c would simply export these functions so you could refer to them in your driver. There is no need to have identical copies in each variant.

Quoted 8 lines
Quoted 4 lines

There are some additional code for suspend and resume, so sdhci_pltfm_suspend may not enough.
For example, when enable wifi host sleep feature, additional register have to be configured.

Well, not all drivers would have to use the common functions, but right now there are a number of identical copies, so it's certainly worth sharing.

Then we use sdhci_pltfm_suspend first, and change to private suspend & resume when supporting additional feature.

Quoted 6 lines

Note that this comment wasn't directed at your patch as much as at the overall design of the sdhci sub-drivers.

? ? ? ?Arnd

#6 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

In reply to zhangfei gao
Quoted 12 lines · zhangfei gao
Quoted 11 lines

There is a little room for simplification, I think:

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+     /* Micro SD does not support write-protect feature */
+     return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Quoted 6 lines

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

The code sets get_ro is for all the controllers. Some board designs may connect the WP signal.

The host->ops field should be filled in using information in the board file using a flag such as the example with PXA_FLAG_CARD_PERMANENT.

eg

	if (pdata && pdata->flags & PXA_FLAG_NO_WP) {
		***** etc ****
	}
#7 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 26 lines · Philip Rakity
Quoted 12 lines · zhangfei gao
Quoted 11 lines

There is a little room for simplification, I think:

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+ ? ? /* Micro SD does not support write-protect feature */
+ ? ? return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Quoted 6 lines

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

The code sets get_ro is for all the controllers. ? Some board designs may connect the WP signal.

Quoted 10 lines

The host->ops field should be filled in using information in the board file using a flag such as the example with ?PXA_FLAG_CARD_PERMANENT.

eg

? ? ? ?if (pdata && pdata->flags & PXA_FLAG_NO_WP) { ? ? ? ? ? ? ? ?***** etc ****
? ? ? ?}

This method is used in v1,
The method makes sdhci_ops non-const and have to dynamically alloc sdhci_ops, since host->ops is pointer.
Will keep use const sdhci_ops, recommended by Arnd.

Quoted 3 lines
#8 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 38 lines · zhangfei gao
Quoted 26 lines · Philip Rakity
Quoted 12 lines · zhangfei gao
Quoted 11 lines

There is a little room for simplification, I think:

drivers/mmc/host/sdhci-mmp2.c line 82

Quoted 5 lines
drivers/mmc/host/sdhci-mmp2.c new file +5 -0
+static unsigned int mmp2_get_ro(struct sdhci_host *host)
+{
+     /* Micro SD does not support write-protect feature */
+     return 0;
+}

You shouldn't need to provide an empty get_ro function, the default is that there is no write-protect.

Quoted 6 lines

Thanks Arnd for review.
The reason to put get_ro here is some board use micro sd, while some board design is general sd card.
The micro sd do not use write-protect, while SDHCI_WRITE_PROTECT will return 1 in our controller, so it shows read only.
So add one call back for the board with micro sd card via flag.

The code sets get_ro is for all the controllers. Some board designs may connect the WP signal.

Quoted 10 lines

The host->ops field should be filled in using information in the board file using a flag such as the example with PXA_FLAG_CARD_PERMANENT.

eg

       if (pdata && pdata->flags & PXA_FLAG_NO_WP) {
               ***** etc ****
       }
Quoted 4 lines

This method is used in v1,
The method makes sdhci_ops non-const and have to dynamically alloc sdhci_ops, since host->ops is pointer.
Will keep use const sdhci_ops, recommended by Arnd.

Not acceptable.

There are 3 cases for WP signal

a) They are connected to the controller using GPIO
b( They are NOT connected and the corresponding pin is not used
c) They are NOT connected and the corresponding pin is used by something else.

case a)
program GPIO as is done today in brownstone and aspen

case b)
configure the MFP pin to be pull high/low to indicate NO WP. The pin cannot be left floating

case c)
you need a quirk and the call back.

#9 lore raw

PATCH v2 1/3 mmc: support sdhci-mmp2

Quoted 16 lines
Quoted 5 lines

This method is used in v1,
The method makes sdhci_ops non-const and have to dynamically alloc sdhci_ops, since host->ops is pointer.
Will keep use const sdhci_ops, recommended by Arnd.

Not acceptable.

There are ?3 cases for ?WP signal

a) They are connected to the controller using GPIO
b( They are NOT connected and the corresponding ?pin is not used
c) They are NOT connected and the corresponding ?pin is used by something else.

Quoted 5 lines

case a)
? ? ? ?program GPIO as is done today in brownstone and aspen

case b)
? ? ? ?configure the MFP pin to be pull high/low to indicate NO WP. ?The pin cannot be left floating

Thanks, configure WP pin to LOW should be work for micro sd card.

Quoted 9 lines

case c)
? ? ? ?you need a quirk and the call back.