mmc.c
来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 663 行 · 第 1/2 页
C
663 行
/* * (C) Copyright 2003 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <config.h>#include <common.h>#include <mmc.h>#include <asm/errno.h>#include <asm/arch/hardware.h>#include <part.h>#ifdef CONFIG_MMCextern int fat_register_device(block_dev_desc_t * dev_desc, int part_no);static block_dev_desc_t mmc_dev;block_dev_desc_t *mmc_get_dev(int dev){ return ((block_dev_desc_t *) & mmc_dev);}/* * FIXME needs to read cid and csd info to determine block size * and other parameters */static uchar mmc_buf[MMC_BLOCK_SIZE];static uchar spec_ver;static int mmc_ready = 0;static int wide = 0;static uint32_t */****************************************************/mmc_cmd(ushort cmd, ushort argh, ushort argl, ushort cmdat)/****************************************************/{ static uint32_t resp[4], a, b, c; ulong status; int i; debug("mmc_cmd %u 0x%04x 0x%04x 0x%04x\n", cmd, argh, argl, cmdat | wide); MMC_STRPCL = MMC_STRPCL_STOP_CLK; MMC_I_MASK = ~MMC_I_MASK_CLK_IS_OFF; while (!(MMC_I_REG & MMC_I_REG_CLK_IS_OFF)) ; MMC_CMD = cmd; MMC_ARGH = argh; MMC_ARGL = argl; MMC_CMDAT = cmdat | wide; MMC_I_MASK = ~MMC_I_MASK_END_CMD_RES; MMC_STRPCL = MMC_STRPCL_START_CLK; while (!(MMC_I_REG & MMC_I_REG_END_CMD_RES)) ; status = MMC_STAT; debug("MMC status 0x%08x\n", status); if (status & MMC_STAT_TIME_OUT_RESPONSE) { return 0; } /* Linux says: * Did I mention this is Sick. We always need to * discard the upper 8 bits of the first 16-bit word. */ a = (MMC_RES & 0xffff); for (i = 0; i < 4; i++) { b = (MMC_RES & 0xffff); c = (MMC_RES & 0xffff); resp[i] = (a << 24) | (b << 8) | (c >> 8); a = c; debug("MMC resp[%d] = %#08x\n", i, resp[i]); } return resp;}int/****************************************************/mmc_block_read(uchar * dst, ulong src, ulong len)/****************************************************/{ ushort argh, argl; ulong status; if (len == 0) { return 0; } debug("mmc_block_rd dst %lx src %lx len %d\n", (ulong) dst, src, len); argh = len >> 16; argl = len & 0xffff; /* set block len */ mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); /* send read command */ argh = src >> 16; argl = src & 0xffff; MMC_STRPCL = MMC_STRPCL_STOP_CLK; MMC_RDTO = 0xffff; MMC_NOB = 1; MMC_BLKLEN = len; mmc_cmd(MMC_CMD_READ_SINGLE_BLOCK, argh, argl, MMC_CMDAT_R1 | MMC_CMDAT_READ | MMC_CMDAT_BLOCK | MMC_CMDAT_DATA_EN); MMC_I_MASK = ~MMC_I_MASK_RXFIFO_RD_REQ; while (len) { if (MMC_I_REG & MMC_I_REG_RXFIFO_RD_REQ) {#ifdef CONFIG_PXA27X int i; for (i = min(len, 32); i; i--) { *dst++ = *((volatile uchar *)&MMC_RXFIFO); len--; }#else *dst++ = MMC_RXFIFO; len--;#endif } status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } } MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)) ; status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } return 0;}int/****************************************************/mmc_block_write(ulong dst, uchar * src, int len)/****************************************************/{ ushort argh, argl; ulong status; if (len == 0) { return 0; } debug("mmc_block_wr dst %lx src %lx len %d\n", dst, (ulong) src, len); argh = len >> 16; argl = len & 0xffff; /* set block len */ mmc_cmd(MMC_CMD_SET_BLOCKLEN, argh, argl, MMC_CMDAT_R1); /* send write command */ argh = dst >> 16; argl = dst & 0xffff; MMC_STRPCL = MMC_STRPCL_STOP_CLK; MMC_NOB = 1; MMC_BLKLEN = len; mmc_cmd(MMC_CMD_WRITE_BLOCK, argh, argl, MMC_CMDAT_R1 | MMC_CMDAT_WRITE | MMC_CMDAT_BLOCK | MMC_CMDAT_DATA_EN); MMC_I_MASK = ~MMC_I_MASK_TXFIFO_WR_REQ; while (len) { if (MMC_I_REG & MMC_I_REG_TXFIFO_WR_REQ) { int i, bytes = min(32, len); for (i = 0; i < bytes; i++) { MMC_TXFIFO = *src++; } if (bytes < 32) { MMC_PRTBUF = MMC_PRTBUF_BUF_PART_FULL; } len -= bytes; } status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } } MMC_I_MASK = ~MMC_I_MASK_DATA_TRAN_DONE; while (!(MMC_I_REG & MMC_I_REG_DATA_TRAN_DONE)) ; MMC_I_MASK = ~MMC_I_MASK_PRG_DONE; while (!(MMC_I_REG & MMC_I_REG_PRG_DONE)) ; status = MMC_STAT; if (status & MMC_STAT_ERRORS) { printf("MMC_STAT error %lx\n", status); return -1; } return 0;}int/****************************************************/mmc_read(ulong src, uchar * dst, int size)/****************************************************/{ ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ulong mmc_block_size, mmc_block_address; if (size == 0) { return 0; } if (!mmc_ready) { printf("Please initial the MMC first\n"); return -1; } mmc_block_size = MMC_BLOCK_SIZE; mmc_block_address = ~(mmc_block_size - 1); src -= CFG_MMC_BASE; end = src + size; part_start = ~mmc_block_address & src; part_end = ~mmc_block_address & end; aligned_start = mmc_block_address & src; aligned_end = mmc_block_address & end; /* all block aligned accesses */ debug ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if (part_start) { part_len = mmc_block_size - part_start; debug ("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) { return -1; } memcpy(dst, mmc_buf + part_start, part_len); dst += part_len; src += part_len; } debug ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); for (; src < aligned_end; src += mmc_block_size, dst += mmc_block_size) { debug ("al src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read((uchar *) (dst), src, mmc_block_size)) < 0) { return -1; } } debug ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if (part_end && src < end) { debug ("pe src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_end, mmc_block_size)) < 0) { return -1; } memcpy(dst, mmc_buf, part_end); } return 0;}int/****************************************************/mmc_write(uchar * src, ulong dst, int size)/****************************************************/{ ulong end, part_start, part_end, part_len, aligned_start, aligned_end; ulong mmc_block_size, mmc_block_address; if (size == 0) { return 0; } if (!mmc_ready) { printf("Please initial the MMC first\n"); return -1; } mmc_block_size = MMC_BLOCK_SIZE; mmc_block_address = ~(mmc_block_size - 1); dst -= CFG_MMC_BASE; end = dst + size; part_start = ~mmc_block_address & dst; part_end = ~mmc_block_address & end; aligned_start = mmc_block_address & dst; aligned_end = mmc_block_address & end; /* all block aligned accesses */ debug ("src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", src, (ulong) dst, end, part_start, part_end, aligned_start, aligned_end); if (part_start) { part_len = mmc_block_size - part_start; debug ("ps src %lx dst %lx end %lx pstart %lx pend %lx astart %lx aend %lx\n", (ulong) src, dst, end, part_start, part_end, aligned_start, aligned_end); if ((mmc_block_read(mmc_buf, aligned_start, mmc_block_size)) < 0) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?