[U-Boot] [PATCH v2 8/9] sunxi: mmc support
As well as the following signed-off-by the sunxi branch shows commits to these files authored by the following: Stefan Roese Tom Cubie yemao Signed-off-by: Henrik Nordstrom Signed-off-by: Luke Leighton Signed-off-by: Oliver Schinagl Signed-off-by: Wills Wang Signed-off-by: Ian Campbell Cc: Pantelis Antoniou --- Pantelis, most of your review comments have been addressed but not all, in particular the timeout loops aren't sorted yet, but I wanted to get the rest of the series reposted. v2: Based on u-boot-sunxi.git#sunxi d9aa5dd3d15c "sunxi: mmc: checkpatch whitespace fixes" with v2014.04-rc2 merged in: - use proper gpio interfaces, removing awkward casts and some magic numbers. - remove magic numbers - other cleanups v1: Based on linux-sunxi#sunxi commit d854c4de2f57 "arm: Handle .gnu.hash section in ldscripts" vs v2014.01. --- arch/arm/include/asm/arch-sunxi/mmc.h | 124 +++ board/sunxi/board.c | 13 + drivers/mmc/Makefile | 1 + drivers/mmc/sunxi_mmc.c | 625 ++ include/configs/sunxi-common.h| 11 + 5 files changed, 774 insertions(+) create mode 100644 arch/arm/include/asm/arch-sunxi/mmc.h create mode 100644 drivers/mmc/sunxi_mmc.c diff --git a/arch/arm/include/asm/arch-sunxi/mmc.h b/arch/arm/include/asm/arch-sunxi/mmc.h new file mode 100644 index 000..97b14c3 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/mmc.h @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2007-2011 + * Allwinner Technology Co., Ltd. + * Aaron + * + * MMC register definition for allwinner sunxi platform. + * + * SPDX-License-Identifier:GPL-2.0+ + */ + +#ifndef _SUNXI_MMC_H +#define _SUNXI_MMC_H + +#include + +struct sunxi_mmc { + u32 gctrl; /* (0x00) SMC Global Control Register */ + u32 clkcr; /* (0x04) SMC Clock Control Register */ + u32 timeout;/* (0x08) SMC Time Out Register */ + u32 width; /* (0x0c) SMC Bus Width Register */ + u32 blksz; /* (0x10) SMC Block Size Register */ + u32 bytecnt;/* (0x14) SMC Byte Count Register */ + u32 cmd;/* (0x18) SMC Command Register */ + u32 arg;/* (0x1c) SMC Argument Register */ + u32 resp0; /* (0x20) SMC Response Register 0 */ + u32 resp1; /* (0x24) SMC Response Register 1 */ + u32 resp2; /* (0x28) SMC Response Register 2 */ + u32 resp3; /* (0x2c) SMC Response Register 3 */ + u32 imask; /* (0x30) SMC Interrupt Mask Register */ + u32 mint; /* (0x34) SMC Masked Interrupt Status Reg */ + u32 rint; /* (0x38) SMC Raw Interrupt Status Register */ + u32 status; /* (0x3c) SMC Status Register */ + u32 ftrglevel; /* (0x40) SMC FIFO Threshold Watermark Reg */ + u32 funcsel;/* (0x44) SMC Function Select Register */ + u32 cbcr; /* (0x48) SMC CIU Byte Count Register */ + u32 bbcr; /* (0x4c) SMC BIU Byte Count Register */ + u32 dbgc; /* (0x50) SMC Debug Enable Register */ + u32 res0[11]; /* (0x54~0x7c) */ + u32 dmac; /* (0x80) SMC IDMAC Control Register */ + u32 dlba; /* (0x84) SMC IDMAC Descr List Base Addr Reg */ + u32 idst; /* (0x88) SMC IDMAC Status Register */ + u32 idie; /* (0x8c) SMC IDMAC Interrupt Enable Register */ + u32 chda; /* (0x90) */ + u32 cbda; /* (0x94) */ + u32 res1[26]; /* (0x98~0xff) */ + u32 fifo; /* (0x100) SMC FIFO Access Address */ +}; + +#define SUNXI_MMC_CLK_POWERSAVE(0x1 << 17) +#define SUNXI_MMC_CLK_ENABLE (0x1 << 16) +#define SUNXI_MMC_CLK_DIVIDER_MASK (0xff) + +#define SUNXI_MMC_GCTRL_SOFT_RESET (0x1 << 0) +#define SUNXI_MMC_GCTRL_FIFO_RESET (0x1 << 1) +#define SUNXI_MMC_GCTRL_DMA_RESET (0x1 << 2) +#define SUNXI_MMC_GCTRL_RESET (SUNXI_MMC_GCTRL_SOFT_RESET|\ +SUNXI_MMC_GCTRL_FIFO_RESET|\ +SUNXI_MMC_GCTRL_DMA_RESET) +#define SUNXI_MMC_GCTRL_DMA_ENABLE (0x1 << 5) +#define SUNXI_MMC_GCTRL_ACCESS_BY_AHB (0x1 << 31) + +#define SUNXI_MMC_CMD_RESP_EXPIRE (0x1 << 6) +#define SUNXI_MMC_CMD_LONG_RESPONSE(0x1 << 7) +#define SUNXI_MMC_CMD_CHK_RESPONSE_CRC (0x1 << 8) +#define SUNXI_MMC_CMD_DATA_EXPIRE (0x1 << 9) +#define SUNXI_MMC_CMD_WRITE(0x1 << 10) +#define SUNXI_MMC_CMD_AUTO_STOP(0x1 << 12) +#define SUNXI_MMC_CMD_WAIT_PRE_OVER(0x1 << 13) +#define SUNXI_MMC_CMD_SEND_INIT_SEQ(0x1 << 15) +#define SUNXI_MMC_CMD_UPCLK_ONLY (0x1 << 21) +#define SUNXI_MMC_CMD_START(0x1 << 31) + +#define SUNXI_MMC_RINT_RESP
Re: [U-Boot] [PATCH v2 8/9] sunxi: mmc support
On Friday, March 21, 2014 at 10:54:25 PM, Ian Campbell wrote: > As well as the following signed-off-by the sunxi branch shows commits to > these files authored by the following: > Stefan Roese > Tom Cubie > yemao > > Signed-off-by: Henrik Nordstrom > Signed-off-by: Luke Leighton > Signed-off-by: Oliver Schinagl > Signed-off-by: Wills Wang > Signed-off-by: Ian Campbell > Cc: Pantelis Antoniou [...] > + > +static void dumphex32(char *name, char *base, int len) > +{ > + __u32 i; > + > + debug("dump %s registers:", name); > + for (i = 0; i < len; i += 4) { > + if (!(i & 0xf)) > + debug("\n0x%p : ", base + i); > + debug("0x%08x ", readl(base + i)); > + } > + debug("\n"); > +} Looks like print_hex_dump() reimplementation ... [...] > +static int mmc_trans_data_by_cpu(struct mmc *mmc, struct mmc_data *data) > +{ > + struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv; > + unsigned i; > + unsigned byte_cnt = data->blocksize * data->blocks; > + unsigned *buff; > + unsigned timeout = 0xf; > + > + if (data->flags & MMC_DATA_READ) { > + buff = (unsigned int *)data->dest; > + for (i = 0; i < (byte_cnt >> 2); i++) { > + while (--timeout && > +(readl(&mmchost->reg->status) & > + SUNXI_MMC_STATUS_FIFO_EMPTY)) > + ; > + if (timeout <= 0) > + goto out; > + buff[i] = readl(mmchost->database); > + timeout = 0xf; > + } > + } else { > + buff = (unsigned int *)data->src; > + for (i = 0; i < (byte_cnt >> 2); i++) { > + while (--timeout && > +(readl(&mmchost->reg->status) & > + SUNXI_MMC_STATUS_FIFO_FULL)) > + ; > + if (timeout <= 0) > + goto out; > + writel(buff[i], mmchost->database); > + timeout = 0xf; Are these two branches almost the same ? Why not just clear that up by squashing them into one with a small if (...) at the begining of this function ? [...] > +static int mmc_trans_data_by_dma(struct mmc *mmc, struct mmc_data *data) > +{ > + struct sunxi_mmc_host *mmchost = (struct sunxi_mmc_host *)mmc->priv; > + unsigned byte_cnt = data->blocksize * data->blocks; > + unsigned char *buff; > + unsigned des_idx = 0; > + unsigned buff_frag_num = > + (byte_cnt + SDXC_DES_BUFFER_MAX_LEN - 1) >> SDXC_DES_NUM_SHIFT; > + unsigned remain; > + unsigned i, rval; > + ALLOC_CACHE_ALIGN_BUFFER(struct sunxi_mmc_des, pdes, buff_frag_num); > + > + buff = data->flags & MMC_DATA_READ ? > + (unsigned char *)data->dest : (unsigned char *)data->src; > + remain = byte_cnt & (SDXC_DES_BUFFER_MAX_LEN - 1); > + if (!remain) > + remain = SDXC_DES_BUFFER_MAX_LEN; > + > + flush_cache((unsigned long)buff, (unsigned long)byte_cnt); > + for (i = 0; i < buff_frag_num; i++, des_idx++) { > + memset((void *)&pdes[des_idx], 0, sizeof(struct sunxi_mmc_des)); > + pdes[des_idx].des_chain = 1; > + pdes[des_idx].own = 1; > + pdes[des_idx].dic = 1; > + if (buff_frag_num > 1 && i != buff_frag_num - 1) > + pdes[des_idx].data_buf1_sz = > + (SDXC_DES_BUFFER_MAX_LEN - > + 1) & SDXC_DES_BUFFER_MAX_LEN; > + else > + pdes[des_idx].data_buf1_sz = remain; > + > + pdes[des_idx].buf_addr_ptr1 = > + (u32) buff + i * SDXC_DES_BUFFER_MAX_LEN; > + if (i == 0) > + pdes[des_idx].first_des = 1; > + > + if (i == buff_frag_num - 1) { > + pdes[des_idx].dic = 0; > + pdes[des_idx].last_des = 1; > + pdes[des_idx].end_of_ring = 1; > + pdes[des_idx].buf_addr_ptr2 = 0; > + } else { > + pdes[des_idx].buf_addr_ptr2 = (u32)&pdes[des_idx + 1]; > + } > + debug("frag %d, remain %d, des[%d](%08x): ", > + i, remain, des_idx, (u32)&pdes[des_idx]); > + debug("[0] = %08x, [1] = %08x, [2] = %08x, [3] = %08x\n", > + (u32)((u32 *)&pdes[des_idx])[0], > + (u32)((u32 *)&pdes[des_idx])[1], > + (u32)((u32 *)&pdes[des_idx])[2], > + (u32)((u32 *)&pdes[des_idx])[3]); Yum, this pointer voodoo looks tasty (and ready for fixing up ... ). [...] ___ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot