[U-Boot] [PATCH 1/6] mxs: dma: Fix APBH DMA driver for MX23

The MX23 has less channels for the APBH DMA, sligtly different register layout and some bits in those registers are placed differently. Reflect this in the driver. This patch fixes MMC/DMA issue on MX23.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/include/asm/arch-mxs/regs-apbh.h | 121 +++++++++++++++++++++++++++++ drivers/dma/apbh_dma.c | 10 ++- 2 files changed, 129 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/regs-apbh.h b/arch/arm/include/asm/arch-mxs/regs-apbh.h index e18e677..fcef4b8 100644 --- a/arch/arm/include/asm/arch-mxs/regs-apbh.h +++ b/arch/arm/include/asm/arch-mxs/regs-apbh.h @@ -29,6 +29,87 @@ #include <asm/arch/regs-common.h>
#ifndef __ASSEMBLY__ + +#if defined(CONFIG_MX23) +struct mxs_apbh_regs { + mxs_reg_32(hw_apbh_ctrl0) + mxs_reg_32(hw_apbh_ctrl1) + mxs_reg_32(hw_apbh_ctrl2) + mxs_reg_32(hw_apbh_channel_ctrl) + + union { + struct { + mxs_reg_32(hw_apbh_ch_curcmdar) + mxs_reg_32(hw_apbh_ch_nxtcmdar) + mxs_reg_32(hw_apbh_ch_cmd) + mxs_reg_32(hw_apbh_ch_bar) + mxs_reg_32(hw_apbh_ch_sema) + mxs_reg_32(hw_apbh_ch_debug1) + mxs_reg_32(hw_apbh_ch_debug2) + } ch[8]; + struct { + mxs_reg_32(hw_apbh_ch0_curcmdar) + mxs_reg_32(hw_apbh_ch0_nxtcmdar) + mxs_reg_32(hw_apbh_ch0_cmd) + mxs_reg_32(hw_apbh_ch0_bar) + mxs_reg_32(hw_apbh_ch0_sema) + mxs_reg_32(hw_apbh_ch0_debug1) + mxs_reg_32(hw_apbh_ch0_debug2) + mxs_reg_32(hw_apbh_ch1_curcmdar) + mxs_reg_32(hw_apbh_ch1_nxtcmdar) + mxs_reg_32(hw_apbh_ch1_cmd) + mxs_reg_32(hw_apbh_ch1_bar) + mxs_reg_32(hw_apbh_ch1_sema) + mxs_reg_32(hw_apbh_ch1_debug1) + mxs_reg_32(hw_apbh_ch1_debug2) + mxs_reg_32(hw_apbh_ch2_curcmdar) + mxs_reg_32(hw_apbh_ch2_nxtcmdar) + mxs_reg_32(hw_apbh_ch2_cmd) + mxs_reg_32(hw_apbh_ch2_bar) + mxs_reg_32(hw_apbh_ch2_sema) + mxs_reg_32(hw_apbh_ch2_debug1) + mxs_reg_32(hw_apbh_ch2_debug2) + mxs_reg_32(hw_apbh_ch3_curcmdar) + mxs_reg_32(hw_apbh_ch3_nxtcmdar) + mxs_reg_32(hw_apbh_ch3_cmd) + mxs_reg_32(hw_apbh_ch3_bar) + mxs_reg_32(hw_apbh_ch3_sema) + mxs_reg_32(hw_apbh_ch3_debug1) + mxs_reg_32(hw_apbh_ch3_debug2) + mxs_reg_32(hw_apbh_ch4_curcmdar) + mxs_reg_32(hw_apbh_ch4_nxtcmdar) + mxs_reg_32(hw_apbh_ch4_cmd) + mxs_reg_32(hw_apbh_ch4_bar) + mxs_reg_32(hw_apbh_ch4_sema) + mxs_reg_32(hw_apbh_ch4_debug1) + mxs_reg_32(hw_apbh_ch4_debug2) + mxs_reg_32(hw_apbh_ch5_curcmdar) + mxs_reg_32(hw_apbh_ch5_nxtcmdar) + mxs_reg_32(hw_apbh_ch5_cmd) + mxs_reg_32(hw_apbh_ch5_bar) + mxs_reg_32(hw_apbh_ch5_sema) + mxs_reg_32(hw_apbh_ch5_debug1) + mxs_reg_32(hw_apbh_ch5_debug2) + mxs_reg_32(hw_apbh_ch6_curcmdar) + mxs_reg_32(hw_apbh_ch6_nxtcmdar) + mxs_reg_32(hw_apbh_ch6_cmd) + mxs_reg_32(hw_apbh_ch6_bar) + mxs_reg_32(hw_apbh_ch6_sema) + mxs_reg_32(hw_apbh_ch6_debug1) + mxs_reg_32(hw_apbh_ch6_debug2) + mxs_reg_32(hw_apbh_ch7_curcmdar) + mxs_reg_32(hw_apbh_ch7_nxtcmdar) + mxs_reg_32(hw_apbh_ch7_cmd) + mxs_reg_32(hw_apbh_ch7_bar) + mxs_reg_32(hw_apbh_ch7_sema) + mxs_reg_32(hw_apbh_ch7_debug1) + mxs_reg_32(hw_apbh_ch7_debug2) + }; + }; + mxs_reg_32(hw_apbh_version) +}; + +#elif defined(CONFIG_MX28) struct mxs_apbh_regs { mxs_reg_32(hw_apbh_ctrl0) mxs_reg_32(hw_apbh_ctrl1) @@ -169,10 +250,26 @@ struct mxs_apbh_regs { }; #endif
+#endif + #define APBH_CTRL0_SFTRST (1 << 31) #define APBH_CTRL0_CLKGATE (1 << 30) #define APBH_CTRL0_AHB_BURST8_EN (1 << 29) #define APBH_CTRL0_APB_BURST_EN (1 << 28) +#if defined(CONFIG_MX23) +#define APBH_CTRL0_RSVD0_MASK (0xf << 24) +#define APBH_CTRL0_RSVD0_OFFSET 24 +#define APBH_CTRL0_RESET_CHANNEL_MASK (0xff << 16) +#define APBH_CTRL0_RESET_CHANNEL_OFFSET 16 +#define APBH_CTRL0_CLKGATE_CHANNEL_MASK (0xff << 8) +#define APBH_CTRL0_CLKGATE_CHANNEL_OFFSET 8 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP0 0x02 +#define APBH_CTRL0_CLKGATE_CHANNEL_SSP1 0x04 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND0 0x10 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND1 0x20 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND2 0x40 +#define APBH_CTRL0_CLKGATE_CHANNEL_NAND3 0x80 +#elif defined(CONFIG_MX28) #define APBH_CTRL0_RSVD0_MASK (0xfff << 16) #define APBH_CTRL0_RSVD0_OFFSET 16 #define APBH_CTRL0_CLKGATE_CHANNEL_MASK 0xffff @@ -191,6 +288,7 @@ struct mxs_apbh_regs { #define APBH_CTRL0_CLKGATE_CHANNEL_NAND7 0x0800 #define APBH_CTRL0_CLKGATE_CHANNEL_HSADC 0x1000 #define APBH_CTRL0_CLKGATE_CHANNEL_LCDIF 0x2000 +#endif
#define APBH_CTRL1_CH15_CMDCMPLT_IRQ_EN (1 << 31) #define APBH_CTRL1_CH14_CMDCMPLT_IRQ_EN (1 << 30) @@ -260,6 +358,7 @@ struct mxs_apbh_regs { #define APBH_CTRL2_CH1_ERROR_IRQ (1 << 1) #define APBH_CTRL2_CH0_ERROR_IRQ (1 << 0)
+#if defined(CONFIG_MX28) #define APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK (0xffff << 16) #define APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET 16 #define APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0 (0x0001 << 16) @@ -292,7 +391,26 @@ struct mxs_apbh_regs { #define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_NAND7 0x0800 #define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_HSADC 0x1000 #define APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF 0x2000 +#endif
+#if defined(CONFIG_MX23) +#define APBH_DEVSEL_CH7_MASK (0xf << 28) +#define APBH_DEVSEL_CH7_OFFSET 28 +#define APBH_DEVSEL_CH6_MASK (0xf << 24) +#define APBH_DEVSEL_CH6_OFFSET 24 +#define APBH_DEVSEL_CH5_MASK (0xf << 20) +#define APBH_DEVSEL_CH5_OFFSET 20 +#define APBH_DEVSEL_CH4_MASK (0xf << 16) +#define APBH_DEVSEL_CH4_OFFSET 16 +#define APBH_DEVSEL_CH3_MASK (0xf << 12) +#define APBH_DEVSEL_CH3_OFFSET 12 +#define APBH_DEVSEL_CH2_MASK (0xf << 8) +#define APBH_DEVSEL_CH2_OFFSET 8 +#define APBH_DEVSEL_CH1_MASK (0xf << 4) +#define APBH_DEVSEL_CH1_OFFSET 4 +#define APBH_DEVSEL_CH0_MASK (0xf << 0) +#define APBH_DEVSEL_CH0_OFFSET 0 +#elif defined(CONFIG_MX28) #define APBH_DEVSEL_CH15_MASK (0x3 << 30) #define APBH_DEVSEL_CH15_OFFSET 30 #define APBH_DEVSEL_CH14_MASK (0x3 << 28) @@ -325,7 +443,9 @@ struct mxs_apbh_regs { #define APBH_DEVSEL_CH1_OFFSET 2 #define APBH_DEVSEL_CH0_MASK (0x3 << 0) #define APBH_DEVSEL_CH0_OFFSET 0 +#endif
+#if defined(CONFIG_MX28) #define APBH_DMA_BURST_SIZE_CH15_MASK (0x3 << 30) #define APBH_DMA_BURST_SIZE_CH15_OFFSET 30 #define APBH_DMA_BURST_SIZE_CH14_MASK (0x3 << 28) @@ -377,6 +497,7 @@ struct mxs_apbh_regs { #define APBH_DMA_BURST_SIZE_CH0_BURST8 0x2
#define APBH_DEBUG_GPMI_ONE_FIFO (1 << 0) +#endif
#define APBH_CHn_CURCMDAR_CMD_ADDR_MASK 0xffffffff #define APBH_CHn_CURCMDAR_CMD_ADDR_OFFSET 0 diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c index 37a941c..0c1cd83 100644 --- a/drivers/dma/apbh_dma.c +++ b/drivers/dma/apbh_dma.c @@ -223,13 +223,19 @@ static int mxs_dma_reset(int channel) struct mxs_apbh_regs *apbh_regs = (struct mxs_apbh_regs *)MXS_APBH_BASE; int ret; +#if defined(CONFIG_MX23) + uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set); + uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET; +#elif defined(CONFIG_MX28) + uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set); + uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET; +#endif
ret = mxs_dma_validate_chan(channel); if (ret) return ret;
- writel(1 << (channel + APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET), - &apbh_regs->hw_apbh_channel_ctrl_set); + writel(1 << (channel + offset), setreg);
return 0; }

The MX23 SSP register layout differs from MX28 in certain bits, adjust the register layout accordingly.
Signed-off-by: Marek Vasut marex@denx.de Signed-off-by: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/include/asm/arch-mxs/regs-ssp.h | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/arch/arm/include/asm/arch-mxs/regs-ssp.h b/arch/arm/include/asm/arch-mxs/regs-ssp.h index b97ac35..9b30f56 100644 --- a/arch/arm/include/asm/arch-mxs/regs-ssp.h +++ b/arch/arm/include/asm/arch-mxs/regs-ssp.h @@ -28,6 +28,28 @@ #include <asm/arch/regs-common.h>
#ifndef __ASSEMBLY__ +#if defined(CONFIG_MX23) +struct mxs_ssp_regs { + mxs_reg_32(hw_ssp_ctrl0) + mxs_reg_32(hw_ssp_cmd0) + mxs_reg_32(hw_ssp_cmd1) + mxs_reg_32(hw_ssp_compref) + mxs_reg_32(hw_ssp_compmask) + mxs_reg_32(hw_ssp_timing) + mxs_reg_32(hw_ssp_ctrl1) + mxs_reg_32(hw_ssp_data) + mxs_reg_32(hw_ssp_sdresp0) + mxs_reg_32(hw_ssp_sdresp1) + mxs_reg_32(hw_ssp_sdresp2) + mxs_reg_32(hw_ssp_sdresp3) + mxs_reg_32(hw_ssp_status) + + uint32_t reserved1[12]; + + mxs_reg_32(hw_ssp_debug) + mxs_reg_32(hw_ssp_version) +}; +#elif defined(CONFIG_MX28) struct mxs_ssp_regs { mxs_reg_32(hw_ssp_ctrl0) mxs_reg_32(hw_ssp_cmd0) @@ -50,6 +72,7 @@ struct mxs_ssp_regs { mxs_reg_32(hw_ssp_debug) mxs_reg_32(hw_ssp_version) }; +#endif
static inline struct mxs_ssp_regs *mxs_ssp_regs_by_bus(unsigned int port) { @@ -90,6 +113,11 @@ static inline struct mxs_ssp_regs *mxs_ssp_regs_by_bus(unsigned int port) #define SSP_CTRL0_GET_RESP (1 << 17) #define SSP_CTRL0_ENABLE (1 << 16)
+#ifdef CONFIG_MX23 +#define SSP_CTRL0_XFER_COUNT_OFFSET 0 +#define SSP_CTRL0_XFER_COUNT_MASK 0xffff +#endif + #define SSP_CMD0_SOFT_TERMINATE (1 << 26) #define SSP_CMD0_DBL_DATA_RATE_EN (1 << 25) #define SSP_CMD0_PRIM_BOOT_OP_EN (1 << 24) @@ -97,6 +125,12 @@ static inline struct mxs_ssp_regs *mxs_ssp_regs_by_bus(unsigned int port) #define SSP_CMD0_SLOW_CLKING_EN (1 << 22) #define SSP_CMD0_CONT_CLKING_EN (1 << 21) #define SSP_CMD0_APPEND_8CYC (1 << 20) +#if defined(CONFIG_MX23) +#define SSP_CMD0_BLOCK_SIZE_MASK (0xf << 16) +#define SSP_CMD0_BLOCK_SIZE_OFFSET 16 +#define SSP_CMD0_BLOCK_COUNT_MASK (0xff << 8) +#define SSP_CMD0_BLOCK_COUNT_OFFSET 8 +#endif #define SSP_CMD0_CMD_MASK 0xff #define SSP_CMD0_CMD_OFFSET 0 #define SSP_CMD0_CMD_MMC_GO_IDLE_STATE 0x00 @@ -170,6 +204,7 @@ static inline struct mxs_ssp_regs *mxs_ssp_regs_by_bus(unsigned int port) #define SSP_CMD1_CMD_ARG_MASK 0xffffffff #define SSP_CMD1_CMD_ARG_OFFSET 0
+#if defined(CONFIG_MX28) #define SSP_XFER_SIZE_XFER_COUNT_MASK 0xffffffff #define SSP_XFER_SIZE_XFER_COUNT_OFFSET 0
@@ -177,6 +212,7 @@ static inline struct mxs_ssp_regs *mxs_ssp_regs_by_bus(unsigned int port) #define SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET 4 #define SSP_BLOCK_SIZE_BLOCK_SIZE_MASK 0xf #define SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET 0 +#endif
#define SSP_COMPREF_REFERENCE_MASK 0xffffffff #define SSP_COMPREF_REFERENCE_OFFSET 0

From: Otavio Salvador otavio@ossystems.com.br
This does the same reset mask as done in v3.7 Linux kernel code. The block is properly configured for MMC operation that way.
Signed-off-by: Otavio Salvador otavio@ossystems.com.br Cc: Marek Vasut marex@denx.de Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- drivers/mmc/mxsmmc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 0c4cd54..9d71202 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -334,11 +334,17 @@ static int mxsmmc_init(struct mmc *mmc) /* Reset SSP */ mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
- /* 8 bits word length in MMC mode */ - clrsetbits_le32(&ssp_regs->hw_ssp_ctrl1, - SSP_CTRL1_SSP_MODE_MASK | SSP_CTRL1_WORD_LENGTH_MASK | - SSP_CTRL1_DMA_ENABLE, - SSP_CTRL1_SSP_MODE_SD_MMC | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS); + /* Reconfigure the SSP block for MMC operation */ + writel(SSP_CTRL1_SSP_MODE_SD_MMC | + SSP_CTRL1_WORD_LENGTH_EIGHT_BITS | + SSP_CTRL1_DMA_ENABLE | + SSP_CTRL1_POLARITY | + SSP_CTRL1_RECV_TIMEOUT_IRQ_EN | + SSP_CTRL1_DATA_CRC_IRQ_EN | + SSP_CTRL1_DATA_TIMEOUT_IRQ_EN | + SSP_CTRL1_RESP_TIMEOUT_IRQ_EN | + SSP_CTRL1_RESP_ERR_IRQ_EN, + &ssp_regs->hw_ssp_ctrl1_set);
/* Set initial bit clock 400 KHz */ mxs_set_ssp_busclock(priv->id, 400);

Some MXS based boards do not implement the card-detect signal. Allow user to specify alternate card-detect implementation.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- arch/arm/include/asm/arch-mxs/sys_proto.h | 2 +- board/bluegiga/apx4devkit/apx4devkit.c | 2 +- board/denx/m28evk/m28evk.c | 2 +- board/freescale/mx28evk/mx28evk.c | 2 +- board/schulercontrol/sc_sps_1/sc_sps_1.c | 2 +- drivers/mmc/mxsmmc.c | 16 ++++++++++++++-- 6 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h index 8aaf196..5bafde5 100644 --- a/arch/arm/include/asm/arch-mxs/sys_proto.h +++ b/arch/arm/include/asm/arch-mxs/sys_proto.h @@ -31,7 +31,7 @@ int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned int timeout);
-int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)); +int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int));
#ifdef CONFIG_SPL_BUILD
diff --git a/board/bluegiga/apx4devkit/apx4devkit.c b/board/bluegiga/apx4devkit/apx4devkit.c index 029b973..5927693 100644 --- a/board/bluegiga/apx4devkit/apx4devkit.c +++ b/board/bluegiga/apx4devkit/apx4devkit.c @@ -69,7 +69,7 @@ int board_init(void) #ifdef CONFIG_CMD_MMC int board_mmc_init(bd_t *bis) { - return mxsmmc_initialize(bis, 0, NULL); + return mxsmmc_initialize(bis, 0, NULL, NULL); } #endif
diff --git a/board/denx/m28evk/m28evk.c b/board/denx/m28evk/m28evk.c index 26f31d6..d93efaf 100644 --- a/board/denx/m28evk/m28evk.c +++ b/board/denx/m28evk/m28evk.c @@ -93,7 +93,7 @@ int board_mmc_init(bd_t *bis) /* Turn on the power to the card. */ gpio_direction_output(MX28_PAD_PWM3__GPIO_3_28, 0);
- return mxsmmc_initialize(bis, 0, m28_mmc_wp); + return mxsmmc_initialize(bis, 0, m28_mmc_wp, NULL); } #endif
diff --git a/board/freescale/mx28evk/mx28evk.c b/board/freescale/mx28evk/mx28evk.c index ad66f29..de7231b 100644 --- a/board/freescale/mx28evk/mx28evk.c +++ b/board/freescale/mx28evk/mx28evk.c @@ -94,7 +94,7 @@ int board_mmc_init(bd_t *bis) /* Configure MMC0 Power Enable */ gpio_direction_output(MX28_PAD_PWM3__GPIO_3_28, 0);
- return mxsmmc_initialize(bis, 0, mx28evk_mmc_wp); + return mxsmmc_initialize(bis, 0, mx28evk_mmc_wp, NULL); } #endif
diff --git a/board/schulercontrol/sc_sps_1/sc_sps_1.c b/board/schulercontrol/sc_sps_1/sc_sps_1.c index fac7e30..8138237 100644 --- a/board/schulercontrol/sc_sps_1/sc_sps_1.c +++ b/board/schulercontrol/sc_sps_1/sc_sps_1.c @@ -78,7 +78,7 @@ int dram_init(void) #ifdef CONFIG_CMD_MMC int board_mmc_init(bd_t *bis) { - return mxsmmc_initialize(bis, 0, NULL); + return mxsmmc_initialize(bis, 0, NULL, NULL); } #endif
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 9d71202..023dbd5 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -49,12 +49,23 @@ struct mxsmmc_priv { struct mxs_ssp_regs *regs; uint32_t buswidth; int (*mmc_is_wp)(int); + int (*mmc_cd)(int); struct mxs_dma_desc *desc; };
#define MXSMMC_MAX_TIMEOUT 10000 #define MXSMMC_SMALL_TRANSFER 512
+static int mxsmmc_cd(struct mxsmmc_priv *priv) +{ + struct mxs_ssp_regs *ssp_regs = priv->regs; + + if (priv->mmc_cd) + return priv->mmc_cd(priv->id); + + return !(readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT); +} + static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data) { struct mxs_ssp_regs *ssp_regs = priv->regs; @@ -166,7 +177,7 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) }
/* See if card is present */ - if (readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT) { + if (!mxsmmc_cd(priv)) { printf("MMC%d: No card detected!\n", mmc->block_dev.dev); return NO_CARD_ERR; } @@ -357,7 +368,7 @@ static int mxsmmc_init(struct mmc *mmc) return 0; }
-int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)) +int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) { struct mmc *mmc = NULL; struct mxsmmc_priv *priv = NULL; @@ -395,6 +406,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)) return ret;
priv->mmc_is_wp = wp; + priv->mmc_cd = cd; priv->id = id; priv->regs = mxs_ssp_regs_by_bus(id);

On 23/01/2013 02:01, Marek Vasut wrote:
Some MXS based boards do not implement the card-detect signal. Allow user to specify alternate card-detect implementation.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
arch/arm/include/asm/arch-mxs/sys_proto.h | 2 +- board/bluegiga/apx4devkit/apx4devkit.c | 2 +- board/denx/m28evk/m28evk.c | 2 +- board/freescale/mx28evk/mx28evk.c | 2 +- board/schulercontrol/sc_sps_1/sc_sps_1.c | 2 +- drivers/mmc/mxsmmc.c | 16 ++++++++++++++-- 6 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h index 8aaf196..5bafde5 100644 --- a/arch/arm/include/asm/arch-mxs/sys_proto.h +++ b/arch/arm/include/asm/arch-mxs/sys_proto.h @@ -31,7 +31,7 @@ int mxs_wait_mask_clr(struct mxs_register_32 *reg, uint32_t mask, unsigned int timeout);
-int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)); +int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int));
#ifdef CONFIG_SPL_BUILD
diff --git a/board/bluegiga/apx4devkit/apx4devkit.c b/board/bluegiga/apx4devkit/apx4devkit.c index 029b973..5927693 100644 --- a/board/bluegiga/apx4devkit/apx4devkit.c +++ b/board/bluegiga/apx4devkit/apx4devkit.c @@ -69,7 +69,7 @@ int board_init(void) #ifdef CONFIG_CMD_MMC int board_mmc_init(bd_t *bis) {
- return mxsmmc_initialize(bis, 0, NULL);
- return mxsmmc_initialize(bis, 0, NULL, NULL);
I see, but it seems to me that mxs is doing different as other SOCs. If there is nothing to set, cpu_mmc_init() should be used, dropping board_mmc_init(). And we implement board_mmc_init() only for boards that really need it, not for all.
Best regards, Stefano Babic

Dear Stefano Babic,
On 23/01/2013 02:01, Marek Vasut wrote:
Some MXS based boards do not implement the card-detect signal. Allow user to specify alternate card-detect implementation.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
arch/arm/include/asm/arch-mxs/sys_proto.h | 2 +- board/bluegiga/apx4devkit/apx4devkit.c | 2 +- board/denx/m28evk/m28evk.c | 2 +- board/freescale/mx28evk/mx28evk.c | 2 +- board/schulercontrol/sc_sps_1/sc_sps_1.c | 2 +- drivers/mmc/mxsmmc.c | 16 ++++++++++++++-- 6 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/sys_proto.h b/arch/arm/include/asm/arch-mxs/sys_proto.h index 8aaf196..5bafde5 100644 --- a/arch/arm/include/asm/arch-mxs/sys_proto.h +++ b/arch/arm/include/asm/arch-mxs/sys_proto.h @@ -31,7 +31,7 @@ int mxs_wait_mask_clr(struct mxs_register_32 *reg,
uint32_t mask, unsigned int timeout);
-int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int)); +int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int));
#ifdef CONFIG_SPL_BUILD
diff --git a/board/bluegiga/apx4devkit/apx4devkit.c b/board/bluegiga/apx4devkit/apx4devkit.c index 029b973..5927693 100644 --- a/board/bluegiga/apx4devkit/apx4devkit.c +++ b/board/bluegiga/apx4devkit/apx4devkit.c @@ -69,7 +69,7 @@ int board_init(void)
#ifdef CONFIG_CMD_MMC int board_mmc_init(bd_t *bis) {
- return mxsmmc_initialize(bis, 0, NULL);
- return mxsmmc_initialize(bis, 0, NULL, NULL);
I see, but it seems to me that mxs is doing different as other SOCs. If there is nothing to set, cpu_mmc_init() should be used, dropping board_mmc_init(). And we implement board_mmc_init() only for boards that really need it, not for all.
That's also an option ... do you want subsequent patch or respin of the series?
Best regards, Marek Vasut

On 24/01/2013 19:29, Marek Vasut wrote:
That's also an option ... do you want subsequent patch or respin of the series?
If I can choose, I prefer a respin of series, but I will surely not block the patchset if you send subsequent patches...
Best regards, Stefano Babic

Dear Stefano Babic,
On 24/01/2013 19:29, Marek Vasut wrote:
That's also an option ... do you want subsequent patch or respin of the series?
If I can choose, I prefer a respin of series, but I will surely not block the patchset if you send subsequent patches...
No, scrap this. See my other email please.
Best regards, Marek Vasut

Dear Stefano Babic, [...]
diff --git a/board/bluegiga/apx4devkit/apx4devkit.c b/board/bluegiga/apx4devkit/apx4devkit.c index 029b973..5927693 100644 --- a/board/bluegiga/apx4devkit/apx4devkit.c +++ b/board/bluegiga/apx4devkit/apx4devkit.c @@ -69,7 +69,7 @@ int board_init(void)
#ifdef CONFIG_CMD_MMC int board_mmc_init(bd_t *bis) {
- return mxsmmc_initialize(bis, 0, NULL);
- return mxsmmc_initialize(bis, 0, NULL, NULL);
I see, but it seems to me that mxs is doing different as other SOCs. If there is nothing to set, cpu_mmc_init() should be used, dropping board_mmc_init(). And we implement board_mmc_init() only for boards that really need it, not for all.
That's also an option ... do you want subsequent patch or respin of the series?
Actually, check how it's distributed:
$ git grep mxsmmc_initialize board | sed "s@.*/@@" apx4devkit.c: return mxsmmc_initialize(bis, 0, NULL, NULL); m28evk.c: return mxsmmc_initialize(bis, 0, m28_mmc_wp, NULL); mx28evk.c: return mxsmmc_initialize(bis, 0, mx28evk_mmc_wp, NULL); mx23_olinuxino.c: return mxsmmc_initialize(bis, 0, NULL, mx23_olx_mmc_cd); sc_sps_1.c: return mxsmmc_initialize(bis, 0, NULL, NULL);
We have quite a bit of variance there. I wonder if using cpu_mmc_init() is worth it.
Best regards, Marek Vasut

On 24/01/2013 19:34, Marek Vasut wrote:
That's also an option ... do you want subsequent patch or respin of the series?
Actually, check how it's distributed:
$ git grep mxsmmc_initialize board | sed "s@.*/@@" apx4devkit.c: return mxsmmc_initialize(bis, 0, NULL, NULL); m28evk.c: return mxsmmc_initialize(bis, 0, m28_mmc_wp, NULL); mx28evk.c: return mxsmmc_initialize(bis, 0, mx28evk_mmc_wp, NULL); mx23_olinuxino.c: return mxsmmc_initialize(bis, 0, NULL, mx23_olx_mmc_cd); sc_sps_1.c: return mxsmmc_initialize(bis, 0, NULL, NULL);
We have quite a bit of variance there. I wonder if using cpu_mmc_init() is worth it.
I see. Ok, then let's the things as they are.
Regards, Stefano Babic

The MX23 has different layout of DMA channels. Fix the MMC driver to support MX23.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- drivers/mmc/mxsmmc.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index 023dbd5..a72f66c 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -53,6 +53,12 @@ struct mxsmmc_priv { struct mxs_dma_desc *desc; };
+#if defined(CONFIG_MX23) +static const unsigned int mxsmmc_id_offset = 1; +#elif defined(CONFIG_MX28) +static const unsigned int mxsmmc_id_offset = 0; +#endif + #define MXSMMC_MAX_TIMEOUT 10000 #define MXSMMC_SMALL_TRANSFER 512
@@ -131,7 +137,7 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM | (data_count << MXS_DMA_DESC_BYTES_OFFSET);
- dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id; + dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id + mxsmmc_id_offset; mxs_dma_desc_append(dmach, priv->desc); if (mxs_dma_go(dmach)) { bounce_buffer_stop(&bbstate); @@ -222,14 +228,25 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) }
ctrl0 |= SSP_CTRL0_DATA_XFER; + + reg = data->blocksize * data->blocks; +#if defined(CONFIG_MX23) + ctrl0 |= reg & SSP_CTRL0_XFER_COUNT_MASK; + + clrsetbits_le32(&ssp_regs->hw_ssp_cmd0, + SSP_CMD0_BLOCK_SIZE_MASK | SSP_CMD0_BLOCK_COUNT_MASK, + ((data->blocks - 1) << SSP_CMD0_BLOCK_COUNT_OFFSET) | + ((ffs(data->blocksize) - 1) << + SSP_CMD0_BLOCK_SIZE_OFFSET)); +#elif defined(CONFIG_MX28) + writel(reg, &ssp_regs->hw_ssp_xfer_size); + reg = ((data->blocks - 1) << SSP_BLOCK_SIZE_BLOCK_COUNT_OFFSET) | ((ffs(data->blocksize) - 1) << SSP_BLOCK_SIZE_BLOCK_SIZE_OFFSET); writel(reg, &ssp_regs->hw_ssp_block_size); - - reg = data->blocksize * data->blocks; - writel(reg, &ssp_regs->hw_ssp_xfer_size); +#endif }
/* Kick off the command */ @@ -401,7 +418,7 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int)) return -ENOMEM; }
- ret = mxs_dma_init_channel(id); + ret = mxs_dma_init_channel(id + mxsmmc_id_offset); if (ret) return ret;

Add support for the MMC attached to SSP1.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de --- board/olimex/mx23_olinuxino/mx23_olinuxino.c | 22 +++++++++++++++++++++- board/olimex/mx23_olinuxino/spl_boot.c | 9 +++++++++ include/configs/mx23_olinuxino.h | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/board/olimex/mx23_olinuxino/mx23_olinuxino.c b/board/olimex/mx23_olinuxino/mx23_olinuxino.c index 2fcad26..6a6053b 100644 --- a/board/olimex/mx23_olinuxino/mx23_olinuxino.c +++ b/board/olimex/mx23_olinuxino/mx23_olinuxino.c @@ -23,7 +23,10 @@ */
#include <common.h> +#include <asm/io.h> +#include <asm/arch/iomux-mx23.h> #include <asm/arch/imx-regs.h> +#include <asm/arch/clock.h> #include <asm/arch/sys_proto.h>
DECLARE_GLOBAL_DATA_PTR; @@ -33,7 +36,12 @@ DECLARE_GLOBAL_DATA_PTR; */ int board_early_init_f(void) { - /* SSP clock init will come here soon. */ + /* IO0 clock at 480MHz */ + mxs_set_ioclk(MXC_IOCLK0, 480000); + + /* SSP0 clock at 96MHz */ + mxs_set_sspclk(MXC_SSPCLK0, 96000, 0); + return 0; }
@@ -42,6 +50,18 @@ int dram_init(void) return mxs_dram_init(); }
+#ifdef CONFIG_CMD_MMC +static int mx23_olx_mmc_cd(int id) +{ + return 1; /* Card always present */ +} + +int board_mmc_init(bd_t *bis) +{ + return mxsmmc_initialize(bis, 0, NULL, mx23_olx_mmc_cd); +} +#endif + int board_init(void) { /* Adress of boot parameters */ diff --git a/board/olimex/mx23_olinuxino/spl_boot.c b/board/olimex/mx23_olinuxino/spl_boot.c index 6cf669f..7def8bc 100644 --- a/board/olimex/mx23_olinuxino/spl_boot.c +++ b/board/olimex/mx23_olinuxino/spl_boot.c @@ -30,6 +30,7 @@ #include <asm/arch/sys_proto.h>
#define MUX_CONFIG_EMI (MXS_PAD_3V3 | MXS_PAD_16MA | MXS_PAD_PULLUP) +#define MUX_CONFIG_SSP (MXS_PAD_3V3 | MXS_PAD_8MA | MXS_PAD_PULLUP)
const iomux_cfg_t iomux_setup[] = { /* DUART */ @@ -82,6 +83,14 @@ const iomux_cfg_t iomux_setup[] = { MX23_PAD_EMI_CKE__EMI_CKE | MUX_CONFIG_EMI, MX23_PAD_EMI_RASN__EMI_RASN | MUX_CONFIG_EMI, MX23_PAD_EMI_WEN__EMI_WEN | MUX_CONFIG_EMI, + + /* MMC 0 */ + MX23_PAD_SSP1_CMD__SSP1_CMD | MUX_CONFIG_SSP, + MX23_PAD_SSP1_DATA0__SSP1_DATA0 | MUX_CONFIG_SSP, + MX23_PAD_SSP1_DATA1__SSP1_DATA1 | MUX_CONFIG_SSP, + MX23_PAD_SSP1_DATA2__SSP1_DATA2 | MUX_CONFIG_SSP, + MX23_PAD_SSP1_DATA3__SSP1_DATA3 | MUX_CONFIG_SSP, + MX23_PAD_SSP1_SCK__SSP1_SCK | MUX_CONFIG_SSP, };
void board_init_ll(void) diff --git a/include/configs/mx23_olinuxino.h b/include/configs/mx23_olinuxino.h index e5e718c..bc63481 100644 --- a/include/configs/mx23_olinuxino.h +++ b/include/configs/mx23_olinuxino.h @@ -53,8 +53,10 @@ #define CONFIG_DOS_PARTITION
#define CONFIG_CMD_CACHE +#define CONFIG_CMD_EXT2 #define CONFIG_CMD_FAT #define CONFIG_CMD_GPIO +#define CONFIG_CMD_MMC
/* * Memory configurations @@ -110,6 +112,16 @@ #define CONFIG_BAUDRATE 115200 /* Default baud rate */
/* + * MMC Driver + */ +#ifdef CONFIG_CMD_MMC +#define CONFIG_MMC +#define CONFIG_BOUNCE_BUFFER +#define CONFIG_GENERIC_MMC +#define CONFIG_MXS_MMC +#endif + +/* * APBH DMA */ #define CONFIG_APBH_DMA

Hi Marek,
On Tue, Jan 22, 2013 at 11:01 PM, Marek Vasut marex@denx.de wrote:
Add support for the MMC attached to SSP1.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
board/olimex/mx23_olinuxino/mx23_olinuxino.c | 22 +++++++++++++++++++++- board/olimex/mx23_olinuxino/spl_boot.c | 9 +++++++++ include/configs/mx23_olinuxino.h | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-)
Good job, that's a nice series!
Can you also remove #define CONFIG_ENV_IS_NOWHERE
and put the env into mmc now that you have mmc working?
Thanks,
Fabio Estevam

Dear Fabio Estevam,
Hi Marek,
On Tue, Jan 22, 2013 at 11:01 PM, Marek Vasut marex@denx.de wrote:
Add support for the MMC attached to SSP1.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
board/olimex/mx23_olinuxino/mx23_olinuxino.c | 22 +++++++++++++++++++++- board/olimex/mx23_olinuxino/spl_boot.c | 9 +++++++++ include/configs/mx23_olinuxino.h | 12 ++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-)
Good job, that's a nice series!
Can you also remove #define CONFIG_ENV_IS_NOWHERE
and put the env into mmc now that you have mmc working?
Let's do it in a subsequent patch, I don't want to mix env patch with MMC addition patch. I guess there's no other place for env than MMC, eh. That sucks.
Fabio, do you feel like rolling out the env patch?
Best regards, Marek Vasut

On Wed, Jan 23, 2013 at 1:33 AM, Marek Vasut marex@denx.de wrote:
Fabio, do you feel like rolling out the env patch?
Sure, I can send it after it reaches Stefano's tree.

On Wed, Jan 23, 2013 at 1:51 AM, Fabio Estevam festevam@gmail.com wrote:
On Wed, Jan 23, 2013 at 1:33 AM, Marek Vasut marex@denx.de wrote:
Fabio, do you feel like rolling out the env patch?
Sure, I can send it after it reaches Stefano's tree.
I have it done; will send it with the fixes Marek has asked.
-- Otavio Salvador O.S. Systems E-mail: otavio@ossystems.com.br http://www.ossystems.com.br Mobile: +55 53 9981-7854 http://projetos.ossystems.com.br

On 23/01/2013 02:01, Marek Vasut wrote:
The MX23 has less channels for the APBH DMA, sligtly different register layout and some bits in those registers are placed differently. Reflect this in the driver. This patch fixes MMC/DMA issue on MX23.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
arch/arm/include/asm/arch-mxs/regs-apbh.h | 121 +++++++++++++++++++++++++++++ drivers/dma/apbh_dma.c | 10 ++- 2 files changed, 129 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/regs-apbh.h b/arch/arm/include/asm/arch-mxs/regs-apbh.h index e18e677..fcef4b8 100644 --- a/arch/arm/include/asm/arch-mxs/regs-apbh.h +++ b/arch/arm/include/asm/arch-mxs/regs-apbh.h @@ -29,6 +29,87 @@ #include <asm/arch/regs-common.h>
#ifndef __ASSEMBLY__
+#if defined(CONFIG_MX23) +struct mxs_apbh_regs {
- mxs_reg_32(hw_apbh_ctrl0)
- mxs_reg_32(hw_apbh_ctrl1)
- mxs_reg_32(hw_apbh_ctrl2)
- mxs_reg_32(hw_apbh_channel_ctrl)
I see there are diffrent definitions, but why do not we set a common name (as an alias) ?
Such as: #define hw_ahph_ctrl_set hw_apbh_ctrl0
+#if defined(CONFIG_MX23)
- uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
- uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
and we could drop the #ifdef in the driver file.
Best regards, Stefano Babic

Dear Stefano Babic,
On 23/01/2013 02:01, Marek Vasut wrote:
The MX23 has less channels for the APBH DMA, sligtly different register layout and some bits in those registers are placed differently. Reflect this in the driver. This patch fixes MMC/DMA issue on MX23.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
arch/arm/include/asm/arch-mxs/regs-apbh.h | 121 +++++++++++++++++++++++++++++ drivers/dma/apbh_dma.c | 10 ++- 2 files changed, 129 insertions(+), 2 deletions(-)
diff --git a/arch/arm/include/asm/arch-mxs/regs-apbh.h b/arch/arm/include/asm/arch-mxs/regs-apbh.h index e18e677..fcef4b8 100644 --- a/arch/arm/include/asm/arch-mxs/regs-apbh.h +++ b/arch/arm/include/asm/arch-mxs/regs-apbh.h @@ -29,6 +29,87 @@
#include <asm/arch/regs-common.h>
#ifndef __ASSEMBLY__
+#if defined(CONFIG_MX23) +struct mxs_apbh_regs {
- mxs_reg_32(hw_apbh_ctrl0)
- mxs_reg_32(hw_apbh_ctrl1)
- mxs_reg_32(hw_apbh_ctrl2)
- mxs_reg_32(hw_apbh_channel_ctrl)
I see there are diffrent definitions, but why do not we set a common name (as an alias) ?
Such as: #define hw_ahph_ctrl_set hw_apbh_ctrl0
+#if defined(CONFIG_MX23)
- uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
- uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
and we could drop the #ifdef in the driver file.
Oh this junk. On mx23, this bitfield is located in ctrl0 at offset 16 ; on mx28 there's a dedicated register for this bitfield (since mx28 has 16 dma channels, mx23 has only 8).
So it's a bit confusing, but that's how it has to be done.
Best regards, Marek Vasut

On 23/01/2013 02:01, Marek Vasut wrote:
The MX23 has less channels for the APBH DMA, sligtly different register layout and some bits in those registers are placed differently. Reflect this in the driver. This patch fixes MMC/DMA issue on MX23.
Signed-off-by: Marek Vasut marex@denx.de Cc: Otavio Salvador otavio@ossystems.com.br Cc: Fabio Estevam fabio.estevam@freescale.com Cc: Stefano Babic sbabic@denx.de
Applied (whole patchset) to u-boot-imx, thanks.
Best regards, Stefano Babic
participants (4)
-
Fabio Estevam
-
Marek Vasut
-
Otavio Salvador
-
Stefano Babic