📄 glamo-mmc.patch
字号:
Index: u-boot/board/neo1973/gta02/Makefile===================================================================--- u-boot.orig/board/neo1973/gta02/Makefile+++ u-boot/board/neo1973/gta02/Makefile@@ -25,7 +25,7 @@ LIB = lib$(BOARD).a -OBJS := gta02.o pcf50633.o nand.o nor.o ../common/cmd_neo1973.o \+OBJS := gta02.o pcf50633.o nand.o nor.o glamo-mmc.o ../common/cmd_neo1973.o \ ../common/gsmver.o \ ../common/jbt6k74.o ../common/udc.o ../common/bootmenu.o SOBJS := ../common/lowlevel_init.oIndex: u-boot/board/neo1973/gta02/glamo-mmc.c===================================================================--- /dev/null+++ u-boot/board/neo1973/gta02/glamo-mmc.c@@ -0,0 +1,828 @@+/*+ * linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver+ *+ * Copyright (C) 2007 OpenMoko, Inc, Andy Green <andy@openmoko.com>+ * Based on the Glamo MCI driver that was -->+ *+ * Copyright (C) 2007 OpenMoko, Inc, Andy Green <andy@openmoko.com>+ * Based on S3C MMC driver that was:+ * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>+ *+ * and+ *+ * Based on S3C MMC driver that was (original copyright notice ---->)+ *+ * (C) Copyright 2006 by OpenMoko, Inc.+ * Author: Harald Welte <laforge@openmoko.org>+ *+ * based on u-boot pxa MMC driver and linux/drivers/mmc/s3c2410mci.c+ * (C) 2005-2005 Thomas Kleffel+ *+ * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>+ *+ * This program is free software; you can redistribute it and/or modify+ * it under the terms of the GNU General Public License version 2 as+ * published by the Free Software Foundation.+ */++#include <config.h>+#include <common.h>+#include <mmc.h>+#include <asm/errno.h>+#include <asm/io.h>+#include <part.h>+#include <fat.h>+#include <pcf50633.h>++#include "glamo-regs.h"+#include "glamo-mmc.h"++#if defined(CONFIG_MMC) && defined(CONFIG_MMC_GLAMO)++#define MMC_BLOCK_SIZE_BITS 9+#define MMC_BLOCK_SIZE (1 << MMC_BLOCK_SIZE_BITS)++#define GLAMO_REG(x) (*(volatile u16 *)(CONFIG_GLAMO_BASE + x))+#define GLAMO_INTRAM_OFFSET (8 * 1024 * 1024)+#define GLAMO_FB_SIZE ((8 * 1024 * 1024) - 0x10000)+#define GLAMO_START_OF_MMC_INTMEM ((volatile u16 *)(CONFIG_GLAMO_BASE + \+ GLAMO_INTRAM_OFFSET + GLAMO_FB_SIZE))++static int ccnt;+static block_dev_desc_t mmc_dev;+static mmc_csd_t mmc_csd;+static int mmc_ready = 0;+static int wide = 0;+static enum card_type card_type = CARDTYPE_NONE;++block_dev_desc_t * mmc_get_dev(int dev)+{+ return (block_dev_desc_t *)&mmc_dev;+}++static void+glamo_reg_write(u_int16_t val, u_int16_t reg)+{+ GLAMO_REG(reg) = val;+}++static u_int16_t+glamo_reg_read(u_int16_t reg)+{+ return GLAMO_REG(reg);+}++unsigned char CRC7(u8 * pu8, int cnt)+{+ u8 crc = 0;++ while (cnt--) {+ int n;+ u8 d = *pu8++;+ for (n = 0; n < 8; n++) {+ crc <<= 1;+ if ((d & 0x80) ^ (crc & 0x80))+ crc ^= 0x09;+ d <<= 1;+ }+ }+ return (crc << 1) | 1;+}++ulong mmc_bread(int dev_num, ulong blknr, ulong blkcnt, void *dst)+{+ ulong src = blknr * MMC_BLOCK_SIZE;++ if (!blkcnt)+ return 0;++/* printf("mmc_bread(%d, %ld, %ld, %p)\n", dev_num, blknr, blkcnt, dst); */+ mmc_read(src, dst, blkcnt * MMC_BLOCK_SIZE);+ return blkcnt;+}++/* MMC_DEFAULT_RCA should probably be just 1, but this may break other code+ that expects it to be shifted. */+static u_int16_t rca = MMC_DEFAULT_RCA >> 16;++static void do_pio_read(u16 *buf, int count_words)+{+ volatile u16 *from_ptr = GLAMO_START_OF_MMC_INTMEM;++ while (count_words--)+ *buf++ = *from_ptr++;+}++static void do_pio_write(u16 *buf, int count_words)+{+ volatile u16 *to_ptr = GLAMO_START_OF_MMC_INTMEM;++ while (count_words--)+ *to_ptr++ = *buf++;+}+++static int mmc_cmd(int opcode, int arg, int flags,+ int data_size, int data_blocks,+ int will_stop, u16 *resp)+{+ u16 * pu16 = (u16 *)&resp[0];+ u16 * reg_resp = (u16 *)(CONFIG_GLAMO_BASE + GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_CMD_RSP1);+ u16 status;+ int n;+ u8 u8a[6];+ u16 fire = 0;+ int cmd_is_stop = 0;+ int error = 0;++#if 0+ printf("mmc_cmd(opcode=%d, arg=0x%08X, flags=0x%x, "+ "data_size=%d, data_blocks=%d, will_stop=%d, resp=%p)\n",+ opcode, arg, flags, data_size, data_blocks, will_stop, resp);+#endif+ switch (opcode) {+ case MMC_STOP_TRANSMISSION:+ cmd_is_stop = 1;+ break;+ default:+ break;+ }++ ccnt++;++ /* this guy has data to read/write? */+ if ((!cmd_is_stop) && (flags & (MMC_DATA_WRITE | MMC_DATA_READ))) {+ /*+ * the S-Media-internal RAM offset for our MMC buffer+ */+ glamo_reg_write((u16)GLAMO_FB_SIZE,+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS1);+ glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_WDATADS2);+ glamo_reg_write((u16)GLAMO_FB_SIZE,+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS1);+ glamo_reg_write((u16)(GLAMO_FB_SIZE >> 16),+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RDATADS2);++ /* set up the block info */+ glamo_reg_write(data_size, GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_DATBLKLEN);+ glamo_reg_write(data_blocks, GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_DATBLKCNT);+ }++ /* if we can't do it, reject as busy */+ if (!glamo_reg_read(GLAMO_REGOFS_MMC + GLAMO_REG_MMC_RB_STAT1) &+ GLAMO_STAT1_MMC_IDLE)+ return -1;++ /* create an array in wire order for CRC computation */+ u8a[0] = 0x40 | (opcode & 0x3f);+ u8a[1] = (arg >> 24);+ u8a[2] = (arg >> 16);+ u8a[3] = (arg >> 8);+ u8a[4] = arg;+ u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */++ /* issue the wire-order array including CRC in register order */+ glamo_reg_write((u8a[4] << 8) | u8a[5],+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG1);+ glamo_reg_write((u8a[2] << 8) | u8a[3],+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG2);+ glamo_reg_write((u8a[0] << 8) | u8a[1],+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_REG3);++ /* command index toggle */+ fire |= (ccnt & 1) << 12;++ /* set type of command */+ switch (mmc_cmd_type(flags)) {+ case MMC_CMD_BC:+ fire |= GLAMO_FIRE_MMC_CMDT_BNR;+ break;+ case MMC_CMD_BCR:+ fire |= GLAMO_FIRE_MMC_CMDT_BR;+ break;+ case MMC_CMD_AC:+ fire |= GLAMO_FIRE_MMC_CMDT_AND;+ break;+ case MMC_CMD_ADTC:+ fire |= GLAMO_FIRE_MMC_CMDT_AD;+ break;+ }+ /*+ * if it expects a response, set the type expected+ *+ * R1, Length : 48bit, Normal response+ * R1b, Length : 48bit, same R1, but added card busy status+ * R2, Length : 136bit (really 128 bits with CRC snipped)+ * R3, Length : 48bit (OCR register value)+ * R4, Length : 48bit, SDIO_OP_CONDITION, Reverse SDIO Card+ * R5, Length : 48bit, IO_RW_DIRECTION, Reverse SDIO Card+ * R6, Length : 48bit (RCA register)+ * R7, Length : 48bit (interface condition, VHS(voltage supplied),+ * check pattern, CRC7)+ */+ switch (mmc_resp_type(flags)) {+ case MMC_RSP_R6: /* same index as R7 and R1 */+ fire |= GLAMO_FIRE_MMC_RSPT_R1;+ break;+ case MMC_RSP_R1B:+ fire |= GLAMO_FIRE_MMC_RSPT_R1b;+ break;+ case MMC_RSP_R2:+ fire |= GLAMO_FIRE_MMC_RSPT_R2;+ break;+ case MMC_RSP_R3:+ fire |= GLAMO_FIRE_MMC_RSPT_R3;+ break;+ /* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */+ }+ /*+ * From the command index, set up the command class in the host ctrllr+ *+ * missing guys present on chip but couldn't figure out how to use yet:+ * 0x0 "stream read"+ * 0x9 "cancel running command"+ */+ switch (opcode) {+ case MMC_READ_SINGLE_BLOCK:+ fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */+ break;+ case MMC_SWITCH: /* 64 byte payload */+ case 0x33: /* observed issued by MCI */+ case MMC_READ_MULTIPLE_BLOCK:+ /* we will get an interrupt off this */+ if (!will_stop)+ /* multiblock no stop */+ fire |= GLAMO_FIRE_MMC_CC_MBRNS;+ else+ /* multiblock with stop */+ fire |= GLAMO_FIRE_MMC_CC_MBRS;+ break;+ case MMC_WRITE_BLOCK:+ fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */+ break;+ case MMC_WRITE_MULTIPLE_BLOCK:+ if (will_stop)+ /* multiblock with stop */+ fire |= GLAMO_FIRE_MMC_CC_MBWS;+ else+ /* multiblock NO stop-- 'RESERVED'? */+ fire |= GLAMO_FIRE_MMC_CC_MBWNS;+ break;+ case MMC_STOP_TRANSMISSION:+ fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */+ break;+ default:+ fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */+ break;+ }+ /* enforce timeout */+ glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);++ /* Generate interrupt on txfer; drive strength max */+ glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_BASIC) & 0xfe) |+ 0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT |+ GLAMO_BASIC_MMC_EN_COMPL_INT |+ GLAMO_BASIC_MMC_EN_DR_STR0 |+ GLAMO_BASIC_MMC_EN_DR_STR1,+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);++ /* send the command out on the wire */+ /* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */+ glamo_reg_write(fire, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_CMD_FIRE);++ /*+ * we must spin until response is ready or timed out+ * -- we don't get interrupts unless there is a bulk rx+ */+ do+ status = glamo_reg_read(GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_RB_STAT1);+ while ((((status >> 15) & 1) != (ccnt & 1)) ||+ (!(status & (GLAMO_STAT1_MMC_RB_RRDY |+ GLAMO_STAT1_MMC_RTOUT |+ GLAMO_STAT1_MMC_DTOUT |+ GLAMO_STAT1_MMC_BWERR |+ GLAMO_STAT1_MMC_BRERR))));++ if (status & (GLAMO_STAT1_MMC_RTOUT | GLAMO_STAT1_MMC_DTOUT))+ error = -4;+ if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))+ error = -5;++ if (cmd_is_stop)+ return 0;++ if (error) {+ printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);+ printf("Error after cmd: 0x%x\n", error);+ goto done;+ }+ /*+ * mangle the response registers in two different exciting+ * undocumented ways discovered by trial and error+ */+ if (mmc_resp_type(flags) == MMC_RSP_R2)+ /* grab the response */+ for (n = 0; n < 8; n++) /* super mangle power 1 */+ pu16[n ^ 6] = reg_resp[n];+ else+ for (n = 0; n < 3; n++) /* super mangle power 2 */+ pu16[n] = (reg_resp[n] >> 8) |+ (reg_resp[n + 1] << 8);+ /*+ * if we don't have bulk data to take care of, we're done+ */+ if (!(flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -