All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
@ 2014-01-09 14:35 ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao

v7:
0002:
use undefined local value in suspend/resume

v6:
0002:
Jaehoon pointed HIGHSPEED cap can be omitted if supports-highspeed is defined.
Seungwon mentioned clk operation should be called after suspend.
Remove k3_dwmmc_caps

V5:
0002:
Follow advice from Arnd, 
Update dt descirption and use of_property_for_each_u32 to get table number.

v4:
Follow Arnd's suggestion abstracting specific tuning to clock,
also because new version ip use different method and not use same tuning registers.

0001 acked by Jaehoon

v3:
0001: 
Put set/clear_bit DW_MMC_CARD_PRESENT in dw_mci_get_cd, 
Since dw_mci_request will check DW_MMC_CARD_PRESENT before sending cmd

0002:
Follow suggestion from Chris, Kumar and Seungwon
Sync to latest mmc-next, which is 3.12-rc2
Remove enum dw_mci_k3_type etc

v2:
Follow Jaehoon's suggestion
Use slot-gpio.c handle cd pin
Move table out to dts
other suggestion


Zhangfei Gao (3):
  mmc: dw_mmc: use slot-gpio to handle cd pin
  mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  clk: hisilicon: add hi3620_mmc_clks

 .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
 .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++
 drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
 drivers/mmc/host/Kconfig                           |   10 +
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++
 drivers/mmc/host/dw_mmc.c                          |   48 +++-
 include/dt-bindings/clock/hi3620-clock.h           |    5 +
 9 files changed, 514 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

-- 
1.7.9.5


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

* [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
@ 2014-01-09 14:35 ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

v7:
0002:
use undefined local value in suspend/resume

v6:
0002:
Jaehoon pointed HIGHSPEED cap can be omitted if supports-highspeed is defined.
Seungwon mentioned clk operation should be called after suspend.
Remove k3_dwmmc_caps

V5:
0002:
Follow advice from Arnd, 
Update dt descirption and use of_property_for_each_u32 to get table number.

v4:
Follow Arnd's suggestion abstracting specific tuning to clock,
also because new version ip use different method and not use same tuning registers.

0001 acked by Jaehoon

v3:
0001: 
Put set/clear_bit DW_MMC_CARD_PRESENT in dw_mci_get_cd, 
Since dw_mci_request will check DW_MMC_CARD_PRESENT before sending cmd

0002:
Follow suggestion from Chris, Kumar and Seungwon
Sync to latest mmc-next, which is 3.12-rc2
Remove enum dw_mci_k3_type etc

v2:
Follow Jaehoon's suggestion
Use slot-gpio.c handle cd pin
Move table out to dts
other suggestion


Zhangfei Gao (3):
  mmc: dw_mmc: use slot-gpio to handle cd pin
  mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  clk: hisilicon: add hi3620_mmc_clks

 .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
 .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++
 drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
 drivers/mmc/host/Kconfig                           |   10 +
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++
 drivers/mmc/host/dw_mmc.c                          |   48 +++-
 include/dt-bindings/clock/hi3620-clock.h           |    5 +
 9 files changed, 514 insertions(+), 13 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

-- 
1.7.9.5

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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-09 14:35 ` Zhangfei Gao
@ 2014-01-09 14:35   ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao

Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
 drivers/mmc/host/dw_mmc.c |   48 +++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 4bce0deec362..a776f24f4311 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -36,6 +36,7 @@
 #include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include "dw_mmc.h"
 
@@ -1032,20 +1033,26 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
+	int gpio_cd = !mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
 		present = 1;
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
+	else if (!IS_ERR_VALUE(gpio_cd))
+		present = !!gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
-	if (present)
+	if (present) {
+		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
-	else
+	} else {
+		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
+	}
 
 	return present;
 }
@@ -1926,10 +1933,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 			/* Card change detected */
 			slot->last_detect_state = present;
 
-			/* Mark card as present if applicable */
-			if (present != 0)
-				set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 			/* Clean up queue if present */
 			mrq = slot->mrq;
 			if (mrq) {
@@ -1977,8 +1980,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 
 			/* Power down slot */
 			if (present == 0) {
-				clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 				/* Clear down the FIFO */
 				dw_mci_fifo_reset(host);
 #ifdef CONFIG_MMC_DW_IDMAC
@@ -2079,6 +2080,26 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 
 	return gpio;
 }
+
+/* find the cd gpio for a given slot; or -1 if none specified */
+static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
+					struct mmc_host *mmc)
+{
+	struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
+	int gpio;
+
+	if (!np)
+		return;
+
+	gpio = of_get_named_gpio(np, "cd-gpios", 0);
+
+	/* Having a missing entry is valid; return silently */
+	if (!gpio_is_valid(gpio))
+		return;
+
+	if (mmc_gpio_request_cd(mmc, gpio, 0))
+		dev_warn(dev, "gpio [%d] request failed\n", gpio);
+}
 #else /* CONFIG_OF */
 static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
 {
@@ -2096,6 +2117,11 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 {
 	return -EINVAL;
 }
+static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
+					struct mmc_host *mmc)
+{
+	return;
+}
 #endif /* CONFIG_OF */
 
 static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
@@ -2197,12 +2223,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 #endif /* CONFIG_MMC_DW_IDMAC */
 	}
 
-	if (dw_mci_get_cd(mmc))
-		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-	else
-		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 	slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
+	dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc);
 
 	ret = mmc_add_host(mmc);
 	if (ret)
-- 
1.7.9.5


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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-09 14:35   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
---
 drivers/mmc/host/dw_mmc.c |   48 +++++++++++++++++++++++++++++++++------------
 1 file changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 4bce0deec362..a776f24f4311 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -36,6 +36,7 @@
 #include <linux/workqueue.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/mmc/slot-gpio.h>
 
 #include "dw_mmc.h"
 
@@ -1032,20 +1033,26 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
+	int gpio_cd = !mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
 		present = 1;
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
+	else if (!IS_ERR_VALUE(gpio_cd))
+		present = !!gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
-	if (present)
+	if (present) {
+		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
-	else
+	} else {
+		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
+	}
 
 	return present;
 }
@@ -1926,10 +1933,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 			/* Card change detected */
 			slot->last_detect_state = present;
 
-			/* Mark card as present if applicable */
-			if (present != 0)
-				set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 			/* Clean up queue if present */
 			mrq = slot->mrq;
 			if (mrq) {
@@ -1977,8 +1980,6 @@ static void dw_mci_work_routine_card(struct work_struct *work)
 
 			/* Power down slot */
 			if (present == 0) {
-				clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 				/* Clear down the FIFO */
 				dw_mci_fifo_reset(host);
 #ifdef CONFIG_MMC_DW_IDMAC
@@ -2079,6 +2080,26 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 
 	return gpio;
 }
+
+/* find the cd gpio for a given slot; or -1 if none specified */
+static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
+					struct mmc_host *mmc)
+{
+	struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
+	int gpio;
+
+	if (!np)
+		return;
+
+	gpio = of_get_named_gpio(np, "cd-gpios", 0);
+
+	/* Having a missing entry is valid; return silently */
+	if (!gpio_is_valid(gpio))
+		return;
+
+	if (mmc_gpio_request_cd(mmc, gpio, 0))
+		dev_warn(dev, "gpio [%d] request failed\n", gpio);
+}
 #else /* CONFIG_OF */
 static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
 {
@@ -2096,6 +2117,11 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 {
 	return -EINVAL;
 }
+static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
+					struct mmc_host *mmc)
+{
+	return;
+}
 #endif /* CONFIG_OF */
 
 static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
@@ -2197,12 +2223,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 #endif /* CONFIG_MMC_DW_IDMAC */
 	}
 
-	if (dw_mci_get_cd(mmc))
-		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-	else
-		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
-
 	slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
+	dw_mci_of_get_cd_gpio(host->dev, slot->id, mmc);
 
 	ret = mmc_add_host(mmc);
 	if (ret)
-- 
1.7.9.5

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-09 14:35 ` Zhangfei Gao
@ 2014-01-09 14:35     ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Zhangfei Gao, Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
 4 files changed, 203 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..68e5e428e8f6
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	if (!rate) {
+		dev_warn(host->dev,
+			"no specified rate in timing %u\n", ios->timing);
+		return;
+	}
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-09 14:35     ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
 4 files changed, 203 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..68e5e428e8f6
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	if (!rate) {
+		dev_warn(host->dev,
+			"no specified rate in timing %u\n", ios->timing);
+		return;
+	}
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* [PATCH 3/3] clk: hisilicon: add hi3620_mmc_clks
  2014-01-09 14:35 ` Zhangfei Gao
@ 2014-01-09 14:35   ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao

Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
 .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
 drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
 include/dt-bindings/clock/hi3620-clock.h           |    5 +
 4 files changed, 282 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
 		resume-offset = <0x308>;
 		reboot-offset = <0x4>;
 	};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+	/* for Hi3620 */
+	pctrl: pctrl@fca09000 {
+		compatible = "hisilicon,pctrl";
+		reg = <0xfca09000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: should be one of the following.
   - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+  - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
 
 - reg: physical base address of the controller and length of memory mapped
   region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..e47a4a659df7 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,265 @@ static void __init hi3620_clk_init(struct device_node *np)
 				   base);
 }
 CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	u32			clken_reg;
+	u32			clken_bit;
+	u32			div_reg;
+	u32			div_off;
+	u32			div_bits;
+	u32			drv_reg;
+	u32			drv_off;
+	u32			drv_bits;
+	u32			sam_reg;
+	u32			sam_off;
+	u32			sam_bits;
+};
+
+struct clk_mmc {
+	struct clk_hw	hw;
+	u32		id;
+	void __iomem	*clken_reg;
+	u32		clken_bit;
+	void __iomem	*div_reg;
+	u32		div_off;
+	u32		div_bits;
+	void __iomem	*drv_reg;
+	u32		drv_off;
+	u32		drv_bits;
+	void __iomem	*sam_reg;
+	u32		sam_off;
+	u32		sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+	{ HI3620_SD_CIUCLK,	"sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+	{ HI3620_MMC_CIUCLK1,   "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+	{ HI3620_MMC_CIUCLK2,   "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+	{ HI3620_MMC_CIUCLK3,   "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+		       unsigned long parent_rate)
+{
+	switch (parent_rate) {
+	case 26000000:
+		return 13000000;
+	case 180000000:
+		return 25000000;
+	case 360000000:
+		return 50000000;
+	case 720000000:
+		return 100000000;
+	default:
+		return parent_rate;
+	}
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *best_parent_rate,
+			      struct clk **best_parent_p)
+{
+	unsigned long best = 0;
+
+	if (rate <= 13000000) {
+		rate = 13000000;
+		best = 26000000;
+	} else if (rate <= 26000000) {
+		rate = 25000000;
+		best = 180000000;
+	} else if (rate <= 52000000) {
+		rate = 50000000;
+		best = 360000000;
+	} else if (rate <= 100000000) {
+		rate = 100000000;
+		best = 720000000;
+	}
+	*best_parent_rate = best;
+	return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+	u32 i;
+
+	if (para >= 0) {
+		for (i = 0; i < len; i++) {
+			if (para % 2)
+				val |= 1 << (off + i);
+			else
+				val &= ~(1 << (off + i));
+			para = para >> 1;
+		}
+	}
+	return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long flags;
+	u32 sam, drv, div, val;
+	static DEFINE_SPINLOCK(mmc_clk_lock);
+
+	switch (rate) {
+	case 13000000:
+		sam = 3;
+		drv = 1;
+		div = 1;
+		break;
+	case 25000000:
+		sam = 13;
+		drv = 6;
+		div = 6;
+		break;
+	case 50000000:
+		sam = 3;
+		drv = 6;
+		div = 6;
+		break;
+	case 100000000:
+		sam = 6;
+		drv = 4;
+		div = 6;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&mmc_clk_lock, flags);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val &= ~(1 << mclk->clken_bit);
+	writel_relaxed(val, mclk->clken_reg);
+
+	val = readl_relaxed(mclk->sam_reg);
+	val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+	writel_relaxed(val, mclk->sam_reg);
+
+	val = readl_relaxed(mclk->drv_reg);
+	val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+	writel_relaxed(val, mclk->drv_reg);
+
+	val = readl_relaxed(mclk->div_reg);
+	val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+	writel_relaxed(val, mclk->div_reg);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val |= 1 << mclk->clken_bit;
+	writel_relaxed(val, mclk->clken_reg);
+
+	spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+	return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long rate;
+
+	if (mclk->id == HI3620_SD_CIUCLK)
+		rate = 13000000;
+	else
+		rate = 25000000;
+
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+	.prepare = mmc_clk_prepare,
+	.determine_rate = mmc_clk_determine_rate,
+	.set_rate = mmc_clk_set_rate,
+	.recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+			void __iomem *base, struct device_node *np)
+{
+	struct clk_mmc *mclk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+	if (!mclk) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = mmc_clk->name;
+	init.ops = &clk_mmc_ops;
+	init.flags = mmc_clk->flags | CLK_IS_BASIC;
+	init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+	init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+	mclk->hw.init = &init;
+
+	mclk->id = mmc_clk->id;
+	mclk->clken_reg = base + mmc_clk->clken_reg;
+	mclk->clken_bit = mmc_clk->clken_bit;
+	mclk->div_reg = base + mmc_clk->div_reg;
+	mclk->div_off = mmc_clk->div_off;
+	mclk->div_bits = mmc_clk->div_bits;
+	mclk->drv_reg = base + mmc_clk->drv_reg;
+	mclk->drv_off = mmc_clk->drv_off;
+	mclk->drv_bits = mmc_clk->drv_bits;
+	mclk->sam_reg = base + mmc_clk->sam_reg;
+	mclk->sam_off = mmc_clk->sam_off;
+	mclk->sam_bits = mmc_clk->sam_bits;
+
+	clk = clk_register(NULL, &mclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		kfree(mclk);
+	return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+	void __iomem *base;
+	int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+	struct clk_onecell_data *clk_data;
+
+	if (!node) {
+		pr_err("failed to find pctrl node in DTS\n");
+		return;
+	}
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("failed to map pctrl\n");
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (WARN_ON(!clk_data))
+		return;
+
+	clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+	if (!clk_data->clks) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num; i++) {
+		struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+		clk_data->clks[mmc_clk->id] =
+			hisi_register_clk_mmc(mmc_clk, base, node);
+	}
+
+	clk_data->clk_num = num;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
 #define HI3620_MMC_CLK3		217
 #define HI3620_MCU_CLK		218
 
+#define HI3620_SD_CIUCLK	0
+#define HI3620_MMC_CIUCLK1	1
+#define HI3620_MMC_CIUCLK2	2
+#define HI3620_MMC_CIUCLK3	3
+
 #define HI3620_NR_CLKS		219
 
 #endif	/* __DTS_HI3620_CLOCK_H */
-- 
1.7.9.5


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

* [PATCH 3/3] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-09 14:35   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-09 14:35 UTC (permalink / raw)
  To: linux-arm-kernel

Suggest by Arnd: abstract mmc tuning as clock behavior,
also because different soc have different tuning method and registers.
hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
---
 .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
 .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
 drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
 include/dt-bindings/clock/hi3620-clock.h           |    5 +
 4 files changed, 282 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
index 8c7a4653508d..df0a452b8526 100644
--- a/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
+++ b/Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
@@ -30,3 +30,17 @@ Example:
 		resume-offset = <0x308>;
 		reboot-offset = <0x4>;
 	};
+
+PCTRL: Peripheral misc control register
+
+Required Properties:
+- compatible: "hisilicon,pctrl"
+- reg: Address and size of pctrl.
+
+Example:
+
+	/* for Hi3620 */
+	pctrl: pctrl at fca09000 {
+		compatible = "hisilicon,pctrl";
+		reg = <0xfca09000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/hi3620-clock.txt b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
index 4b71ab41be53..dad6269f52c5 100644
--- a/Documentation/devicetree/bindings/clock/hi3620-clock.txt
+++ b/Documentation/devicetree/bindings/clock/hi3620-clock.txt
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: should be one of the following.
   - "hisilicon,hi3620-clock" - controller compatible with Hi3620 SoC.
+  - "hisilicon,hi3620-mmc-clock" - controller specific for Hi3620 mmc.
 
 - reg: physical base address of the controller and length of memory mapped
   region.
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index f24ad6a3a797..e47a4a659df7 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -240,3 +240,265 @@ static void __init hi3620_clk_init(struct device_node *np)
 				   base);
 }
 CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
+
+struct hisi_mmc_clock {
+	unsigned int		id;
+	const char		*name;
+	const char		*parent_name;
+	unsigned long		flags;
+	u32			clken_reg;
+	u32			clken_bit;
+	u32			div_reg;
+	u32			div_off;
+	u32			div_bits;
+	u32			drv_reg;
+	u32			drv_off;
+	u32			drv_bits;
+	u32			sam_reg;
+	u32			sam_off;
+	u32			sam_bits;
+};
+
+struct clk_mmc {
+	struct clk_hw	hw;
+	u32		id;
+	void __iomem	*clken_reg;
+	u32		clken_bit;
+	void __iomem	*div_reg;
+	u32		div_off;
+	u32		div_bits;
+	void __iomem	*drv_reg;
+	u32		drv_off;
+	u32		drv_bits;
+	void __iomem	*sam_reg;
+	u32		sam_off;
+	u32		sam_bits;
+};
+
+#define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
+
+static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
+	{ HI3620_SD_CIUCLK,	"sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
+	{ HI3620_MMC_CIUCLK1,   "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
+	{ HI3620_MMC_CIUCLK2,   "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
+	{ HI3620_MMC_CIUCLK3,   "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
+};
+
+static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
+		       unsigned long parent_rate)
+{
+	switch (parent_rate) {
+	case 26000000:
+		return 13000000;
+	case 180000000:
+		return 25000000;
+	case 360000000:
+		return 50000000;
+	case 720000000:
+		return 100000000;
+	default:
+		return parent_rate;
+	}
+}
+
+static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
+			      unsigned long *best_parent_rate,
+			      struct clk **best_parent_p)
+{
+	unsigned long best = 0;
+
+	if (rate <= 13000000) {
+		rate = 13000000;
+		best = 26000000;
+	} else if (rate <= 26000000) {
+		rate = 25000000;
+		best = 180000000;
+	} else if (rate <= 52000000) {
+		rate = 50000000;
+		best = 360000000;
+	} else if (rate <= 100000000) {
+		rate = 100000000;
+		best = 720000000;
+	}
+	*best_parent_rate = best;
+	return rate;
+}
+
+static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
+{
+	u32 i;
+
+	if (para >= 0) {
+		for (i = 0; i < len; i++) {
+			if (para % 2)
+				val |= 1 << (off + i);
+			else
+				val &= ~(1 << (off + i));
+			para = para >> 1;
+		}
+	}
+	return val;
+}
+
+static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long flags;
+	u32 sam, drv, div, val;
+	static DEFINE_SPINLOCK(mmc_clk_lock);
+
+	switch (rate) {
+	case 13000000:
+		sam = 3;
+		drv = 1;
+		div = 1;
+		break;
+	case 25000000:
+		sam = 13;
+		drv = 6;
+		div = 6;
+		break;
+	case 50000000:
+		sam = 3;
+		drv = 6;
+		div = 6;
+		break;
+	case 100000000:
+		sam = 6;
+		drv = 4;
+		div = 6;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&mmc_clk_lock, flags);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val &= ~(1 << mclk->clken_bit);
+	writel_relaxed(val, mclk->clken_reg);
+
+	val = readl_relaxed(mclk->sam_reg);
+	val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
+	writel_relaxed(val, mclk->sam_reg);
+
+	val = readl_relaxed(mclk->drv_reg);
+	val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
+	writel_relaxed(val, mclk->drv_reg);
+
+	val = readl_relaxed(mclk->div_reg);
+	val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
+	writel_relaxed(val, mclk->div_reg);
+
+	val = readl_relaxed(mclk->clken_reg);
+	val |= 1 << mclk->clken_bit;
+	writel_relaxed(val, mclk->clken_reg);
+
+	spin_unlock_irqrestore(&mmc_clk_lock, flags);
+
+	return 0;
+}
+
+static int mmc_clk_prepare(struct clk_hw *hw)
+{
+	struct clk_mmc *mclk = to_mmc(hw);
+	unsigned long rate;
+
+	if (mclk->id == HI3620_SD_CIUCLK)
+		rate = 13000000;
+	else
+		rate = 25000000;
+
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	return mmc_clk_set_timing(hw, rate);
+}
+
+static struct clk_ops clk_mmc_ops = {
+	.prepare = mmc_clk_prepare,
+	.determine_rate = mmc_clk_determine_rate,
+	.set_rate = mmc_clk_set_rate,
+	.recalc_rate = mmc_clk_recalc_rate,
+};
+
+static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
+			void __iomem *base, struct device_node *np)
+{
+	struct clk_mmc *mclk;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+	if (!mclk) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = mmc_clk->name;
+	init.ops = &clk_mmc_ops;
+	init.flags = mmc_clk->flags | CLK_IS_BASIC;
+	init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
+	init.num_parents = (mmc_clk->parent_name ? 1 : 0);
+	mclk->hw.init = &init;
+
+	mclk->id = mmc_clk->id;
+	mclk->clken_reg = base + mmc_clk->clken_reg;
+	mclk->clken_bit = mmc_clk->clken_bit;
+	mclk->div_reg = base + mmc_clk->div_reg;
+	mclk->div_off = mmc_clk->div_off;
+	mclk->div_bits = mmc_clk->div_bits;
+	mclk->drv_reg = base + mmc_clk->drv_reg;
+	mclk->drv_off = mmc_clk->drv_off;
+	mclk->drv_bits = mmc_clk->drv_bits;
+	mclk->sam_reg = base + mmc_clk->sam_reg;
+	mclk->sam_off = mmc_clk->sam_off;
+	mclk->sam_bits = mmc_clk->sam_bits;
+
+	clk = clk_register(NULL, &mclk->hw);
+	if (WARN_ON(IS_ERR(clk)))
+		kfree(mclk);
+	return clk;
+}
+
+static void __init hi3620_mmc_clk_init(struct device_node *node)
+{
+	void __iomem *base;
+	int i, num = ARRAY_SIZE(hi3620_mmc_clks);
+	struct clk_onecell_data *clk_data;
+
+	if (!node) {
+		pr_err("failed to find pctrl node in DTS\n");
+		return;
+	}
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("failed to map pctrl\n");
+		return;
+	}
+
+	clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
+	if (WARN_ON(!clk_data))
+		return;
+
+	clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
+	if (!clk_data->clks) {
+		pr_err("%s: fail to allocate mmc clk\n", __func__);
+		return;
+	}
+
+	for (i = 0; i < num; i++) {
+		struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
+		clk_data->clks[mmc_clk->id] =
+			hisi_register_clk_mmc(mmc_clk, base, node);
+	}
+
+	clk_data->clk_num = num;
+	of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);
diff --git a/include/dt-bindings/clock/hi3620-clock.h b/include/dt-bindings/clock/hi3620-clock.h
index 6eaa6a45e110..21b9d0e2eb0c 100644
--- a/include/dt-bindings/clock/hi3620-clock.h
+++ b/include/dt-bindings/clock/hi3620-clock.h
@@ -147,6 +147,11 @@
 #define HI3620_MMC_CLK3		217
 #define HI3620_MCU_CLK		218
 
+#define HI3620_SD_CIUCLK	0
+#define HI3620_MMC_CIUCLK1	1
+#define HI3620_MMC_CIUCLK2	2
+#define HI3620_MMC_CIUCLK3	3
+
 #define HI3620_NR_CLKS		219
 
 #endif	/* __DTS_HI3620_CLOCK_H */
-- 
1.7.9.5

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

* Re: [PATCH 3/3] clk: hisilicon: add hi3620_mmc_clks
  2014-01-09 14:35   ` Zhangfei Gao
@ 2014-01-09 14:38     ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:38 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* [PATCH 3/3] clk: hisilicon: add hi3620_mmc_clks
@ 2014-01-09 14:38     ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Suggest by Arnd: abstract mmc tuning as clock behavior,
> also because different soc have different tuning method and registers.
> hi3620_mmc_clks is added to handle mmc clock specifically on hi3620.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-09 14:35   ` Zhangfei Gao
@ 2014-01-09 14:38     ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:38 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
>  drivers/mmc/host/dw_mmc.c |   48 +++++++++++++++++++++++++++++++++------------
>  1 file changed, 35 insertions(+), 13 deletions(-)

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-09 14:38     ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
> ---
>  drivers/mmc/host/dw_mmc.c |   48 +++++++++++++++++++++++++++++++++------------
>  1 file changed, 35 insertions(+), 13 deletions(-)

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-09 14:35     ` Zhangfei Gao
@ 2014-01-09 14:45       ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:45 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree, Zhigang Wang

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>

This looks basically, sorry for taking so long for the review.
I thought there were a couple of tricky bugs in there, but
discussing them on IRC showed that I was wrong about all of them.

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-09 14:45       ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-09 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 09 January 2014, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>

This looks basically, sorry for taking so long for the review.
I thought there were a couple of tricky bugs in there, but
discussing them on IRC showed that I was wrong about all of them.

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
  2014-01-09 14:35 ` Zhangfei Gao
@ 2014-01-10  3:41   ` Jaehoon Chung
  -1 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2014-01-10  3:41 UTC (permalink / raw)
  To: Zhangfei Gao, Chris Ball, Arnd Bergmann, Mike Turquette,
	Rob Herring, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree

This patchset looks good to me.

Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

On 01/09/2014 11:35 PM, Zhangfei Gao wrote:
> v7:
> 0002:
> use undefined local value in suspend/resume
> 
> v6:
> 0002:
> Jaehoon pointed HIGHSPEED cap can be omitted if supports-highspeed is defined.
> Seungwon mentioned clk operation should be called after suspend.
> Remove k3_dwmmc_caps
> 
> V5:
> 0002:
> Follow advice from Arnd, 
> Update dt descirption and use of_property_for_each_u32 to get table number.
> 
> v4:
> Follow Arnd's suggestion abstracting specific tuning to clock,
> also because new version ip use different method and not use same tuning registers.
> 
> 0001 acked by Jaehoon
> 
> v3:
> 0001: 
> Put set/clear_bit DW_MMC_CARD_PRESENT in dw_mci_get_cd, 
> Since dw_mci_request will check DW_MMC_CARD_PRESENT before sending cmd
> 
> 0002:
> Follow suggestion from Chris, Kumar and Seungwon
> Sync to latest mmc-next, which is 3.12-rc2
> Remove enum dw_mci_k3_type etc
> 
> v2:
> Follow Jaehoon's suggestion
> Use slot-gpio.c handle cd pin
> Move table out to dts
> other suggestion
> 
> 
> Zhangfei Gao (3):
>   mmc: dw_mmc: use slot-gpio to handle cd pin
>   mmc: dw_mmc: add dw_mmc-k3 for k3 platform
>   clk: hisilicon: add hi3620_mmc_clks
> 
>  .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
>  .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++
>  drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
>  drivers/mmc/host/Kconfig                           |   10 +
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++
>  drivers/mmc/host/dw_mmc.c                          |   48 +++-
>  include/dt-bindings/clock/hi3620-clock.h           |    5 +
>  9 files changed, 514 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 


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

* [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
@ 2014-01-10  3:41   ` Jaehoon Chung
  0 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2014-01-10  3:41 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset looks good to me.

Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

Best Regards,
Jaehoon Chung

On 01/09/2014 11:35 PM, Zhangfei Gao wrote:
> v7:
> 0002:
> use undefined local value in suspend/resume
> 
> v6:
> 0002:
> Jaehoon pointed HIGHSPEED cap can be omitted if supports-highspeed is defined.
> Seungwon mentioned clk operation should be called after suspend.
> Remove k3_dwmmc_caps
> 
> V5:
> 0002:
> Follow advice from Arnd, 
> Update dt descirption and use of_property_for_each_u32 to get table number.
> 
> v4:
> Follow Arnd's suggestion abstracting specific tuning to clock,
> also because new version ip use different method and not use same tuning registers.
> 
> 0001 acked by Jaehoon
> 
> v3:
> 0001: 
> Put set/clear_bit DW_MMC_CARD_PRESENT in dw_mci_get_cd, 
> Since dw_mci_request will check DW_MMC_CARD_PRESENT before sending cmd
> 
> 0002:
> Follow suggestion from Chris, Kumar and Seungwon
> Sync to latest mmc-next, which is 3.12-rc2
> Remove enum dw_mci_k3_type etc
> 
> v2:
> Follow Jaehoon's suggestion
> Use slot-gpio.c handle cd pin
> Move table out to dts
> other suggestion
> 
> 
> Zhangfei Gao (3):
>   mmc: dw_mmc: use slot-gpio to handle cd pin
>   mmc: dw_mmc: add dw_mmc-k3 for k3 platform
>   clk: hisilicon: add hi3620_mmc_clks
> 
>  .../bindings/arm/hisilicon/hisilicon.txt           |   14 ++
>  .../devicetree/bindings/clock/hi3620-clock.txt     |    1 +
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++
>  drivers/clk/hisilicon/clk-hi3620.c                 |  262 ++++++++++++++++++++
>  drivers/mmc/host/Kconfig                           |   10 +
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++
>  drivers/mmc/host/dw_mmc.c                          |   48 +++-
>  include/dt-bindings/clock/hi3620-clock.h           |    5 +
>  9 files changed, 514 insertions(+), 13 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-09 14:35     ` Zhangfei Gao
@ 2014-01-10 13:39       ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-10 13:39 UTC (permalink / raw)
  To: 'Zhangfei Gao', 'Chris Ball',
	'Arnd Bergmann', 'Mike Turquette',
	'Rob Herring', 'Jaehoon Chung',
	'Kumar Gala', 'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

Hi Zhangfei,

On Thursday, January 09, 2014, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
>  4 files changed, 203 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0@fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> +	};
> +
> +	/* Board portion */
> +	dwmmc0@fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot@0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
> 
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC
> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..68e5e428e8f6
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];

First, sorry for quick review even though your effort.
But I still worry about this change.
Currently k3 host's clock table depends on value number of SD/MMC mode value.
It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
Can you modify to mmc_clk_determine_rate() in your another patch-set?
I guess required actual target rate could be determined depending on ios->clock.

Thanks,
Seungwon Jeon

> +	int ret;
> +
> +	if (!rate) {
> +		dev_warn(host->dev,
> +			"no specified rate in timing %u\n", ios->timing);
> +		return;
> +	}
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = dw_mci_suspend(host);
> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}
> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> --
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-10 13:39       ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-10 13:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Zhangfei,

On Thursday, January 09, 2014, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
>  4 files changed, 203 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0 at fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> +	};
> +
> +	/* Board portion */
> +	dwmmc0 at fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot at 0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
> 
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC
> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..68e5e428e8f6
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,132 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];

First, sorry for quick review even though your effort.
But I still worry about this change.
Currently k3 host's clock table depends on value number of SD/MMC mode value.
It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
Can you modify to mmc_clk_determine_rate() in your another patch-set?
I guess required actual target rate could be determined depending on ios->clock.

Thanks,
Seungwon Jeon

> +	int ret;
> +
> +	if (!rate) {
> +		dev_warn(host->dev,
> +			"no specified rate in timing %u\n", ios->timing);
> +		return;
> +	}
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = dw_mci_suspend(host);
> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}
> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> --
> 1.7.9.5
> 
> --
> 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

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-10 13:39       ` Seungwon Jeon
@ 2014-01-10 14:12         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-10 14:12 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'



On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>> +	u32 rate = priv->clk_table[ios->timing];
> 
> First, sorry for quick review even though your effort.
> But I still worry about this change.
> Currently k3 host's clock table depends on value number of SD/MMC mode value.
> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> Can you modify to mmc_clk_determine_rate() in your another patch-set?
> I guess required actual target rate could be determined depending on ios->clock.
> 

No, it can not get input clock source rate simply from ios->clock, also
requied info like which controller, which mode etc.
Here is setting clock source rate, not the working clock rate.

For example, emmc init clock source rate is 13M, while sd init clock
source is 25M, it can not simply get such info from ios->clock.
And for HS200, emmc may have to set clock source rate to 104M since the
controller limitation and can not work stable as 208M.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-10 14:12         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-10 14:12 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>> +	u32 rate = priv->clk_table[ios->timing];
> 
> First, sorry for quick review even though your effort.
> But I still worry about this change.
> Currently k3 host's clock table depends on value number of SD/MMC mode value.
> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> Can you modify to mmc_clk_determine_rate() in your another patch-set?
> I guess required actual target rate could be determined depending on ios->clock.
> 

No, it can not get input clock source rate simply from ios->clock, also
requied info like which controller, which mode etc.
Here is setting clock source rate, not the working clock rate.

For example, emmc init clock source rate is 13M, while sd init clock
source is 25M, it can not simply get such info from ios->clock.
And for HS200, emmc may have to set clock source rate to 104M since the
controller limitation and can not work stable as 208M.

Thanks

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

* Re: [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
  2014-01-09 14:35 ` Zhangfei Gao
@ 2014-01-12 16:35   ` Chris Ball
  -1 siblings, 0 replies; 146+ messages in thread
From: Chris Ball @ 2014-01-12 16:35 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, patches, devicetree

Hi,

I've pushed patches 1 and 2 to mmc-next for 3.14, with Arnd and
Jaehoon's ACK -- since patch 3 depends on files that aren't in my
tree, please can you push that one through arm-soc?

Thanks,

- Chris.
-- 
Chris Ball   <chris@printf.net>   <http://printf.net/>

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

* [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
@ 2014-01-12 16:35   ` Chris Ball
  0 siblings, 0 replies; 146+ messages in thread
From: Chris Ball @ 2014-01-12 16:35 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

I've pushed patches 1 and 2 to mmc-next for 3.14, with Arnd and
Jaehoon's ACK -- since patch 3 depends on files that aren't in my
tree, please can you push that one through arm-soc?

Thanks,

- Chris.
-- 
Chris Ball   <chris@printf.net>   <http://printf.net/>

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

* Re: [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
  2014-01-12 16:35   ` Chris Ball
@ 2014-01-13  1:00     ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-13  1:00 UTC (permalink / raw)
  To: Chris Ball
  Cc: Zhangfei Gao, devicetree, Mike Turquette, Arnd Bergmann, patches,
	Seungwon Jeon, linux-mmc, Jaehoon Chung, Haojian Zhuang,
	Kumar Gala, Chris Ball, linux-arm-kernel

On Mon, Jan 13, 2014 at 12:35 AM, Chris Ball <chris@printf.net> wrote:
> Hi,
>
> I've pushed patches 1 and 2 to mmc-next for 3.14, with Arnd and
> Jaehoon's ACK -- since patch 3 depends on files that aren't in my
> tree, please can you push that one through arm-soc?

Great, thanks Chris.
The 3rd patch may need go to Mike's tree, will search Mike's help.

Thanks.

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

* [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3
@ 2014-01-13  1:00     ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-13  1:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Jan 13, 2014 at 12:35 AM, Chris Ball <chris@printf.net> wrote:
> Hi,
>
> I've pushed patches 1 and 2 to mmc-next for 3.14, with Arnd and
> Jaehoon's ACK -- since patch 3 depends on files that aren't in my
> tree, please can you push that one through arm-soc?

Great, thanks Chris.
The 3rd patch may need go to Mike's tree, will search Mike's help.

Thanks.

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-10 14:12         ` zhangfei
@ 2014-01-13  2:09           ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-13  2:09 UTC (permalink / raw)
  To: 'zhangfei', 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

On Fri, January 10, 2014, Zhangfei Gao wrote:
> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
> >> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >> +{
> >> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >> +	u32 rate = priv->clk_table[ios->timing];
> >
> > First, sorry for quick review even though your effort.
> > But I still worry about this change.
> > Currently k3 host's clock table depends on value number of SD/MMC mode value.
> > It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> > Can you modify to mmc_clk_determine_rate() in your another patch-set?
> > I guess required actual target rate could be determined depending on ios->clock.
> >
> 
> No, it can not get input clock source rate simply from ios->clock, also
> requied info like which controller, which mode etc.
> Here is setting clock source rate, not the working clock rate.
> 
> For example, emmc init clock source rate is 13M, while sd init clock
> source is 25M, it can not simply get such info from ios->clock.
> And for HS200, emmc may have to set clock source rate to 104M since the
> controller limitation and can not work stable as 208M.

Yes, clock table is source clock rate, not actual working clock rate.
I was not saying that 'ios->clock' would be used for source clock directly.
I meant that you can adjust the source clock rate depending on 'ios->clock'.
You've already done with clock table similarly in mmc_clk_determine_rate().

For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
Also, 'ios->clock' with 400KHz or less may be passed for init clock.
If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
If it should be considered with other conditions, please let me know.

Thanks,
Seungwon Jeon


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-13  2:09           ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-13  2:09 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, January 10, 2014, Zhangfei Gao wrote:
> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
> >> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >> +{
> >> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >> +	u32 rate = priv->clk_table[ios->timing];
> >
> > First, sorry for quick review even though your effort.
> > But I still worry about this change.
> > Currently k3 host's clock table depends on value number of SD/MMC mode value.
> > It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> > Can you modify to mmc_clk_determine_rate() in your another patch-set?
> > I guess required actual target rate could be determined depending on ios->clock.
> >
> 
> No, it can not get input clock source rate simply from ios->clock, also
> requied info like which controller, which mode etc.
> Here is setting clock source rate, not the working clock rate.
> 
> For example, emmc init clock source rate is 13M, while sd init clock
> source is 25M, it can not simply get such info from ios->clock.
> And for HS200, emmc may have to set clock source rate to 104M since the
> controller limitation and can not work stable as 208M.

Yes, clock table is source clock rate, not actual working clock rate.
I was not saying that 'ios->clock' would be used for source clock directly.
I meant that you can adjust the source clock rate depending on 'ios->clock'.
You've already done with clock table similarly in mmc_clk_determine_rate().

For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
Also, 'ios->clock' with 400KHz or less may be passed for init clock.
If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
If it should be considered with other conditions, please let me know.

Thanks,
Seungwon Jeon

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-13  2:09           ` Seungwon Jeon
@ 2014-01-13  2:37             ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-13  2:37 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'



On 01/13/2014 10:09 AM, Seungwon Jeon wrote:
> On Fri, January 10, 2014, Zhangfei Gao wrote:
>> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>> +{
>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>>> +	u32 rate = priv->clk_table[ios->timing];
>>>
>>> First, sorry for quick review even though your effort.
>>> But I still worry about this change.
>>> Currently k3 host's clock table depends on value number of SD/MMC mode value.
>>> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
>>> Can you modify to mmc_clk_determine_rate() in your another patch-set?
>>> I guess required actual target rate could be determined depending on ios->clock.
>>>
>>
>> No, it can not get input clock source rate simply from ios->clock, also
>> requied info like which controller, which mode etc.
>> Here is setting clock source rate, not the working clock rate.
>>
>> For example, emmc init clock source rate is 13M, while sd init clock
>> source is 25M, it can not simply get such info from ios->clock.
>> And for HS200, emmc may have to set clock source rate to 104M since the
>> controller limitation and can not work stable as 208M.
> 
> Yes, clock table is source clock rate, not actual working clock rate.
> I was not saying that 'ios->clock' would be used for source clock directly.
> I meant that you can adjust the source clock rate depending on 'ios->clock'.
> You've already done with clock table similarly in mmc_clk_determine_rate().
> 
> For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
> And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
> Also, 'ios->clock' with 400KHz or less may be passed for init clock.
> If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
> If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
> If it should be considered with other conditions, please let me know.

However, I am afraid this will make things complicated rather than
simplified.

The function mmc_clk_determine_rate() will need the info which
controller it is, what's the init clock rate, what's the max clock rate,
and what's the limitation, which may be different as different soc, and
can not be hardcoded.
The limitation may in HS200 and SDR104 mode.

The plan is only input init rate and max rate instead of the table,
while others directly use ios->clock, only if the the limitation resolved.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-13  2:37             ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-13  2:37 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/13/2014 10:09 AM, Seungwon Jeon wrote:
> On Fri, January 10, 2014, Zhangfei Gao wrote:
>> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>> +{
>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>>> +	u32 rate = priv->clk_table[ios->timing];
>>>
>>> First, sorry for quick review even though your effort.
>>> But I still worry about this change.
>>> Currently k3 host's clock table depends on value number of SD/MMC mode value.
>>> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
>>> Can you modify to mmc_clk_determine_rate() in your another patch-set?
>>> I guess required actual target rate could be determined depending on ios->clock.
>>>
>>
>> No, it can not get input clock source rate simply from ios->clock, also
>> requied info like which controller, which mode etc.
>> Here is setting clock source rate, not the working clock rate.
>>
>> For example, emmc init clock source rate is 13M, while sd init clock
>> source is 25M, it can not simply get such info from ios->clock.
>> And for HS200, emmc may have to set clock source rate to 104M since the
>> controller limitation and can not work stable as 208M.
> 
> Yes, clock table is source clock rate, not actual working clock rate.
> I was not saying that 'ios->clock' would be used for source clock directly.
> I meant that you can adjust the source clock rate depending on 'ios->clock'.
> You've already done with clock table similarly in mmc_clk_determine_rate().
> 
> For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
> And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
> Also, 'ios->clock' with 400KHz or less may be passed for init clock.
> If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
> If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
> If it should be considered with other conditions, please let me know.

However, I am afraid this will make things complicated rather than
simplified.

The function mmc_clk_determine_rate() will need the info which
controller it is, what's the init clock rate, what's the max clock rate,
and what's the limitation, which may be different as different soc, and
can not be hardcoded.
The limitation may in HS200 and SDR104 mode.

The plan is only input init rate and max rate instead of the table,
while others directly use ios->clock, only if the the limitation resolved.

Thanks

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-13  2:37             ` zhangfei
@ 2014-01-13  5:32               ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-13  5:32 UTC (permalink / raw)
  To: 'zhangfei', 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: devicetree, 'Zhigang Wang', linux-mmc, linux-arm-kernel, patches

On Mon, January 13, 2014, zhangfei wrote:
> On 01/13/2014 10:09 AM, Seungwon Jeon wrote:
> > On Fri, January 10, 2014, Zhangfei Gao wrote:
> >> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
> >>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >>>> +{
> >>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >>>> +	u32 rate = priv->clk_table[ios->timing];
> >>>
> >>> First, sorry for quick review even though your effort.
> >>> But I still worry about this change.
> >>> Currently k3 host's clock table depends on value number of SD/MMC mode value.
> >>> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> >>> Can you modify to mmc_clk_determine_rate() in your another patch-set?
> >>> I guess required actual target rate could be determined depending on ios->clock.
> >>>
> >>
> >> No, it can not get input clock source rate simply from ios->clock, also
> >> requied info like which controller, which mode etc.
> >> Here is setting clock source rate, not the working clock rate.
> >>
> >> For example, emmc init clock source rate is 13M, while sd init clock
> >> source is 25M, it can not simply get such info from ios->clock.
> >> And for HS200, emmc may have to set clock source rate to 104M since the
> >> controller limitation and can not work stable as 208M.
> >
> > Yes, clock table is source clock rate, not actual working clock rate.
> > I was not saying that 'ios->clock' would be used for source clock directly.
> > I meant that you can adjust the source clock rate depending on 'ios->clock'.
> > You've already done with clock table similarly in mmc_clk_determine_rate().
> >
> > For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
> > And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
> > Also, 'ios->clock' with 400KHz or less may be passed for init clock.
> > If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
> > If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
> > If it should be considered with other conditions, please let me know.
> 
> However, I am afraid this will make things complicated rather than
> simplified.
> 
> The function mmc_clk_determine_rate() will need the info which
> controller it is, what's the init clock rate, what's the max clock rate,
> and what's the limitation, which may be different as different soc, and
> can not be hardcoded.
> The limitation may in HS200 and SDR104 mode.
> 
> The plan is only input init rate and max rate instead of the table,
> while others directly use ios->clock, only if the the limitation resolved.

Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
Currently only hi3620 has been introduced.
If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock enough.
I feel like clock table is redundant.
Ok. It's just my suggestion.  But I still point dependency of mode index number.
K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
If new mode is added or modified, it should be considered and also may make complicated.

Thanks,
Seungwon Jeon

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-13  5:32               ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-13  5:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, January 13, 2014, zhangfei wrote:
> On 01/13/2014 10:09 AM, Seungwon Jeon wrote:
> > On Fri, January 10, 2014, Zhangfei Gao wrote:
> >> On 01/10/2014 09:39 PM, Seungwon Jeon wrote:
> >>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >>>> +{
> >>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >>>> +	u32 rate = priv->clk_table[ios->timing];
> >>>
> >>> First, sorry for quick review even though your effort.
> >>> But I still worry about this change.
> >>> Currently k3 host's clock table depends on value number of SD/MMC mode value.
> >>> It seems close to identifier for eachg mode. I think it's not good way to use as table's index.
> >>> Can you modify to mmc_clk_determine_rate() in your another patch-set?
> >>> I guess required actual target rate could be determined depending on ios->clock.
> >>>
> >>
> >> No, it can not get input clock source rate simply from ios->clock, also
> >> requied info like which controller, which mode etc.
> >> Here is setting clock source rate, not the working clock rate.
> >>
> >> For example, emmc init clock source rate is 13M, while sd init clock
> >> source is 25M, it can not simply get such info from ios->clock.
> >> And for HS200, emmc may have to set clock source rate to 104M since the
> >> controller limitation and can not work stable as 208M.
> >
> > Yes, clock table is source clock rate, not actual working clock rate.
> > I was not saying that 'ios->clock' would be used for source clock directly.
> > I meant that you can adjust the source clock rate depending on 'ios->clock'.
> > You've already done with clock table similarly in mmc_clk_determine_rate().
> >
> > For example, in case of HS200, 'ios->clock' will be passed with 200MHz.
> > And then, mmc_clk_determine_rate() can set the 'rate & best' to 100000000 and 720000000 respectively.
> > Also, 'ios->clock' with 400KHz or less may be passed for init clock.
> > If clock id is HI3620_SD_CIUCLK, 'rate & best' can be selected with 13000000 and 26000000.
> > If not and it's case of MMC,  'rate & best' can be selected with 25000000 and 180000000.
> > If it should be considered with other conditions, please let me know.
> 
> However, I am afraid this will make things complicated rather than
> simplified.
> 
> The function mmc_clk_determine_rate() will need the info which
> controller it is, what's the init clock rate, what's the max clock rate,
> and what's the limitation, which may be different as different soc, and
> can not be hardcoded.
> The limitation may in HS200 and SDR104 mode.
> 
> The plan is only input init rate and max rate instead of the table,
> while others directly use ios->clock, only if the the limitation resolved.

Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
Currently only hi3620 has been introduced.
If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock enough.
I feel like clock table is redundant.
Ok. It's just my suggestion.  But I still point dependency of mode index number.
K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
If new mode is added or modified, it should be considered and also may make complicated.

Thanks,
Seungwon Jeon

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-13  5:32               ` Seungwon Jeon
@ 2014-01-13  8:30                 ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-13  8:30 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

Dear Seungwon

On 01/13/2014 01:32 PM, Seungwon Jeon wrote:
>>>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>>>> +{
>>>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>>>>> +	u32 rate = priv->clk_table[ios->timing];
>>>>>

>>
>> The function mmc_clk_determine_rate() will need the info which
>> controller it is, what's the init clock rate, what's the max clock rate,
>> and what's the limitation, which may be different as different soc, and
>> can not be hardcoded.
>> The limitation may in HS200 and SDR104 mode.
>>
>> The plan is only input init rate and max rate instead of the table,
>> while others directly use ios->clock, only if the the limitation resolved.
> 
> Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
> Currently only hi3620 has been introduced.
> If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock enough.
> I feel like clock table is redundant.
> Ok. It's just my suggestion.  But I still point dependency of mode index number.
> K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
> If new mode is added or modified, it should be considered and also may make complicated.
> 

Looks like you dislike the clk_table very much :)

Double checked with the silicon guy, currently it is said the limitation
in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
replaced with ios->clock directly, though they have concern it is not so
convinent when removing clk_table in case limitation rate is not equal
to max_rate again in future.

Will update accordingly, thanks for the suggestion.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-13  8:30                 ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-13  8:30 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Seungwon

On 01/13/2014 01:32 PM, Seungwon Jeon wrote:
>>>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>>>> +{
>>>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>>>>> +	u32 rate = priv->clk_table[ios->timing];
>>>>>

>>
>> The function mmc_clk_determine_rate() will need the info which
>> controller it is, what's the init clock rate, what's the max clock rate,
>> and what's the limitation, which may be different as different soc, and
>> can not be hardcoded.
>> The limitation may in HS200 and SDR104 mode.
>>
>> The plan is only input init rate and max rate instead of the table,
>> while others directly use ios->clock, only if the the limitation resolved.
> 
> Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
> Currently only hi3620 has been introduced.
> If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock enough.
> I feel like clock table is redundant.
> Ok. It's just my suggestion.  But I still point dependency of mode index number.
> K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
> If new mode is added or modified, it should be considered and also may make complicated.
> 

Looks like you dislike the clk_table very much :)

Double checked with the silicon guy, currently it is said the limitation
in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
replaced with ios->clock directly, though they have concern it is not so
convinent when removing clk_table in case limitation rate is not equal
to max_rate again in future.

Will update accordingly, thanks for the suggestion.

Thanks

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-13  8:30                 ` zhangfei
@ 2014-01-14  9:38                   ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-14  9:38 UTC (permalink / raw)
  To: 'zhangfei', 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

On Mon, January 13, 2014, Zhangfei Gao wrote:
> Dear Seungwon
> 
> On 01/13/2014 01:32 PM, Seungwon Jeon wrote:
> >>>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >>>>>> +{
> >>>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >>>>>> +	u32 rate = priv->clk_table[ios->timing];
> >>>>>
> 
> >>
> >> The function mmc_clk_determine_rate() will need the info which
> >> controller it is, what's the init clock rate, what's the max clock rate,
> >> and what's the limitation, which may be different as different soc, and
> >> can not be hardcoded.
> >> The limitation may in HS200 and SDR104 mode.
> >>
> >> The plan is only input init rate and max rate instead of the table,
> >> while others directly use ios->clock, only if the the limitation resolved.
> >
> > Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
> > Currently only hi3620 has been introduced.
> > If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock
> enough.
> > I feel like clock table is redundant.
> > Ok. It's just my suggestion.  But I still point dependency of mode index number.
> > K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
> > If new mode is added or modified, it should be considered and also may make complicated.
> >
> 
> Looks like you dislike the clk_table very much :)
Oh, I just want to remove dependency as I mentioned.

> 
> Double checked with the silicon guy, currently it is said the limitation
> in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
> replaced with ios->clock directly, though they have concern it is not so
> convinent when removing clk_table in case limitation rate is not equal
> to max_rate again in future.
I guess specific clock handling(clk-hi3620.c) can adjust required source clock rate.

> 
> Will update accordingly, thanks for the suggestion.
Thank you for consideration.

Thanks,
Seungwon Jeon


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-14  9:38                   ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-14  9:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, January 13, 2014, Zhangfei Gao wrote:
> Dear Seungwon
> 
> On 01/13/2014 01:32 PM, Seungwon Jeon wrote:
> >>>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> >>>>>> +{
> >>>>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
> >>>>>> +	u32 rate = priv->clk_table[ios->timing];
> >>>>>
> 
> >>
> >> The function mmc_clk_determine_rate() will need the info which
> >> controller it is, what's the init clock rate, what's the max clock rate,
> >> and what's the limitation, which may be different as different soc, and
> >> can not be hardcoded.
> >> The limitation may in HS200 and SDR104 mode.
> >>
> >> The plan is only input init rate and max rate instead of the table,
> >> while others directly use ios->clock, only if the the limitation resolved.
> >
> > Handling mmc clock for hi3620 is in drivers/clk/hisilicon/clk-hi3620.c, right?
> > Currently only hi3620 has been introduced.
> > If hi3620's host has a limitation, clk-hi3620.c can handle clock range(init, max) for source clock
> enough.
> > I feel like clock table is redundant.
> > Ok. It's just my suggestion.  But I still point dependency of mode index number.
> > K3's clock table refers and depends mode definition value from include/linux/mmc/host.h
> > If new mode is added or modified, it should be considered and also may make complicated.
> >
> 
> Looks like you dislike the clk_table very much :)
Oh, I just want to remove dependency as I mentioned.

> 
> Double checked with the silicon guy, currently it is said the limitation
> in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
> replaced with ios->clock directly, though they have concern it is not so
> convinent when removing clk_table in case limitation rate is not equal
> to max_rate again in future.
I guess specific clock handling(clk-hi3620.c) can adjust required source clock rate.

> 
> Will update accordingly, thanks for the suggestion.
Thank you for consideration.

Thanks,
Seungwon Jeon

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2014-01-14  9:38                   ` Seungwon Jeon
@ 2014-01-14  9:47                     ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-14  9:47 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

Dear Seungwon

On 01/14/2014 05:38 PM, Seungwon Jeon wrote:

>> Looks like you dislike the clk_table very much :)
> Oh, I just want to remove dependency as I mentioned.
> 
>>
>> Double checked with the silicon guy, currently it is said the limitation
>> in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
>> replaced with ios->clock directly, though they have concern it is not so
>> convinent when removing clk_table in case limitation rate is not equal
>> to max_rate again in future.
> I guess specific clock handling(clk-hi3620.c) can adjust required source clock rate.
> 
It is doable now since the soc has been updated with the limitation,
which can reuse max_rate now.
The patch "mmc: dw_mmc: k3 remove clk_table" has been updated, and have
modified clk-hi3620.c accordingly.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-14  9:47                     ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-14  9:47 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Seungwon

On 01/14/2014 05:38 PM, Seungwon Jeon wrote:

>> Looks like you dislike the clk_table very much :)
> Oh, I just want to remove dependency as I mentioned.
> 
>>
>> Double checked with the silicon guy, currently it is said the limitation
>> in HS200 and SDR104 can be replaced by the max_rate, so clk_table can be
>> replaced with ios->clock directly, though they have concern it is not so
>> convinent when removing clk_table in case limitation rate is not equal
>> to max_rate again in future.
> I guess specific clock handling(clk-hi3620.c) can adjust required source clock rate.
> 
It is doable now since the soc has been updated with the limitation,
which can reuse max_rate now.
The patch "mmc: dw_mmc: k3 remove clk_table" has been updated, and have
modified clk-hi3620.c accordingly.

Thanks

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

* Re: [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-09 14:35   ` Zhangfei Gao
@ 2014-01-14 15:58     ` Kevin Hilman
  -1 siblings, 0 replies; 146+ messages in thread
From: Kevin Hilman @ 2014-01-14 15:58 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, Patch Tracking, devicetree,
	Olof Johansson, Tomasz Figa

On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

The Samsung Arndale board started failing boot from MMC root tests
starting with next-20140113 and I bisected it down to this patch.
Reverting this patch on top of next-20140114 gets Arndale booting
again from MMC.  Is there some supporting DT data that's missing for
Arndale?

Kevin

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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-14 15:58     ` Kevin Hilman
  0 siblings, 0 replies; 146+ messages in thread
From: Kevin Hilman @ 2014-01-14 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>

The Samsung Arndale board started failing boot from MMC root tests
starting with next-20140113 and I bisected it down to this patch.
Reverting this patch on top of next-20140114 gets Arndale booting
again from MMC.  Is there some supporting DT data that's missing for
Arndale?

Kevin

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

* Re: [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-14 15:58     ` Kevin Hilman
@ 2014-01-14 17:23       ` Olof Johansson
  -1 siblings, 0 replies; 146+ messages in thread
From: Olof Johansson @ 2014-01-14 17:23 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Zhangfei Gao, Chris Ball, Arnd Bergmann, Mike Turquette,
	Rob Herring, Jaehoon Chung, Seungwon Jeon, Kumar Gala,
	Haojian Zhuang, linux-mmc, linux-arm-kernel, Patch Tracking,
	devicetree, Tomasz Figa

On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> The Samsung Arndale board started failing boot from MMC root tests
> starting with next-20140113 and I bisected it down to this patch.
> Reverting this patch on top of next-20140114 gets Arndale booting
> again from MMC.  Is there some supporting DT data that's missing for
> Arndale?

Rather, it looks like this patch changes behaviour and no longer uses
dw_mci_get_cd() to find out if there's a card attached -- it switches
to rely only on GPIO (see the last chunk in the patch). That seems
broken?


-Olof

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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-14 17:23       ` Olof Johansson
  0 siblings, 0 replies; 146+ messages in thread
From: Olof Johansson @ 2014-01-14 17:23 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>
> The Samsung Arndale board started failing boot from MMC root tests
> starting with next-20140113 and I bisected it down to this patch.
> Reverting this patch on top of next-20140114 gets Arndale booting
> again from MMC.  Is there some supporting DT data that's missing for
> Arndale?

Rather, it looks like this patch changes behaviour and no longer uses
dw_mci_get_cd() to find out if there's a card attached -- it switches
to rely only on GPIO (see the last chunk in the patch). That seems
broken?


-Olof

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

* Re: [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-14 17:23       ` Olof Johansson
@ 2014-01-15  1:09         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  1:09 UTC (permalink / raw)
  To: Olof Johansson, Kevin Hilman
  Cc: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, Patch Tracking, devicetree,
	Tomasz Figa



On 01/15/2014 01:23 AM, Olof Johansson wrote:
> On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
>> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
>>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>>
>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>
>> The Samsung Arndale board started failing boot from MMC root tests
>> starting with next-20140113 and I bisected it down to this patch.
>> Reverting this patch on top of next-20140114 gets Arndale booting
>> again from MMC.  Is there some supporting DT data that's missing for
>> Arndale?
>
> Rather, it looks like this patch changes behaviour and no longer uses
> dw_mci_get_cd() to find out if there's a card attached -- it switches
> to rely only on GPIO (see the last chunk in the patch). That seems
> broken?
>
Oops,
Change using dw_mci_get_cd set flag DW_MMC_CARD_PRESENT.
And dw_mci_get_cd is called from mmc_rescan, a litter later than 
dw_mci_probe.
Is that too late?

Thanks

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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-15  1:09         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  1:09 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/15/2014 01:23 AM, Olof Johansson wrote:
> On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
>> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao <zhangfei.gao@linaro.org> wrote:
>>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>>
>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>
>> The Samsung Arndale board started failing boot from MMC root tests
>> starting with next-20140113 and I bisected it down to this patch.
>> Reverting this patch on top of next-20140114 gets Arndale booting
>> again from MMC.  Is there some supporting DT data that's missing for
>> Arndale?
>
> Rather, it looks like this patch changes behaviour and no longer uses
> dw_mci_get_cd() to find out if there's a card attached -- it switches
> to rely only on GPIO (see the last chunk in the patch). That seems
> broken?
>
Oops,
Change using dw_mci_get_cd set flag DW_MMC_CARD_PRESENT.
And dw_mci_get_cd is called from mmc_rescan, a litter later than 
dw_mci_probe.
Is that too late?

Thanks

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

* Re: [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
  2014-01-15  1:09         ` zhangfei
@ 2014-01-15  5:16           ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  5:16 UTC (permalink / raw)
  To: Olof Johansson, Kevin Hilman
  Cc: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, Patch Tracking, devicetree,
	Tomasz Figa

Dear Kevin

On 01/15/2014 09:09 AM, zhangfei wrote:
>
>
> On 01/15/2014 01:23 AM, Olof Johansson wrote:
>> On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
>>> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao
>>> <zhangfei.gao@linaro.org> wrote:
>>>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>>>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>>>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>>
>>> The Samsung Arndale board started failing boot from MMC root tests
>>> starting with next-20140113 and I bisected it down to this patch.
>>> Reverting this patch on top of next-20140114 gets Arndale booting
>>> again from MMC.  Is there some supporting DT data that's missing for
>>> Arndale?
>>
>> Rather, it looks like this patch changes behaviour and no longer uses
>> dw_mci_get_cd() to find out if there's a card attached -- it switches
>> to rely only on GPIO (see the last chunk in the patch). That seems
>> broken?
>>
> Oops,
> Change using dw_mci_get_cd set flag DW_MMC_CARD_PRESENT.
> And dw_mci_get_cd is called from mmc_rescan, a litter later than
> dw_mci_probe.
> Is that too late?

Should have found the issue, CDETECT is ignored since IS_ERR_VALUE does 
not workable to !mmc_gpio_get_cd(mmc), which used for adding debounce.
Sorry for that.

However, with this change the debounce seems not stable as before.
In the test of plug-in-out, sometimes sd detect will return timeout 
although present indicates as 1, while next time it can be detected again.
Still want to check more.


diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..f1683ba194ee 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
         int present;
         struct dw_mci_slot *slot = mmc_priv(mmc);
         struct dw_mci_board *brd = slot->host->pdata;
-       int gpio_cd = !mmc_gpio_get_cd(mmc);
+       int gpio_cd = mmc_gpio_get_cd(mmc);

         /* Use platform get_cd function, else try onboard card detect */
         if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,7 +1041,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
         else if (brd->get_cd)
                 present = !brd->get_cd(slot->id);
         else if (!IS_ERR_VALUE(gpio_cd))
-               present = !!gpio_cd;
+               present = !gpio_cd;
         else
                 present = (mci_readl(slot->host, CDETECT) & (1 << 
slot->id))
                         == 0 ? 1 : 0;


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

* [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin
@ 2014-01-15  5:16           ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  5:16 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Kevin

On 01/15/2014 09:09 AM, zhangfei wrote:
>
>
> On 01/15/2014 01:23 AM, Olof Johansson wrote:
>> On Tue, Jan 14, 2014 at 7:58 AM, Kevin Hilman <khilman@linaro.org> wrote:
>>> On Thu, Jan 9, 2014 at 6:35 AM, Zhangfei Gao
>>> <zhangfei.gao@linaro.org> wrote:
>>>> Suggested by Jaehoon: Use slot-gpio to handle cd-gpio
>>>> Add function dw_mci_of_get_cd_gpio to check "cd-gpios" from dts.
>>>> mmc_gpio_request_cd and mmc_gpio_get_cd are used to handle cd pin
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
>>>
>>> The Samsung Arndale board started failing boot from MMC root tests
>>> starting with next-20140113 and I bisected it down to this patch.
>>> Reverting this patch on top of next-20140114 gets Arndale booting
>>> again from MMC.  Is there some supporting DT data that's missing for
>>> Arndale?
>>
>> Rather, it looks like this patch changes behaviour and no longer uses
>> dw_mci_get_cd() to find out if there's a card attached -- it switches
>> to rely only on GPIO (see the last chunk in the patch). That seems
>> broken?
>>
> Oops,
> Change using dw_mci_get_cd set flag DW_MMC_CARD_PRESENT.
> And dw_mci_get_cd is called from mmc_rescan, a litter later than
> dw_mci_probe.
> Is that too late?

Should have found the issue, CDETECT is ignored since IS_ERR_VALUE does 
not workable to !mmc_gpio_get_cd(mmc), which used for adding debounce.
Sorry for that.

However, with this change the debounce seems not stable as before.
In the test of plug-in-out, sometimes sd detect will return timeout 
although present indicates as 1, while next time it can be detected again.
Still want to check more.


diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..f1683ba194ee 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
         int present;
         struct dw_mci_slot *slot = mmc_priv(mmc);
         struct dw_mci_board *brd = slot->host->pdata;
-       int gpio_cd = !mmc_gpio_get_cd(mmc);
+       int gpio_cd = mmc_gpio_get_cd(mmc);

         /* Use platform get_cd function, else try onboard card detect */
         if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,7 +1041,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
         else if (brd->get_cd)
                 present = !brd->get_cd(slot->id);
         else if (!IS_ERR_VALUE(gpio_cd))
-               present = !!gpio_cd;
+               present = !gpio_cd;
         else
                 present = (mci_readl(slot->host, CDETECT) & (1 << 
slot->id))
                         == 0 ? 1 : 0;

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-14 15:58     ` Kevin Hilman
@ 2014-01-15  7:15       ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15  7:15 UTC (permalink / raw)
  To: Kevin Hilman, Chris Ball, Arnd Bergmann, Mike Turquette,
	Jaehoon Chung, Seungwon Jeon, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, Zhangfei Gao

Introdeced from commit b7db86adfa58b
CDETECT is ingored since IS_ERR_VALUE(!mmc_gpio_get_cd(mmc)) does not work
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
---
 drivers/mmc/host/dw_mmc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..9ded62c8225e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = !gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
-- 
1.7.9.5


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15  7:15       ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15  7:15 UTC (permalink / raw)
  To: linux-arm-kernel

Introdeced from commit b7db86adfa58b
CDETECT is ingored since IS_ERR_VALUE(!mmc_gpio_get_cd(mmc)) does not work
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
---
 drivers/mmc/host/dw_mmc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..9ded62c8225e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = !gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
-- 
1.7.9.5

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15  7:15       ` Zhangfei Gao
@ 2014-01-15  7:31         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  7:31 UTC (permalink / raw)
  To: Zhangfei Gao, Kevin Hilman, Chris Ball, Arnd Bergmann,
	Mike Turquette, Jaehoon Chung, Seungwon Jeon, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches

Hi Kevin

Would you mind check whehter this patch solve the issue of "The Samsung 
Arndale board started failing boot from MMC".

I am sorry about that.

On 01/15/2014 03:15 PM, Zhangfei Gao wrote:
> Introdeced from commit b7db86adfa58b
commit should be bf626e5550f24aec24975a0e85ad8e572ca76a6b, from mmc-next

> CDETECT is ingored since IS_ERR_VALUE(!mmc_gpio_get_cd(mmc)) does not work
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> ---
>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
>   1 file changed, 6 insertions(+), 3 deletions(-)


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15  7:31         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Kevin

Would you mind check whehter this patch solve the issue of "The Samsung 
Arndale board started failing boot from MMC".

I am sorry about that.

On 01/15/2014 03:15 PM, Zhangfei Gao wrote:
> Introdeced from commit b7db86adfa58b
commit should be bf626e5550f24aec24975a0e85ad8e572ca76a6b, from mmc-next

> CDETECT is ingored since IS_ERR_VALUE(!mmc_gpio_get_cd(mmc)) does not work
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> ---
>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
>   1 file changed, 6 insertions(+), 3 deletions(-)

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15  7:15       ` Zhangfei Gao
@ 2014-01-15 10:07         ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15 10:07 UTC (permalink / raw)
  To: Kevin Hilman, Sachin Kamat, Chris Ball, Arnd Bergmann,
	Mike Turquette, Jaehoon Chung, Seungwon Jeon
  Cc: linux-mmc, linux-arm-kernel, patches, Zhangfei Gao

Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
can not be checked by IS_ERR_VALUE.
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
otherwise sd detect may occasionally fail.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
---
 drivers/mmc/host/dw_mmc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..9ded62c8225e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = !gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
-- 
1.7.9.5


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 10:07         ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
can not be checked by IS_ERR_VALUE.
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
otherwise sd detect may occasionally fail.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
---
 drivers/mmc/host/dw_mmc.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..9ded62c8225e 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = !gpio_cd;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
-- 
1.7.9.5

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

* RE: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 10:07         ` Zhangfei Gao
@ 2014-01-15 11:58           ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 11:58 UTC (permalink / raw)
  To: 'Zhangfei Gao', 'Kevin Hilman',
	'Sachin Kamat', 'Chris Ball',
	'Arnd Bergmann', 'Mike Turquette',
	'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches

On Wed, January 15, 2014, Zhangfei Gao wrote:
> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> can not be checked by IS_ERR_VALUE.
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> otherwise sd detect may occasionally fail.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
>  drivers/mmc/host/dw_mmc.c |    9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a776f24f4311..9ded62c8225e 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	int present;
>  	struct dw_mci_slot *slot = mmc_priv(mmc);
>  	struct dw_mci_board *brd = slot->host->pdata;
> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> +	struct dw_mci *host = slot->host;
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> 
>  	/* Use platform get_cd function, else try onboard card detect */
>  	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	else if (brd->get_cd)
>  		present = !brd->get_cd(slot->id);
>  	else if (!IS_ERR_VALUE(gpio_cd))
> -		present = !!gpio_cd;
> +		present = !gpio_cd;
!!gpio_cd or gpio_cd is correct, isn't it?

Thanks,
Seungwon Jeon

>  	else
>  		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
>  			== 0 ? 1 : 0;
> 
> +	spin_lock_bh(&host->lock);
>  	if (present) {
>  		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>  		dev_dbg(&mmc->class_dev, "card is present\n");
> @@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>  		dev_dbg(&mmc->class_dev, "card is not present\n");
>  	}
> +	spin_unlock_bh(&host->lock);
> 
>  	return present;
>  }
> @@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
>  	return gpio;
>  }
> 
> -/* find the cd gpio for a given slot; or -1 if none specified */
> +/* find the cd gpio for a given slot */
>  static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
>  					struct mmc_host *mmc)
>  {
> --
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 11:58           ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 11:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, January 15, 2014, Zhangfei Gao wrote:
> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> can not be checked by IS_ERR_VALUE.
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> otherwise sd detect may occasionally fail.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
>  drivers/mmc/host/dw_mmc.c |    9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a776f24f4311..9ded62c8225e 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	int present;
>  	struct dw_mci_slot *slot = mmc_priv(mmc);
>  	struct dw_mci_board *brd = slot->host->pdata;
> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> +	struct dw_mci *host = slot->host;
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> 
>  	/* Use platform get_cd function, else try onboard card detect */
>  	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	else if (brd->get_cd)
>  		present = !brd->get_cd(slot->id);
>  	else if (!IS_ERR_VALUE(gpio_cd))
> -		present = !!gpio_cd;
> +		present = !gpio_cd;
!!gpio_cd or gpio_cd is correct, isn't it?

Thanks,
Seungwon Jeon

>  	else
>  		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
>  			== 0 ? 1 : 0;
> 
> +	spin_lock_bh(&host->lock);
>  	if (present) {
>  		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>  		dev_dbg(&mmc->class_dev, "card is present\n");
> @@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
>  		dev_dbg(&mmc->class_dev, "card is not present\n");
>  	}
> +	spin_unlock_bh(&host->lock);
> 
>  	return present;
>  }
> @@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
>  	return gpio;
>  }
> 
> -/* find the cd gpio for a given slot; or -1 if none specified */
> +/* find the cd gpio for a given slot */
>  static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
>  					struct mmc_host *mmc)
>  {
> --
> 1.7.9.5
> 
> --
> 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

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 11:58           ` Seungwon Jeon
@ 2014-01-15 12:10             ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 12:10 UTC (permalink / raw)
  To: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches



On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> On Wed, January 15, 2014, Zhangfei Gao wrote:
>> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
>> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
>> can not be checked by IS_ERR_VALUE.
>> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
>> otherwise sd detect may occasionally fail.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Reported-by: Kevin Hilman <khilman@linaro.org>
>> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
>> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
>> ---
>>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
>>   1 file changed, 6 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index a776f24f4311..9ded62c8225e 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>   	int present;
>>   	struct dw_mci_slot *slot = mmc_priv(mmc);
>>   	struct dw_mci_board *brd = slot->host->pdata;
>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
>> +	struct dw_mci *host = slot->host;
>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>>
>>   	/* Use platform get_cd function, else try onboard card detect */
>>   	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>   	else if (brd->get_cd)
>>   		present = !brd->get_cd(slot->id);
>>   	else if (!IS_ERR_VALUE(gpio_cd))
>> -		present = !!gpio_cd;
>> +		present = !gpio_cd;
> !!gpio_cd or gpio_cd is correct, isn't it?
>

No, mmc_gpio_get_cd(mmc) has to revert.
!!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
before.

Thanks

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 12:10             ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 12:10 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> On Wed, January 15, 2014, Zhangfei Gao wrote:
>> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
>> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
>> can not be checked by IS_ERR_VALUE.
>> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
>> otherwise sd detect may occasionally fail.
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Reported-by: Kevin Hilman <khilman@linaro.org>
>> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
>> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
>> ---
>>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
>>   1 file changed, 6 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index a776f24f4311..9ded62c8225e 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>   	int present;
>>   	struct dw_mci_slot *slot = mmc_priv(mmc);
>>   	struct dw_mci_board *brd = slot->host->pdata;
>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
>> +	struct dw_mci *host = slot->host;
>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>>
>>   	/* Use platform get_cd function, else try onboard card detect */
>>   	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>   	else if (brd->get_cd)
>>   		present = !brd->get_cd(slot->id);
>>   	else if (!IS_ERR_VALUE(gpio_cd))
>> -		present = !!gpio_cd;
>> +		present = !gpio_cd;
> !!gpio_cd or gpio_cd is correct, isn't it?
>

No, mmc_gpio_get_cd(mmc) has to revert.
!!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
before.

Thanks

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

* RE: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 12:10             ` zhangfei
@ 2014-01-15 12:26               ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 12:26 UTC (permalink / raw)
  To: 'zhangfei', 'Kevin Hilman',
	'Sachin Kamat', 'Chris Ball',
	'Arnd Bergmann', 'Mike Turquette',
	'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches

On Wed, January 15, 2014, Zhangfei Gao wrote:
> On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> > On Wed, January 15, 2014, Zhangfei Gao wrote:
> >> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> >> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> >> can not be checked by IS_ERR_VALUE.
> >> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> >> otherwise sd detect may occasionally fail.
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Reported-by: Kevin Hilman <khilman@linaro.org>
> >> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> ---
> >>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
> >>   1 file changed, 6 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> >> index a776f24f4311..9ded62c8225e 100644
> >> --- a/drivers/mmc/host/dw_mmc.c
> >> +++ b/drivers/mmc/host/dw_mmc.c
> >> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>   	int present;
> >>   	struct dw_mci_slot *slot = mmc_priv(mmc);
> >>   	struct dw_mci_board *brd = slot->host->pdata;
> >> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> >> +	struct dw_mci *host = slot->host;
> >> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> >>
> >>   	/* Use platform get_cd function, else try onboard card detect */
> >>   	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> >> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>   	else if (brd->get_cd)
> >>   		present = !brd->get_cd(slot->id);
> >>   	else if (!IS_ERR_VALUE(gpio_cd))
> >> -		present = !!gpio_cd;
> >> +		present = !gpio_cd;
> > !!gpio_cd or gpio_cd is correct, isn't it?
> >
> 
> No, mmc_gpio_get_cd(mmc) has to revert.
I'm missing something?
If card is detected, mmc_gpio_get_cd() returns non-zero, right?
I guess gpio_cd should be kept.

> !!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
> before.
> 
> Thanks
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 12:26               ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 12:26 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, January 15, 2014, Zhangfei Gao wrote:
> On 01/15/2014 07:58 PM, Seungwon Jeon wrote:
> > On Wed, January 15, 2014, Zhangfei Gao wrote:
> >> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> >> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> >> can not be checked by IS_ERR_VALUE.
> >> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> >> otherwise sd detect may occasionally fail.
> >>
> >> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> >> Reported-by: Kevin Hilman <khilman@linaro.org>
> >> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> >> ---
> >>   drivers/mmc/host/dw_mmc.c |    9 ++++++---
> >>   1 file changed, 6 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> >> index a776f24f4311..9ded62c8225e 100644
> >> --- a/drivers/mmc/host/dw_mmc.c
> >> +++ b/drivers/mmc/host/dw_mmc.c
> >> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>   	int present;
> >>   	struct dw_mci_slot *slot = mmc_priv(mmc);
> >>   	struct dw_mci_board *brd = slot->host->pdata;
> >> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> >> +	struct dw_mci *host = slot->host;
> >> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> >>
> >>   	/* Use platform get_cd function, else try onboard card detect */
> >>   	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> >> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>   	else if (brd->get_cd)
> >>   		present = !brd->get_cd(slot->id);
> >>   	else if (!IS_ERR_VALUE(gpio_cd))
> >> -		present = !!gpio_cd;
> >> +		present = !gpio_cd;
> > !!gpio_cd or gpio_cd is correct, isn't it?
> >
> 
> No, mmc_gpio_get_cd(mmc) has to revert.
I'm missing something?
If card is detected, mmc_gpio_get_cd() returns non-zero, right?
I guess gpio_cd should be kept.

> !!gpio_cd is used before since gpio_cd = !mmc_gpio_get_cd(mmc) is used
> before.
> 
> Thanks
> --
> 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

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 12:26               ` Seungwon Jeon
@ 2014-01-15 13:56                 ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 13:56 UTC (permalink / raw)
  To: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches



On 01/15/2014 08:26 PM, Seungwon Jeon wrote:

>>>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>>>    	int present;
>>>>    	struct dw_mci_slot *slot = mmc_priv(mmc);
>>>>    	struct dw_mci_board *brd = slot->host->pdata;
>>>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
>>>> +	struct dw_mci *host = slot->host;
>>>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>>>>
>>>>    	/* Use platform get_cd function, else try onboard card detect */
>>>>    	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
>>>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>>>    	else if (brd->get_cd)
>>>>    		present = !brd->get_cd(slot->id);
>>>>    	else if (!IS_ERR_VALUE(gpio_cd))
>>>> -		present = !!gpio_cd;
>>>> +		present = !gpio_cd;
>>> !!gpio_cd or gpio_cd is correct, isn't it?
>>>
>>
>> No, mmc_gpio_get_cd(mmc) has to revert.
> I'm missing something?
> If card is detected, mmc_gpio_get_cd() returns non-zero, right?
> I guess gpio_cd should be kept.
> 

Hmm, looks you are right.
Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
directly set get_cd as mmc_gpio_get_cd.
.get_cd	= mmc_gpio_get_cd

However, in our board cd =0 when card is deteced while cd=1 when card is
removed.
In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
set, as well as new property "caps2-mmc-cd-active-low".

--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
@@ -73,6 +73,8 @@ Optional properties:
+* caps2-mmc-cd-active-low: cd pin is low when card active
+

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
+               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+

But it looks strange "cd-active-low" describing "CD_ACTIVE_HIGH" flag.
When card active, cd = 0, and ACTIVE_HIGH is required to make
mmc_gpio_get_cd return 1.
int mmc_gpio_get_cd(struct mmc_host *host)
{
        return !gpio_get_value_cansleep(ctx->cd_gpio) ^
                !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
}

Thanks

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 13:56                 ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 13:56 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/15/2014 08:26 PM, Seungwon Jeon wrote:

>>>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>>>    	int present;
>>>>    	struct dw_mci_slot *slot = mmc_priv(mmc);
>>>>    	struct dw_mci_board *brd = slot->host->pdata;
>>>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
>>>> +	struct dw_mci *host = slot->host;
>>>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>>>>
>>>>    	/* Use platform get_cd function, else try onboard card detect */
>>>>    	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
>>>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>>>>    	else if (brd->get_cd)
>>>>    		present = !brd->get_cd(slot->id);
>>>>    	else if (!IS_ERR_VALUE(gpio_cd))
>>>> -		present = !!gpio_cd;
>>>> +		present = !gpio_cd;
>>> !!gpio_cd or gpio_cd is correct, isn't it?
>>>
>>
>> No, mmc_gpio_get_cd(mmc) has to revert.
> I'm missing something?
> If card is detected, mmc_gpio_get_cd() returns non-zero, right?
> I guess gpio_cd should be kept.
> 

Hmm, looks you are right.
Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
directly set get_cd as mmc_gpio_get_cd.
.get_cd	= mmc_gpio_get_cd

However, in our board cd =0 when card is deteced while cd=1 when card is
removed.
In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
set, as well as new property "caps2-mmc-cd-active-low".

--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
@@ -73,6 +73,8 @@ Optional properties:
+* caps2-mmc-cd-active-low: cd pin is low when card active
+

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
+               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+

But it looks strange "cd-active-low" describing "CD_ACTIVE_HIGH" flag.
When card active, cd = 0, and ACTIVE_HIGH is required to make
mmc_gpio_get_cd return 1.
int mmc_gpio_get_cd(struct mmc_host *host)
{
        return !gpio_get_value_cansleep(ctx->cd_gpio) ^
                !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
}

Thanks

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 13:56                 ` zhangfei
@ 2014-01-15 13:59                   ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 13:59 UTC (permalink / raw)
  To: zhangfei
  Cc: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Mike Turquette',
	'Jaehoon Chung',
	linux-mmc, linux-arm-kernel, patches

On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> However, in our board cd =0 when card is deteced while cd=1 when card is
> removed.
> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> set, as well as new property "caps2-mmc-cd-active-low".
> 
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -73,6 +73,8 @@ Optional properties:
> +* caps2-mmc-cd-active-low: cd pin is low when card active
> +
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> +

The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
legacy platforms. With DT parsing, you can normally specify
the polarity of the GPIO line in the GPIO specifier in DT.


	Arnd

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 13:59                   ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 13:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> However, in our board cd =0 when card is deteced while cd=1 when card is
> removed.
> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> set, as well as new property "caps2-mmc-cd-active-low".
> 
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -73,6 +73,8 @@ Optional properties:
> +* caps2-mmc-cd-active-low: cd pin is low when card active
> +
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> +

The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
legacy platforms. With DT parsing, you can normally specify
the polarity of the GPIO line in the GPIO specifier in DT.


	Arnd

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 13:59                   ` Arnd Bergmann
@ 2014-01-15 14:20                     ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 14:20 UTC (permalink / raw)
  To: zhangfei
  Cc: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Mike Turquette',
	'Jaehoon Chung',
	linux-mmc, linux-arm-kernel, patches

On Wednesday 15 January 2014 14:59:59 Arnd Bergmann wrote:
> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > However, in our board cd =0 when card is deteced while cd=1 when card is
> > removed.
> > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > @@ -73,6 +73,8 @@ Optional properties:
> > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > +
> > 
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > +
> 
> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> legacy platforms. With DT parsing, you can normally specify
> the polarity of the GPIO line in the GPIO specifier in DT.

I missed the fact that we already have a "cd-inverted" property
as specified in bindings/mmc/mmc.txt. If your GPIO controller
does not handle polarity, you can use that.

	Arnd

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 14:20                     ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 14:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 January 2014 14:59:59 Arnd Bergmann wrote:
> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > However, in our board cd =0 when card is deteced while cd=1 when card is
> > removed.
> > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > @@ -73,6 +73,8 @@ Optional properties:
> > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > +
> > 
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > +
> 
> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> legacy platforms. With DT parsing, you can normally specify
> the polarity of the GPIO line in the GPIO specifier in DT.

I missed the fact that we already have a "cd-inverted" property
as specified in bindings/mmc/mmc.txt. If your GPIO controller
does not handle polarity, you can use that.

	Arnd

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

* RE: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 13:56                 ` zhangfei
@ 2014-01-15 14:38                   ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 14:38 UTC (permalink / raw)
  To: 'zhangfei', 'Kevin Hilman',
	'Sachin Kamat', 'Chris Ball',
	'Arnd Bergmann', 'Mike Turquette',
	'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches

On Wed, January 15, 2014, Zhangfei wrote:
> On 01/15/2014 08:26 PM, Seungwon Jeon wrote:
> 
> >>>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>>>    	int present;
> >>>>    	struct dw_mci_slot *slot = mmc_priv(mmc);
> >>>>    	struct dw_mci_board *brd = slot->host->pdata;
> >>>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> >>>> +	struct dw_mci *host = slot->host;
> >>>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> >>>>
> >>>>    	/* Use platform get_cd function, else try onboard card detect */
> >>>>    	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> >>>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>>>    	else if (brd->get_cd)
> >>>>    		present = !brd->get_cd(slot->id);
> >>>>    	else if (!IS_ERR_VALUE(gpio_cd))
> >>>> -		present = !!gpio_cd;
> >>>> +		present = !gpio_cd;
> >>> !!gpio_cd or gpio_cd is correct, isn't it?
> >>>
> >>
> >> No, mmc_gpio_get_cd(mmc) has to revert.
> > I'm missing something?
> > If card is detected, mmc_gpio_get_cd() returns non-zero, right?
> > I guess gpio_cd should be kept.
> >
> 
> Hmm, looks you are right.
> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
> directly set get_cd as mmc_gpio_get_cd.
> .get_cd	= mmc_gpio_get_cd
> 
> However, in our board cd =0 when card is deteced while cd=1 when card is
> removed.
> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> set, as well as new property "caps2-mmc-cd-active-low".

Ok, you could do more.
mmc_gpio_get_cd() is expected to return non-zero if card is detection.

> 
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -73,6 +73,8 @@ Optional properties:
> +* caps2-mmc-cd-active-low: cd pin is low when card active
> +
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> +
> 
> But it looks strange "cd-active-low" describing "CD_ACTIVE_HIGH" flag.
> When card active, cd = 0, and ACTIVE_HIGH is required to make
> mmc_gpio_get_cd return 1.

I think your board seems not to use pull-up on GPIO line for card detection.
So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.

Thanks,
Seungwon Jeon

> int mmc_gpio_get_cd(struct mmc_host *host)
> {
>         return !gpio_get_value_cansleep(ctx->cd_gpio) ^
>                 !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
> }
> 
> Thanks
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 14:38                   ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2014-01-15 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, January 15, 2014, Zhangfei wrote:
> On 01/15/2014 08:26 PM, Seungwon Jeon wrote:
> 
> >>>> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>>>    	int present;
> >>>>    	struct dw_mci_slot *slot = mmc_priv(mmc);
> >>>>    	struct dw_mci_board *brd = slot->host->pdata;
> >>>> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> >>>> +	struct dw_mci *host = slot->host;
> >>>> +	int gpio_cd = mmc_gpio_get_cd(mmc);
> >>>>
> >>>>    	/* Use platform get_cd function, else try onboard card detect */
> >>>>    	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> >>>> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
> >>>>    	else if (brd->get_cd)
> >>>>    		present = !brd->get_cd(slot->id);
> >>>>    	else if (!IS_ERR_VALUE(gpio_cd))
> >>>> -		present = !!gpio_cd;
> >>>> +		present = !gpio_cd;
> >>> !!gpio_cd or gpio_cd is correct, isn't it?
> >>>
> >>
> >> No, mmc_gpio_get_cd(mmc) has to revert.
> > I'm missing something?
> > If card is detected, mmc_gpio_get_cd() returns non-zero, right?
> > I guess gpio_cd should be kept.
> >
> 
> Hmm, looks you are right.
> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
> directly set get_cd as mmc_gpio_get_cd.
> .get_cd	= mmc_gpio_get_cd
> 
> However, in our board cd =0 when card is deteced while cd=1 when card is
> removed.
> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> set, as well as new property "caps2-mmc-cd-active-low".

Ok, you could do more.
mmc_gpio_get_cd() is expected to return non-zero if card is detection.

> 
> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> @@ -73,6 +73,8 @@ Optional properties:
> +* caps2-mmc-cd-active-low: cd pin is low when card active
> +
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> +
> 
> But it looks strange "cd-active-low" describing "CD_ACTIVE_HIGH" flag.
> When card active, cd = 0, and ACTIVE_HIGH is required to make
> mmc_gpio_get_cd return 1.

I think your board seems not to use pull-up on GPIO line for card detection.
So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.

Thanks,
Seungwon Jeon

> int mmc_gpio_get_cd(struct mmc_host *host)
> {
>         return !gpio_get_value_cansleep(ctx->cd_gpio) ^
>                 !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
> }
> 
> Thanks
> --
> 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

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 14:38                   ` Seungwon Jeon
@ 2014-01-15 15:32                     ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 15:32 UTC (permalink / raw)
  To: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Jaehoon Chung'
  Cc: linux-mmc, linux-arm-kernel, patches


On 01/15/2014 10:38 PM, Seungwon Jeon wrote:
>> Hmm, looks you are right.
>> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
>> directly set get_cd as mmc_gpio_get_cd.
>> .get_cd	= mmc_gpio_get_cd
>>
>> However, in our board cd =0 when card is deteced while cd=1 when card is
>> removed.
>> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
>> set, as well as new property "caps2-mmc-cd-active-low".
> 
> Ok, you could do more.
> mmc_gpio_get_cd() is expected to return non-zero if card is detection.

> I think your board seems not to use pull-up on GPIO line for card detection.
> So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.

Unfortunately, the specific cd pin can not be configured.
Suspect on our board the cd =1 when card is inserted, can not measure as
no clear resister and need check with hardware guy tomorrow.

"cd-inverted" may be required as mentioned by Arnd.
Will update the patch as following if no problem.

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 9ded62c8225e..8326e54b96a8 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1042,7 +1042,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        else if (brd->get_cd)
                present = !brd->get_cd(slot->id);
        else if (!IS_ERR_VALUE(gpio_cd))
-               present = !gpio_cd;
+               present = gpio_cd ^ brd->cd_inverted;
        else
                present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
                        == 0 ? 1 : 0;
@@ -2414,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct
dw_mci *host)
        if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
                pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;

+       if (of_get_property(np, "cd-inverted", NULL))
+               pdata->cd_inverted = 1;
+
        return pdata;
 }

diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 6ce7d2cd3c7a..4535282589ab 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -238,6 +238,7 @@ struct dw_mci_board {
        u32 caps;       /* Capabilities */
        u32 caps2;      /* More capabilities */
        u32 pm_caps;    /* PM capabilities */
+       u8 cd_inverted;

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 15:32                     ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 15:32 UTC (permalink / raw)
  To: linux-arm-kernel


On 01/15/2014 10:38 PM, Seungwon Jeon wrote:
>> Hmm, looks you are right.
>> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
>> directly set get_cd as mmc_gpio_get_cd.
>> .get_cd	= mmc_gpio_get_cd
>>
>> However, in our board cd =0 when card is deteced while cd=1 when card is
>> removed.
>> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
>> set, as well as new property "caps2-mmc-cd-active-low".
> 
> Ok, you could do more.
> mmc_gpio_get_cd() is expected to return non-zero if card is detection.

> I think your board seems not to use pull-up on GPIO line for card detection.
> So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.

Unfortunately, the specific cd pin can not be configured.
Suspect on our board the cd =1 when card is inserted, can not measure as
no clear resister and need check with hardware guy tomorrow.

"cd-inverted" may be required as mentioned by Arnd.
Will update the patch as following if no problem.

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 9ded62c8225e..8326e54b96a8 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1042,7 +1042,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        else if (brd->get_cd)
                present = !brd->get_cd(slot->id);
        else if (!IS_ERR_VALUE(gpio_cd))
-               present = !gpio_cd;
+               present = gpio_cd ^ brd->cd_inverted;
        else
                present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
                        == 0 ? 1 : 0;
@@ -2414,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct
dw_mci *host)
        if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
                pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;

+       if (of_get_property(np, "cd-inverted", NULL))
+               pdata->cd_inverted = 1;
+
        return pdata;
 }

diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 6ce7d2cd3c7a..4535282589ab 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -238,6 +238,7 @@ struct dw_mci_board {
        u32 caps;       /* Capabilities */
        u32 caps2;      /* More capabilities */
        u32 pm_caps;    /* PM capabilities */
+       u8 cd_inverted;

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 14:20                     ` Arnd Bergmann
@ 2014-01-15 15:36                       ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 15:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Mike Turquette',
	'Jaehoon Chung',
	linux-mmc, linux-arm-kernel, patches



On 01/15/2014 10:20 PM, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 14:59:59 Arnd Bergmann wrote:
>> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
>>> However, in our board cd =0 when card is deteced while cd=1 when card is
>>> removed.
>>> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
>>> set, as well as new property "caps2-mmc-cd-active-low".
>>>
>>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>>> @@ -73,6 +73,8 @@ Optional properties:
>>> +* caps2-mmc-cd-active-low: cd pin is low when card active
>>> +
>>>
>>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>>> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
>>> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
>>> +
>>
>> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
>> legacy platforms. With DT parsing, you can normally specify
>> the polarity of the GPIO line in the GPIO specifier in DT.
>
> I missed the fact that we already have a "cd-inverted" property
> as specified in bindings/mmc/mmc.txt. If your GPIO controller
> does not handle polarity, you can use that.
>

Thanks Arnd

GPIO controller drivers/gpio/gpio-pl061.c still not handle polarity, so 
use "cd-inverted" instead.

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 15:36                       ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-15 15:36 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/15/2014 10:20 PM, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 14:59:59 Arnd Bergmann wrote:
>> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
>>> However, in our board cd =0 when card is deteced while cd=1 when card is
>>> removed.
>>> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
>>> set, as well as new property "caps2-mmc-cd-active-low".
>>>
>>> --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>>> +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
>>> @@ -73,6 +73,8 @@ Optional properties:
>>> +* caps2-mmc-cd-active-low: cd pin is low when card active
>>> +
>>>
>>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>>> +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
>>> +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
>>> +
>>
>> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
>> legacy platforms. With DT parsing, you can normally specify
>> the polarity of the GPIO line in the GPIO specifier in DT.
>
> I missed the fact that we already have a "cd-inverted" property
> as specified in bindings/mmc/mmc.txt. If your GPIO controller
> does not handle polarity, you can use that.
>

Thanks Arnd

GPIO controller drivers/gpio/gpio-pl061.c still not handle polarity, so 
use "cd-inverted" instead.

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 15:32                     ` zhangfei
@ 2014-01-15 15:51                       ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15 15:51 UTC (permalink / raw)
  To: Kevin Hilman, Sachin Kamat, Chris Ball, Arnd Bergmann,
	Mike Turquette, Jaehoon Chung, Seungwon Jeon
  Cc: linux-mmc, linux-arm-kernel, patches, Zhangfei Gao

Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
can not be checked by IS_ERR_VALUE.
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
otherwise sd detect may occasionally fail.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
---
 drivers/mmc/host/dw_mmc.c  |   12 +++++++++---
 include/linux/mmc/dw_mmc.h |    1 +
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..8326e54b96a8 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = gpio_cd ^ brd->cd_inverted;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
@@ -2411,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
 		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
 
+	if (of_get_property(np, "cd-inverted", NULL))
+		pdata->cd_inverted = 1;
+
 	return pdata;
 }
 
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 6ce7d2cd3c7a..4535282589ab 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -238,6 +238,7 @@ struct dw_mci_board {
 	u32 caps;	/* Capabilities */
 	u32 caps2;	/* More capabilities */
 	u32 pm_caps;	/* PM capabilities */
+	u8 cd_inverted;
 	/*
 	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
 	 * but note that this may not be reliable after a bootloader has used
-- 
1.7.9.5


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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 15:51                       ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-15 15:51 UTC (permalink / raw)
  To: linux-arm-kernel

Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
can not be checked by IS_ERR_VALUE.
Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
otherwise sd detect may occasionally fail.

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Reported-by: Kevin Hilman <khilman@linaro.org>
Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
---
 drivers/mmc/host/dw_mmc.c  |   12 +++++++++---
 include/linux/mmc/dw_mmc.h |    1 +
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a776f24f4311..8326e54b96a8 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	int present;
 	struct dw_mci_slot *slot = mmc_priv(mmc);
 	struct dw_mci_board *brd = slot->host->pdata;
-	int gpio_cd = !mmc_gpio_get_cd(mmc);
+	struct dw_mci *host = slot->host;
+	int gpio_cd = mmc_gpio_get_cd(mmc);
 
 	/* Use platform get_cd function, else try onboard card detect */
 	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
@@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else if (!IS_ERR_VALUE(gpio_cd))
-		present = !!gpio_cd;
+		present = gpio_cd ^ brd->cd_inverted;
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
 			== 0 ? 1 : 0;
 
+	spin_lock_bh(&host->lock);
 	if (present) {
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is present\n");
@@ -1053,6 +1055,7 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
 		clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 		dev_dbg(&mmc->class_dev, "card is not present\n");
 	}
+	spin_unlock_bh(&host->lock);
 
 	return present;
 }
@@ -2081,7 +2084,7 @@ static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
 	return gpio;
 }
 
-/* find the cd gpio for a given slot; or -1 if none specified */
+/* find the cd gpio for a given slot */
 static void dw_mci_of_get_cd_gpio(struct device *dev, u8 slot,
 					struct mmc_host *mmc)
 {
@@ -2411,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 	if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
 		pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;
 
+	if (of_get_property(np, "cd-inverted", NULL))
+		pdata->cd_inverted = 1;
+
 	return pdata;
 }
 
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 6ce7d2cd3c7a..4535282589ab 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -238,6 +238,7 @@ struct dw_mci_board {
 	u32 caps;	/* Capabilities */
 	u32 caps2;	/* More capabilities */
 	u32 pm_caps;	/* PM capabilities */
+	u8 cd_inverted;
 	/*
 	 * Override fifo depth. If 0, autodetect it from the FIFOTH register,
 	 * but note that this may not be reliable after a bootloader has used
-- 
1.7.9.5

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 15:32                     ` zhangfei
@ 2014-01-15 15:54                       ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 15:54 UTC (permalink / raw)
  To: zhangfei
  Cc: Seungwon Jeon, 'Kevin Hilman', 'Sachin Kamat',
	'Chris Ball', 'Mike Turquette',
	'Jaehoon Chung',
	linux-mmc, linux-arm-kernel, patches

On Wednesday 15 January 2014, zhangfei wrote:
> 
> On 01/15/2014 10:38 PM, Seungwon Jeon wrote:
> >> Hmm, looks you are right.
> >> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
> >> directly set get_cd as mmc_gpio_get_cd.
> >> .get_cd	= mmc_gpio_get_cd
> >>
> >> However, in our board cd =0 when card is deteced while cd=1 when card is
> >> removed.
> >> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> >> set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > Ok, you could do more.
> > mmc_gpio_get_cd() is expected to return non-zero if card is detection.
> 
> > I think your board seems not to use pull-up on GPIO line for card detection.
> > So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.
> 
> Unfortunately, the specific cd pin can not be configured.
> Suspect on our board the cd =1 when card is inserted, can not measure as
> no clear resister and need check with hardware guy tomorrow.
> 
> "cd-inverted" may be required as mentioned by Arnd.
> Will update the patch as following if no problem.

The patch looks right, but I wonder if a better longer-term
solution would be to just the common mmc_of_parse() function
rather than duplicating it in dw_mmc.

	Arnd

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 15:54                       ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 15:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 January 2014, zhangfei wrote:
> 
> On 01/15/2014 10:38 PM, Seungwon Jeon wrote:
> >> Hmm, looks you are right.
> >> Though not see clearly mmc_gpio_get_cd declaratoin, other drivers
> >> directly set get_cd as mmc_gpio_get_cd.
> >> .get_cd	= mmc_gpio_get_cd
> >>
> >> However, in our board cd =0 when card is deteced while cd=1 when card is
> >> removed.
> >> In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> >> set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > Ok, you could do more.
> > mmc_gpio_get_cd() is expected to return non-zero if card is detection.
> 
> > I think your board seems not to use pull-up on GPIO line for card detection.
> > So, MMC_CAP2_CD_ACTIVE_HIGH would be needed.
> 
> Unfortunately, the specific cd pin can not be configured.
> Suspect on our board the cd =1 when card is inserted, can not measure as
> no clear resister and need check with hardware guy tomorrow.
> 
> "cd-inverted" may be required as mentioned by Arnd.
> Will update the patch as following if no problem.

The patch looks right, but I wonder if a better longer-term
solution would be to just the common mmc_of_parse() function
rather than duplicating it in dw_mmc.

	Arnd

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 15:51                       ` Zhangfei Gao
@ 2014-01-15 15:59                         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 15:59 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Kevin Hilman, Sachin Kamat, Chris Ball, Arnd Bergmann,
	Mike Turquette, Jaehoon Chung, Seungwon Jeon, linux-mmc,
	linux-arm-kernel, patches

On Wed, Jan 15, 2014 at 11:51:01PM +0800, Zhangfei Gao wrote:
> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> can not be checked by IS_ERR_VALUE.
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> otherwise sd detect may occasionally fail.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
>  drivers/mmc/host/dw_mmc.c  |   12 +++++++++---
>  include/linux/mmc/dw_mmc.h |    1 +
>  2 files changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a776f24f4311..8326e54b96a8 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	int present;
>  	struct dw_mci_slot *slot = mmc_priv(mmc);
>  	struct dw_mci_board *brd = slot->host->pdata;
> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> +	struct dw_mci *host = slot->host;
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>  
>  	/* Use platform get_cd function, else try onboard card detect */
>  	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	else if (brd->get_cd)
>  		present = !brd->get_cd(slot->id);
>  	else if (!IS_ERR_VALUE(gpio_cd))
> -		present = !!gpio_cd;
> +		present = gpio_cd ^ brd->cd_inverted;

I assume you haven't read the contents of mmc_gpio_get_cd()?

int mmc_gpio_get_cd(struct mmc_host *host)
{
        struct mmc_gpio *ctx = host->slot.handler_priv;

        if (!ctx || !gpio_is_valid(ctx->cd_gpio))
                return -ENOSYS;

        return !gpio_get_value_cansleep(ctx->cd_gpio) ^
                !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
}
EXPORT_SYMBOL(mmc_gpio_get_cd);

What facility does host->caps2 give you here?  Yes, you don't need
your own cd_inverted stuff.  You should check that you're interpreting
this correctly.  When this returns true, there is a card present.

When MMC_CAP2_CD_ACTIVE_HIGH is set, gpio_get_value_cansleep() must
return non-zero when a card is inserted.  When it isn't set,
gpio_get_value_cansleep must return zero when a card is inserted.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 15:59                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 15:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 15, 2014 at 11:51:01PM +0800, Zhangfei Gao wrote:
> Introduced from commit bf626e5550f24aec24975a0e85ad8e572ca76a6b
> CDETECT is ignored since negated return value of mmc_gpio_get_cd(mmc)
> can not be checked by IS_ERR_VALUE.
> Add spin_lock_bh(&host->lock) for atomic accessing DW_MMC_CARD_PRESENT,
> otherwise sd detect may occasionally fail.
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Reported-by: Kevin Hilman <khilman@linaro.org>
> Reviewed-by: Sachin Kamat <sachin.kamat@linaro.org>
> Tested-by: Sachin Kamat <sachin.kamat@linaro.org>
> ---
>  drivers/mmc/host/dw_mmc.c  |   12 +++++++++---
>  include/linux/mmc/dw_mmc.h |    1 +
>  2 files changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index a776f24f4311..8326e54b96a8 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -1033,7 +1033,8 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	int present;
>  	struct dw_mci_slot *slot = mmc_priv(mmc);
>  	struct dw_mci_board *brd = slot->host->pdata;
> -	int gpio_cd = !mmc_gpio_get_cd(mmc);
> +	struct dw_mci *host = slot->host;
> +	int gpio_cd = mmc_gpio_get_cd(mmc);
>  
>  	/* Use platform get_cd function, else try onboard card detect */
>  	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
> @@ -1041,11 +1042,12 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
>  	else if (brd->get_cd)
>  		present = !brd->get_cd(slot->id);
>  	else if (!IS_ERR_VALUE(gpio_cd))
> -		present = !!gpio_cd;
> +		present = gpio_cd ^ brd->cd_inverted;

I assume you haven't read the contents of mmc_gpio_get_cd()?

int mmc_gpio_get_cd(struct mmc_host *host)
{
        struct mmc_gpio *ctx = host->slot.handler_priv;

        if (!ctx || !gpio_is_valid(ctx->cd_gpio))
                return -ENOSYS;

        return !gpio_get_value_cansleep(ctx->cd_gpio) ^
                !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
}
EXPORT_SYMBOL(mmc_gpio_get_cd);

What facility does host->caps2 give you here?  Yes, you don't need
your own cd_inverted stuff.  You should check that you're interpreting
this correctly.  When this returns true, there is a card present.

When MMC_CAP2_CD_ACTIVE_HIGH is set, gpio_get_value_cansleep() must
return non-zero when a card is inserted.  When it isn't set,
gpio_get_value_cansleep must return zero when a card is inserted.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 13:59                   ` Arnd Bergmann
@ 2014-01-15 16:01                     ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 16:01 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhangfei, 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel

On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > However, in our board cd =0 when card is deteced while cd=1 when card is
> > removed.
> > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > @@ -73,6 +73,8 @@ Optional properties:
> > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > +
> > 
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > +
> 
> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> legacy platforms. With DT parsing, you can normally specify
> the polarity of the GPIO line in the GPIO specifier in DT.

Since when?

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 16:01                     ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 16:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > However, in our board cd =0 when card is deteced while cd=1 when card is
> > removed.
> > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > set, as well as new property "caps2-mmc-cd-active-low".
> > 
> > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > @@ -73,6 +73,8 @@ Optional properties:
> > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > +
> > 
> > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > +
> 
> The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> legacy platforms. With DT parsing, you can normally specify
> the polarity of the GPIO line in the GPIO specifier in DT.

Since when?

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 16:01                     ` Russell King - ARM Linux
@ 2014-01-15 16:07                       ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 16:07 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: zhangfei, 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel

On Wednesday 15 January 2014 16:01:46 Russell King - ARM Linux wrote:
> On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> > On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > > However, in our board cd =0 when card is deteced while cd=1 when card is
> > > removed.
> > > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > > set, as well as new property "caps2-mmc-cd-active-low".
> > > 
> > > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > @@ -73,6 +73,8 @@ Optional properties:
> > > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > > +
> > > 
> > > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > > +
> > 
> > The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> > legacy platforms. With DT parsing, you can normally specify
> > the polarity of the GPIO line in the GPIO specifier in DT.
> 
> Since when?

I just looked through the bindings and found that about half
of them allow passing polarity in the gpio specifier. I thought
it was more than that and IIRC the outcome of a previous discussion
was that when the gpio controller allows passing polarity, you
should use that rather than a separate flag.

Not a problem though, since we can use the cd-inverted and
wp-inverted properties.

	Arnd

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 16:07                       ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-15 16:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 January 2014 16:01:46 Russell King - ARM Linux wrote:
> On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> > On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > > However, in our board cd =0 when card is deteced while cd=1 when card is
> > > removed.
> > > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > > set, as well as new property "caps2-mmc-cd-active-low".
> > > 
> > > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > @@ -73,6 +73,8 @@ Optional properties:
> > > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > > +
> > > 
> > > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > > +
> > 
> > The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> > legacy platforms. With DT parsing, you can normally specify
> > the polarity of the GPIO line in the GPIO specifier in DT.
> 
> Since when?

I just looked through the bindings and found that about half
of them allow passing polarity in the gpio specifier. I thought
it was more than that and IIRC the outcome of a previous discussion
was that when the gpio controller allows passing polarity, you
should use that rather than a separate flag.

Not a problem though, since we can use the cd-inverted and
wp-inverted properties.

	Arnd

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 16:07                       ` Arnd Bergmann
@ 2014-01-15 16:22                         ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 16:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhangfei, 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel

On Wed, Jan 15, 2014 at 05:07:49PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 16:01:46 Russell King - ARM Linux wrote:
> > On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> > > On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > > > However, in our board cd =0 when card is deteced while cd=1 when card is
> > > > removed.
> > > > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > > > set, as well as new property "caps2-mmc-cd-active-low".
> > > > 
> > > > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > > @@ -73,6 +73,8 @@ Optional properties:
> > > > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > > > +
> > > > 
> > > > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > > > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > > > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > > > +
> > > 
> > > The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> > > legacy platforms. With DT parsing, you can normally specify
> > > the polarity of the GPIO line in the GPIO specifier in DT.
> > 
> > Since when?
> 
> I just looked through the bindings and found that about half
> of them allow passing polarity in the gpio specifier. I thought
> it was more than that and IIRC the outcome of a previous discussion
> was that when the gpio controller allows passing polarity, you
> should use that rather than a separate flag.
> 
> Not a problem though, since we can use the cd-inverted and
> wp-inverted properties.

Well, having this in the gpio level as well as in subsystems like MMC
is going to create confusion - and from the results of this patch _IS_
causing confusion.  You've just encouraged one implementation to have
things setup such that mmc_gpio_get_cd() returns false when a card is
inserted, rather than it correctly returning true.

The issue here is that we'll potentially now end up with _three_
inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
another in every driver which uses the GPIO layer inversion.  This
is hardly the right approach as it leads to multiple points where
confusion about the inverted status can occur.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-15 16:22                         ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-15 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jan 15, 2014 at 05:07:49PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014 16:01:46 Russell King - ARM Linux wrote:
> > On Wed, Jan 15, 2014 at 02:59:59PM +0100, Arnd Bergmann wrote:
> > > On Wednesday 15 January 2014 21:56:26 zhangfei wrote:
> > > > However, in our board cd =0 when card is deteced while cd=1 when card is
> > > > removed.
> > > > In order to mmc_gpio_get_cd return 1, MMC_CAP2_CD_ACTIVE_HIGH has to be
> > > > set, as well as new property "caps2-mmc-cd-active-low".
> > > > 
> > > > --- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > > +++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
> > > > @@ -73,6 +73,8 @@ Optional properties:
> > > > +* caps2-mmc-cd-active-low: cd pin is low when card active
> > > > +
> > > > 
> > > > diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> > > > +       if (of_find_property(np, "caps2-mmc-cd-active-low", NULL))
> > > > +               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
> > > > +
> > > 
> > > The MMC_CAP2_CD_ACTIVE_HIGH flag should only be required for
> > > legacy platforms. With DT parsing, you can normally specify
> > > the polarity of the GPIO line in the GPIO specifier in DT.
> > 
> > Since when?
> 
> I just looked through the bindings and found that about half
> of them allow passing polarity in the gpio specifier. I thought
> it was more than that and IIRC the outcome of a previous discussion
> was that when the gpio controller allows passing polarity, you
> should use that rather than a separate flag.
> 
> Not a problem though, since we can use the cd-inverted and
> wp-inverted properties.

Well, having this in the gpio level as well as in subsystems like MMC
is going to create confusion - and from the results of this patch _IS_
causing confusion.  You've just encouraged one implementation to have
things setup such that mmc_gpio_get_cd() returns false when a card is
inserted, rather than it correctly returning true.

The issue here is that we'll potentially now end up with _three_
inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
another in every driver which uses the GPIO layer inversion.  This
is hardly the right approach as it leads to multiple points where
confusion about the inverted status can occur.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 16:22                         ` Russell King - ARM Linux
@ 2014-01-16  2:10                           ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-16  2:10 UTC (permalink / raw)
  To: Russell King - ARM Linux, Arnd Bergmann
  Cc: 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel



On 01/16/2014 12:22 AM, Russell King - ARM Linux wrote:

> Well, having this in the gpio level as well as in subsystems like MMC
> is going to create confusion - and from the results of this patch _IS_
> causing confusion.  You've just encouraged one implementation to have
> things setup such that mmc_gpio_get_cd() returns false when a card is
> inserted, rather than it correctly returning true.
>
> The issue here is that we'll potentially now end up with _three_
> inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> another in every driver which uses the GPIO layer inversion.  This
> is hardly the right approach as it leads to multiple points where
> confusion about the inverted status can occur.
>

Thanks Russell, make sense.

Double checked with the hardware guy, cd pin is high when card inserted 
on the board.
The cd pin is originally connected to vout via a resister, and 
internally short to gound, which is broken when card inserted.

Then Optional properties "caps2-mmc-cd-active-high" has to be added.

--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt

+* caps2-mmc-cd-active-high: cd pin is high when card present

@@ -2411,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct 
dw_mci *host)
         if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
                 pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;

+       if (of_find_property(np, "caps2-mmc-cd-active-high", NULL))
+               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+

Thanks

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-16  2:10                           ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-16  2:10 UTC (permalink / raw)
  To: linux-arm-kernel



On 01/16/2014 12:22 AM, Russell King - ARM Linux wrote:

> Well, having this in the gpio level as well as in subsystems like MMC
> is going to create confusion - and from the results of this patch _IS_
> causing confusion.  You've just encouraged one implementation to have
> things setup such that mmc_gpio_get_cd() returns false when a card is
> inserted, rather than it correctly returning true.
>
> The issue here is that we'll potentially now end up with _three_
> inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> another in every driver which uses the GPIO layer inversion.  This
> is hardly the right approach as it leads to multiple points where
> confusion about the inverted status can occur.
>

Thanks Russell, make sense.

Double checked with the hardware guy, cd pin is high when card inserted 
on the board.
The cd pin is originally connected to vout via a resister, and 
internally short to gound, which is broken when card inserted.

Then Optional properties "caps2-mmc-cd-active-high" has to be added.

--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.txt

+* caps2-mmc-cd-active-high: cd pin is high when card present

@@ -2411,6 +2414,9 @@ static struct dw_mci_board *dw_mci_parse_dt(struct 
dw_mci *host)
         if (of_find_property(np, "caps2-mmc-hs200-1_2v", NULL))
                 pdata->caps2 |= MMC_CAP2_HS200_1_2V_SDR;

+       if (of_find_property(np, "caps2-mmc-cd-active-high", NULL))
+               pdata->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
+

Thanks

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-15 16:22                         ` Russell King - ARM Linux
@ 2014-01-16 11:12                           ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-16 11:12 UTC (permalink / raw)
  To: Russell King - ARM Linux
  Cc: zhangfei, 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel

On Wednesday 15 January 2014, Russell King - ARM Linux wrote:
> The issue here is that we'll potentially now end up with three
> inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> another in every driver which uses the GPIO layer inversion.  This
> is hardly the right approach as it leads to multiple points where
> confusion about the inverted status can occur.

I did not mean to suggest adding a third inversion. We already have
to deal with the one in the GPIO layer and the one in mmc_gpio_get_cd(),
which I absolutely agree is unfortunate. As was pointed out already,
the gpio driver used in this system does not support the inversion
in the DT binding, so the only proper solution is to use the
inversion from mmc_gpio_get_cd if MMC_CAP2_CD_ACTIVE_HIGH is set
in host->caps2. This flag gets set from mmc_of_parse based
on the presence of the "cd-inverted" flag, in the absence of the
gpio flags. The dw_mmc driver does not use mmc_of_parse() at the
moment, and while it probably should use that in the future,
it should definitely read the same DT properties with the
same semantics already and not introduce new properties.

	Arnd

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-16 11:12                           ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2014-01-16 11:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 15 January 2014, Russell King - ARM Linux wrote:
> The issue here is that we'll potentially now end up with three
> inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> another in every driver which uses the GPIO layer inversion.  This
> is hardly the right approach as it leads to multiple points where
> confusion about the inverted status can occur.

I did not mean to suggest adding a third inversion. We already have
to deal with the one in the GPIO layer and the one in mmc_gpio_get_cd(),
which I absolutely agree is unfortunate. As was pointed out already,
the gpio driver used in this system does not support the inversion
in the DT binding, so the only proper solution is to use the
inversion from mmc_gpio_get_cd if MMC_CAP2_CD_ACTIVE_HIGH is set
in host->caps2. This flag gets set from mmc_of_parse based
on the presence of the "cd-inverted" flag, in the absence of the
gpio flags. The dw_mmc driver does not use mmc_of_parse() at the
moment, and while it probably should use that in the future,
it should definitely read the same DT properties with the
same semantics already and not introduce new properties.

	Arnd

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

* Re: [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
  2014-01-16 11:12                           ` Arnd Bergmann
@ 2014-01-16 11:25                             ` Russell King - ARM Linux
  -1 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-16 11:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: zhangfei, 'Kevin Hilman', 'Mike Turquette',
	patches, Seungwon Jeon, linux-mmc, 'Jaehoon Chung',
	'Sachin Kamat', 'Chris Ball',
	linux-arm-kernel

On Thu, Jan 16, 2014 at 12:12:10PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014, Russell King - ARM Linux wrote:
> > The issue here is that we'll potentially now end up with three
> > inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> > another in every driver which uses the GPIO layer inversion.  This
> > is hardly the right approach as it leads to multiple points where
> > confusion about the inverted status can occur.
> 
> I did not mean to suggest adding a third inversion. We already have
> to deal with the one in the GPIO layer and the one in mmc_gpio_get_cd(),
> which I absolutely agree is unfortunate. As was pointed out already,
> the gpio driver used in this system does not support the inversion
> in the DT binding, so the only proper solution is to use the
> inversion from mmc_gpio_get_cd if MMC_CAP2_CD_ACTIVE_HIGH is set
> in host->caps2. This flag gets set from mmc_of_parse based
> on the presence of the "cd-inverted" flag, in the absence of the
> gpio flags. The dw_mmc driver does not use mmc_of_parse() at the
> moment, and while it probably should use that in the future,
> it should definitely read the same DT properties with the
> same semantics already and not introduce new properties.

Arnd,

The issue I'm pointing out is that _if_ you use the GPIO layer to do
the inversion, then you end up with _three_ inversions of the signal,
which is excessive and confusing - and makes the sense of
mmc_gpio_get_cd() completely indeterminant without reading the DT
files and the code.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* [PATCH] mmc: dw_mmc: fix dw_mci_get_cd
@ 2014-01-16 11:25                             ` Russell King - ARM Linux
  0 siblings, 0 replies; 146+ messages in thread
From: Russell King - ARM Linux @ 2014-01-16 11:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Jan 16, 2014 at 12:12:10PM +0100, Arnd Bergmann wrote:
> On Wednesday 15 January 2014, Russell King - ARM Linux wrote:
> > The issue here is that we'll potentially now end up with three
> > inversions.  One in the GPIO layers.  One in mmc_gpio_get_cd(), and
> > another in every driver which uses the GPIO layer inversion.  This
> > is hardly the right approach as it leads to multiple points where
> > confusion about the inverted status can occur.
> 
> I did not mean to suggest adding a third inversion. We already have
> to deal with the one in the GPIO layer and the one in mmc_gpio_get_cd(),
> which I absolutely agree is unfortunate. As was pointed out already,
> the gpio driver used in this system does not support the inversion
> in the DT binding, so the only proper solution is to use the
> inversion from mmc_gpio_get_cd if MMC_CAP2_CD_ACTIVE_HIGH is set
> in host->caps2. This flag gets set from mmc_of_parse based
> on the presence of the "cd-inverted" flag, in the absence of the
> gpio flags. The dw_mmc driver does not use mmc_of_parse() at the
> moment, and while it probably should use that in the future,
> it should definitely read the same DT properties with the
> same semantics already and not introduce new properties.

Arnd,

The issue I'm pointing out is that _if_ you use the GPIO layer to do
the inversion, then you end up with _three_ inversions of the signal,
which is excessive and confusing - and makes the sense of
mmc_gpio_get_cd() completely indeterminant without reading the DT
files and the code.

-- 
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up.  Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-28 14:34   ` Zhangfei Gao
@ 2014-01-02  3:07     ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-02  3:07 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao,
	Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
 4 files changed, 203 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..68e5e428e8f6
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	if (!rate) {
+		dev_warn(host->dev,
+			"no specified rate in timing %u\n", ios->timing);
+		return;
+	}
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-02  3:07     ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2014-01-02  3:07 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  132 ++++++++++++++++++++
 4 files changed, 203 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..68e5e428e8f6
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	if (!rate) {
+		dev_warn(host->dev,
+			"no specified rate in timing %u\n", ios->timing);
+		return;
+	}
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-31 13:20       ` Gerhard Sittig
@ 2014-01-02  2:19         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-02  2:19 UTC (permalink / raw)
  To: Arnd Bergmann, Chris Ball, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, patches, devicetree, Zhigang Wang



On 12/31/2013 09:20 PM, Gerhard Sittig wrote:
> On Sun, Dec 29, 2013 at 22:05 +0100, Arnd Bergmann wrote:
>>
>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>
>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>> +{
>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>> +	u32 rate = priv->clk_table[ios->timing];
>>> +	int ret;
>>
>> [ ... ]
>>
>>> +
>>> +	ret = clk_set_rate(host->ciu_clk, rate);
>>> +	if (ret)
>>> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>> +
>>> +	host->bus_hz = clk_get_rate(host->ciu_clk);
>>> +}
>>
>> Why do you call clk_get_rate() here, shouldn't it always be the same
>> rate that you have just set?
>
> Not necessarily.  What you pass to clk_set_rate() is the
> rate/frequency that you _want_, while what you get from
> clk_get_rate() is the rate you _got_ taking the specific input
> clock rate and the available sets of multipliers/dividers into
> consideration.  Both values should be similar (roughly the same),
> but they need not be identical.  The order of the difference
> depends on the granularity of the hardware dividers or whether
> PLLs are used.
>
> So, re-fetching the resulting rate after setting up a desired
> rate actually better reflects the status-quo for diagnostics or
> for subsequent processing.

Thanks Gerhard for the professional explanation.


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2014-01-02  2:19         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2014-01-02  2:19 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/31/2013 09:20 PM, Gerhard Sittig wrote:
> On Sun, Dec 29, 2013 at 22:05 +0100, Arnd Bergmann wrote:
>>
>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>
>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>> +{
>>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>>> +	u32 rate = priv->clk_table[ios->timing];
>>> +	int ret;
>>
>> [ ... ]
>>
>>> +
>>> +	ret = clk_set_rate(host->ciu_clk, rate);
>>> +	if (ret)
>>> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>> +
>>> +	host->bus_hz = clk_get_rate(host->ciu_clk);
>>> +}
>>
>> Why do you call clk_get_rate() here, shouldn't it always be the same
>> rate that you have just set?
>
> Not necessarily.  What you pass to clk_set_rate() is the
> rate/frequency that you _want_, while what you get from
> clk_get_rate() is the rate you _got_ taking the specific input
> clock rate and the available sets of multipliers/dividers into
> consideration.  Both values should be similar (roughly the same),
> but they need not be identical.  The order of the difference
> depends on the granularity of the hardware dividers or whether
> PLLs are used.
>
> So, re-fetching the resulting rate after setting up a desired
> rate actually better reflects the status-quo for diagnostics or
> for subsequent processing.

Thanks Gerhard for the professional explanation.

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-29 21:05     ` Arnd Bergmann
@ 2013-12-31 13:20       ` Gerhard Sittig
  -1 siblings, 0 replies; 146+ messages in thread
From: Gerhard Sittig @ 2013-12-31 13:20 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Zhangfei Gao, Chris Ball, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc, linux-arm-kernel, patches, devicetree, Zhigang Wang

On Sun, Dec 29, 2013 at 22:05 +0100, Arnd Bergmann wrote:
> 
> On Saturday 28 December 2013, Zhangfei Gao wrote:
> 
> > +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> > +{
> > +	struct dw_mci_k3_priv_data *priv = host->priv;
> > +	u32 rate = priv->clk_table[ios->timing];
> > +	int ret;
> 
> [ ... ]
> 
> > +
> > +	ret = clk_set_rate(host->ciu_clk, rate);
> > +	if (ret)
> > +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> > +
> > +	host->bus_hz = clk_get_rate(host->ciu_clk);
> > +}
> 
> Why do you call clk_get_rate() here, shouldn't it always be the same
> rate that you have just set?

Not necessarily.  What you pass to clk_set_rate() is the
rate/frequency that you _want_, while what you get from
clk_get_rate() is the rate you _got_ taking the specific input
clock rate and the available sets of multipliers/dividers into
consideration.  Both values should be similar (roughly the same),
but they need not be identical.  The order of the difference
depends on the granularity of the hardware dividers or whether
PLLs are used.

So, re-fetching the resulting rate after setting up a desired
rate actually better reflects the status-quo for diagnostics or
for subsequent processing.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-31 13:20       ` Gerhard Sittig
  0 siblings, 0 replies; 146+ messages in thread
From: Gerhard Sittig @ 2013-12-31 13:20 UTC (permalink / raw)
  To: linux-arm-kernel

On Sun, Dec 29, 2013 at 22:05 +0100, Arnd Bergmann wrote:
> 
> On Saturday 28 December 2013, Zhangfei Gao wrote:
> 
> > +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> > +{
> > +	struct dw_mci_k3_priv_data *priv = host->priv;
> > +	u32 rate = priv->clk_table[ios->timing];
> > +	int ret;
> 
> [ ... ]
> 
> > +
> > +	ret = clk_set_rate(host->ciu_clk, rate);
> > +	if (ret)
> > +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> > +
> > +	host->bus_hz = clk_get_rate(host->ciu_clk);
> > +}
> 
> Why do you call clk_get_rate() here, shouldn't it always be the same
> rate that you have just set?

Not necessarily.  What you pass to clk_set_rate() is the
rate/frequency that you _want_, while what you get from
clk_get_rate() is the rate you _got_ taking the specific input
clock rate and the available sets of multipliers/dividers into
consideration.  Both values should be similar (roughly the same),
but they need not be identical.  The order of the difference
depends on the granularity of the hardware dividers or whether
PLLs are used.

So, re-fetching the resulting rate after setting up a desired
rate actually better reflects the status-quo for diagnostics or
for subsequent processing.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office at denx.de

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-30 20:27             ` Arnd Bergmann
@ 2013-12-31  4:43               ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-31  4:43 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Zhangfei Gao, Jaehoon Chung, devicetree, Mike Turquette, patches,
	Seungwon Jeon, linux-mmc, Haojian Zhuang, cpgs, Kumar Gala,
	Chris Ball, Zhigang Wang, linux-arm-kernel

Dear Arnd,

On 12/31/2013 04:27 AM, Arnd Bergmann wrote:
> On Monday 30 December 2013, zhangfei wrote:
>>>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>>>> +{
>>>>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>>>>> +    int ret = 0;
>>>>>> +
>>>>>> +    ret = dw_mci_suspend(host);
>>>>>
>>>>> You should never initialize local variables when they are set later in the
>>>>> function (the ret = 0 part above). For more complex functions, this prevents
>>>>> gcc from warning you about accidentally uninitialized uses.
>>
>> I am sorry I may fall into the dead end, but still quite not understand
>> this rule.
>> I alwayes thought it would be a good habit to init local variables before.
>> Do you mean it should NOT init local variable as much as possible and
>> only init on demand, like solving the gcc warning.
>> Why not init the them at start in case random value cause unpredicted error?
>
> The gcc warnings are 100% correct, we can use them as a tool to write better
> code. If you write code that has no warnings with a modern compiler, you will
> never use random values, but if you always initialize the local variables,
> you can end up accidentally using '0' where you shouldn't have.
>
> See http://rusty.ozlabs.org/?p=232 for an excellent article on the topic
> by former Linaro assignee Rusty Russell.
>

Excellent, this is what I am looking for.
Thanks for the patience.
I may need some time and gradually change the habit to diminish the hurt 
memory caused by uninitialized vector.
Will update and take care latter.

By the way, are you fine with the other comments' explanation.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-31  4:43               ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-31  4:43 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Arnd,

On 12/31/2013 04:27 AM, Arnd Bergmann wrote:
> On Monday 30 December 2013, zhangfei wrote:
>>>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>>>> +{
>>>>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>>>>> +    int ret = 0;
>>>>>> +
>>>>>> +    ret = dw_mci_suspend(host);
>>>>>
>>>>> You should never initialize local variables when they are set later in the
>>>>> function (the ret = 0 part above). For more complex functions, this prevents
>>>>> gcc from warning you about accidentally uninitialized uses.
>>
>> I am sorry I may fall into the dead end, but still quite not understand
>> this rule.
>> I alwayes thought it would be a good habit to init local variables before.
>> Do you mean it should NOT init local variable as much as possible and
>> only init on demand, like solving the gcc warning.
>> Why not init the them at start in case random value cause unpredicted error?
>
> The gcc warnings are 100% correct, we can use them as a tool to write better
> code. If you write code that has no warnings with a modern compiler, you will
> never use random values, but if you always initialize the local variables,
> you can end up accidentally using '0' where you shouldn't have.
>
> See http://rusty.ozlabs.org/?p=232 for an excellent article on the topic
> by former Linaro assignee Rusty Russell.
>

Excellent, this is what I am looking for.
Thanks for the patience.
I may need some time and gradually change the habit to diminish the hurt 
memory caused by uninitialized vector.
Will update and take care latter.

By the way, are you fine with the other comments' explanation.

Thanks

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-30 17:19           ` zhangfei
@ 2013-12-30 20:27             ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-30 20:27 UTC (permalink / raw)
  To: zhangfei
  Cc: Zhangfei Gao, Jaehoon Chung, devicetree, Mike Turquette, patches,
	Seungwon Jeon, linux-mmc, Haojian Zhuang, cpgs, Kumar Gala,
	Chris Ball, Zhigang Wang, linux-arm-kernel

On Monday 30 December 2013, zhangfei wrote:
> >>>> +static int dw_mci_k3_suspend(struct device *dev)
> >>>> +{
> >>>> +    struct dw_mci *host = dev_get_drvdata(dev);
> >>>> +    int ret = 0;
> >>>> +
> >>>> +    ret = dw_mci_suspend(host);
> >>>
> >>> You should never initialize local variables when they are set later in the
> >>> function (the ret = 0 part above). For more complex functions, this prevents
> >>> gcc from warning you about accidentally uninitialized uses.
> 
> I am sorry I may fall into the dead end, but still quite not understand 
> this rule.
> I alwayes thought it would be a good habit to init local variables before.
> Do you mean it should NOT init local variable as much as possible and 
> only init on demand, like solving the gcc warning.
> Why not init the them at start in case random value cause unpredicted error?

The gcc warnings are 100% correct, we can use them as a tool to write better
code. If you write code that has no warnings with a modern compiler, you will
never use random values, but if you always initialize the local variables,
you can end up accidentally using '0' where you shouldn't have.

See http://rusty.ozlabs.org/?p=232 for an excellent article on the topic
by former Linaro assignee Rusty Russell.

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-30 20:27             ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-30 20:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Monday 30 December 2013, zhangfei wrote:
> >>>> +static int dw_mci_k3_suspend(struct device *dev)
> >>>> +{
> >>>> +    struct dw_mci *host = dev_get_drvdata(dev);
> >>>> +    int ret = 0;
> >>>> +
> >>>> +    ret = dw_mci_suspend(host);
> >>>
> >>> You should never initialize local variables when they are set later in the
> >>> function (the ret = 0 part above). For more complex functions, this prevents
> >>> gcc from warning you about accidentally uninitialized uses.
> 
> I am sorry I may fall into the dead end, but still quite not understand 
> this rule.
> I alwayes thought it would be a good habit to init local variables before.
> Do you mean it should NOT init local variable as much as possible and 
> only init on demand, like solving the gcc warning.
> Why not init the them at start in case random value cause unpredicted error?

The gcc warnings are 100% correct, we can use them as a tool to write better
code. If you write code that has no warnings with a modern compiler, you will
never use random values, but if you always initialize the local variables,
you can end up accidentally using '0' where you shouldn't have.

See http://rusty.ozlabs.org/?p=232 for an excellent article on the topic
by former Linaro assignee Rusty Russell.

	Arnd

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-30  2:32         ` Zhangfei Gao
@ 2013-12-30 17:19           ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-30 17:19 UTC (permalink / raw)
  To: Zhangfei Gao, Jaehoon Chung
  Cc: Arnd Bergmann, devicetree, Mike Turquette, patches,
	Seungwon Jeon, linux-mmc, Haojian Zhuang, cpgs, Kumar Gala,
	Chris Ball, Zhigang Wang, linux-arm-kernel



On 12/30/2013 10:32 AM, Zhangfei Gao wrote:
> On Mon, Dec 30, 2013 at 7:55 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
>>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>>>> ---
>>>>   .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>>>   drivers/mmc/host/Kconfig                           |   10 ++
>>>>   drivers/mmc/host/Makefile                          |    1 +
>>>>   drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>>>   4 files changed, 197 insertions(+)
>>>>   create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>>   create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>> new file mode 100644
>>>> index 000000000000..d7e2d7f159bb
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>> @@ -0,0 +1,60 @@
>>>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>>>> +  Storage Host Controller
>>>> +
>>>> +Read synopsys-dw-mshc.txt for more details
>>>> +
>>>> +The Synopsys designware mobile storage host controller is used to interface
>>>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>>>> +differences between the core Synopsys dw mshc controller properties described
>>>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>>>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>>>> +
>>>> +Required Properties:
>>>> +
>>>> +* compatible: should be one of the following.
>>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>>>
>>> I wonder if this is actually a different variant of the mshc hardware, or just
>>> wired up in a different way. Do you know details?
>>>
>>> Since the only difference in the binding is the presence of the "clock-freq-table"
>>> property, we could also make this property generic for the mshc driver and use
>>> it if present but fall back to the normal behavior when it is absent.
>
> There are still other differences and limitations besides "clock-freq-table".
> The controller seems less intelligent than other Synopsys mmc controller.
> The tuning process like HS200 is not intelligent, as a result, some
> local registers are added to help this.
>
>>>
>>>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>>>> +    in each supported mode.
>>>> +    0. CIU clock rate in Hz for DS mode
>>>> +    1. CIU clock rate in Hz for MMC HS mode
>>>> +    2. CIU clock rate in Hz for SD HS mode
>>>> +    3. CIU clock rate in Hz for SDR12 mode
>>>> +    4. CIU clock rate in Hz for SDR25 mode
>>>> +    5. CIU clock rate in Hz for SDR50 mode
>>>> +    6. CIU clock rate in Hz for SDR104 mode
>>>> +    7. CIU clock rate in Hz for DDR50 mode
>>>> +    8. CIU clock rate in Hz for HS200 mode
>>>
>>> This looks god now.
>>>
>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>> +{
>>>> +    struct dw_mci_k3_priv_data *priv = host->priv;
>>>> +    u32 rate = priv->clk_table[ios->timing];
>>>> +    int ret;
>>>
>>> I think this should have some range checking to see if the mode that is
>>> being set had a clock frequency set in the DT.
>
> The range safety should be ensured by the clk_table array, MAX_NUMS=10.
>>>
>>>> +
>>>> +    ret = clk_set_rate(host->ciu_clk, rate);
>>>> +    if (ret)
>>>> +            dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>>> +
>>>> +    host->bus_hz = clk_get_rate(host->ciu_clk);
>>>> +}
>>>
>>> Why do you call clk_get_rate() here, shouldn't it always be the same
>>> rate that you have just set?
>
> It is more accurate to use clk_get_rate here.
> For example, if switch to ios->clock as you suggested before, 52M will
> be set for mmc, while 50M is supported.
> However, it can simply use rate set currently.
>
>>>
>>>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>>>> +{
>>>> +    struct dw_mci_k3_priv_data *priv;
>>>> +    struct device_node *node = host->dev->of_node;
>>>> +    struct property *prop;
>>>> +    const __be32 *cur;
>>>> +    u32 val, num = 0;
>>>> +
>>>> +    priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>>>> +    if (!priv) {
>>>> +            dev_err(host->dev, "mem alloc failed for private data\n");
>>>> +            return -ENOMEM;
>>>> +    }
>>>> +    host->priv = priv;
>>>> +
>>>> +    of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>>>> +            if (num >= MAX_NUMS)
>>>> +                    break;
>>>> +            priv->clk_table[num++] = val;
>>>> +    }
>>>> +    return 0;
>>>> +}
>>>
>>> If we make this property part of the generic binding, this function could
>>> also get moved to the main dw_mci driver.
>
> This may be not general.
> The controller does not generate the clock itself, and set rate to the
> outside clock source, which may be different according to the working
> mode.
>
>>>
>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>> +{
>>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>>> +    int ret = 0;
>>>> +
>>>> +    ret = dw_mci_suspend(host);
>>>
>>> You should never initialize local variables when they are set later in the
>>> function (the ret = 0 part above). For more complex functions, this prevents
>>> gcc from warning you about accidentally uninitialized uses.

I am sorry I may fall into the dead end, but still quite not understand 
this rule.
I alwayes thought it would be a good habit to init local variables before.
Do you mean it should NOT init local variable as much as possible and 
only init on demand, like solving the gcc warning.
Why not init the them at start in case random value cause unpredicted error?

>
> Frankly speaking, I didn't know this rule at all.
> Often see the warning before like “Variable to be used not initialized”,
> so preferred to init the local variable as much as possible.
> Looks like it is wrong.
>
>>>
>>>> +    if (!ret)
>>>> +            clk_disable_unprepare(host->ciu_clk);
>>>> +
>>>> +    return ret;
>>>> +}
>>>
>>> The suspend/resume code also looks very generic. Can't we make these the
>>> default for dw-mci? If you do both, you won't even need a k3 specific driver.
>>> I think in general we should try hard to add code like this to the common
>>> driver when there is a chance that it can be shared with other platforms.
>>
>> Dw-mmc has the LOW_POWER mode feature at CLKENA register,
>> this feature is running like clock-gating.
>> So i have known it didn't control clock enable/disable in dw-mmc.c.
>
> It is added here since we have to set special register when resume
> back, which has been abstracted to ciu_clk prepare operation.
>
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>>        Arnd
>>>
>>
>>
>> _______________________________________________
>> 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] 146+ messages in thread

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-30 17:19           ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-30 17:19 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/30/2013 10:32 AM, Zhangfei Gao wrote:
> On Mon, Dec 30, 2013 at 7:55 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>> On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
>>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>>>
>>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>>>> ---
>>>>   .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>>>   drivers/mmc/host/Kconfig                           |   10 ++
>>>>   drivers/mmc/host/Makefile                          |    1 +
>>>>   drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>>>   4 files changed, 197 insertions(+)
>>>>   create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>>   create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>> new file mode 100644
>>>> index 000000000000..d7e2d7f159bb
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>> @@ -0,0 +1,60 @@
>>>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>>>> +  Storage Host Controller
>>>> +
>>>> +Read synopsys-dw-mshc.txt for more details
>>>> +
>>>> +The Synopsys designware mobile storage host controller is used to interface
>>>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>>>> +differences between the core Synopsys dw mshc controller properties described
>>>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>>>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>>>> +
>>>> +Required Properties:
>>>> +
>>>> +* compatible: should be one of the following.
>>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>>>
>>> I wonder if this is actually a different variant of the mshc hardware, or just
>>> wired up in a different way. Do you know details?
>>>
>>> Since the only difference in the binding is the presence of the "clock-freq-table"
>>> property, we could also make this property generic for the mshc driver and use
>>> it if present but fall back to the normal behavior when it is absent.
>
> There are still other differences and limitations besides "clock-freq-table".
> The controller seems less intelligent than other Synopsys mmc controller.
> The tuning process like HS200 is not intelligent, as a result, some
> local registers are added to help this.
>
>>>
>>>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>>>> +    in each supported mode.
>>>> +    0. CIU clock rate in Hz for DS mode
>>>> +    1. CIU clock rate in Hz for MMC HS mode
>>>> +    2. CIU clock rate in Hz for SD HS mode
>>>> +    3. CIU clock rate in Hz for SDR12 mode
>>>> +    4. CIU clock rate in Hz for SDR25 mode
>>>> +    5. CIU clock rate in Hz for SDR50 mode
>>>> +    6. CIU clock rate in Hz for SDR104 mode
>>>> +    7. CIU clock rate in Hz for DDR50 mode
>>>> +    8. CIU clock rate in Hz for HS200 mode
>>>
>>> This looks god now.
>>>
>>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>>> +{
>>>> +    struct dw_mci_k3_priv_data *priv = host->priv;
>>>> +    u32 rate = priv->clk_table[ios->timing];
>>>> +    int ret;
>>>
>>> I think this should have some range checking to see if the mode that is
>>> being set had a clock frequency set in the DT.
>
> The range safety should be ensured by the clk_table array, MAX_NUMS=10.
>>>
>>>> +
>>>> +    ret = clk_set_rate(host->ciu_clk, rate);
>>>> +    if (ret)
>>>> +            dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>>> +
>>>> +    host->bus_hz = clk_get_rate(host->ciu_clk);
>>>> +}
>>>
>>> Why do you call clk_get_rate() here, shouldn't it always be the same
>>> rate that you have just set?
>
> It is more accurate to use clk_get_rate here.
> For example, if switch to ios->clock as you suggested before, 52M will
> be set for mmc, while 50M is supported.
> However, it can simply use rate set currently.
>
>>>
>>>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>>>> +{
>>>> +    struct dw_mci_k3_priv_data *priv;
>>>> +    struct device_node *node = host->dev->of_node;
>>>> +    struct property *prop;
>>>> +    const __be32 *cur;
>>>> +    u32 val, num = 0;
>>>> +
>>>> +    priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>>>> +    if (!priv) {
>>>> +            dev_err(host->dev, "mem alloc failed for private data\n");
>>>> +            return -ENOMEM;
>>>> +    }
>>>> +    host->priv = priv;
>>>> +
>>>> +    of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>>>> +            if (num >= MAX_NUMS)
>>>> +                    break;
>>>> +            priv->clk_table[num++] = val;
>>>> +    }
>>>> +    return 0;
>>>> +}
>>>
>>> If we make this property part of the generic binding, this function could
>>> also get moved to the main dw_mci driver.
>
> This may be not general.
> The controller does not generate the clock itself, and set rate to the
> outside clock source, which may be different according to the working
> mode.
>
>>>
>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>> +{
>>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>>> +    int ret = 0;
>>>> +
>>>> +    ret = dw_mci_suspend(host);
>>>
>>> You should never initialize local variables when they are set later in the
>>> function (the ret = 0 part above). For more complex functions, this prevents
>>> gcc from warning you about accidentally uninitialized uses.

I am sorry I may fall into the dead end, but still quite not understand 
this rule.
I alwayes thought it would be a good habit to init local variables before.
Do you mean it should NOT init local variable as much as possible and 
only init on demand, like solving the gcc warning.
Why not init the them at start in case random value cause unpredicted error?

>
> Frankly speaking, I didn't know this rule at all.
> Often see the warning before like ?Variable to be used not initialized?,
> so preferred to init the local variable as much as possible.
> Looks like it is wrong.
>
>>>
>>>> +    if (!ret)
>>>> +            clk_disable_unprepare(host->ciu_clk);
>>>> +
>>>> +    return ret;
>>>> +}
>>>
>>> The suspend/resume code also looks very generic. Can't we make these the
>>> default for dw-mci? If you do both, you won't even need a k3 specific driver.
>>> I think in general we should try hard to add code like this to the common
>>> driver when there is a chance that it can be shared with other platforms.
>>
>> Dw-mmc has the LOW_POWER mode feature at CLKENA register,
>> this feature is running like clock-gating.
>> So i have known it didn't control clock enable/disable in dw-mmc.c.
>
> It is added here since we have to set special register when resume
> back, which has been abstracted to ciu_clk prepare operation.
>
>>
>> Best Regards,
>> Jaehoon Chung
>>
>>>
>>>        Arnd
>>>
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-29 23:55       ` Jaehoon Chung
@ 2013-12-30  2:32         ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-30  2:32 UTC (permalink / raw)
  To: Jaehoon Chung
  Cc: Arnd Bergmann, Zhangfei Gao, devicetree, Mike Turquette, patches,
	Seungwon Jeon, linux-mmc, Haojian Zhuang, cpgs, Kumar Gala,
	Chris Ball, Zhigang Wang, linux-arm-kernel

On Mon, Dec 30, 2013 at 7:55 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>>
>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>>> ---
>>>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>>  drivers/mmc/host/Kconfig                           |   10 ++
>>>  drivers/mmc/host/Makefile                          |    1 +
>>>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>>  4 files changed, 197 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>> new file mode 100644
>>> index 000000000000..d7e2d7f159bb
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>> @@ -0,0 +1,60 @@
>>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>>> +  Storage Host Controller
>>> +
>>> +Read synopsys-dw-mshc.txt for more details
>>> +
>>> +The Synopsys designware mobile storage host controller is used to interface
>>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>>> +differences between the core Synopsys dw mshc controller properties described
>>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>>> +
>>> +Required Properties:
>>> +
>>> +* compatible: should be one of the following.
>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>>
>> I wonder if this is actually a different variant of the mshc hardware, or just
>> wired up in a different way. Do you know details?
>>
>> Since the only difference in the binding is the presence of the "clock-freq-table"
>> property, we could also make this property generic for the mshc driver and use
>> it if present but fall back to the normal behavior when it is absent.

There are still other differences and limitations besides "clock-freq-table".
The controller seems less intelligent than other Synopsys mmc controller.
The tuning process like HS200 is not intelligent, as a result, some
local registers are added to help this.

>>
>>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>>> +    in each supported mode.
>>> +    0. CIU clock rate in Hz for DS mode
>>> +    1. CIU clock rate in Hz for MMC HS mode
>>> +    2. CIU clock rate in Hz for SD HS mode
>>> +    3. CIU clock rate in Hz for SDR12 mode
>>> +    4. CIU clock rate in Hz for SDR25 mode
>>> +    5. CIU clock rate in Hz for SDR50 mode
>>> +    6. CIU clock rate in Hz for SDR104 mode
>>> +    7. CIU clock rate in Hz for DDR50 mode
>>> +    8. CIU clock rate in Hz for HS200 mode
>>
>> This looks god now.
>>
>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>> +{
>>> +    struct dw_mci_k3_priv_data *priv = host->priv;
>>> +    u32 rate = priv->clk_table[ios->timing];
>>> +    int ret;
>>
>> I think this should have some range checking to see if the mode that is
>> being set had a clock frequency set in the DT.

The range safety should be ensured by the clk_table array, MAX_NUMS=10.
>>
>>> +
>>> +    ret = clk_set_rate(host->ciu_clk, rate);
>>> +    if (ret)
>>> +            dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>> +
>>> +    host->bus_hz = clk_get_rate(host->ciu_clk);
>>> +}
>>
>> Why do you call clk_get_rate() here, shouldn't it always be the same
>> rate that you have just set?

It is more accurate to use clk_get_rate here.
For example, if switch to ios->clock as you suggested before, 52M will
be set for mmc, while 50M is supported.
However, it can simply use rate set currently.

>>
>>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>>> +{
>>> +    struct dw_mci_k3_priv_data *priv;
>>> +    struct device_node *node = host->dev->of_node;
>>> +    struct property *prop;
>>> +    const __be32 *cur;
>>> +    u32 val, num = 0;
>>> +
>>> +    priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>>> +    if (!priv) {
>>> +            dev_err(host->dev, "mem alloc failed for private data\n");
>>> +            return -ENOMEM;
>>> +    }
>>> +    host->priv = priv;
>>> +
>>> +    of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>>> +            if (num >= MAX_NUMS)
>>> +                    break;
>>> +            priv->clk_table[num++] = val;
>>> +    }
>>> +    return 0;
>>> +}
>>
>> If we make this property part of the generic binding, this function could
>> also get moved to the main dw_mci driver.

This may be not general.
The controller does not generate the clock itself, and set rate to the
outside clock source, which may be different according to the working
mode.

>>
>>> +static int dw_mci_k3_suspend(struct device *dev)
>>> +{
>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>> +    int ret = 0;
>>> +
>>> +    ret = dw_mci_suspend(host);
>>
>> You should never initialize local variables when they are set later in the
>> function (the ret = 0 part above). For more complex functions, this prevents
>> gcc from warning you about accidentally uninitialized uses.

Frankly speaking, I didn't know this rule at all.
Often see the warning before like “Variable to be used not initialized”,
so preferred to init the local variable as much as possible.
Looks like it is wrong.

>>
>>> +    if (!ret)
>>> +            clk_disable_unprepare(host->ciu_clk);
>>> +
>>> +    return ret;
>>> +}
>>
>> The suspend/resume code also looks very generic. Can't we make these the
>> default for dw-mci? If you do both, you won't even need a k3 specific driver.
>> I think in general we should try hard to add code like this to the common
>> driver when there is a chance that it can be shared with other platforms.
>
> Dw-mmc has the LOW_POWER mode feature at CLKENA register,
> this feature is running like clock-gating.
> So i have known it didn't control clock enable/disable in dw-mmc.c.

It is added here since we have to set special register when resume
back, which has been abstracted to ciu_clk prepare operation.

>
> Best Regards,
> Jaehoon Chung
>
>>
>>       Arnd
>>
>
>
> _______________________________________________
> 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] 146+ messages in thread

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-30  2:32         ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-30  2:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Dec 30, 2013 at 7:55 AM, Jaehoon Chung <jh80.chung@samsung.com> wrote:
> On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
>> On Saturday 28 December 2013, Zhangfei Gao wrote:
>>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>>
>>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>>> ---
>>>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>>  drivers/mmc/host/Kconfig                           |   10 ++
>>>  drivers/mmc/host/Makefile                          |    1 +
>>>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>>  4 files changed, 197 insertions(+)
>>>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>> new file mode 100644
>>> index 000000000000..d7e2d7f159bb
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>> @@ -0,0 +1,60 @@
>>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>>> +  Storage Host Controller
>>> +
>>> +Read synopsys-dw-mshc.txt for more details
>>> +
>>> +The Synopsys designware mobile storage host controller is used to interface
>>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>>> +differences between the core Synopsys dw mshc controller properties described
>>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>>> +
>>> +Required Properties:
>>> +
>>> +* compatible: should be one of the following.
>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>>
>> I wonder if this is actually a different variant of the mshc hardware, or just
>> wired up in a different way. Do you know details?
>>
>> Since the only difference in the binding is the presence of the "clock-freq-table"
>> property, we could also make this property generic for the mshc driver and use
>> it if present but fall back to the normal behavior when it is absent.

There are still other differences and limitations besides "clock-freq-table".
The controller seems less intelligent than other Synopsys mmc controller.
The tuning process like HS200 is not intelligent, as a result, some
local registers are added to help this.

>>
>>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>>> +    in each supported mode.
>>> +    0. CIU clock rate in Hz for DS mode
>>> +    1. CIU clock rate in Hz for MMC HS mode
>>> +    2. CIU clock rate in Hz for SD HS mode
>>> +    3. CIU clock rate in Hz for SDR12 mode
>>> +    4. CIU clock rate in Hz for SDR25 mode
>>> +    5. CIU clock rate in Hz for SDR50 mode
>>> +    6. CIU clock rate in Hz for SDR104 mode
>>> +    7. CIU clock rate in Hz for DDR50 mode
>>> +    8. CIU clock rate in Hz for HS200 mode
>>
>> This looks god now.
>>
>>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>>> +{
>>> +    struct dw_mci_k3_priv_data *priv = host->priv;
>>> +    u32 rate = priv->clk_table[ios->timing];
>>> +    int ret;
>>
>> I think this should have some range checking to see if the mode that is
>> being set had a clock frequency set in the DT.

The range safety should be ensured by the clk_table array, MAX_NUMS=10.
>>
>>> +
>>> +    ret = clk_set_rate(host->ciu_clk, rate);
>>> +    if (ret)
>>> +            dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>>> +
>>> +    host->bus_hz = clk_get_rate(host->ciu_clk);
>>> +}
>>
>> Why do you call clk_get_rate() here, shouldn't it always be the same
>> rate that you have just set?

It is more accurate to use clk_get_rate here.
For example, if switch to ios->clock as you suggested before, 52M will
be set for mmc, while 50M is supported.
However, it can simply use rate set currently.

>>
>>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>>> +{
>>> +    struct dw_mci_k3_priv_data *priv;
>>> +    struct device_node *node = host->dev->of_node;
>>> +    struct property *prop;
>>> +    const __be32 *cur;
>>> +    u32 val, num = 0;
>>> +
>>> +    priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>>> +    if (!priv) {
>>> +            dev_err(host->dev, "mem alloc failed for private data\n");
>>> +            return -ENOMEM;
>>> +    }
>>> +    host->priv = priv;
>>> +
>>> +    of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>>> +            if (num >= MAX_NUMS)
>>> +                    break;
>>> +            priv->clk_table[num++] = val;
>>> +    }
>>> +    return 0;
>>> +}
>>
>> If we make this property part of the generic binding, this function could
>> also get moved to the main dw_mci driver.

This may be not general.
The controller does not generate the clock itself, and set rate to the
outside clock source, which may be different according to the working
mode.

>>
>>> +static int dw_mci_k3_suspend(struct device *dev)
>>> +{
>>> +    struct dw_mci *host = dev_get_drvdata(dev);
>>> +    int ret = 0;
>>> +
>>> +    ret = dw_mci_suspend(host);
>>
>> You should never initialize local variables when they are set later in the
>> function (the ret = 0 part above). For more complex functions, this prevents
>> gcc from warning you about accidentally uninitialized uses.

Frankly speaking, I didn't know this rule at all.
Often see the warning before like ?Variable to be used not initialized?,
so preferred to init the local variable as much as possible.
Looks like it is wrong.

>>
>>> +    if (!ret)
>>> +            clk_disable_unprepare(host->ciu_clk);
>>> +
>>> +    return ret;
>>> +}
>>
>> The suspend/resume code also looks very generic. Can't we make these the
>> default for dw-mci? If you do both, you won't even need a k3 specific driver.
>> I think in general we should try hard to add code like this to the common
>> driver when there is a chance that it can be shared with other platforms.
>
> Dw-mmc has the LOW_POWER mode feature at CLKENA register,
> this feature is running like clock-gating.
> So i have known it didn't control clock enable/disable in dw-mmc.c.

It is added here since we have to set special register when resume
back, which has been abstracted to ciu_clk prepare operation.

>
> Best Regards,
> Jaehoon Chung
>
>>
>>       Arnd
>>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-29 21:05     ` Arnd Bergmann
@ 2013-12-29 23:55       ` Jaehoon Chung
  -1 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2013-12-29 23:55 UTC (permalink / raw)
  To: Arnd Bergmann, Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Seungwon Jeon,
	Kumar Gala, Haojian Zhuang, linux-mmc, linux-arm-kernel, patches,
	devicetree, Zhigang Wang, cpgs

On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
> On Saturday 28 December 2013, Zhangfei Gao wrote:
>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>> ---
>>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>  drivers/mmc/host/Kconfig                           |   10 ++
>>  drivers/mmc/host/Makefile                          |    1 +
>>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>  4 files changed, 197 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>> new file mode 100644
>> index 000000000000..d7e2d7f159bb
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>> @@ -0,0 +1,60 @@
>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>> +  Storage Host Controller
>> +
>> +Read synopsys-dw-mshc.txt for more details
>> +
>> +The Synopsys designware mobile storage host controller is used to interface
>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>> +differences between the core Synopsys dw mshc controller properties described
>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>> +
>> +Required Properties:
>> +
>> +* compatible: should be one of the following.
>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> 
> I wonder if this is actually a different variant of the mshc hardware, or just
> wired up in a different way. Do you know details?
> 
> Since the only difference in the binding is the presence of the "clock-freq-table"
> property, we could also make this property generic for the mshc driver and use
> it if present but fall back to the normal behavior when it is absent.
> 
>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>> +	in each	supported mode.
>> +	0. CIU clock rate in Hz for DS mode
>> +	1. CIU clock rate in Hz for MMC HS mode
>> +	2. CIU clock rate in Hz for SD HS mode
>> +	3. CIU clock rate in Hz for SDR12 mode
>> +	4. CIU clock rate in Hz for SDR25 mode
>> +	5. CIU clock rate in Hz for SDR50 mode
>> +	6. CIU clock rate in Hz for SDR104 mode
>> +	7. CIU clock rate in Hz for DDR50 mode
>> +	8. CIU clock rate in Hz for HS200 mode
> 
> This looks god now.
> 
>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>> +	u32 rate = priv->clk_table[ios->timing];
>> +	int ret;
> 
> I think this should have some range checking to see if the mode that is
> being set had a clock frequency set in the DT.
> 
>> +
>> +	ret = clk_set_rate(host->ciu_clk, rate);
>> +	if (ret)
>> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>> +
>> +	host->bus_hz = clk_get_rate(host->ciu_clk);
>> +}
> 
> Why do you call clk_get_rate() here, shouldn't it always be the same
> rate that you have just set?
> 
>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>> +{
>> +	struct dw_mci_k3_priv_data *priv;
>> +	struct device_node *node = host->dev->of_node;
>> +	struct property *prop;
>> +	const __be32 *cur;
>> +	u32 val, num = 0;
>> +
>> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv) {
>> +		dev_err(host->dev, "mem alloc failed for private data\n");
>> +		return -ENOMEM;
>> +	}
>> +	host->priv = priv;
>> +
>> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>> +		if (num >= MAX_NUMS)
>> +			break;
>> +		priv->clk_table[num++] = val;
>> +	}
>> +	return 0;
>> +}
> 
> If we make this property part of the generic binding, this function could
> also get moved to the main dw_mci driver.
> 
>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = dw_mci_suspend(host);
> 
> You should never initialize local variables when they are set later in the
> function (the ret = 0 part above). For more complex functions, this prevents
> gcc from warning you about accidentally uninitialized uses.
> 
>> +	if (!ret)
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return ret;
>> +}
> 
> The suspend/resume code also looks very generic. Can't we make these the
> default for dw-mci? If you do both, you won't even need a k3 specific driver.
> I think in general we should try hard to add code like this to the common
> driver when there is a chance that it can be shared with other platforms.

Dw-mmc has the LOW_POWER mode feature at CLKENA register,
this feature is running like clock-gating.
So i have known it didn't control clock enable/disable in dw-mmc.c.

Best Regards,
Jaehoon Chung

> 
> 	Arnd
> 


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-29 23:55       ` Jaehoon Chung
  0 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2013-12-29 23:55 UTC (permalink / raw)
  To: linux-arm-kernel

On 12/30/2013 06:05 AM, Arnd Bergmann wrote:
> On Saturday 28 December 2013, Zhangfei Gao wrote:
>> Add dw_mmc-k3.c for k3v2, support sd/emmc
>>
>> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
>> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
>> ---
>>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>>  drivers/mmc/host/Kconfig                           |   10 ++
>>  drivers/mmc/host/Makefile                          |    1 +
>>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>>  4 files changed, 197 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>> new file mode 100644
>> index 000000000000..d7e2d7f159bb
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>> @@ -0,0 +1,60 @@
>> +* Hisilicon specific extensions to the Synopsys Designware Mobile
>> +  Storage Host Controller
>> +
>> +Read synopsys-dw-mshc.txt for more details
>> +
>> +The Synopsys designware mobile storage host controller is used to interface
>> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
>> +differences between the core Synopsys dw mshc controller properties described
>> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
>> +extensions to the Synopsys Designware Mobile Storage Host Controller.
>> +
>> +Required Properties:
>> +
>> +* compatible: should be one of the following.
>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> 
> I wonder if this is actually a different variant of the mshc hardware, or just
> wired up in a different way. Do you know details?
> 
> Since the only difference in the binding is the presence of the "clock-freq-table"
> property, we could also make this property generic for the mshc driver and use
> it if present but fall back to the normal behavior when it is absent.
> 
>> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
>> +	in each	supported mode.
>> +	0. CIU clock rate in Hz for DS mode
>> +	1. CIU clock rate in Hz for MMC HS mode
>> +	2. CIU clock rate in Hz for SD HS mode
>> +	3. CIU clock rate in Hz for SDR12 mode
>> +	4. CIU clock rate in Hz for SDR25 mode
>> +	5. CIU clock rate in Hz for SDR50 mode
>> +	6. CIU clock rate in Hz for SDR104 mode
>> +	7. CIU clock rate in Hz for DDR50 mode
>> +	8. CIU clock rate in Hz for HS200 mode
> 
> This looks god now.
> 
>> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
>> +{
>> +	struct dw_mci_k3_priv_data *priv = host->priv;
>> +	u32 rate = priv->clk_table[ios->timing];
>> +	int ret;
> 
> I think this should have some range checking to see if the mode that is
> being set had a clock frequency set in the DT.
> 
>> +
>> +	ret = clk_set_rate(host->ciu_clk, rate);
>> +	if (ret)
>> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
>> +
>> +	host->bus_hz = clk_get_rate(host->ciu_clk);
>> +}
> 
> Why do you call clk_get_rate() here, shouldn't it always be the same
> rate that you have just set?
> 
>> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
>> +{
>> +	struct dw_mci_k3_priv_data *priv;
>> +	struct device_node *node = host->dev->of_node;
>> +	struct property *prop;
>> +	const __be32 *cur;
>> +	u32 val, num = 0;
>> +
>> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
>> +	if (!priv) {
>> +		dev_err(host->dev, "mem alloc failed for private data\n");
>> +		return -ENOMEM;
>> +	}
>> +	host->priv = priv;
>> +
>> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
>> +		if (num >= MAX_NUMS)
>> +			break;
>> +		priv->clk_table[num++] = val;
>> +	}
>> +	return 0;
>> +}
> 
> If we make this property part of the generic binding, this function could
> also get moved to the main dw_mci driver.
> 
>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = dw_mci_suspend(host);
> 
> You should never initialize local variables when they are set later in the
> function (the ret = 0 part above). For more complex functions, this prevents
> gcc from warning you about accidentally uninitialized uses.
> 
>> +	if (!ret)
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return ret;
>> +}
> 
> The suspend/resume code also looks very generic. Can't we make these the
> default for dw-mci? If you do both, you won't even need a k3 specific driver.
> I think in general we should try hard to add code like this to the common
> driver when there is a chance that it can be shared with other platforms.

Dw-mmc has the LOW_POWER mode feature at CLKENA register,
this feature is running like clock-gating.
So i have known it didn't control clock enable/disable in dw-mmc.c.

Best Regards,
Jaehoon Chung

> 
> 	Arnd
> 

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-28 14:34   ` Zhangfei Gao
@ 2013-12-29 21:05     ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-29 21:05 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree, Zhigang Wang

On Saturday 28 December 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>  4 files changed, 197 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.

I wonder if this is actually a different variant of the mshc hardware, or just
wired up in a different way. Do you know details?

Since the only difference in the binding is the presence of the "clock-freq-table"
property, we could also make this property generic for the mshc driver and use
it if present but fall back to the normal behavior when it is absent.

> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode

This looks god now.

> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;

I think this should have some range checking to see if the mode that is
being set had a clock frequency set in the DT.

> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}

Why do you call clk_get_rate() here, shouldn't it always be the same
rate that you have just set?

> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}

If we make this property part of the generic binding, this function could
also get moved to the main dw_mci driver.

> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = dw_mci_suspend(host);

You should never initialize local variables when they are set later in the
function (the ret = 0 part above). For more complex functions, this prevents
gcc from warning you about accidentally uninitialized uses.

> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}

The suspend/resume code also looks very generic. Can't we make these the
default for dw-mci? If you do both, you won't even need a k3 specific driver.
I think in general we should try hard to add code like this to the common
driver when there is a chance that it can be shared with other platforms.

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-29 21:05     ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-29 21:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Saturday 28 December 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
>  4 files changed, 197 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.

I wonder if this is actually a different variant of the mshc hardware, or just
wired up in a different way. Do you know details?

Since the only difference in the binding is the presence of the "clock-freq-table"
property, we could also make this property generic for the mshc driver and use
it if present but fall back to the normal behavior when it is absent.

> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode

This looks god now.

> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;

I think this should have some range checking to see if the mode that is
being set had a clock frequency set in the DT.

> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}

Why do you call clk_get_rate() here, shouldn't it always be the same
rate that you have just set?

> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}

If we make this property part of the generic binding, this function could
also get moved to the main dw_mci driver.

> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = dw_mci_suspend(host);

You should never initialize local variables when they are set later in the
function (the ret = 0 part above). For more complex functions, this prevents
gcc from warning you about accidentally uninitialized uses.

> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}

The suspend/resume code also looks very generic. Can't we make these the
default for dw-mci? If you do both, you won't even need a k3 specific driver.
I think in general we should try hard to add code like this to the common
driver when there is a chance that it can be shared with other platforms.

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-28 14:34 [PATCH v6 " Zhangfei Gao
@ 2013-12-28 14:34   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-28 14:34 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao,
	Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
 4 files changed, 197 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..89f69428e3dc
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-28 14:34   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-28 14:34 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 ++++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  126 ++++++++++++++++++++
 4 files changed, 197 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..89f69428e3dc
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-26  4:33       ` Jaehoon Chung
@ 2013-12-27  6:13         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-27  6:13 UTC (permalink / raw)
  To: Jaehoon Chung, Chris Ball, Arnd Bergmann, Mike Turquette,
	Rob Herring, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhigang Wang, cpgs

Dear Jaehoon

Thanks for the reviewing.

On 12/26/2013 12:33 PM, Jaehoon Chung wrote:

>> +config MMC_DW_K3
>> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
>> +	depends on MMC_DW
>> +	select MMC_DW_PLTFM
>> +	select MMC_DW_IDMAC
>
> Only use the IDMAC?

IDMAC has to be set here since we found the controller have some issue 
in non-dma mode.


>> +static unsigned long k3_dwmmc_caps[4] = {
>> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
>> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
>> +	0,
>> +	0,
>> +};
>
> If supports-highspeed is defined at dt-file,
> then MMC_CAP_SD_HIGHSEEPD and MMC_CAP_MMC_HIGHSPEED should set in dw-mmc.c

Yes, good catch, they can be removed.

>
>> +
>> +static const struct dw_mci_drv_data k3_drv_data = {
>> +	.caps			= k3_dwmmc_caps,
>> +	.set_ios		= dw_mci_k3_set_ios,
>> +	.parse_dt		= dw_mci_k3_parse_dt,
>> +};
>> +
>> +static const struct of_device_id dw_mci_k3_match[] = {
>> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
>> +	{},
>> +};
>> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
>> +
>> +static int dw_mci_k3_probe(struct platform_device *pdev)
>> +{
>> +	const struct dw_mci_drv_data *drv_data;
>> +	const struct of_device_id *match;
>> +
>> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
>> +	drv_data = match->data;
>> +
>> +	return dw_mci_pltfm_register(pdev, drv_data);
>> +}
>> +
>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = dw_mci_suspend(host);
>> +	if (!ret)
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dw_mci_k3_resume(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = clk_prepare_enable(host->ciu_clk);
>> +	if (ret) {
>> +		dev_err(host->dev, "failed to enable ciu clock\n");
>> +		return ret;
>> +	}
>> +
>> +	return dw_mci_resume(host);
>> +}
>
> Clock control need in suspend/resume? ciu-clk is used into dw-mmc.c.

The ciu-clk is required here not only for power, but also clk prepare 
have to be triggered in the resume operation as well as init process, 
otherwise sd register access will fail. Some tuning registers accessing 
have been abstracted to clock.

Thanks


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-27  6:13         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-27  6:13 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Jaehoon

Thanks for the reviewing.

On 12/26/2013 12:33 PM, Jaehoon Chung wrote:

>> +config MMC_DW_K3
>> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
>> +	depends on MMC_DW
>> +	select MMC_DW_PLTFM
>> +	select MMC_DW_IDMAC
>
> Only use the IDMAC?

IDMAC has to be set here since we found the controller have some issue 
in non-dma mode.


>> +static unsigned long k3_dwmmc_caps[4] = {
>> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
>> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
>> +	0,
>> +	0,
>> +};
>
> If supports-highspeed is defined at dt-file,
> then MMC_CAP_SD_HIGHSEEPD and MMC_CAP_MMC_HIGHSPEED should set in dw-mmc.c

Yes, good catch, they can be removed.

>
>> +
>> +static const struct dw_mci_drv_data k3_drv_data = {
>> +	.caps			= k3_dwmmc_caps,
>> +	.set_ios		= dw_mci_k3_set_ios,
>> +	.parse_dt		= dw_mci_k3_parse_dt,
>> +};
>> +
>> +static const struct of_device_id dw_mci_k3_match[] = {
>> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
>> +	{},
>> +};
>> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
>> +
>> +static int dw_mci_k3_probe(struct platform_device *pdev)
>> +{
>> +	const struct dw_mci_drv_data *drv_data;
>> +	const struct of_device_id *match;
>> +
>> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
>> +	drv_data = match->data;
>> +
>> +	return dw_mci_pltfm_register(pdev, drv_data);
>> +}
>> +
>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = dw_mci_suspend(host);
>> +	if (!ret)
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return ret;
>> +}
>> +
>> +static int dw_mci_k3_resume(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +	int ret = 0;
>> +
>> +	ret = clk_prepare_enable(host->ciu_clk);
>> +	if (ret) {
>> +		dev_err(host->dev, "failed to enable ciu clock\n");
>> +		return ret;
>> +	}
>> +
>> +	return dw_mci_resume(host);
>> +}
>
> Clock control need in suspend/resume? ciu-clk is used into dw-mmc.c.

The ciu-clk is required here not only for power, but also clk prepare 
have to be triggered in the resume operation as well as init process, 
otherwise sd register access will fail. Some tuning registers accessing 
have been abstracted to clock.

Thanks

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16 13:12     ` Zhangfei Gao
@ 2013-12-26  4:33       ` Jaehoon Chung
  -1 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2013-12-26  4:33 UTC (permalink / raw)
  To: Zhangfei Gao, Chris Ball, Arnd Bergmann, Mike Turquette,
	Rob Herring, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhigang Wang, cpgs

Hi, Zhangfei,

On 12/16/2013 10:12 PM, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
>  4 files changed, 205 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0@fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> +	};
> +
> +	/* Board portion */
> +	dwmmc0@fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot@0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
>  
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC

Only use the IDMAC?

> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..e3eea2883ae7
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static unsigned long k3_dwmmc_caps[4] = {
> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
> +	0,
> +	0,
> +};

If supports-highspeed is defined at dt-file,
then MMC_CAP_SD_HIGHSEEPD and MMC_CAP_MMC_HIGHSPEED should set in dw-mmc.c 

> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.caps			= k3_dwmmc_caps,
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = dw_mci_suspend(host);
> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}

Clock control need in suspend/resume? ciu-clk is used into dw-mmc.c.

Best Regards,
Jaehoon Chung

> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> 


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-26  4:33       ` Jaehoon Chung
  0 siblings, 0 replies; 146+ messages in thread
From: Jaehoon Chung @ 2013-12-26  4:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi, Zhangfei,

On 12/16/2013 10:12 PM, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
>  4 files changed, 205 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0 at fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> +	};
> +
> +	/* Board portion */
> +	dwmmc0 at fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot at 0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
>  
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC

Only use the IDMAC?

> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..e3eea2883ae7
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,134 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static unsigned long k3_dwmmc_caps[4] = {
> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
> +	0,
> +	0,
> +};

If supports-highspeed is defined at dt-file,
then MMC_CAP_SD_HIGHSEEPD and MMC_CAP_MMC_HIGHSPEED should set in dw-mmc.c 

> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.caps			= k3_dwmmc_caps,
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = dw_mci_suspend(host);
> +	if (!ret)
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return ret;
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}

Clock control need in suspend/resume? ciu-clk is used into dw-mmc.c.

Best Regards,
Jaehoon Chung

> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> 

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16 13:12     ` Zhangfei Gao
@ 2013-12-20  2:31       ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-20  2:31 UTC (permalink / raw)
  To: Zhangfei Gao, Chris Ball, Arnd Bergmann, Mike Turquette,
	Rob Herring, Jaehoon Chung, Seungwon Jeon, Kumar Gala,
	Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhigang Wang



On 12/16/2013 09:12 PM, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>   .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>   drivers/mmc/host/Kconfig                           |   10 ++
>   drivers/mmc/host/Makefile                          |    1 +
>   drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
>   4 files changed, 205 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>   create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>

Any comments?

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-20  2:31       ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-20  2:31 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/16/2013 09:12 PM, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>   .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>   drivers/mmc/host/Kconfig                           |   10 ++
>   drivers/mmc/host/Makefile                          |    1 +
>   drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
>   4 files changed, 205 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>   create mode 100644 drivers/mmc/host/dw_mmc-k3.c
>

Any comments?

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-14  2:12   ` Zhangfei Gao
@ 2013-12-16 13:12     ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-16 13:12 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao,
	Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
 4 files changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..e3eea2883ae7
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16 13:12     ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-16 13:12 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  134 ++++++++++++++++++++
 4 files changed, 205 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..e3eea2883ae7
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc", .data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = dw_mci_suspend(host);
+	if (!ret)
+		clk_disable_unprepare(host->ciu_clk);
+
+	return ret;
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16  9:18             ` Seungwon Jeon
@ 2013-12-16 11:07               ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16 11:07 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'



On 12/16/2013 05:18 PM, Seungwon Jeon wrote:
> On Mon, December 16, 2013, Zhangfei Gao wrote:
>> On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
>>> On Mon, December 16, 2013, Zhangfei Gao wrote:
>>>> Dear Seungwon
>>>>
>>>> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
>>>>> On Sat, December 14, 2013, Zhangfei Gao wrote:
>>>>
>>>>>> +	/* SoC portion */
>>>>>> +	dwmmc_0: dwmmc0@fcd03000 {
>>>>>> +		compatible = "hisilicon,hi4511-dw-mshc";
>>>>>> +		reg = <0xfcd03000 0x1000>;
>>>>>> +		interrupts = <0 16 4>;
>>>>>> +		#address-cells = <1>;
>>>>>> +		#size-cells = <0>;
>>>>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>>>>>> +		clock-names = "ciu", "biu";
>>>>>> +		clock-freq-table =
>>>>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
>>>>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
>>>>> if there is no limitation per each speed mode. As seeing described table, it looks that.
>>>>
>>>> Have tried them before, but unfortunately, they are different.
>>>>
>>>> The controller can not generate clock itself, while depending on the
>>>> outside clock generator, which may require to change clock source in
>>>> differnt mode.
>>>>
>>>> The value we want is set the capacibility of the clock input and the max
>>>> clock freq where mmc works stable in that mode, which may be different
>>>> in different mode.
>>>>
>>>> clock-freq-min-max will set the value for set_ios.
>>>> For example, we use 25M as clock capability when init, which can not be
>>>> set as freq-min, and used as set_ios, where 400K should be used,
>>>> otherwise init definitely fail.
>>> Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
>>> If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through
>> 'ios.clock'
>>> Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
>>
>> This means controller directly use 25M init emmc and sd card, it will fail.
>> We still need 400K init freq, while the input clock source is 25M,
>> divided by the controller.
>>
>>> And other required speeds for each mode seem not specific compared with standard spec.
>>> Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
>>> I just referred your example's clock-freq-table above.
>> There also some controller limitation currently.
>> In some mode, the controller only works well in the limited freq.
>> For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
>> be reached, at least currently
> Ok. I see your condition. I misunderstood a little bit.
> I wonder whether limitation is only max frequency(SDR104 or HS200) except for init-freq.
> How about other mode? Working is fine with normal clock rate(from clock-freq-table)?
> 

The root cause is the controller can not generate stable clock itself,
but depends on outside clock source, which is varying, and driver need
to decide input clock rate / choose clock source according to the
working mode.

Three cases here:
1. Input rate for init are diferent for different controller, not the
init 400K, some are 13M, others are 25M, since different clock source.
This can be easily solved by clock-freq-init = <25000000>

2. There is maxmum limit, also can be easily solved by define CLK_MAX.
For example, CLK_MAX = 180M.

3. However some mode can not use the max speed from ios->clock
for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
be reached, at least currently.

The third case is current limitation, after this limitation is solved,
we can switch to ios->clock directly.

Considering all these cases, we think using table is more suitable now.

Thanks


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16 11:07               ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16 11:07 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/16/2013 05:18 PM, Seungwon Jeon wrote:
> On Mon, December 16, 2013, Zhangfei Gao wrote:
>> On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
>>> On Mon, December 16, 2013, Zhangfei Gao wrote:
>>>> Dear Seungwon
>>>>
>>>> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
>>>>> On Sat, December 14, 2013, Zhangfei Gao wrote:
>>>>
>>>>>> +	/* SoC portion */
>>>>>> +	dwmmc_0: dwmmc0 at fcd03000 {
>>>>>> +		compatible = "hisilicon,hi4511-dw-mshc";
>>>>>> +		reg = <0xfcd03000 0x1000>;
>>>>>> +		interrupts = <0 16 4>;
>>>>>> +		#address-cells = <1>;
>>>>>> +		#size-cells = <0>;
>>>>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>>>>>> +		clock-names = "ciu", "biu";
>>>>>> +		clock-freq-table =
>>>>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
>>>>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
>>>>> if there is no limitation per each speed mode. As seeing described table, it looks that.
>>>>
>>>> Have tried them before, but unfortunately, they are different.
>>>>
>>>> The controller can not generate clock itself, while depending on the
>>>> outside clock generator, which may require to change clock source in
>>>> differnt mode.
>>>>
>>>> The value we want is set the capacibility of the clock input and the max
>>>> clock freq where mmc works stable in that mode, which may be different
>>>> in different mode.
>>>>
>>>> clock-freq-min-max will set the value for set_ios.
>>>> For example, we use 25M as clock capability when init, which can not be
>>>> set as freq-min, and used as set_ios, where 400K should be used,
>>>> otherwise init definitely fail.
>>> Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
>>> If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through
>> 'ios.clock'
>>> Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
>>
>> This means controller directly use 25M init emmc and sd card, it will fail.
>> We still need 400K init freq, while the input clock source is 25M,
>> divided by the controller.
>>
>>> And other required speeds for each mode seem not specific compared with standard spec.
>>> Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
>>> I just referred your example's clock-freq-table above.
>> There also some controller limitation currently.
>> In some mode, the controller only works well in the limited freq.
>> For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
>> be reached, at least currently
> Ok. I see your condition. I misunderstood a little bit.
> I wonder whether limitation is only max frequency(SDR104 or HS200) except for init-freq.
> How about other mode? Working is fine with normal clock rate(from clock-freq-table)?
> 

The root cause is the controller can not generate stable clock itself,
but depends on outside clock source, which is varying, and driver need
to decide input clock rate / choose clock source according to the
working mode.

Three cases here:
1. Input rate for init are diferent for different controller, not the
init 400K, some are 13M, others are 25M, since different clock source.
This can be easily solved by clock-freq-init = <25000000>

2. There is maxmum limit, also can be easily solved by define CLK_MAX.
For example, CLK_MAX = 180M.

3. However some mode can not use the max speed from ios->clock
for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
be reached, at least currently.

The third case is current limitation, after this limitation is solved,
we can switch to ios->clock directly.

Considering all these cases, we think using table is more suitable now.

Thanks

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16  8:08           ` zhangfei
@ 2013-12-16  9:18             ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  9:18 UTC (permalink / raw)
  To: 'zhangfei', 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

On Mon, December 16, 2013, Zhangfei Gao wrote:
> On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
> > On Mon, December 16, 2013, Zhangfei Gao wrote:
> >> Dear Seungwon
> >>
> >> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> >>> On Sat, December 14, 2013, Zhangfei Gao wrote:
> >>
> >>>> +	/* SoC portion */
> >>>> +	dwmmc_0: dwmmc0@fcd03000 {
> >>>> +		compatible = "hisilicon,hi4511-dw-mshc";
> >>>> +		reg = <0xfcd03000 0x1000>;
> >>>> +		interrupts = <0 16 4>;
> >>>> +		#address-cells = <1>;
> >>>> +		#size-cells = <0>;
> >>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> >>>> +		clock-names = "ciu", "biu";
> >>>> +		clock-freq-table =
> >>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> >>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> >>> if there is no limitation per each speed mode. As seeing described table, it looks that.
> >>
> >> Have tried them before, but unfortunately, they are different.
> >>
> >> The controller can not generate clock itself, while depending on the
> >> outside clock generator, which may require to change clock source in
> >> differnt mode.
> >>
> >> The value we want is set the capacibility of the clock input and the max
> >> clock freq where mmc works stable in that mode, which may be different
> >> in different mode.
> >>
> >> clock-freq-min-max will set the value for set_ios.
> >> For example, we use 25M as clock capability when init, which can not be
> >> set as freq-min, and used as set_ios, where 400K should be used,
> >> otherwise init definitely fail.
> > Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
> > If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through
> 'ios.clock'
> > Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
> 
> This means controller directly use 25M init emmc and sd card, it will fail.
> We still need 400K init freq, while the input clock source is 25M,
> divided by the controller.
> 
> > And other required speeds for each mode seem not specific compared with standard spec.
> > Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
> > I just referred your example's clock-freq-table above.
> There also some controller limitation currently.
> In some mode, the controller only works well in the limited freq.
> For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
> be reached, at least currently
Ok. I see your condition. I misunderstood a little bit.
I wonder whether limitation is only max frequency(SDR104 or HS200) except for init-freq.
How about other mode? Working is fine with normal clock rate(from clock-freq-table)?

Thanks,
Seungwon Jeon

> 
> >
> >>
> >>>> +static int dw_mci_k3_suspend(struct device *dev)
> >>>> +{
> >>>> +	struct dw_mci *host = dev_get_drvdata(dev);
> >>>> +
> >>>> +	if (!IS_ERR(host->ciu_clk))
> >>>> +		clk_disable_unprepare(host->ciu_clk);
> >>>> +
> >>>> +	return dw_mci_suspend(host);
> >>> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
> >> clk_disable_unprepare()?
> >>> Of course, it's ok at present though.
> >>>
> >>
> >> Sure, it can be switched, though dw_mci_suspend does nothing related
> >> with clock now.
> > Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.
> >
> Sorry for the misunderstood, I mean it make sense and will change.
> Thanks the advice.
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16  9:18             ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  9:18 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, December 16, 2013, Zhangfei Gao wrote:
> On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
> > On Mon, December 16, 2013, Zhangfei Gao wrote:
> >> Dear Seungwon
> >>
> >> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> >>> On Sat, December 14, 2013, Zhangfei Gao wrote:
> >>
> >>>> +	/* SoC portion */
> >>>> +	dwmmc_0: dwmmc0 at fcd03000 {
> >>>> +		compatible = "hisilicon,hi4511-dw-mshc";
> >>>> +		reg = <0xfcd03000 0x1000>;
> >>>> +		interrupts = <0 16 4>;
> >>>> +		#address-cells = <1>;
> >>>> +		#size-cells = <0>;
> >>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> >>>> +		clock-names = "ciu", "biu";
> >>>> +		clock-freq-table =
> >>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> >>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> >>> if there is no limitation per each speed mode. As seeing described table, it looks that.
> >>
> >> Have tried them before, but unfortunately, they are different.
> >>
> >> The controller can not generate clock itself, while depending on the
> >> outside clock generator, which may require to change clock source in
> >> differnt mode.
> >>
> >> The value we want is set the capacibility of the clock input and the max
> >> clock freq where mmc works stable in that mode, which may be different
> >> in different mode.
> >>
> >> clock-freq-min-max will set the value for set_ios.
> >> For example, we use 25M as clock capability when init, which can not be
> >> set as freq-min, and used as set_ios, where 400K should be used,
> >> otherwise init definitely fail.
> > Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
> > If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through
> 'ios.clock'
> > Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
> 
> This means controller directly use 25M init emmc and sd card, it will fail.
> We still need 400K init freq, while the input clock source is 25M,
> divided by the controller.
> 
> > And other required speeds for each mode seem not specific compared with standard spec.
> > Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
> > I just referred your example's clock-freq-table above.
> There also some controller limitation currently.
> In some mode, the controller only works well in the limited freq.
> For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
> be reached, at least currently
Ok. I see your condition. I misunderstood a little bit.
I wonder whether limitation is only max frequency(SDR104 or HS200) except for init-freq.
How about other mode? Working is fine with normal clock rate(from clock-freq-table)?

Thanks,
Seungwon Jeon

> 
> >
> >>
> >>>> +static int dw_mci_k3_suspend(struct device *dev)
> >>>> +{
> >>>> +	struct dw_mci *host = dev_get_drvdata(dev);
> >>>> +
> >>>> +	if (!IS_ERR(host->ciu_clk))
> >>>> +		clk_disable_unprepare(host->ciu_clk);
> >>>> +
> >>>> +	return dw_mci_suspend(host);
> >>> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
> >> clk_disable_unprepare()?
> >>> Of course, it's ok at present though.
> >>>
> >>
> >> Sure, it can be switched, though dw_mci_suspend does nothing related
> >> with clock now.
> > Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.
> >
> Sorry for the misunderstood, I mean it make sense and will change.
> Thanks the advice.
> 
> 
> --
> 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

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16  7:29         ` Seungwon Jeon
@ 2013-12-16  8:08           ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16  8:08 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'



On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
> On Mon, December 16, 2013, Zhangfei Gao wrote:
>> Dear Seungwon
>>
>> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
>>> On Sat, December 14, 2013, Zhangfei Gao wrote:
>>
>>>> +	/* SoC portion */
>>>> +	dwmmc_0: dwmmc0@fcd03000 {
>>>> +		compatible = "hisilicon,hi4511-dw-mshc";
>>>> +		reg = <0xfcd03000 0x1000>;
>>>> +		interrupts = <0 16 4>;
>>>> +		#address-cells = <1>;
>>>> +		#size-cells = <0>;
>>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>>>> +		clock-names = "ciu", "biu";
>>>> +		clock-freq-table =
>>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
>>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
>>> if there is no limitation per each speed mode. As seeing described table, it looks that.
>>
>> Have tried them before, but unfortunately, they are different.
>>
>> The controller can not generate clock itself, while depending on the
>> outside clock generator, which may require to change clock source in
>> differnt mode.
>>
>> The value we want is set the capacibility of the clock input and the max
>> clock freq where mmc works stable in that mode, which may be different
>> in different mode.
>>
>> clock-freq-min-max will set the value for set_ios.
>> For example, we use 25M as clock capability when init, which can not be
>> set as freq-min, and used as set_ios, where 400K should be used,
>> otherwise init definitely fail.
> Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
> If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through 'ios.clock'
> Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().

This means controller directly use 25M init emmc and sd card, it will fail.
We still need 400K init freq, while the input clock source is 25M,
divided by the controller.

> And other required speeds for each mode seem not specific compared with standard spec.
> Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
> I just referred your example's clock-freq-table above.
There also some controller limitation currently.
In some mode, the controller only works well in the limited freq.
For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
be reached, at least currently

> 
>>
>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>> +{
>>>> +	struct dw_mci *host = dev_get_drvdata(dev);
>>>> +
>>>> +	if (!IS_ERR(host->ciu_clk))
>>>> +		clk_disable_unprepare(host->ciu_clk);
>>>> +
>>>> +	return dw_mci_suspend(host);
>>> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
>> clk_disable_unprepare()?
>>> Of course, it's ok at present though.
>>>
>>
>> Sure, it can be switched, though dw_mci_suspend does nothing related
>> with clock now.
> Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.
> 
Sorry for the misunderstood, I mean it make sense and will change.
Thanks the advice.



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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16  8:08           ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16  8:08 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/16/2013 03:29 PM, Seungwon Jeon wrote:
> On Mon, December 16, 2013, Zhangfei Gao wrote:
>> Dear Seungwon
>>
>> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
>>> On Sat, December 14, 2013, Zhangfei Gao wrote:
>>
>>>> +	/* SoC portion */
>>>> +	dwmmc_0: dwmmc0 at fcd03000 {
>>>> +		compatible = "hisilicon,hi4511-dw-mshc";
>>>> +		reg = <0xfcd03000 0x1000>;
>>>> +		interrupts = <0 16 4>;
>>>> +		#address-cells = <1>;
>>>> +		#size-cells = <0>;
>>>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>>>> +		clock-names = "ciu", "biu";
>>>> +		clock-freq-table =
>>>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
>>> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
>>> if there is no limitation per each speed mode. As seeing described table, it looks that.
>>
>> Have tried them before, but unfortunately, they are different.
>>
>> The controller can not generate clock itself, while depending on the
>> outside clock generator, which may require to change clock source in
>> differnt mode.
>>
>> The value we want is set the capacibility of the clock input and the max
>> clock freq where mmc works stable in that mode, which may be different
>> in different mode.
>>
>> clock-freq-min-max will set the value for set_ios.
>> For example, we use 25M as clock capability when init, which can not be
>> set as freq-min, and used as set_ios, where 400K should be used,
>> otherwise init definitely fail.
> Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
> If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through 'ios.clock'
> Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().

This means controller directly use 25M init emmc and sd card, it will fail.
We still need 400K init freq, while the input clock source is 25M,
divided by the controller.

> And other required speeds for each mode seem not specific compared with standard spec.
> Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
> I just referred your example's clock-freq-table above.
There also some controller limitation currently.
In some mode, the controller only works well in the limited freq.
For example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
be reached, at least currently

> 
>>
>>>> +static int dw_mci_k3_suspend(struct device *dev)
>>>> +{
>>>> +	struct dw_mci *host = dev_get_drvdata(dev);
>>>> +
>>>> +	if (!IS_ERR(host->ciu_clk))
>>>> +		clk_disable_unprepare(host->ciu_clk);
>>>> +
>>>> +	return dw_mci_suspend(host);
>>> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
>> clk_disable_unprepare()?
>>> Of course, it's ok at present though.
>>>
>>
>> Sure, it can be switched, though dw_mci_suspend does nothing related
>> with clock now.
> Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.
> 
Sorry for the misunderstood, I mean it make sense and will change.
Thanks the advice.

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16  5:05       ` zhangfei
@ 2013-12-16  7:29         ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  7:29 UTC (permalink / raw)
  To: 'zhangfei', 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

On Mon, December 16, 2013, Zhangfei Gao wrote: 
> Dear Seungwon
> 
> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> > On Sat, December 14, 2013, Zhangfei Gao wrote:
> 
> >> +	/* SoC portion */
> >> +	dwmmc_0: dwmmc0@fcd03000 {
> >> +		compatible = "hisilicon,hi4511-dw-mshc";
> >> +		reg = <0xfcd03000 0x1000>;
> >> +		interrupts = <0 16 4>;
> >> +		#address-cells = <1>;
> >> +		#size-cells = <0>;
> >> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> >> +		clock-names = "ciu", "biu";
> >> +		clock-freq-table =
> >> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> > I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> > if there is no limitation per each speed mode. As seeing described table, it looks that.
> 
> Have tried them before, but unfortunately, they are different.
> 
> The controller can not generate clock itself, while depending on the
> outside clock generator, which may require to change clock source in
> differnt mode.
> 
> The value we want is set the capacibility of the clock input and the max
> clock freq where mmc works stable in that mode, which may be different
> in different mode.
> 
> clock-freq-min-max will set the value for set_ios.
> For example, we use 25M as clock capability when init, which can not be
> set as freq-min, and used as set_ios, where 400K should be used,
> otherwise init definitely fail.
Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through 'ios.clock'
Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
And other required speeds for each mode seem not specific compared with standard spec.
Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
I just referred your example's clock-freq-table above.

> 
> >> +static int dw_mci_k3_suspend(struct device *dev)
> >> +{
> >> +	struct dw_mci *host = dev_get_drvdata(dev);
> >> +
> >> +	if (!IS_ERR(host->ciu_clk))
> >> +		clk_disable_unprepare(host->ciu_clk);
> >> +
> >> +	return dw_mci_suspend(host);
> > If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
> clk_disable_unprepare()?
> > Of course, it's ok at present though.
> >
> 
> Sure, it can be switched, though dw_mci_suspend does nothing related
> with clock now.
Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.

Thanks,
Seungwon Jeon


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16  7:29         ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  7:29 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, December 16, 2013, Zhangfei Gao wrote: 
> Dear Seungwon
> 
> On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> > On Sat, December 14, 2013, Zhangfei Gao wrote:
> 
> >> +	/* SoC portion */
> >> +	dwmmc_0: dwmmc0 at fcd03000 {
> >> +		compatible = "hisilicon,hi4511-dw-mshc";
> >> +		reg = <0xfcd03000 0x1000>;
> >> +		interrupts = <0 16 4>;
> >> +		#address-cells = <1>;
> >> +		#size-cells = <0>;
> >> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> >> +		clock-names = "ciu", "biu";
> >> +		clock-freq-table =
> >> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> > I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> > if there is no limitation per each speed mode. As seeing described table, it looks that.
> 
> Have tried them before, but unfortunately, they are different.
> 
> The controller can not generate clock itself, while depending on the
> outside clock generator, which may require to change clock source in
> differnt mode.
> 
> The value we want is set the capacibility of the clock input and the max
> clock freq where mmc works stable in that mode, which may be different
> in different mode.
> 
> clock-freq-min-max will set the value for set_ios.
> For example, we use 25M as clock capability when init, which can not be
> set as freq-min, and used as set_ios, where 400K should be used,
> otherwise init definitely fail.
Can you check 'f_init' within 'drivers/mmc/core/core.c' file?
If you set 'f_min = 25000000' for init-sequence, mmc_set_ios() will pass that rate through 'ios.clock'
Then, dw_mmc-k3 can do clk_set_rate() with 25MHz at dw_mci_k3_set_ios().
And other required speeds for each mode seem not specific compared with standard spec.
Also clk_set_rate() would be possible with 'ios.clock' instead of specific table.
I just referred your example's clock-freq-table above.

> 
> >> +static int dw_mci_k3_suspend(struct device *dev)
> >> +{
> >> +	struct dw_mci *host = dev_get_drvdata(dev);
> >> +
> >> +	if (!IS_ERR(host->ciu_clk))
> >> +		clk_disable_unprepare(host->ciu_clk);
> >> +
> >> +	return dw_mci_suspend(host);
> > If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to
> clk_disable_unprepare()?
> > Of course, it's ok at present though.
> >
> 
> Sure, it can be switched, though dw_mci_suspend does nothing related
> with clock now.
Yes, but if some works with ciu_clk is added in dw_mci_suspend(), it will affect.

Thanks,
Seungwon Jeon

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-16  3:50     ` Seungwon Jeon
@ 2013-12-16  5:05       ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16  5:05 UTC (permalink / raw)
  To: Seungwon Jeon, 'Chris Ball', 'Arnd Bergmann',
	'Mike Turquette', 'Rob Herring',
	'Jaehoon Chung', 'Kumar Gala',
	'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'


Dear Seungwon

On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> On Sat, December 14, 2013, Zhangfei Gao wrote:

>> +	/* SoC portion */
>> +	dwmmc_0: dwmmc0@fcd03000 {
>> +		compatible = "hisilicon,hi4511-dw-mshc";
>> +		reg = <0xfcd03000 0x1000>;
>> +		interrupts = <0 16 4>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>> +		clock-names = "ciu", "biu";
>> +		clock-freq-table =
>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> if there is no limitation per each speed mode. As seeing described table, it looks that.

Have tried them before, but unfortunately, they are different.

The controller can not generate clock itself, while depending on the
outside clock generator, which may require to change clock source in
differnt mode.

The value we want is set the capacibility of the clock input and the max
clock freq where mmc works stable in that mode, which may be different
in different mode.

clock-freq-min-max will set the value for set_ios.
For example, we use 25M as clock capability when init, which can not be
set as freq-min, and used as set_ios, where 400K should be used,
otherwise init definitely fail.

>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +
>> +	if (!IS_ERR(host->ciu_clk))
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return dw_mci_suspend(host);
> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to clk_disable_unprepare()?
> Of course, it's ok at present though.
> 

Sure, it can be switched, though dw_mci_suspend does nothing related
with clock now.

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16  5:05       ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-16  5:05 UTC (permalink / raw)
  To: linux-arm-kernel


Dear Seungwon

On 12/16/2013 11:50 AM, Seungwon Jeon wrote:
> On Sat, December 14, 2013, Zhangfei Gao wrote:

>> +	/* SoC portion */
>> +	dwmmc_0: dwmmc0 at fcd03000 {
>> +		compatible = "hisilicon,hi4511-dw-mshc";
>> +		reg = <0xfcd03000 0x1000>;
>> +		interrupts = <0 16 4>;
>> +		#address-cells = <1>;
>> +		#size-cells = <0>;
>> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
>> +		clock-names = "ciu", "biu";
>> +		clock-freq-table =
>> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
> if there is no limitation per each speed mode. As seeing described table, it looks that.

Have tried them before, but unfortunately, they are different.

The controller can not generate clock itself, while depending on the
outside clock generator, which may require to change clock source in
differnt mode.

The value we want is set the capacibility of the clock input and the max
clock freq where mmc works stable in that mode, which may be different
in different mode.

clock-freq-min-max will set the value for set_ios.
For example, we use 25M as clock capability when init, which can not be
set as freq-min, and used as set_ios, where 400K should be used,
otherwise init definitely fail.

>> +static int dw_mci_k3_suspend(struct device *dev)
>> +{
>> +	struct dw_mci *host = dev_get_drvdata(dev);
>> +
>> +	if (!IS_ERR(host->ciu_clk))
>> +		clk_disable_unprepare(host->ciu_clk);
>> +
>> +	return dw_mci_suspend(host);
> If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to clk_disable_unprepare()?
> Of course, it's ok at present though.
> 

Sure, it can be switched, though dw_mci_suspend does nothing related
with clock now.

Thanks

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

* RE: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-14  2:12   ` Zhangfei Gao
@ 2013-12-16  3:50     ` Seungwon Jeon
  -1 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  3:50 UTC (permalink / raw)
  To: 'Zhangfei Gao', 'Chris Ball',
	'Arnd Bergmann', 'Mike Turquette',
	'Rob Herring', 'Jaehoon Chung',
	'Kumar Gala', 'Haojian Zhuang'
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, 'Zhigang Wang'

On Sat, December 14, 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  133 ++++++++++++++++++++
>  4 files changed, 204 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0@fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
if there is no limitation per each speed mode. As seeing described table, it looks that.

> +	};
> +
> +	/* Board portion */
> +	dwmmc0@fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot@0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
> 
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC
> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..90ebee0ce5ef
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,133 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static unsigned long k3_dwmmc_caps[4] = {
> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
> +	0,
> +	0,
> +};
> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.caps			= k3_dwmmc_caps,
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc",
> +			.data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +
> +	if (!IS_ERR(host->ciu_clk))
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return dw_mci_suspend(host);
If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to clk_disable_unprepare()?
Of course, it's ok at present though. 

Thanks,
Seungwon Jeon
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}
> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> --
> 1.7.9.5
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-16  3:50     ` Seungwon Jeon
  0 siblings, 0 replies; 146+ messages in thread
From: Seungwon Jeon @ 2013-12-16  3:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, December 14, 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  133 ++++++++++++++++++++
>  4 files changed, 204 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d7e2d7f159bb
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,60 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +
> +* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
> +	in each	supported mode.
> +	0. CIU clock rate in Hz for DS mode
> +	1. CIU clock rate in Hz for MMC HS mode
> +	2. CIU clock rate in Hz for SD HS mode
> +	3. CIU clock rate in Hz for SDR12 mode
> +	4. CIU clock rate in Hz for SDR25 mode
> +	5. CIU clock rate in Hz for SDR50 mode
> +	6. CIU clock rate in Hz for SDR104 mode
> +	7. CIU clock rate in Hz for DDR50 mode
> +	8. CIU clock rate in Hz for HS200 mode
> +
> +Example:
> +
> +	/* for Hi3620 */
> +
> +	/* SoC portion */
> +	dwmmc_0: dwmmc0 at fcd03000 {
> +		compatible = "hisilicon,hi4511-dw-mshc";
> +		reg = <0xfcd03000 0x1000>;
> +		interrupts = <0 16 4>;
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
> +		clock-names = "ciu", "biu";
> +		clock-freq-table =
> +		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
I think it could be solved with mmc->f_min and mmc->f_max(from clock-freq-min-max property)
if there is no limitation per each speed mode. As seeing described table, it looks that.

> +	};
> +
> +	/* Board portion */
> +	dwmmc0 at fcd03000 {
> +		num-slots = <1>;
> +		vmmc-supply = <&ldo12>;
> +		fifo-depth = <0x100>;
> +		supports-highspeed;
> +		pinctrl-names = "default";
> +		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
> +		slot at 0 {
> +			reg = <0>;
> +			bus-width = <4>;
> +			disable-wp;
> +			cd-gpios = <&gpio10 3 0>;
> +		};
> +	};
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index 7fc5099e44b2..45aaa2de0f58 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
>  	  This selects support for Altera SoCFPGA specific extensions to the
>  	  Synopsys DesignWare Memory Card Interface driver.
> 
> +config MMC_DW_K3
> +	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
> +	depends on MMC_DW
> +	select MMC_DW_PLTFM
> +	select MMC_DW_IDMAC
> +	help
> +	  This selects support for Hisilicon K3 SoC specific extensions to the
> +	  Synopsys DesignWare Memory Card Interface driver. Select this option
> +	  for platforms based on Hisilicon K3 SoC's.
> +
>  config MMC_DW_PCI
>  	tristate "Synopsys Designware MCI support on PCI bus"
>  	depends on MMC_DW && PCI
> diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
> index c41d0c364509..64f5f8d35839 100644
> --- a/drivers/mmc/host/Makefile
> +++ b/drivers/mmc/host/Makefile
> @@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
>  obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
>  obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
>  obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
> +obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
>  obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
>  obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
>  obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
> diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
> new file mode 100644
> index 000000000000..90ebee0ce5ef
> --- /dev/null
> +++ b/drivers/mmc/host/dw_mmc-k3.c
> @@ -0,0 +1,133 @@
> +/*
> + * Copyright (c) 2013 Linaro Ltd.
> + * Copyright (c) 2013 Hisilicon Limited.
> + *
> + * 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; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/mmc/host.h>
> +#include <linux/mmc/dw_mmc.h>
> +#include <linux/of_address.h>
> +
> +#include "dw_mmc.h"
> +#include "dw_mmc-pltfm.h"
> +
> +#define MAX_NUMS	10
> +struct dw_mci_k3_priv_data {
> +	u32	clk_table[MAX_NUMS];
> +};
> +
> +static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
> +{
> +	struct dw_mci_k3_priv_data *priv = host->priv;
> +	u32 rate = priv->clk_table[ios->timing];
> +	int ret;
> +
> +	ret = clk_set_rate(host->ciu_clk, rate);
> +	if (ret)
> +		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
> +
> +	host->bus_hz = clk_get_rate(host->ciu_clk);
> +}
> +
> +static int dw_mci_k3_parse_dt(struct dw_mci *host)
> +{
> +	struct dw_mci_k3_priv_data *priv;
> +	struct device_node *node = host->dev->of_node;
> +	struct property *prop;
> +	const __be32 *cur;
> +	u32 val, num = 0;
> +
> +	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
> +	if (!priv) {
> +		dev_err(host->dev, "mem alloc failed for private data\n");
> +		return -ENOMEM;
> +	}
> +	host->priv = priv;
> +
> +	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
> +		if (num >= MAX_NUMS)
> +			break;
> +		priv->clk_table[num++] = val;
> +	}
> +	return 0;
> +}
> +
> +static unsigned long k3_dwmmc_caps[4] = {
> +	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
> +	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
> +	0,
> +	0,
> +};
> +
> +static const struct dw_mci_drv_data k3_drv_data = {
> +	.caps			= k3_dwmmc_caps,
> +	.set_ios		= dw_mci_k3_set_ios,
> +	.parse_dt		= dw_mci_k3_parse_dt,
> +};
> +
> +static const struct of_device_id dw_mci_k3_match[] = {
> +	{ .compatible = "hisilicon,hi4511-dw-mshc",
> +			.data = &k3_drv_data, },
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
> +
> +static int dw_mci_k3_probe(struct platform_device *pdev)
> +{
> +	const struct dw_mci_drv_data *drv_data;
> +	const struct of_device_id *match;
> +
> +	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
> +	drv_data = match->data;
> +
> +	return dw_mci_pltfm_register(pdev, drv_data);
> +}
> +
> +static int dw_mci_k3_suspend(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +
> +	if (!IS_ERR(host->ciu_clk))
> +		clk_disable_unprepare(host->ciu_clk);
> +
> +	return dw_mci_suspend(host);
If k3 needs clk_disable here, dw_mci_suspend()is expected to be called prior to clk_disable_unprepare()?
Of course, it's ok at present though. 

Thanks,
Seungwon Jeon
> +}
> +
> +static int dw_mci_k3_resume(struct device *dev)
> +{
> +	struct dw_mci *host = dev_get_drvdata(dev);
> +	int ret = 0;
> +
> +	ret = clk_prepare_enable(host->ciu_clk);
> +	if (ret) {
> +		dev_err(host->dev, "failed to enable ciu clock\n");
> +		return ret;
> +	}
> +
> +	return dw_mci_resume(host);
> +}
> +
> +SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
> +
> +static struct platform_driver dw_mci_k3_pltfm_driver = {
> +	.probe		= dw_mci_k3_probe,
> +	.remove		= dw_mci_pltfm_remove,
> +	.driver		= {
> +		.name		= "dwmmc_k3",
> +		.of_match_table	= dw_mci_k3_match,
> +		.pm		= &dw_mci_k3_pmops,
> +	},
> +};
> +
> +module_platform_driver(dw_mci_k3_pltfm_driver);
> +
> +MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform:dwmmc-k3");
> --
> 1.7.9.5
> 
> --
> 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

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-14  2:12 [PATCH v5 0/3] mmc: dw_mmc: add dw_mmc-k3 Zhangfei Gao
@ 2013-12-14  2:12   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-14  2:12 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao,
	Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  133 ++++++++++++++++++++
 4 files changed, 204 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..90ebee0ce5ef
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-14  2:12   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-14  2:12 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   60 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  133 ++++++++++++++++++++
 4 files changed, 204 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d7e2d7f159bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,60 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported mode.
+	0. CIU clock rate in Hz for DS mode
+	1. CIU clock rate in Hz for MMC HS mode
+	2. CIU clock rate in Hz for SD HS mode
+	3. CIU clock rate in Hz for SDR12 mode
+	4. CIU clock rate in Hz for SDR25 mode
+	5. CIU clock rate in Hz for SDR50 mode
+	6. CIU clock rate in Hz for SDR104 mode
+	7. CIU clock rate in Hz for DDR50 mode
+	8. CIU clock rate in Hz for HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clock-freq-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..90ebee0ce5ef
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+	u32 rate = priv->clk_table[ios->timing];
+	int ret;
+
+	ret = clk_set_rate(host->ciu_clk, rate);
+	if (ret)
+		dev_warn(host->dev, "failed to set clock rate %uHz\n", rate);
+
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-12 20:40               ` Arnd Bergmann
@ 2013-12-13  2:57                 ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-13  2:57 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree, Heiko Stuebner,
	Dinh Nguyen



On 12/13/2013 04:40 AM, Arnd Bergmann wrote:
> On Thursday 12 December 2013, zhangfei wrote:
>> On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
>>> On Wednesday 11 December 2013, zhangfei wrote:
>>>
>>> But aren't the times fixed for each mode? Why do you need to specify them in
>>> the DT? I would expect that the clock rates for each mode are set in the
>>> MMC and SD specifications. When you call clk_set_rate(), it should normally
>>> be enough to ask for the clock you actually want and let the clk subsystem
>>> figure out how to set up the parents and multipliers on the way.
>>
>> Yes. that's will be perfect.
>>
>> However, currently this ip still has no such capability.
>>   Input rate for init are diferent for different controller, not the
>> init 400K, some are 13M, others are 25M, since different clock source.
>> This can be easily solved by clock-freq-init = <25000000>
>> 2. There is maxmum limit, also can be easily solved by define CLK_MAX.
>> 3. However some mode can not use the max speed from ios->clock
>> for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
>> be reached, at least currently.
>
> I don't fully understand the explanation,

This is the ip's limitation currently, that some mode can only operate 
at limited freq, rather than the max freq from spec.
Will upgrade to use ios->clock once the limitation is solved.

but if some of the other
> people with interest in dw-mmc (I've added some more to Cc now) think
> this makes sense, I'm fine with it too.
>
Could I treat this as Ack or Partially Ack for the next version :)

>> How about this desc
>>
>> * clock-freq-table: should be the frequency (in Hz) array of the ciu
>> clock
>>           in each supported timing.
>>
>>           1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode
>>
>>           2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
>>           3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>>           4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode
>>
>>           5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode
>>
>>           6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode
>>
>>           7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode
>>
>>           8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>>
>>           9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode
>>
>
> Yes, that is much better. but please avoid using Linux internal
> identifiers (e.g. MMC_TIMING_LEGACY) and instead use the terminology from
> the MMC and SD specs. Also 'Hz' is the official symbol for Hertz, not 'HZ'.
>

Update to

* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
         in each supported mode.
         0. CIU clock rate in Hz for DS mode
         1. CIU clock rate in Hz for MMC HS mode
         2. CIU clock rate in Hz for SD HS mode
         3. CIU clock rate in Hz for SDR12 mode
         4. CIU clock rate in Hz for SDR25 mode
         5. CIU clock rate in Hz for SDR50 mode
         6. CIU clock rate in Hz for SDR104 mode
         7. CIU clock rate in Hz for DDR50 mode
         8. CIU clock rate in Hz for HS200 mode

Thanks

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-13  2:57                 ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-13  2:57 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/13/2013 04:40 AM, Arnd Bergmann wrote:
> On Thursday 12 December 2013, zhangfei wrote:
>> On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
>>> On Wednesday 11 December 2013, zhangfei wrote:
>>>
>>> But aren't the times fixed for each mode? Why do you need to specify them in
>>> the DT? I would expect that the clock rates for each mode are set in the
>>> MMC and SD specifications. When you call clk_set_rate(), it should normally
>>> be enough to ask for the clock you actually want and let the clk subsystem
>>> figure out how to set up the parents and multipliers on the way.
>>
>> Yes. that's will be perfect.
>>
>> However, currently this ip still has no such capability.
>>   Input rate for init are diferent for different controller, not the
>> init 400K, some are 13M, others are 25M, since different clock source.
>> This can be easily solved by clock-freq-init = <25000000>
>> 2. There is maxmum limit, also can be easily solved by define CLK_MAX.
>> 3. However some mode can not use the max speed from ios->clock
>> for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may
>> be reached, at least currently.
>
> I don't fully understand the explanation,

This is the ip's limitation currently, that some mode can only operate 
at limited freq, rather than the max freq from spec.
Will upgrade to use ios->clock once the limitation is solved.

but if some of the other
> people with interest in dw-mmc (I've added some more to Cc now) think
> this makes sense, I'm fine with it too.
>
Could I treat this as Ack or Partially Ack for the next version :)

>> How about this desc
>>
>> * clock-freq-table: should be the frequency (in Hz) array of the ciu
>> clock
>>           in each supported timing.
>>
>>           1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode
>>
>>           2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
>>           3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>>           4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode
>>
>>           5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode
>>
>>           6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode
>>
>>           7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode
>>
>>           8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>>
>>           9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode
>>
>
> Yes, that is much better. but please avoid using Linux internal
> identifiers (e.g. MMC_TIMING_LEGACY) and instead use the terminology from
> the MMC and SD specs. Also 'Hz' is the official symbol for Hertz, not 'HZ'.
>

Update to

* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
         in each supported mode.
         0. CIU clock rate in Hz for DS mode
         1. CIU clock rate in Hz for MMC HS mode
         2. CIU clock rate in Hz for SD HS mode
         3. CIU clock rate in Hz for SDR12 mode
         4. CIU clock rate in Hz for SDR25 mode
         5. CIU clock rate in Hz for SDR50 mode
         6. CIU clock rate in Hz for SDR104 mode
         7. CIU clock rate in Hz for DDR50 mode
         8. CIU clock rate in Hz for HS200 mode

Thanks

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-12 13:27             ` zhangfei
@ 2013-12-12 20:40               ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-12 20:40 UTC (permalink / raw)
  To: zhangfei
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree, Heiko Stuebner,
	Dinh Nguyen

On Thursday 12 December 2013, zhangfei wrote:
> On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
> > On Wednesday 11 December 2013, zhangfei wrote:
> >
> > But aren't the times fixed for each mode? Why do you need to specify them in
> > the DT? I would expect that the clock rates for each mode are set in the
> > MMC and SD specifications. When you call clk_set_rate(), it should normally
> > be enough to ask for the clock you actually want and let the clk subsystem
> > figure out how to set up the parents and multipliers on the way.
> 
> Yes. that's will be perfect.
>
> However, currently this ip still has no such capability.
>  Input rate for init are diferent for different controller, not the 
> init 400K, some are 13M, others are 25M, since different clock source.
> This can be easily solved by clock-freq-init = <25000000>
> 2. There is maxmum limit, also can be easily solved by define CLK_MAX.
> 3. However some mode can not use the max speed from ios->clock
> for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may 
> be reached, at least currently.

I don't fully understand the explanation, but if some of the other
people with interest in dw-mmc (I've added some more to Cc now) think
this makes sense, I'm fine with it too. 

> How about this desc
> 
> * clock-freq-table: should be the frequency (in Hz) array of the ciu 
> clock
>          in each supported timing. 
> 
>          1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode 
> 
>          2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
>          3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>          4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode 
> 
>          5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode 
> 
>          6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode 
> 
>          7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode 
> 
>          8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode 
> 
>          9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode 
> 

Yes, that is much better. but please avoid using Linux internal
identifiers (e.g. MMC_TIMING_LEGACY) and instead use the terminology from
the MMC and SD specs. Also 'Hz' is the official symbol for Hertz, not 'HZ'.

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-12 20:40               ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-12 20:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 12 December 2013, zhangfei wrote:
> On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
> > On Wednesday 11 December 2013, zhangfei wrote:
> >
> > But aren't the times fixed for each mode? Why do you need to specify them in
> > the DT? I would expect that the clock rates for each mode are set in the
> > MMC and SD specifications. When you call clk_set_rate(), it should normally
> > be enough to ask for the clock you actually want and let the clk subsystem
> > figure out how to set up the parents and multipliers on the way.
> 
> Yes. that's will be perfect.
>
> However, currently this ip still has no such capability.
>  Input rate for init are diferent for different controller, not the 
> init 400K, some are 13M, others are 25M, since different clock source.
> This can be easily solved by clock-freq-init = <25000000>
> 2. There is maxmum limit, also can be easily solved by define CLK_MAX.
> 3. However some mode can not use the max speed from ios->clock
> for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may 
> be reached, at least currently.

I don't fully understand the explanation, but if some of the other
people with interest in dw-mmc (I've added some more to Cc now) think
this makes sense, I'm fine with it too. 

> How about this desc
> 
> * clock-freq-table: should be the frequency (in Hz) array of the ciu 
> clock
>          in each supported timing. 
> 
>          1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode 
> 
>          2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
>          3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
>          4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode 
> 
>          5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode 
> 
>          6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode 
> 
>          7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode 
> 
>          8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode 
> 
>          9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode 
> 

Yes, that is much better. but please avoid using Linux internal
identifiers (e.g. MMC_TIMING_LEGACY) and instead use the terminology from
the MMC and SD specs. Also 'Hz' is the official symbol for Hertz, not 'HZ'.

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-12 13:27             ` zhangfei
@ 2013-12-12 14:13               ` Zhangfei Gao
  -1 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-12 14:13 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao,
	Zhigang Wang

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   59 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  128 ++++++++++++++++++++
 4 files changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..5501c7c1138f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,59 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported timing mode.
+	1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode
+	2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
+	3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
+	4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode
+	5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode
+	6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode
+	7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode
+	8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
+	9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clk-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..54b2503b211f
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+
+	clk_set_rate(host->ciu_clk, priv->clk_table[ios->timing]);
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-12 14:13               ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-12 14:13 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   59 +++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  128 ++++++++++++++++++++
 4 files changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..5501c7c1138f
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,59 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+* clock-freq-table: should be the frequency (in Hz) array of the ciu clock
+	in each	supported timing mode.
+	1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode
+	2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
+	3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
+	4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode
+	5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode
+	6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode
+	7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode
+	8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
+	9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clk-table =
+		<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..54b2503b211f
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+
+	clk_set_rate(host->ciu_clk, priv->clk_table[ios->timing]);
+	host->bus_hz = clk_get_rate(host->ciu_clk);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	struct device_node *node = host->dev->of_node;
+	struct property *prop;
+	const __be32 *cur;
+	u32 val, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	of_property_for_each_u32(node, "clock-freq-table", prop, cur, val) {
+		if (num >= MAX_NUMS)
+			break;
+		priv->clk_table[num++] = val;
+	}
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 20:12         ` Arnd Bergmann
@ 2013-12-12 13:27             ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-12 13:27 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang,
	linux-mmc-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	patches-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA

Dear Arnd

On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
> On Wednesday 11 December 2013, zhangfei wrote:
>>>
>>> I have not seen "clk-table" and "clk-table-num" before. Are these standard
>>> properties? What are the units that are used here, what does the index mean?
>>>
>>
>> "clk-table" and "clk-table-num" are private properties.
>> Instead simply on/off, the ip need different ciu clock for each timing mode.
>
> But aren't the times fixed for each mode? Why do you need to specify them in
> the DT? I would expect that the clock rates for each mode are set in the
> MMC and SD specifications. When you call clk_set_rate(), it should normally
> be enough to ask for the clock you actually want and let the clk subsystem
> figure out how to set up the parents and multipliers on the way.

Yes. that's will be perfect.

However, currently this ip still has no such capability.
1. Input rate for init are diferent for different controller, not the 
init 400K, some are 13M, others are 25M, since different clock source.
This can be easily solved by clock-freq-init = <25000000>
2. There is maxmum limit, also can be easily solved by define CLK_MAX.
3. However some mode can not use the max speed from ios->clock
for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may 
be reached, at least currently.

>
>> Take emmc as example,
>> clk-table-num = <8>;
>> clk-table =
>> <13000000 50000000 0 0 13000000 50000000 0 100000000>;
>> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
>> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
>>
>> "clk-table" list all clocks to be set in all supported timing one by one.
>> "clk-table-num" is the table number, since not find function getting
>> table number.
>> For example, next version will support MMC_TIMING_MMC_HS200 mode, the
>> clk-table-num = <9> with 9 clocks in the "clk-table"
>
> If you have a property with an array, you can use of_find_property()
> to get to the 'struct property' and then read the 'length' member
> of that struct, or you can use of_property_for_each_u32() to iterate
> through each value.

Great, this works.

>
> While I still hope that you don't even need this array as per the reasoning
> above, if you actually need it, you should specify exactly what each
> value means, such as
>
> 1. CIU clock rate in HZ for 20MHz SPI mode operation
> 2. CIU clock rate in HZ for 25MHz SD card operation
> 3. CIU clock rate in HZ for 26MHz MMC card operation
> 4. CIU clock rate in HZ for 50MHz SD card operation
> ...

How about this desc

* clock-freq-table: should be the frequency (in Hz) array of the ciu 
clock
         in each supported timing. 

         1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode 

         2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
         3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
         4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode 

         5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode 

         6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode 

         7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode 

         8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode 

         9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode 


Thanks
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-12 13:27             ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-12 13:27 UTC (permalink / raw)
  To: linux-arm-kernel

Dear Arnd

On 12/12/2013 04:12 AM, Arnd Bergmann wrote:
> On Wednesday 11 December 2013, zhangfei wrote:
>>>
>>> I have not seen "clk-table" and "clk-table-num" before. Are these standard
>>> properties? What are the units that are used here, what does the index mean?
>>>
>>
>> "clk-table" and "clk-table-num" are private properties.
>> Instead simply on/off, the ip need different ciu clock for each timing mode.
>
> But aren't the times fixed for each mode? Why do you need to specify them in
> the DT? I would expect that the clock rates for each mode are set in the
> MMC and SD specifications. When you call clk_set_rate(), it should normally
> be enough to ask for the clock you actually want and let the clk subsystem
> figure out how to set up the parents and multipliers on the way.

Yes. that's will be perfect.

However, currently this ip still has no such capability.
1. Input rate for init are diferent for different controller, not the 
init 400K, some are 13M, others are 25M, since different clock source.
This can be easily solved by clock-freq-init = <25000000>
2. There is maxmum limit, also can be easily solved by define CLK_MAX.
3. However some mode can not use the max speed from ios->clock
for example UHS_SDR104_MAX_DTR 208000000 can not be used, only half may 
be reached, at least currently.

>
>> Take emmc as example,
>> clk-table-num = <8>;
>> clk-table =
>> <13000000 50000000 0 0 13000000 50000000 0 100000000>;
>> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
>> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
>>
>> "clk-table" list all clocks to be set in all supported timing one by one.
>> "clk-table-num" is the table number, since not find function getting
>> table number.
>> For example, next version will support MMC_TIMING_MMC_HS200 mode, the
>> clk-table-num = <9> with 9 clocks in the "clk-table"
>
> If you have a property with an array, you can use of_find_property()
> to get to the 'struct property' and then read the 'length' member
> of that struct, or you can use of_property_for_each_u32() to iterate
> through each value.

Great, this works.

>
> While I still hope that you don't even need this array as per the reasoning
> above, if you actually need it, you should specify exactly what each
> value means, such as
>
> 1. CIU clock rate in HZ for 20MHz SPI mode operation
> 2. CIU clock rate in HZ for 25MHz SD card operation
> 3. CIU clock rate in HZ for 26MHz MMC card operation
> 4. CIU clock rate in HZ for 50MHz SD card operation
> ...

How about this desc

* clock-freq-table: should be the frequency (in Hz) array of the ciu 
clock
         in each supported timing. 

         1. CIU clock rate in HZ for MMC_TIMING_LEGACY mode 

         2. CIU clock rate in HZ for MMC_TIMING_MMC_HS mode
         3. CIU clock rate in HZ for MMC_TIMING_SD_HS mode
         4. CIU clock rate in HZ for MMC_TIMING_UHS_SDR12 mode 

         5. CIU clock rate in HZ for MMC_TIMING_UHS_SDR25 mode 

         6. CIU clock rate in HZ for MMC_TIMING_UHS_SDR50 mode 

         7. CIU clock rate in HZ for MMC_TIMING_UHS_SDR104 mode 

         8. CIU clock rate in HZ for MMC_TIMING_SD_HS mode 

         9. CIU clock rate in HZ for MMC_TIMING_MMC_HS200 mode 


Thanks

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 15:36       ` zhangfei
@ 2013-12-11 20:12         ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-11 20:12 UTC (permalink / raw)
  To: zhangfei
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree

On Wednesday 11 December 2013, zhangfei wrote:
> >
> > I have not seen "clk-table" and "clk-table-num" before. Are these standard
> > properties? What are the units that are used here, what does the index mean?
> >
> 
> "clk-table" and "clk-table-num" are private properties.
> Instead simply on/off, the ip need different ciu clock for each timing mode.

But aren't the times fixed for each mode? Why do you need to specify them in
the DT? I would expect that the clock rates for each mode are set in the
MMC and SD specifications. When you call clk_set_rate(), it should normally
be enough to ask for the clock you actually want and let the clk subsystem
figure out how to set up the parents and multipliers on the way.

> Take emmc as example,
> clk-table-num = <8>;
> clk-table =
> <13000000 50000000 0 0 13000000 50000000 0 100000000>;
> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
> 
> "clk-table" list all clocks to be set in all supported timing one by one.
> "clk-table-num" is the table number, since not find function getting 
> table number.
> For example, next version will support MMC_TIMING_MMC_HS200 mode, the 
> clk-table-num = <9> with 9 clocks in the "clk-table"

If you have a property with an array, you can use of_find_property()
to get to the 'struct property' and then read the 'length' member
of that struct, or you can use of_property_for_each_u32() to iterate
through each value.

While I still hope that you don't even need this array as per the reasoning
above, if you actually need it, you should specify exactly what each
value means, such as

1. CIU clock rate in HZ for 20MHz SPI mode operation 
2. CIU clock rate in HZ for 25MHz SD card operation
3. CIU clock rate in HZ for 26MHz MMC card operation
4. CIU clock rate in HZ for 50MHz SD card operation
...

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-11 20:12         ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-11 20:12 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 11 December 2013, zhangfei wrote:
> >
> > I have not seen "clk-table" and "clk-table-num" before. Are these standard
> > properties? What are the units that are used here, what does the index mean?
> >
> 
> "clk-table" and "clk-table-num" are private properties.
> Instead simply on/off, the ip need different ciu clock for each timing mode.

But aren't the times fixed for each mode? Why do you need to specify them in
the DT? I would expect that the clock rates for each mode are set in the
MMC and SD specifications. When you call clk_set_rate(), it should normally
be enough to ask for the clock you actually want and let the clk subsystem
figure out how to set up the parents and multipliers on the way.

> Take emmc as example,
> clk-table-num = <8>;
> clk-table =
> <13000000 50000000 0 0 13000000 50000000 0 100000000>;
> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
> 
> "clk-table" list all clocks to be set in all supported timing one by one.
> "clk-table-num" is the table number, since not find function getting 
> table number.
> For example, next version will support MMC_TIMING_MMC_HS200 mode, the 
> clk-table-num = <9> with 9 clocks in the "clk-table"

If you have a property with an array, you can use of_find_property()
to get to the 'struct property' and then read the 'length' member
of that struct, or you can use of_property_for_each_u32() to iterate
through each value.

While I still hope that you don't even need this array as per the reasoning
above, if you actually need it, you should specify exactly what each
value means, such as

1. CIU clock rate in HZ for 20MHz SPI mode operation 
2. CIU clock rate in HZ for 25MHz SD card operation
3. CIU clock rate in HZ for 26MHz MMC card operation
4. CIU clock rate in HZ for 50MHz SD card operation
...

	Arnd

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 15:36       ` zhangfei
@ 2013-12-11 15:53         ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-11 15:53 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree



On 12/11/2013 11:36 PM, zhangfei wrote:
>
>
> On 12/11/2013 10:49 PM, Arnd Bergmann wrote:
>> On Wednesday 11 December 2013, Zhangfei Gao wrote:
>
>>> +Required Properties:
>>> +
>>> +* compatible: should be one of the following.
>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific
>>> extentions.
>>> +* clk-table-num: should be number of clks in clk-table required by
>>> each mmc timing
>>> +* clk-table: should clock list required by each mmc timing
>>
>> I have not seen "clk-table" and "clk-table-num" before. Are these
>> standard
>> properties? What are the units that are used here, what does the index
>> mean?
>>
>
> "clk-table" and "clk-table-num" are private properties.
> Instead simply on/off, the ip need different ciu clock for each timing
> mode.
> Take emmc as example,
> clk-table-num = <8>;
> clk-table =

My bad, this is for sd.
> <13000000 50000000 0 0 13000000 50000000 0 100000000>;

<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
>
> "clk-table" list all clocks to be set in all supported timing one by one.
> "clk-table-num" is the table number, since not find function getting
> table number.
> For example, next version will support MMC_TIMING_MMC_HS200 mode, the
> clk-table-num = <9> with 9 clocks in the "clk-table"
>
> Thanks
>
>

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-11 15:53         ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-11 15:53 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/11/2013 11:36 PM, zhangfei wrote:
>
>
> On 12/11/2013 10:49 PM, Arnd Bergmann wrote:
>> On Wednesday 11 December 2013, Zhangfei Gao wrote:
>
>>> +Required Properties:
>>> +
>>> +* compatible: should be one of the following.
>>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific
>>> extentions.
>>> +* clk-table-num: should be number of clks in clk-table required by
>>> each mmc timing
>>> +* clk-table: should clock list required by each mmc timing
>>
>> I have not seen "clk-table" and "clk-table-num" before. Are these
>> standard
>> properties? What are the units that are used here, what does the index
>> mean?
>>
>
> "clk-table" and "clk-table-num" are private properties.
> Instead simply on/off, the ip need different ciu clock for each timing
> mode.
> Take emmc as example,
> clk-table-num = <8>;
> clk-table =

My bad, this is for sd.
> <13000000 50000000 0 0 13000000 50000000 0 100000000>;

<25000000 0 50000000 25000000 50000000 100000000 0 50000000>;
> MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
> MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M
>
> "clk-table" list all clocks to be set in all supported timing one by one.
> "clk-table-num" is the table number, since not find function getting
> table number.
> For example, next version will support MMC_TIMING_MMC_HS200 mode, the
> clk-table-num = <9> with 9 clocks in the "clk-table"
>
> Thanks
>
>

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 14:49     ` Arnd Bergmann
@ 2013-12-11 15:36       ` zhangfei
  -1 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-11 15:36 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree



On 12/11/2013 10:49 PM, Arnd Bergmann wrote:
> On Wednesday 11 December 2013, Zhangfei Gao wrote:

>> +Required Properties:
>> +
>> +* compatible: should be one of the following.
>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>> +* clk-table-num: should be number of clks in clk-table required by each mmc timing
>> +* clk-table: should clock list required by each mmc timing
>
> I have not seen "clk-table" and "clk-table-num" before. Are these standard
> properties? What are the units that are used here, what does the index mean?
>

"clk-table" and "clk-table-num" are private properties.
Instead simply on/off, the ip need different ciu clock for each timing mode.
Take emmc as example,
clk-table-num = <8>;
clk-table =
<13000000 50000000 0 0 13000000 50000000 0 100000000>;
MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M

"clk-table" list all clocks to be set in all supported timing one by one.
"clk-table-num" is the table number, since not find function getting 
table number.
For example, next version will support MMC_TIMING_MMC_HS200 mode, the 
clk-table-num = <9> with 9 clocks in the "clk-table"

Thanks



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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-11 15:36       ` zhangfei
  0 siblings, 0 replies; 146+ messages in thread
From: zhangfei @ 2013-12-11 15:36 UTC (permalink / raw)
  To: linux-arm-kernel



On 12/11/2013 10:49 PM, Arnd Bergmann wrote:
> On Wednesday 11 December 2013, Zhangfei Gao wrote:

>> +Required Properties:
>> +
>> +* compatible: should be one of the following.
>> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
>> +* clk-table-num: should be number of clks in clk-table required by each mmc timing
>> +* clk-table: should clock list required by each mmc timing
>
> I have not seen "clk-table" and "clk-table-num" before. Are these standard
> properties? What are the units that are used here, what does the index mean?
>

"clk-table" and "clk-table-num" are private properties.
Instead simply on/off, the ip need different ciu clock for each timing mode.
Take emmc as example,
clk-table-num = <8>;
clk-table =
<13000000 50000000 0 0 13000000 50000000 0 100000000>;
MMC_TIMING_LEGACY mode, 25M should be set with parent clock 180M,
MMC_TIMING_MMC_HS mode, 50M is required with parent clock 360M

"clk-table" list all clocks to be set in all supported timing one by one.
"clk-table-num" is the table number, since not find function getting 
table number.
For example, next version will support MMC_TIMING_MMC_HS200 mode, the 
clk-table-num = <9> with 9 clocks in the "clk-table"

Thanks

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

* Re: [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 14:02   ` Zhangfei Gao
@ 2013-12-11 14:49     ` Arnd Bergmann
  -1 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-11 14:49 UTC (permalink / raw)
  To: Zhangfei Gao
  Cc: Chris Ball, Mike Turquette, Rob Herring, Jaehoon Chung,
	Seungwon Jeon, Kumar Gala, Haojian Zhuang, linux-mmc,
	linux-arm-kernel, patches, devicetree

On Wednesday 11 December 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Tested-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   51 ++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  136 ++++++++++++++++++++
>  4 files changed, 198 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d816b89c386a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,51 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +* clk-table-num: should be number of clks in clk-table required by each mmc timing
> +* clk-table: should clock list required by each mmc timing

I have not seen "clk-table" and "clk-table-num" before. Are these standard
properties? What are the units that are used here, what does the index mean?

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-11 14:49     ` Arnd Bergmann
  0 siblings, 0 replies; 146+ messages in thread
From: Arnd Bergmann @ 2013-12-11 14:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Wednesday 11 December 2013, Zhangfei Gao wrote:
> Add dw_mmc-k3.c for k3v2, support sd/emmc
> 
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Tested-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
> ---
>  .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   51 ++++++++
>  drivers/mmc/host/Kconfig                           |   10 ++
>  drivers/mmc/host/Makefile                          |    1 +
>  drivers/mmc/host/dw_mmc-k3.c                       |  136 ++++++++++++++++++++
>  4 files changed, 198 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
>  create mode 100644 drivers/mmc/host/dw_mmc-k3.c
> 
> diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> new file mode 100644
> index 000000000000..d816b89c386a
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
> @@ -0,0 +1,51 @@
> +* Hisilicon specific extensions to the Synopsys Designware Mobile
> +  Storage Host Controller
> +
> +Read synopsys-dw-mshc.txt for more details
> +
> +The Synopsys designware mobile storage host controller is used to interface
> +a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
> +differences between the core Synopsys dw mshc controller properties described
> +by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
> +extensions to the Synopsys Designware Mobile Storage Host Controller.
> +
> +Required Properties:
> +
> +* compatible: should be one of the following.
> +  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
> +* clk-table-num: should be number of clks in clk-table required by each mmc timing
> +* clk-table: should clock list required by each mmc timing

I have not seen "clk-table" and "clk-table-num" before. Are these standard
properties? What are the units that are used here, what does the index mean?

	Arnd

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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
  2013-12-11 14:02 [PATCH v4 0/3] mmc: dw_mmc: add dw_mmc-k3 Zhangfei Gao
@ 2013-12-11 14:02   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-11 14:02 UTC (permalink / raw)
  To: Chris Ball, Arnd Bergmann, Mike Turquette, Rob Herring,
	Jaehoon Chung, Seungwon Jeon, Kumar Gala, Haojian Zhuang
  Cc: linux-mmc, linux-arm-kernel, patches, devicetree, Zhangfei Gao

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   51 ++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  136 ++++++++++++++++++++
 4 files changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d816b89c386a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,51 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+* clk-table-num: should be number of clks in clk-table required by each mmc timing
+* clk-table: should clock list required by each mmc timing
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0@fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clk-table-num = <8>;
+		clk-table =
+		<13000000 50000000 0 0 13000000 50000000 0 100000000>;
+	};
+
+	/* Board portion */
+	dwmmc0@fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot@0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..08fd7d7bbb23
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+
+	clk_set_rate(host->ciu_clk, priv->clk_table[ios->timing]);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	int ret = 0, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	ret = of_property_read_u32(host->dev->of_node, "clk-table-num", &num);
+	if (ret < 0) {
+		dev_err(host->dev, "not found clk-table-num\n");
+		return ret;
+	}
+	if (num > MAX_NUMS) {
+		dev_err(host->dev, "clk-table-num too big\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(host->dev->of_node, "clk-table",
+			priv->clk_table, num);
+	if (ret) {
+		dev_err(host->dev, "not found clk-table\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5


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

* [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform
@ 2013-12-11 14:02   ` Zhangfei Gao
  0 siblings, 0 replies; 146+ messages in thread
From: Zhangfei Gao @ 2013-12-11 14:02 UTC (permalink / raw)
  To: linux-arm-kernel

Add dw_mmc-k3.c for k3v2, support sd/emmc

Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Tested-by: Zhigang Wang <brooke.wangzhigang@huawei.com>
---
 .../devicetree/bindings/mmc/k3-dw-mshc.txt         |   51 ++++++++
 drivers/mmc/host/Kconfig                           |   10 ++
 drivers/mmc/host/Makefile                          |    1 +
 drivers/mmc/host/dw_mmc-k3.c                       |  136 ++++++++++++++++++++
 4 files changed, 198 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
 create mode 100644 drivers/mmc/host/dw_mmc-k3.c

diff --git a/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
new file mode 100644
index 000000000000..d816b89c386a
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/k3-dw-mshc.txt
@@ -0,0 +1,51 @@
+* Hisilicon specific extensions to the Synopsys Designware Mobile
+  Storage Host Controller
+
+Read synopsys-dw-mshc.txt for more details
+
+The Synopsys designware mobile storage host controller is used to interface
+a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
+differences between the core Synopsys dw mshc controller properties described
+by synopsys-dw-mshc.txt and the properties used by the Hisilicon specific
+extensions to the Synopsys Designware Mobile Storage Host Controller.
+
+Required Properties:
+
+* compatible: should be one of the following.
+  - "hisilicon,hi4511-dw-mshc": for controllers with hi4511 specific extentions.
+* clk-table-num: should be number of clks in clk-table required by each mmc timing
+* clk-table: should clock list required by each mmc timing
+
+Example:
+
+	/* for Hi3620 */
+
+	/* SoC portion */
+	dwmmc_0: dwmmc0 at fcd03000 {
+		compatible = "hisilicon,hi4511-dw-mshc";
+		reg = <0xfcd03000 0x1000>;
+		interrupts = <0 16 4>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		clocks = <&mmc_clock HI3620_SD_CIUCLK>, <&clock HI3620_DDRC_PER_CLK>;
+		clock-names = "ciu", "biu";
+		clk-table-num = <8>;
+		clk-table =
+		<13000000 50000000 0 0 13000000 50000000 0 100000000>;
+	};
+
+	/* Board portion */
+	dwmmc0 at fcd03000 {
+		num-slots = <1>;
+		vmmc-supply = <&ldo12>;
+		fifo-depth = <0x100>;
+		supports-highspeed;
+		pinctrl-names = "default";
+		pinctrl-0 = <&sd_pmx_pins &sd_cfg_func1 &sd_cfg_func2>;
+		slot at 0 {
+			reg = <0>;
+			bus-width = <4>;
+			disable-wp;
+			cd-gpios = <&gpio10 3 0>;
+		};
+	};
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 7fc5099e44b2..45aaa2de0f58 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -575,6 +575,16 @@ config MMC_DW_SOCFPGA
 	  This selects support for Altera SoCFPGA specific extensions to the
 	  Synopsys DesignWare Memory Card Interface driver.
 
+config MMC_DW_K3
+	tristate "K3 specific extensions for Synopsys DW Memory Card Interface"
+	depends on MMC_DW
+	select MMC_DW_PLTFM
+	select MMC_DW_IDMAC
+	help
+	  This selects support for Hisilicon K3 SoC specific extensions to the
+	  Synopsys DesignWare Memory Card Interface driver. Select this option
+	  for platforms based on Hisilicon K3 SoC's.
+
 config MMC_DW_PCI
 	tristate "Synopsys Designware MCI support on PCI bus"
 	depends on MMC_DW && PCI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index c41d0c364509..64f5f8d35839 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
 obj-$(CONFIG_MMC_DW_PLTFM)	+= dw_mmc-pltfm.o
 obj-$(CONFIG_MMC_DW_EXYNOS)	+= dw_mmc-exynos.o
 obj-$(CONFIG_MMC_DW_SOCFPGA)	+= dw_mmc-socfpga.o
+obj-$(CONFIG_MMC_DW_K3)		+= dw_mmc-k3.o
 obj-$(CONFIG_MMC_DW_PCI)	+= dw_mmc-pci.o
 obj-$(CONFIG_MMC_SH_MMCIF)	+= sh_mmcif.o
 obj-$(CONFIG_MMC_JZ4740)	+= jz4740_mmc.o
diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c
new file mode 100644
index 000000000000..08fd7d7bbb23
--- /dev/null
+++ b/drivers/mmc/host/dw_mmc-k3.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2013 Linaro Ltd.
+ * Copyright (c) 2013 Hisilicon Limited.
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/dw_mmc.h>
+#include <linux/of_address.h>
+
+#include "dw_mmc.h"
+#include "dw_mmc-pltfm.h"
+
+#define MAX_NUMS	10
+struct dw_mci_k3_priv_data {
+	u32	clk_table[MAX_NUMS];
+};
+
+static void dw_mci_k3_set_ios(struct dw_mci *host, struct mmc_ios *ios)
+{
+	struct dw_mci_k3_priv_data *priv = host->priv;
+
+	clk_set_rate(host->ciu_clk, priv->clk_table[ios->timing]);
+}
+
+static int dw_mci_k3_parse_dt(struct dw_mci *host)
+{
+	struct dw_mci_k3_priv_data *priv;
+	int ret = 0, num = 0;
+
+	priv = devm_kzalloc(host->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(host->dev, "mem alloc failed for private data\n");
+		return -ENOMEM;
+	}
+	host->priv = priv;
+
+	ret = of_property_read_u32(host->dev->of_node, "clk-table-num", &num);
+	if (ret < 0) {
+		dev_err(host->dev, "not found clk-table-num\n");
+		return ret;
+	}
+	if (num > MAX_NUMS) {
+		dev_err(host->dev, "clk-table-num too big\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_array(host->dev->of_node, "clk-table",
+			priv->clk_table, num);
+	if (ret) {
+		dev_err(host->dev, "not found clk-table\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static unsigned long k3_dwmmc_caps[4] = {
+	MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED,
+	MMC_CAP_8_BIT_DATA | MMC_CAP_MMC_HIGHSPEED,
+	0,
+	0,
+};
+
+static const struct dw_mci_drv_data k3_drv_data = {
+	.caps			= k3_dwmmc_caps,
+	.set_ios		= dw_mci_k3_set_ios,
+	.parse_dt		= dw_mci_k3_parse_dt,
+};
+
+static const struct of_device_id dw_mci_k3_match[] = {
+	{ .compatible = "hisilicon,hi4511-dw-mshc",
+			.data = &k3_drv_data, },
+	{},
+};
+MODULE_DEVICE_TABLE(of, dw_mci_k3_match);
+
+static int dw_mci_k3_probe(struct platform_device *pdev)
+{
+	const struct dw_mci_drv_data *drv_data;
+	const struct of_device_id *match;
+
+	match = of_match_node(dw_mci_k3_match, pdev->dev.of_node);
+	drv_data = match->data;
+
+	return dw_mci_pltfm_register(pdev, drv_data);
+}
+
+static int dw_mci_k3_suspend(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+
+	if (!IS_ERR(host->ciu_clk))
+		clk_disable_unprepare(host->ciu_clk);
+
+	return dw_mci_suspend(host);
+}
+
+static int dw_mci_k3_resume(struct device *dev)
+{
+	struct dw_mci *host = dev_get_drvdata(dev);
+	int ret = 0;
+
+	ret = clk_prepare_enable(host->ciu_clk);
+	if (ret) {
+		dev_err(host->dev, "failed to enable ciu clock\n");
+		return ret;
+	}
+
+	return dw_mci_resume(host);
+}
+
+SIMPLE_DEV_PM_OPS(dw_mci_k3_pmops, dw_mci_k3_suspend, dw_mci_k3_resume);
+
+static struct platform_driver dw_mci_k3_pltfm_driver = {
+	.probe		= dw_mci_k3_probe,
+	.remove		= dw_mci_pltfm_remove,
+	.driver		= {
+		.name		= "dwmmc_k3",
+		.of_match_table	= dw_mci_k3_match,
+		.pm		= &dw_mci_k3_pmops,
+	},
+};
+
+module_platform_driver(dw_mci_k3_pltfm_driver);
+
+MODULE_DESCRIPTION("K3 Specific DW-MSHC Driver Extension");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:dwmmc-k3");
-- 
1.7.9.5

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

end of thread, other threads:[~2014-01-16 11:25 UTC | newest]

Thread overview: 146+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-01-09 14:35 [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3 Zhangfei Gao
2014-01-09 14:35 ` Zhangfei Gao
2014-01-09 14:35 ` [PATCH 1/3] mmc: dw_mmc: use slot-gpio to handle cd pin Zhangfei Gao
2014-01-09 14:35   ` Zhangfei Gao
2014-01-09 14:38   ` Arnd Bergmann
2014-01-09 14:38     ` Arnd Bergmann
2014-01-14 15:58   ` Kevin Hilman
2014-01-14 15:58     ` Kevin Hilman
2014-01-14 17:23     ` Olof Johansson
2014-01-14 17:23       ` Olof Johansson
2014-01-15  1:09       ` zhangfei
2014-01-15  1:09         ` zhangfei
2014-01-15  5:16         ` zhangfei
2014-01-15  5:16           ` zhangfei
2014-01-15  7:15     ` [PATCH] mmc: dw_mmc: fix dw_mci_get_cd Zhangfei Gao
2014-01-15  7:15       ` Zhangfei Gao
2014-01-15  7:31       ` zhangfei
2014-01-15  7:31         ` zhangfei
2014-01-15 10:07       ` Zhangfei Gao
2014-01-15 10:07         ` Zhangfei Gao
2014-01-15 11:58         ` Seungwon Jeon
2014-01-15 11:58           ` Seungwon Jeon
2014-01-15 12:10           ` zhangfei
2014-01-15 12:10             ` zhangfei
2014-01-15 12:26             ` Seungwon Jeon
2014-01-15 12:26               ` Seungwon Jeon
2014-01-15 13:56               ` zhangfei
2014-01-15 13:56                 ` zhangfei
2014-01-15 13:59                 ` Arnd Bergmann
2014-01-15 13:59                   ` Arnd Bergmann
2014-01-15 14:20                   ` Arnd Bergmann
2014-01-15 14:20                     ` Arnd Bergmann
2014-01-15 15:36                     ` zhangfei
2014-01-15 15:36                       ` zhangfei
2014-01-15 16:01                   ` Russell King - ARM Linux
2014-01-15 16:01                     ` Russell King - ARM Linux
2014-01-15 16:07                     ` Arnd Bergmann
2014-01-15 16:07                       ` Arnd Bergmann
2014-01-15 16:22                       ` Russell King - ARM Linux
2014-01-15 16:22                         ` Russell King - ARM Linux
2014-01-16  2:10                         ` zhangfei
2014-01-16  2:10                           ` zhangfei
2014-01-16 11:12                         ` Arnd Bergmann
2014-01-16 11:12                           ` Arnd Bergmann
2014-01-16 11:25                           ` Russell King - ARM Linux
2014-01-16 11:25                             ` Russell King - ARM Linux
2014-01-15 14:38                 ` Seungwon Jeon
2014-01-15 14:38                   ` Seungwon Jeon
2014-01-15 15:32                   ` zhangfei
2014-01-15 15:32                     ` zhangfei
2014-01-15 15:51                     ` Zhangfei Gao
2014-01-15 15:51                       ` Zhangfei Gao
2014-01-15 15:59                       ` Russell King - ARM Linux
2014-01-15 15:59                         ` Russell King - ARM Linux
2014-01-15 15:54                     ` Arnd Bergmann
2014-01-15 15:54                       ` Arnd Bergmann
     [not found] ` <1389278112-7099-1-git-send-email-zhangfei.gao-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-01-09 14:35   ` [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform Zhangfei Gao
2014-01-09 14:35     ` Zhangfei Gao
2014-01-09 14:45     ` Arnd Bergmann
2014-01-09 14:45       ` Arnd Bergmann
2014-01-10 13:39     ` Seungwon Jeon
2014-01-10 13:39       ` Seungwon Jeon
2014-01-10 14:12       ` zhangfei
2014-01-10 14:12         ` zhangfei
2014-01-13  2:09         ` Seungwon Jeon
2014-01-13  2:09           ` Seungwon Jeon
2014-01-13  2:37           ` zhangfei
2014-01-13  2:37             ` zhangfei
2014-01-13  5:32             ` Seungwon Jeon
2014-01-13  5:32               ` Seungwon Jeon
2014-01-13  8:30               ` zhangfei
2014-01-13  8:30                 ` zhangfei
2014-01-14  9:38                 ` Seungwon Jeon
2014-01-14  9:38                   ` Seungwon Jeon
2014-01-14  9:47                   ` zhangfei
2014-01-14  9:47                     ` zhangfei
2014-01-09 14:35 ` [PATCH 3/3] clk: hisilicon: add hi3620_mmc_clks Zhangfei Gao
2014-01-09 14:35   ` Zhangfei Gao
2014-01-09 14:38   ` Arnd Bergmann
2014-01-09 14:38     ` Arnd Bergmann
2014-01-10  3:41 ` [PATCH v7 0/3] mmc: dw_mmc: add dw_mmc-k3 Jaehoon Chung
2014-01-10  3:41   ` Jaehoon Chung
2014-01-12 16:35 ` Chris Ball
2014-01-12 16:35   ` Chris Ball
2014-01-13  1:00   ` Zhangfei Gao
2014-01-13  1:00     ` Zhangfei Gao
  -- strict thread matches above, loose matches on Subject: below --
2013-12-28 14:34 [PATCH v6 " Zhangfei Gao
2013-12-28 14:34 ` [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform Zhangfei Gao
2013-12-28 14:34   ` Zhangfei Gao
2013-12-29 21:05   ` Arnd Bergmann
2013-12-29 21:05     ` Arnd Bergmann
2013-12-29 23:55     ` Jaehoon Chung
2013-12-29 23:55       ` Jaehoon Chung
2013-12-30  2:32       ` Zhangfei Gao
2013-12-30  2:32         ` Zhangfei Gao
2013-12-30 17:19         ` zhangfei
2013-12-30 17:19           ` zhangfei
2013-12-30 20:27           ` Arnd Bergmann
2013-12-30 20:27             ` Arnd Bergmann
2013-12-31  4:43             ` zhangfei
2013-12-31  4:43               ` zhangfei
2013-12-31 13:20     ` Gerhard Sittig
2013-12-31 13:20       ` Gerhard Sittig
2014-01-02  2:19       ` zhangfei
2014-01-02  2:19         ` zhangfei
2014-01-02  3:07   ` Zhangfei Gao
2014-01-02  3:07     ` Zhangfei Gao
2013-12-14  2:12 [PATCH v5 0/3] mmc: dw_mmc: add dw_mmc-k3 Zhangfei Gao
2013-12-14  2:12 ` [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform Zhangfei Gao
2013-12-14  2:12   ` Zhangfei Gao
2013-12-16  3:50   ` Seungwon Jeon
2013-12-16  3:50     ` Seungwon Jeon
2013-12-16  5:05     ` zhangfei
2013-12-16  5:05       ` zhangfei
2013-12-16  7:29       ` Seungwon Jeon
2013-12-16  7:29         ` Seungwon Jeon
2013-12-16  8:08         ` zhangfei
2013-12-16  8:08           ` zhangfei
2013-12-16  9:18           ` Seungwon Jeon
2013-12-16  9:18             ` Seungwon Jeon
2013-12-16 11:07             ` zhangfei
2013-12-16 11:07               ` zhangfei
2013-12-16 13:12   ` Zhangfei Gao
2013-12-16 13:12     ` Zhangfei Gao
2013-12-20  2:31     ` zhangfei
2013-12-20  2:31       ` zhangfei
2013-12-26  4:33     ` Jaehoon Chung
2013-12-26  4:33       ` Jaehoon Chung
2013-12-27  6:13       ` zhangfei
2013-12-27  6:13         ` zhangfei
2013-12-11 14:02 [PATCH v4 0/3] mmc: dw_mmc: add dw_mmc-k3 Zhangfei Gao
2013-12-11 14:02 ` [PATCH 2/3] mmc: dw_mmc: add dw_mmc-k3 for k3 platform Zhangfei Gao
2013-12-11 14:02   ` Zhangfei Gao
2013-12-11 14:49   ` Arnd Bergmann
2013-12-11 14:49     ` Arnd Bergmann
2013-12-11 15:36     ` zhangfei
2013-12-11 15:36       ` zhangfei
2013-12-11 15:53       ` zhangfei
2013-12-11 15:53         ` zhangfei
2013-12-11 20:12       ` Arnd Bergmann
2013-12-11 20:12         ` Arnd Bergmann
     [not found]         ` <201312112112.52746.arnd-r2nGTMty4D4@public.gmane.org>
2013-12-12 13:27           ` zhangfei
2013-12-12 13:27             ` zhangfei
2013-12-12 14:13             ` Zhangfei Gao
2013-12-12 14:13               ` Zhangfei Gao
2013-12-12 20:40             ` Arnd Bergmann
2013-12-12 20:40               ` Arnd Bergmann
2013-12-13  2:57               ` zhangfei
2013-12-13  2:57                 ` zhangfei

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.