linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mx51: add resources for SD/MMC on i.MX51
@ 2010-10-11 16:05 Eric Bénard
  2010-10-11 16:28 ` Wolfram Sang
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Bénard @ 2010-10-11 16:05 UTC (permalink / raw)
  To: linux-arm-kernel

the attached patch allows SD to work on i.MX51 with Wolfram's drivers
Tested on i.MX51.

From: Richard Zhu <r65037@freescale.com>
Signed-off-by: Eric B?nard <eric@eukrea.com>
---
 arch/arm/mach-mx5/clock-mx51.c              |  193 +++++++++++++++++++++++++++
 arch/arm/mach-mx5/devices-imx51.h           |    9 ++
 arch/arm/plat-mxc/include/mach/iomux-mx51.h |   33 +++--
 3 files changed, 221 insertions(+), 14 deletions(-)

diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 21cecc0..eee2814 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -41,6 +41,35 @@ static struct clk usboh3_clk;
 
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+	u32 min_pre, temp_pre, old_err, err;
+
+	if (div >= 512) {
+		*pre = 8;
+		*post = 64;
+	} else if (div >= 8) {
+		min_pre = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+			err = div % temp_pre;
+			if (err == 0) {
+				*pre = temp_pre;
+				break;
+			}
+			err = temp_pre - err;
+			if (err < old_err) {
+				old_err = err;
+				*pre = temp_pre;
+			}
+		}
+		*post = (div + *pre - 1) / *pre;
+	} else if (div < 8) {
+		*pre = div;
+		*post = 1;
+	}
+}
+
 static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
 {
 	u32 reg = __raw_readl(clk->enable_reg);
@@ -893,6 +922,160 @@ static struct clk ecspi_main_clk = {
 	.set_parent = clk_ecspi_set_parent,
 };
 
+static int _clk_esdhc1_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, mux;
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+			&pll3_sw_clk, &lp_apm_clk);
+	reg = __raw_readl(MXC_CCM_CSCMR1) &
+		~MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static unsigned long _clk_esdhc1_get_rate(struct clk *clk)
+{
+	u32 reg, prediv, podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CSCDR1);
+	prediv = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK) >>
+		  MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET) + 1;
+	podf = ((reg & MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK) >>
+		MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET) + 1;
+
+	return parent_rate / (prediv * podf);
+}
+
+static int _clk_esdhc1_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div, parent_rate;
+	u32 pre = 0, post = 0;
+
+	parent_rate = clk_get_rate(clk->parent);
+	div = parent_rate / rate;
+
+	if ((parent_rate / div) != rate)
+		return -EINVAL;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	/* Set sdhc1 clock divider */
+	reg = __raw_readl(MXC_CCM_CSCDR1) &
+		~(MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK
+				| MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_MASK);
+	reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PODF_OFFSET;
+	reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET;
+	__raw_writel(reg, MXC_CCM_CSCDR1);
+
+	return 0;
+}
+
+static struct clk esdhc1_clk[] = {
+	{
+		.id = 0,
+		.parent = &pll2_sw_clk,
+		.secondary = &esdhc1_clk[1],
+		.enable_shift = MXC_CCM_CCGRx_CG1_OFFSET,
+		.enable_reg = MXC_CCM_CCGR3,
+		.get_rate = _clk_esdhc1_get_rate,
+		.set_rate = _clk_esdhc1_set_rate,
+		.enable = _clk_max_enable,
+		.disable = _clk_max_disable,
+		.set_parent = _clk_esdhc1_set_parent,
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.secondary = NULL,
+		.enable = _clk_max_enable,
+		.enable_reg = MXC_CCM_CCGR3,
+		.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,
+		.disable = _clk_max_disable,
+	}
+};
+
+static int _clk_esdhc2_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg, mux;
+
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,
+			&pll3_sw_clk, &lp_apm_clk);
+	reg = __raw_readl(MXC_CCM_CSCMR1) &
+		~MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK;
+	reg |= mux << MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET;
+
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+	return 0;
+}
+
+static unsigned long _clk_esdhc2_get_rate(struct clk *clk)
+{
+	u32 reg, prediv, podf;
+	unsigned long parent_rate;
+
+	parent_rate = clk_get_rate(clk->parent);
+
+	reg = __raw_readl(MXC_CCM_CSCDR1);
+	prediv = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK) >>
+		  MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET) + 1;
+	podf = ((reg & MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK) >>
+		MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET) + 1;
+
+	return parent_rate / (prediv * podf);
+}
+
+static int _clk_esdhc2_set_rate(struct clk *clk, unsigned long rate)
+{
+	u32 reg, div, parent_rate;
+	u32 pre = 0, post = 0;
+
+	parent_rate = clk_get_rate(clk->parent);
+	div = parent_rate / rate;
+	if ((parent_rate / div) != rate)
+		return -EINVAL;
+
+	__calc_pre_post_dividers(div, &pre, &post);
+
+	/* Set sdhc1 clock divider */
+	reg = __raw_readl(MXC_CCM_CSCDR1) &
+		~(MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK
+				| MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK);
+	reg |= (post - 1) << MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET;
+	reg |= (pre - 1) << MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET;
+	__raw_writel(reg, MXC_CCM_CSCDR1);
+
+	return 0;
+}
+
+static struct clk esdhc2_clk[] = {
+	{
+		.id = 1,
+		.parent = &pll2_sw_clk,
+		.secondary = &esdhc2_clk[1],
+		.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+		.enable_reg = MXC_CCM_CCGR3,
+		.get_rate = _clk_esdhc2_get_rate,
+		.set_rate = _clk_esdhc2_set_rate,
+		.enable = _clk_max_enable,
+		.disable = _clk_max_disable,
+		.set_parent = _clk_esdhc2_set_parent,
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.secondary = NULL,
+		.enable_shift = MXC_CCM_CCGRx_CG2_OFFSET,
+		.enable_reg = MXC_CCM_CCGR3,
+		.enable = _clk_max_enable,
+		.disable = _clk_max_disable,
+	}
+};
+
 #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
 	static struct clk name = {					\
 		.id		= i,					\
@@ -1014,6 +1197,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
 	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK(NULL, "sdhc", esdhc1_clk[0])
+	_REGISTER_CLOCK(NULL, "sdhc", esdhc2_clk[0])
 };
 
 static void clk_tree_init(void)
@@ -1057,6 +1242,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 	/* set the usboh3_clk parent to pll2_sw_clk */
 	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
 
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk[0], &pll2_sw_clk);
+	clk_set_parent(&esdhc2_clk[0], &pll2_sw_clk);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(&esdhc1_clk[0], 166250000);
+	clk_set_rate(&esdhc2_clk[0], 166250000);
+
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
 		MX51_MXC_INT_GPT);
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index c233379..547432d 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -36,3 +36,12 @@ extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
 extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
 #define imx51_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+#define imx51_add_esdhc0(pdata)	\
+	imx_add_esdhc(0, MX51_MMC_SDHC1_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC1, pdata)
+#define imx51_add_esdhc1(pdata)	\
+	imx_add_esdhc(1, MX51_MMC_SDHC2_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC2, pdata)
+#define imx51_add_esdhc2(pdata)	\
+	imx_add_esdhc(2, MX51_MMC_SDHC3_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC3, pdata)
+#define imx51_add_esdhc3(pdata)	\
+	imx_add_esdhc(3, MX51_MMC_SDHC4_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC4, pdata)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index 633650d..4b8c61e 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -47,6 +47,9 @@ typedef enum iomux_config {
 				PAD_CTL_SRE_FAST)
 #define MX51_ECSPI_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
 				PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL 	(PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
+				PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
+				PAD_CTL_DVS)
 
 #define MX51_PAD_CTRL_1	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
 					PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
@@ -333,20 +336,22 @@ typedef enum iomux_config {
 #define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD               IOMUX_PAD(0x79C, 0x394, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK               IOMUX_PAD(0x7A0, 0x398, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0           IOMUX_PAD(0x7A4, 0x39C, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1           IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2           IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3           IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK 	IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL \
+		| PAD_CTL_HYS)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0	IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1	IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2	IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3	IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD               IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK               IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0           IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1           IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2           IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3           IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO_1_1	IOMUX_PAD(0x7B8, 0x3B0, IOMUX_CONFIG_GPIO, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL \
+		| PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0	IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1	IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2	IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3	IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__I2C2_SCL		IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
 							0x9b8,   3, MX51_I2C_PAD_CTRL)
@@ -355,7 +360,7 @@ typedef enum iomux_config {
 							0x9bc,   3, MX51_I2C_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO_1_5	IOMUX_PAD(0x808, 0x3DC, IOMUX_CONFIG_GPIO, 0x0, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 0, 0x0,   1, MX51_GPIO_PAD_CTRL)
-- 
1.7.0.4

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

* [PATCH] mx51: add resources for SD/MMC on i.MX51
  2010-10-11 16:05 [PATCH] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
@ 2010-10-11 16:28 ` Wolfram Sang
  2010-10-11 16:55   ` Eric Bénard
  0 siblings, 1 reply; 9+ messages in thread
From: Wolfram Sang @ 2010-10-11 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 11, 2010 at 06:05:42PM +0200, Eric B?nard wrote:
> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
> Tested on i.MX51.
> 
> From: Richard Zhu <r65037@freescale.com>
> Signed-off-by: Eric B?nard <eric@eukrea.com>

Hmm, Uwe had some (valid IMHO) comments about this patch which have not all
been addressed so far. Richard, are you still working on this?

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20101011/a0c2ff0c/attachment.sig>

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

* [PATCH] mx51: add resources for SD/MMC on i.MX51
  2010-10-11 16:28 ` Wolfram Sang
@ 2010-10-11 16:55   ` Eric Bénard
  2010-10-11 17:04     ` Wolfram Sang
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Bénard @ 2010-10-11 16:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Wolfram,

Le 11/10/2010 18:28, Wolfram Sang a ?crit :
> On Mon, Oct 11, 2010 at 06:05:42PM +0200, Eric B?nard wrote:
>> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
>> Tested on i.MX51.
>>
>> From: Richard Zhu<r65037@freescale.com>
>> Signed-off-by: Eric B?nard<eric@eukrea.com>
>
> Hmm, Uwe had some (valid IMHO) comments about this patch which have not all
> been addressed so far. Richard, are you still working on this?
>
OK, is this this review
http://lists.infradead.org/pipermail/linux-arm-kernel/2010-September/027269.html 
? If yes, I can submit a fixed patch asap.

Eric

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

* [PATCH] mx51: add resources for SD/MMC on i.MX51
  2010-10-11 16:55   ` Eric Bénard
@ 2010-10-11 17:04     ` Wolfram Sang
  2010-10-12  7:31       ` [PATCH 1/2] clock-mx51: factorize clk_set_parent and clk_get_rate Eric Bénard
  2010-10-12  7:31       ` [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
  0 siblings, 2 replies; 9+ messages in thread
From: Wolfram Sang @ 2010-10-11 17:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Mon, Oct 11, 2010 at 06:55:38PM +0200, Eric B?nard wrote:
> Hi Wolfram,
>
> Le 11/10/2010 18:28, Wolfram Sang a ?crit :
>> On Mon, Oct 11, 2010 at 06:05:42PM +0200, Eric B?nard wrote:
>>> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
>>> Tested on i.MX51.
>>>
>>> From: Richard Zhu<r65037@freescale.com>
>>> Signed-off-by: Eric B?nard<eric@eukrea.com>
>>
>> Hmm, Uwe had some (valid IMHO) comments about this patch which have not all
>> been addressed so far. Richard, are you still working on this?
>>
> OK, is this this review
 
> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-September/027269.html 
> ? If yes, I can submit a fixed patch asap.

Yes, that is the one. Sorry, I also wanted to give a pointer to this mail but
it dropped off my mind. Patch would be awesome!

Regards,

   Wolfram

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20101011/0d9efbae/attachment.sig>

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

* [PATCH 1/2] clock-mx51: factorize clk_set_parent and clk_get_rate
  2010-10-11 17:04     ` Wolfram Sang
@ 2010-10-12  7:31       ` Eric Bénard
  2010-10-12  7:31       ` [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
  1 sibling, 0 replies; 9+ messages in thread
From: Eric Bénard @ 2010-10-12  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Eric B?nard <eric@eukrea.com>
---
 arch/arm/mach-mx5/clock-mx51.c |  142 ++++++++++++++--------------------------
 1 files changed, 48 insertions(+), 94 deletions(-)

diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 21cecc0..7deb683 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -544,35 +544,6 @@ static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)
 	return 0;
 }
 
-static unsigned long clk_uart_get_rate(struct clk *clk)
-{
-	u32 reg, prediv, podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CSCDR1);
-	prediv = ((reg & MXC_CCM_CSCDR1_UART_CLK_PRED_MASK) >>
-		  MXC_CCM_CSCDR1_UART_CLK_PRED_OFFSET) + 1;
-	podf = ((reg & MXC_CCM_CSCDR1_UART_CLK_PODF_MASK) >>
-		MXC_CCM_CSCDR1_UART_CLK_PODF_OFFSET) + 1;
-
-	return parent_rate / (prediv * podf);
-}
-
-static int _clk_uart_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-		       &lp_apm_clk);
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_UART_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CSCMR1_UART_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
 #define clk_nfc_set_parent	NULL
 
 static unsigned long clk_nfc_get_rate(struct clk *clk)
@@ -631,35 +602,6 @@ static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)
 	return 0;
 }
 
-static unsigned long clk_usboh3_get_rate(struct clk *clk)
-{
-	u32 reg, prediv, podf;
-	unsigned long parent_rate;
-
-	parent_rate = clk_get_rate(clk->parent);
-
-	reg = __raw_readl(MXC_CCM_CSCDR1);
-	prediv = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PRED_MASK) >>
-		  MXC_CCM_CSCDR1_USBOH3_CLK_PRED_OFFSET) + 1;
-	podf = ((reg & MXC_CCM_CSCDR1_USBOH3_CLK_PODF_MASK) >>
-		MXC_CCM_CSCDR1_USBOH3_CLK_PODF_OFFSET) + 1;
-
-	return parent_rate / (prediv * podf);
-}
-
-static int _clk_usboh3_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
-
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-		       &lp_apm_clk);
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USBOH3_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CSCMR1_USBOH3_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
-
-	return 0;
-}
-
 static unsigned long get_high_reference_clock_rate(struct clk *clk)
 {
 	return external_high_reference;
@@ -786,18 +728,6 @@ static struct clk ipg_perclk = {
 	.set_parent = _clk_ipg_per_set_parent,
 };
 
-static struct clk uart_root_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_uart_get_rate,
-	.set_parent = _clk_uart_set_parent,
-};
-
-static struct clk usboh3_clk = {
-	.parent = &pll2_sw_clk,
-	.get_rate = clk_usboh3_get_rate,
-	.set_parent = _clk_usboh3_set_parent,
-};
-
 static struct clk ahb_max_clk = {
 	.parent = &ahb_clk,
 	.enable_reg = MXC_CCM_CCGR0,
@@ -857,35 +787,59 @@ static struct clk emi_slow_clk = {
 		.secondary	= s,			\
 	}
 
-/* eCSPI */
-static unsigned long clk_ecspi_get_rate(struct clk *clk)
-{
-	u32 reg, pred, podf;
-
-	reg = __raw_readl(MXC_CCM_CSCDR2);
-
-	pred = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PRED_MASK) >>
-			MXC_CCM_CSCDR2_CSPI_CLK_PRED_OFFSET;
-	podf = (reg & MXC_CCM_CSCDR2_CSPI_CLK_PODF_MASK) >>
-			MXC_CCM_CSCDR2_CSPI_CLK_PODF_OFFSET;
-
-	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),
-			(pred + 1) * (podf + 1));
+#define CLK_GET_RATE(name, nr, bitsname)				\
+static unsigned long clk_##name##_get_rate(struct clk *clk)		\
+{									\
+	u32 reg, pred, podf;						\
+									\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr);				\
+	pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK)	\
+		>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+									\
+	return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent),		\
+			(pred + 1) * (podf + 1));			\
+}
+
+#define CLK_SET_PARENT(name, nr, bitsname)				\
+static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
+{									\
+	u32 reg, mux;							\
+									\
+	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk,		\
+			&pll3_sw_clk, &lp_apm_clk);			\
+	reg = __raw_readl(MXC_CCM_CSCMR##nr) &				\
+		~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK;		\
+	reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCMR##nr);				\
+									\
+	return 0;							\
 }
 
-static int clk_ecspi_set_parent(struct clk *clk, struct clk *parent)
-{
-	u32 reg, mux;
+/* UART */
+CLK_GET_RATE(uart, 1, UART)
+CLK_SET_PARENT(uart, 1, UART)
 
-	mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, &pll3_sw_clk,
-			&lp_apm_clk);
+static struct clk uart_root_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_uart_get_rate,
+	.set_parent = clk_uart_set_parent,
+};
 
-	reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_CSPI_CLK_SEL_MASK;
-	reg |= mux << MXC_CCM_CSCMR1_CSPI_CLK_SEL_OFFSET;
-	__raw_writel(reg, MXC_CCM_CSCMR1);
+/* USBOH3 */
+CLK_GET_RATE(usboh3, 1, USBOH3)
+CLK_SET_PARENT(usboh3, 1, USBOH3)
 
-	return 0;
-}
+static struct clk usboh3_clk = {
+	.parent = &pll2_sw_clk,
+	.get_rate = clk_usboh3_get_rate,
+	.set_parent = clk_usboh3_set_parent,
+};
+
+/* eCSPI */
+CLK_GET_RATE(ecspi, 2, CSPI)
+CLK_SET_PARENT(ecspi, 1, CSPI)
 
 static struct clk ecspi_main_clk = {
 	.parent = &pll3_sw_clk,
-- 
1.7.0.4

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

* [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51
  2010-10-11 17:04     ` Wolfram Sang
  2010-10-12  7:31       ` [PATCH 1/2] clock-mx51: factorize clk_set_parent and clk_get_rate Eric Bénard
@ 2010-10-12  7:31       ` Eric Bénard
  2010-10-12  8:18         ` Uwe Kleine-König
  1 sibling, 1 reply; 9+ messages in thread
From: Eric Bénard @ 2010-10-12  7:31 UTC (permalink / raw)
  To: linux-arm-kernel

the attached patch allows SD to work on i.MX51 with Wolfram's drivers
Tested on i.MX51.

Based on original patch from: Richard Zhu <r65037@freescale.com>
Signed-off-by: Eric B?nard <eric@eukrea.com>
---
 arch/arm/mach-mx5/clock-mx51.c              |  102 ++++++++++++++++++++++++++-
 arch/arm/mach-mx5/devices-imx51.h           |    9 +++
 arch/arm/plat-mxc/include/mach/iomux-mx51.h |   45 ++++++++----
 3 files changed, 140 insertions(+), 16 deletions(-)

diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
index 7deb683..9e8b268 100644
--- a/arch/arm/mach-mx5/clock-mx51.c
+++ b/arch/arm/mach-mx5/clock-mx51.c
@@ -41,6 +41,34 @@ static struct clk usboh3_clk;
 
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
+static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
+{
+	if (div >= 512) {
+		*pre = 8;
+		*post = 64;
+	} else if (div >= 8) {
+		u32 min_pre, temp_pre, old_err, err;
+		min_pre = (div - 1) / 64 + 1;
+		old_err = 8;
+		for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
+			err = div % temp_pre;
+			if (err == 0) {
+				*pre = temp_pre;
+				break;
+			}
+			err = temp_pre - err;
+			if (err < old_err) {
+				old_err = err;
+				*pre = temp_pre;
+			}
+		}
+		*post = (div + *pre - 1) / *pre;
+	} else {
+		*pre = div;
+		*post = 1;
+	}
+}
+
 static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
 {
 	u32 reg = __raw_readl(clk->enable_reg);
@@ -772,7 +800,7 @@ static struct clk emi_slow_clk = {
 	.get_rate = clk_emi_slow_get_rate,
 };
 
-#define DEFINE_CLOCK1(name, i, er, es, pfx, p, s)	\
+#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
 	static struct clk name = {			\
 		.id		= i,			\
 		.enable_reg	= er,			\
@@ -787,6 +815,20 @@ static struct clk emi_slow_clk = {
 		.secondary	= s,			\
 	}
 
+#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
+	static struct clk name = {			\
+		.id		= i,			\
+		.enable_reg	= er,			\
+		.enable_shift	= es,			\
+		.get_rate	= pfx##_get_rate,	\
+		.set_rate	= pfx##_set_rate,	\
+		.set_parent	= pfx##_set_parent,	\
+		.enable		= _clk_max_enable,	\
+		.disable	= _clk_max_disable,	\
+		.parent		= p,			\
+		.secondary	= s,			\
+	}
+
 #define CLK_GET_RATE(name, nr, bitsname)				\
 static unsigned long clk_##name##_get_rate(struct clk *clk)		\
 {									\
@@ -817,6 +859,33 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
 	return 0;							\
 }
 
+#define CLK_SET_RATE(name, nr, bitsname)				\
+static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
+{									\
+	u32 reg, div, parent_rate;					\
+	u32 pre = 0, post = 0;						\
+									\
+	parent_rate = clk_get_rate(clk->parent);			\
+	div = parent_rate / rate;					\
+									\
+	if ((parent_rate / div) != rate)				\
+		return -EINVAL;						\
+									\
+	__calc_pre_post_dividers(div, &pre, &post);			\
+									\
+	/* Set sdhc1 clock divider */					\
+	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
+		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
+		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
+	reg |= (post - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
+	reg |= (pre - 1) <<						\
+		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
+	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
+									\
+	return 0;							\
+}
+
 /* UART */
 CLK_GET_RATE(uart, 1, UART)
 CLK_SET_PARENT(uart, 1, UART)
@@ -847,6 +916,15 @@ static struct clk ecspi_main_clk = {
 	.set_parent = clk_ecspi_set_parent,
 };
 
+/* eSDHC */
+CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
+CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
+
+CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
+CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
+
 #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
 	static struct clk name = {					\
 		.id		= i,					\
@@ -900,7 +978,7 @@ DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
 	NULL,  NULL, &ipg_clk, NULL);
 
 /* NFC */
-DEFINE_CLOCK1(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
+DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
 	clk_nfc, &emi_slow_clk, NULL);
 
 /* SSI */
@@ -935,6 +1013,16 @@ DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
 DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
 		NULL, NULL, &ahb_clk, NULL);
 
+/* eSDHC */
+DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
+	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
+DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
+	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
+
 #define _REGISTER_CLOCK(d, n, c) \
        { \
 		.dev_id = d, \
@@ -968,6 +1056,8 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
 	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
 };
 
 static void clk_tree_init(void)
@@ -1011,6 +1101,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
 	/* set the usboh3_clk parent to pll2_sw_clk */
 	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
 
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 166.25MHZ*/
+	clk_set_rate(&esdhc1_clk, 166250000);
+	clk_set_rate(&esdhc2_clk, 166250000);
+
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
 		MX51_MXC_INT_GPT);
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index c233379..547432d 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -36,3 +36,12 @@ extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
 extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
 #define imx51_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
+
+#define imx51_add_esdhc0(pdata)	\
+	imx_add_esdhc(0, MX51_MMC_SDHC1_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC1, pdata)
+#define imx51_add_esdhc1(pdata)	\
+	imx_add_esdhc(1, MX51_MMC_SDHC2_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC2, pdata)
+#define imx51_add_esdhc2(pdata)	\
+	imx_add_esdhc(2, MX51_MMC_SDHC3_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC3, pdata)
+#define imx51_add_esdhc3(pdata)	\
+	imx_add_esdhc(3, MX51_MMC_SDHC4_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC4, pdata)
diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
index 5160f10..c5adb42 100644
--- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
+++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
@@ -47,6 +47,9 @@ typedef enum iomux_config {
 				PAD_CTL_SRE_FAST)
 #define MX51_ECSPI_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
 				PAD_CTL_SRE_FAST)
+#define MX51_SDHCI_PAD_CTRL 	(PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
+				PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
+				PAD_CTL_DVS)
 
 #define MX51_PAD_CTRL_1	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
 					PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
@@ -333,26 +336,39 @@ typedef enum iomux_config {
 #define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CMD__SD1_CMD               IOMUX_PAD(0x79C, 0x394, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_SD1_CMD__AUD5_RXFS             IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_CLK__SD1_CLK               IOMUX_PAD(0x7A0, 0x398, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
 #define MX51_PAD_SD1_CLK__AUD5_RXC              IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA0__SD1_DATA0           IOMUX_PAD(0x7A4, 0x39C, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_SD1_DATA0__AUD5_TXD            IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA1__SD1_DATA1           IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_SD1_DATA1__AUD5_RXD            IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA2__SD1_DATA2           IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_SD1_DATA2__AUD5_TXC            IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
-#define MX51_PAD_SD1_DATA3__SD1_DATA3           IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_SD1_DATA3__AUD5_TXFS           IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
+#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CMD__SD2_CMD               IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_CLK__SD2_CLK               IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA0__SD2_DATA0           IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA1__SD2_DATA1           IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA2__SD2_DATA2           IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_SD2_DATA3__SD2_DATA3           IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, IOMUX_CONFIG_GPIO, 0x0, 0, \
+							MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_2__I2C2_SCL		IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
 							0x9b8,   3, MX51_I2C_PAD_CTRL)
@@ -361,7 +377,8 @@ typedef enum iomux_config {
 							0x9bc,   3, MX51_I2C_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 0, 0x0,   0, NO_PAD_CTRL)
-#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, IOMUX_CONFIG_GPIO, 0x0, 1, \
+							NO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 0, 0x0,   1, MX51_GPIO_PAD_CTRL)
-- 
1.7.0.4

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

* [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51
  2010-10-12  7:31       ` [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
@ 2010-10-12  8:18         ` Uwe Kleine-König
  2010-10-12  8:50           ` Eric Bénard
  0 siblings, 1 reply; 9+ messages in thread
From: Uwe Kleine-König @ 2010-10-12  8:18 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

great you pick up this topic.

On Tue, Oct 12, 2010 at 09:31:25AM +0200, Eric B?nard wrote:
> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
> Tested on i.MX51.
> 
> Based on original patch from: Richard Zhu <r65037@freescale.com>
> Signed-off-by: Eric B?nard <eric@eukrea.com>
> ---
>  arch/arm/mach-mx5/clock-mx51.c              |  102 ++++++++++++++++++++++++++-
>  arch/arm/mach-mx5/devices-imx51.h           |    9 +++
>  arch/arm/plat-mxc/include/mach/iomux-mx51.h |   45 ++++++++----
>  3 files changed, 140 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
> index 7deb683..9e8b268 100644
> --- a/arch/arm/mach-mx5/clock-mx51.c
> +++ b/arch/arm/mach-mx5/clock-mx51.c
> @@ -41,6 +41,34 @@ static struct clk usboh3_clk;
>  
>  #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
>  
> +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
> +{
I asked for a comment here.  E.g. valid ranges of pre and post and the
task solved here (I assume it's "Find pre and post with pre * post =
div"?).

> +	if (div >= 512) {
> +		*pre = 8;
> +		*post = 64;
> +	} else if (div >= 8) {
> +		u32 min_pre, temp_pre, old_err, err;
> +		min_pre = (div - 1) / 64 + 1;
		min_pre = DIV_ROUND_UP(div, 64); ?

> +		old_err = 8;
> +		for (temp_pre = 8; temp_pre >= min_pre; temp_pre--) {
> +			err = div % temp_pre;
> +			if (err == 0) {
> +				*pre = temp_pre;
> +				break;
> +			}
> +			err = temp_pre - err;
> +			if (err < old_err) {
> +				old_err = err;
> +				*pre = temp_pre;
> +			}
> +		}
> +		*post = (div + *pre - 1) / *pre;
		*post = DIV_ROUND_UP(div, *pre);

I don't know if DIV_ROUND_UP is sensible, maybe use DIV_ROUND_CLOSEST?
I'd look into that when the comment above is in place.

> +	} else {
> +		*pre = div;
> +		*post = 1;
> +	}
> +}
> +
>  static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)
>  {
>  	u32 reg = __raw_readl(clk->enable_reg);
> @@ -772,7 +800,7 @@ static struct clk emi_slow_clk = {
>  	.get_rate = clk_emi_slow_get_rate,
>  };
>  
> -#define DEFINE_CLOCK1(name, i, er, es, pfx, p, s)	\
> +#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
This is IMHO a good idea, but it should go in a seperate patch.  These
clock changes are very sensible and so a working bisection is important
here.

>  	static struct clk name = {			\
>  		.id		= i,			\
>  		.enable_reg	= er,			\
> @@ -787,6 +815,20 @@ static struct clk emi_slow_clk = {
>  		.secondary	= s,			\
>  	}
>  
> +#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s)	\
> +	static struct clk name = {			\
> +		.id		= i,			\
> +		.enable_reg	= er,			\
> +		.enable_shift	= es,			\
> +		.get_rate	= pfx##_get_rate,	\
> +		.set_rate	= pfx##_set_rate,	\
> +		.set_parent	= pfx##_set_parent,	\
> +		.enable		= _clk_max_enable,	\
> +		.disable	= _clk_max_disable,	\
> +		.parent		= p,			\
> +		.secondary	= s,			\
> +	}
> +
>  #define CLK_GET_RATE(name, nr, bitsname)				\
>  static unsigned long clk_##name##_get_rate(struct clk *clk)		\
>  {									\
> @@ -817,6 +859,33 @@ static int clk_##name##_set_parent(struct clk *clk, struct clk *parent)	\
>  	return 0;							\
>  }
>  
> +#define CLK_SET_RATE(name, nr, bitsname)				\
> +static int clk_##name##_set_rate(struct clk *clk, unsigned long rate)	\
> +{									\
> +	u32 reg, div, parent_rate;					\
> +	u32 pre = 0, post = 0;						\
> +									\
> +	parent_rate = clk_get_rate(clk->parent);			\
> +	div = parent_rate / rate;					\
> +									\
> +	if ((parent_rate / div) != rate)				\
> +		return -EINVAL;						\
> +									\
> +	__calc_pre_post_dividers(div, &pre, &post);			\
> +									\
> +	/* Set sdhc1 clock divider */					\
> +	reg = __raw_readl(MXC_CCM_CSCDR##nr) &				\
> +		~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK	\
> +		| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK);	\
> +	reg |= (post - 1) <<						\
> +		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET;	\
> +	reg |= (pre - 1) <<						\
> +		MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET;	\
> +	__raw_writel(reg, MXC_CCM_CSCDR##nr);				\
> +									\
> +	return 0;							\
> +}
> +
>  /* UART */
>  CLK_GET_RATE(uart, 1, UART)
>  CLK_SET_PARENT(uart, 1, UART)
> @@ -847,6 +916,15 @@ static struct clk ecspi_main_clk = {
>  	.set_parent = clk_ecspi_set_parent,
>  };
>  
> +/* eSDHC */
> +CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)
> +CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
> +CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
> +
> +CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
> +CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
> +CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
> +
>  #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
>  	static struct clk name = {					\
>  		.id		= i,					\
> @@ -900,7 +978,7 @@ DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,
>  	NULL,  NULL, &ipg_clk, NULL);
>  
>  /* NFC */
> -DEFINE_CLOCK1(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
> +DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,
>  	clk_nfc, &emi_slow_clk, NULL);
>  
>  /* SSI */
> @@ -935,6 +1013,16 @@ DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,
>  DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,
>  		NULL, NULL, &ahb_clk, NULL);
>  
> +/* eSDHC */
> +DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,
> +	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
> +DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,
> +	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
> +DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
> +	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
> +DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
> +	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
> +
>  #define _REGISTER_CLOCK(d, n, c) \
>         { \
>  		.dev_id = d, \
> @@ -968,6 +1056,8 @@ static struct clk_lookup lookups[] = {
>  	_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)
>  	_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)
>  	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
> +	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
> +	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
>  };
>  
>  static void clk_tree_init(void)
> @@ -1011,6 +1101,14 @@ int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,
>  	/* set the usboh3_clk parent to pll2_sw_clk */
>  	clk_set_parent(&usboh3_clk, &pll2_sw_clk);
>  
> +	/* Set SDHC parents to be PLL2 */
> +	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
> +	clk_set_parent(&esdhc2_clk, &pll2_sw_clk);
> +
> +	/* set SDHC root clock as 166.25MHZ*/
> +	clk_set_rate(&esdhc1_clk, 166250000);
> +	clk_set_rate(&esdhc2_clk, 166250000);
> +
>  	/* System timer */
>  	mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),
>  		MX51_MXC_INT_GPT);
> diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
> index c233379..547432d 100644
> --- a/arch/arm/mach-mx5/devices-imx51.h
> +++ b/arch/arm/mach-mx5/devices-imx51.h
> @@ -36,3 +36,12 @@ extern const struct imx_spi_imx_data imx51_cspi_data __initconst;
>  extern const struct imx_spi_imx_data imx51_ecspi_data[] __initconst;
>  #define imx51_add_ecspi(id, pdata)	\
>  	imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
> +
> +#define imx51_add_esdhc0(pdata)	\
> +	imx_add_esdhc(0, MX51_MMC_SDHC1_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC1, pdata)
> +#define imx51_add_esdhc1(pdata)	\
> +	imx_add_esdhc(1, MX51_MMC_SDHC2_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC2, pdata)
> +#define imx51_add_esdhc2(pdata)	\
> +	imx_add_esdhc(2, MX51_MMC_SDHC3_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC3, pdata)
> +#define imx51_add_esdhc3(pdata)	\
> +	imx_add_esdhc(3, MX51_MMC_SDHC4_BASE_ADDR, SZ_16K, MX51_MXC_INT_MMC_SDHC4, pdata)
I'd prefer to have these values in a struct.  This makes calling the
function much cheaper.  Look above, imx51_add_ecspi uses it.

> diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx51.h b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> index 5160f10..c5adb42 100644
> --- a/arch/arm/plat-mxc/include/mach/iomux-mx51.h
> +++ b/arch/arm/plat-mxc/include/mach/iomux-mx51.h
Changes to this file deserve to be in a seperate patch, too.

> @@ -47,6 +47,9 @@ typedef enum iomux_config {
>  				PAD_CTL_SRE_FAST)
>  #define MX51_ECSPI_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_DSE_HIGH | \
>  				PAD_CTL_SRE_FAST)
> +#define MX51_SDHCI_PAD_CTRL 	(PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP | \
> +				PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_SRE_FAST | \
> +				PAD_CTL_DVS)
>  
>  #define MX51_PAD_CTRL_1	(PAD_CTL_SRE_FAST | PAD_CTL_DSE_HIGH | \
>  					PAD_CTL_PUE | PAD_CTL_PKE | PAD_CTL_HYS)
> @@ -333,26 +336,39 @@ typedef enum iomux_config {
>  #define MX51_PAD_DISP2_DAT13__DISP2_DAT13       IOMUX_PAD(0x790, 0x388, 0, 0x0,   0, NO_PAD_CTRL)
>  #define MX51_PAD_DISP2_DAT14__DISP2_DAT14       IOMUX_PAD(0x794, 0x38C, 0, 0x0,   0, NO_PAD_CTRL)
>  #define MX51_PAD_DISP2_DAT15__DISP2_DAT15       IOMUX_PAD(0x798, 0x390, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_CMD__SD1_CMD               IOMUX_PAD(0x79C, 0x394, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_CMD__SD1_CMD		IOMUX_PAD(0x79C, 0x394, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_SD1_CMD__AUD5_RXFS             IOMUX_PAD(0x79C, 0x394, 1, 0x8e0, 1, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_CLK__SD1_CLK               IOMUX_PAD(0x7A0, 0x398, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_CLK__SD1_CLK		IOMUX_PAD(0x7A0, 0x398, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
>  #define MX51_PAD_SD1_CLK__AUD5_RXC              IOMUX_PAD(0x7A0, 0x398, 1, 0x8dc, 1, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA0__SD1_DATA0           IOMUX_PAD(0x7A4, 0x39C, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA0__SD1_DATA0		IOMUX_PAD(0x7A4, 0x39C, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_SD1_DATA0__AUD5_TXD            IOMUX_PAD(0x7A4, 0x39C, 1, 0x8d8, 2, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA1__SD1_DATA1           IOMUX_PAD(0x7A8, 0x3A0, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA1__SD1_DATA1		IOMUX_PAD(0x7A8, 0x3A0, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_SD1_DATA1__AUD5_RXD            IOMUX_PAD(0x7A8, 0x3A0, 1, 0x8d4, 2, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA2__SD1_DATA2           IOMUX_PAD(0x7AC, 0x3A4, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA2__SD1_DATA2		IOMUX_PAD(0x7AC, 0x3A4, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_SD1_DATA2__AUD5_TXC            IOMUX_PAD(0x7AC, 0x3A4, 1, 0x8e4, 2, NO_PAD_CTRL)
> -#define MX51_PAD_SD1_DATA3__SD1_DATA3           IOMUX_PAD(0x7B0, 0x3A8, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_SD1_DATA3__SD1_DATA3		IOMUX_PAD(0x7B0, 0x3A8, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_SD1_DATA3__AUD5_TXFS           IOMUX_PAD(0x7B0, 0x3A8, 1, 0x8e8, 2, NO_PAD_CTRL)
> +#define MX51_PAD_SD2_CMD__SD2_CMD		IOMUX_PAD(0x7BC, 0x3B4, IOMUX_CONFIG_SION, 0x0, 1, \
> +							MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_CLK__SD2_CLK		IOMUX_PAD(0x7C0, 0x3B8, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS)
> +#define MX51_PAD_SD2_DATA0__SD2_DATA0		IOMUX_PAD(0x7C4, 0x3BC, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA1__SD2_DATA1		IOMUX_PAD(0x7C8, 0x3C0, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA2__SD2_DATA2		IOMUX_PAD(0x7CC, 0x3C4, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
> +#define MX51_PAD_SD2_DATA3__SD2_DATA3		IOMUX_PAD(0x7D0, 0x3C8, IOMUX_CONFIG_SION, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_0__GPIO_1_0		IOMUX_PAD(0x7B4, 0x3AC, 1, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, 1, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_CMD__SD2_CMD               IOMUX_PAD(0x7BC, 0x3B4, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_CLK__SD2_CLK               IOMUX_PAD(0x7C0, 0x3B8, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA0__SD2_DATA0           IOMUX_PAD(0x7C4, 0x3BC, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA1__SD2_DATA1           IOMUX_PAD(0x7C8, 0x3C0, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA2__SD2_DATA2           IOMUX_PAD(0x7CC, 0x3C4, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_SD2_DATA3__SD2_DATA3           IOMUX_PAD(0x7D0, 0x3C8, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_GPIO_1_1__GPIO_1_1		IOMUX_PAD(0x7B8, 0x3B0, IOMUX_CONFIG_GPIO, 0x0, 0, \
> +							MX51_SDHCI_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_2__GPIO_1_2		IOMUX_PAD(0x7D4, 0x3CC, 0, 0x0,   0, NO_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_2__I2C2_SCL		IOMUX_PAD(0x7D4, 0x3CC, (2 | IOMUX_CONFIG_SION), \
>  							0x9b8,   3, MX51_I2C_PAD_CTRL)
> @@ -361,7 +377,8 @@ typedef enum iomux_config {
>  							0x9bc,   3, MX51_I2C_PAD_CTRL)
>  #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ	IOMUX_PAD(0x7FC, 0x3D4, 0, 0x0,   0, NO_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_4__GPIO_1_4		IOMUX_PAD(0x804, 0x3D8, 0, 0x0,   0, NO_PAD_CTRL)
> -#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, 0, 0x0,   0, NO_PAD_CTRL)
> +#define MX51_PAD_GPIO_1_5__GPIO_1_5		IOMUX_PAD(0x808, 0x3DC, IOMUX_CONFIG_GPIO, 0x0, 1, \
> +							NO_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_6__GPIO_1_6		IOMUX_PAD(0x80C, 0x3E0, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_7__GPIO_1_7		IOMUX_PAD(0x810, 0x3E4, 0, 0x0,   0, MX51_GPIO_PAD_CTRL)
>  #define MX51_PAD_GPIO_1_8__GPIO_1_8		IOMUX_PAD(0x814, 0x3E8, 0, 0x0,   1, MX51_GPIO_PAD_CTRL)
> -- 
> 1.7.0.4
> 
> 

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

* [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51
  2010-10-12  8:18         ` Uwe Kleine-König
@ 2010-10-12  8:50           ` Eric Bénard
  2010-10-12  9:32             ` Uwe Kleine-König
  0 siblings, 1 reply; 9+ messages in thread
From: Eric Bénard @ 2010-10-12  8:50 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Uwe,

Le 12/10/2010 10:18, Uwe Kleine-K?nig a ?crit :
> On Tue, Oct 12, 2010 at 09:31:25AM +0200, Eric B?nard wrote:
>> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
>> Tested on i.MX51.
>>
>> Based on original patch from: Richard Zhu<r65037@freescale.com>
>> Signed-off-by: Eric B?nard<eric@eukrea.com>
>> ---
>>   arch/arm/mach-mx5/clock-mx51.c              |  102 ++++++++++++++++++++++++++-
>>   arch/arm/mach-mx5/devices-imx51.h           |    9 +++
>>   arch/arm/plat-mxc/include/mach/iomux-mx51.h |   45 ++++++++----
>>   3 files changed, 140 insertions(+), 16 deletions(-)
>>
>> diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
>> index 7deb683..9e8b268 100644
>> --- a/arch/arm/mach-mx5/clock-mx51.c
>> +++ b/arch/arm/mach-mx5/clock-mx51.c
>> @@ -41,6 +41,34 @@ static struct clk usboh3_clk;
>>
>>   #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
>>
>> +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
>> +{
> I asked for a comment here.  E.g. valid ranges of pre and post and the
> task solved here (I assume it's "Find pre and post with pre * post =
> div"?).
>
will try to write something.
Richard : do you have a comment in mind for this function ?

 >> +		}
 >> +		*post = (div + *pre - 1) / *pre;
 > 		*post = DIV_ROUND_UP(div, *pre);
 >
 > I don't know if DIV_ROUND_UP is sensible, maybe use DIV_ROUND_CLOSEST?
 > I'd look into that when the comment above is in place.
 >
if you have an opinion before, this would be great to avoid a n+1 
version of this patch ;-)

>> -#define DEFINE_CLOCK1(name, i, er, es, pfx, p, s)	\
>> +#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
> This is IMHO a good idea, but it should go in a seperate patch.  These
> clock changes are very sensible and so a working bisection is important
> here.
>
there is no clock change here only a define rename to avoid having 
DEFINE_CLOCK1, DEFINE_CLOCK2 ... is a separate patch really needed ?

Eric

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

* [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51
  2010-10-12  8:50           ` Eric Bénard
@ 2010-10-12  9:32             ` Uwe Kleine-König
  0 siblings, 0 replies; 9+ messages in thread
From: Uwe Kleine-König @ 2010-10-12  9:32 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

On Tue, Oct 12, 2010 at 10:50:52AM +0200, Eric B?nard wrote:
> Le 12/10/2010 10:18, Uwe Kleine-K?nig a ?crit :
>> On Tue, Oct 12, 2010 at 09:31:25AM +0200, Eric B?nard wrote:
>>> the attached patch allows SD to work on i.MX51 with Wolfram's drivers
>>> Tested on i.MX51.
>>>
>>> Based on original patch from: Richard Zhu<r65037@freescale.com>
>>> Signed-off-by: Eric B?nard<eric@eukrea.com>
>>> ---
>>>   arch/arm/mach-mx5/clock-mx51.c              |  102 ++++++++++++++++++++++++++-
>>>   arch/arm/mach-mx5/devices-imx51.h           |    9 +++
>>>   arch/arm/plat-mxc/include/mach/iomux-mx51.h |   45 ++++++++----
>>>   3 files changed, 140 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/arch/arm/mach-mx5/clock-mx51.c b/arch/arm/mach-mx5/clock-mx51.c
>>> index 7deb683..9e8b268 100644
>>> --- a/arch/arm/mach-mx5/clock-mx51.c
>>> +++ b/arch/arm/mach-mx5/clock-mx51.c
>>> @@ -41,6 +41,34 @@ static struct clk usboh3_clk;
>>>
>>>   #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
>>>
>>> +static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post)
>>> +{
>> I asked for a comment here.  E.g. valid ranges of pre and post and the
>> task solved here (I assume it's "Find pre and post with pre * post =
>> div"?).
>>
> will try to write something.
> Richard : do you have a comment in mind for this function ?
>
> >> +		}
> >> +		*post = (div + *pre - 1) / *pre;
> > 		*post = DIV_ROUND_UP(div, *pre);
> >
> > I don't know if DIV_ROUND_UP is sensible, maybe use DIV_ROUND_CLOSEST?
> > I'd look into that when the comment above is in place.
> >
> if you have an opinion before, this would be great to avoid a n+1  
> version of this patch ;-)
I'm lazy.  To analyse this I need to know how pre and post are used.  I
assume you (and/or Richard) already know that so I'm not keen to search
this info in the reference manuals.  See it as a quality test for the
comment I asked for :-)

>>> -#define DEFINE_CLOCK1(name, i, er, es, pfx, p, s)	\
>>> +#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s)	\
>> This is IMHO a good idea, but it should go in a seperate patch.  These
>> clock changes are very sensible and so a working bisection is important
>> here.
>>
> there is no clock change here only a define rename to avoid having  
> DEFINE_CLOCK1, DEFINE_CLOCK2 ... is a separate patch really needed ?
Yep, please do.  I don't hope your patch breaks anything, but if it
does, it's easier to find out the actual breakage if there is no noise
in the patch.

Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

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

end of thread, other threads:[~2010-10-12  9:32 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-11 16:05 [PATCH] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
2010-10-11 16:28 ` Wolfram Sang
2010-10-11 16:55   ` Eric Bénard
2010-10-11 17:04     ` Wolfram Sang
2010-10-12  7:31       ` [PATCH 1/2] clock-mx51: factorize clk_set_parent and clk_get_rate Eric Bénard
2010-10-12  7:31       ` [PATCH 2/2] mx51: add resources for SD/MMC on i.MX51 Eric Bénard
2010-10-12  8:18         ` Uwe Kleine-König
2010-10-12  8:50           ` Eric Bénard
2010-10-12  9:32             ` Uwe Kleine-König

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