📄 glamo-mmc.patch
字号:
+ goto done;++ /* enforce timeout */+ glamo_reg_write(0xfff, GLAMO_REGOFS_MMC + GLAMO_REG_MMC_TIMEOUT);+ /*+ * spin+ */+ while (!(glamo_reg_read(GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC))+ ;+ /* ack this interrupt source */+ glamo_reg_write(GLAMO_IRQ_MMC, GLAMO_REG_IRQ_CLEAR);++ if (status & GLAMO_STAT1_MMC_DTOUT)+ error = -1;+ if (status & (GLAMO_STAT1_MMC_BWERR | GLAMO_STAT1_MMC_BRERR))+ error = -2;+ if (status & GLAMO_STAT1_MMC_RTOUT)+ error = -5;+ if (error) {+ printf("cmd 0x%x, arg 0x%x flags 0x%x\n", opcode, arg, flags);+ printf("Error after resp: 0x%x\n", status);+ goto done;+ }+#if 0+ if (flags & MMC_DATA_READ) {+ volatile u8 * pu8 = (volatile u8 *)GLAMO_START_OF_MMC_INTMEM;+ for (n = 0; n < 512; n += 16) {+ int n1;+ for (n1 = 0; n1 < 16; n1++) {+ printf("%02X ", pu8[n + n1]);+ }+ printf("\n");+ }+ }+#endif+ return 0;++done:+ return error;+}++static void glamo_mci_reset(void)+{+ /* reset MMC controller */+ glamo_reg_write(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |+ GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |+ GLAMO_CLOCK_MMC_EN_M9CLK,+ GLAMO_REG_CLOCK_MMC);+ udelay(100000);+ /* and disable reset */+ glamo_reg_write(GLAMO_CLOCK_MMC_DG_TCLK |+ GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |+ GLAMO_CLOCK_MMC_EN_M9CLK,+ GLAMO_REG_CLOCK_MMC);+}+++static u_int8_t ldo_voltage(unsigned int millivolts)+{+ if (millivolts < 900)+ return 0;+ else if (millivolts > 3600)+ return 0x1f;++ millivolts -= 900;+ return millivolts / 100;+}++int mmc_read(ulong src, uchar *dst, int size)+{+ int resp;+ u8 response[16];+ int size_original = size;++ if ((!size) || (size & (MMC_BLOCK_SIZE - 1))) {+ printf("Bad size %d\n", size);+ return 0;+ }++ if (((int)dst) & 1) {+ printf("Bad align on dst\n");+ return 0;+ }++ resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,+ MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,+ (u16 *)&response[0]);++ while (size) {+ switch (card_type) {+ case CARDTYPE_SDHC: /* block addressing */+ resp = mmc_cmd(MMC_READ_SINGLE_BLOCK,+ src >> MMC_BLOCK_SIZE_BITS,+ MMC_CMD_ADTC | MMC_RSP_R1 |+ MMC_DATA_READ, MMC_BLOCK_SIZE, 1, 0,+ (u16 *)&response[0]);+ break;+ default: /* byte addressing */+ resp = mmc_cmd(MMC_READ_SINGLE_BLOCK, src,+ MMC_CMD_ADTC | MMC_RSP_R1 | MMC_DATA_READ,+ MMC_BLOCK_SIZE, 1, 0,+ (u16 *)&response[0]);+ break;+ }+ do_pio_read((u16 *)dst, MMC_BLOCK_SIZE >> 1);++ if (size >= MMC_BLOCK_SIZE)+ size -= MMC_BLOCK_SIZE;+ else+ size = 0;+ dst += MMC_BLOCK_SIZE;+ src += MMC_BLOCK_SIZE;+ }+ return size_original;+}++int mmc_write(uchar *src, ulong dst, int size)+{+ int resp;+ u8 response[16];+ int size_original = size;++ if ((!size) || (size & (MMC_BLOCK_SIZE - 1))) {+ printf("Bad size %d\n", size);+ return 0;+ }++ if (((int)dst) & 1) {+ printf("Bad align on dst\n");+ return 0;+ }++ resp = mmc_cmd(MMC_SET_BLOCKLEN, MMC_BLOCK_SIZE,+ MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,+ (u16 *)&response[0]);++ while (size) {+ do_pio_write((u16 *)src, MMC_BLOCK_SIZE >> 1);+ switch (card_type) {+ case CARDTYPE_SDHC: /* block addressing */+ resp = mmc_cmd(MMC_WRITE_BLOCK,+ dst >> MMC_BLOCK_SIZE_BITS,+ MMC_CMD_ADTC | MMC_RSP_R1 |+ MMC_DATA_WRITE,+ MMC_BLOCK_SIZE, 1, 0,+ (u16 *)&response[0]);+ break;+ default: /* byte addressing */+ resp = mmc_cmd(MMC_WRITE_BLOCK, dst,+ MMC_CMD_ADTC | MMC_RSP_R1 |+ MMC_DATA_WRITE,+ MMC_BLOCK_SIZE, 1, 0,+ (u16 *)&response[0]);+ break;+ }+ if (size >= MMC_BLOCK_SIZE)+ size -= MMC_BLOCK_SIZE;+ else+ size = 0;+ dst += MMC_BLOCK_SIZE;+ src += MMC_BLOCK_SIZE;+ }+ return size_original;+}++static void print_mmc_cid(mmc_cid_t *cid)+{+ printf("MMC found. Card desciption is:\n");+ printf("Manufacturer ID = %02x%02x%02x\n",+ cid->id[0], cid->id[1], cid->id[2]);+ printf("HW/FW Revision = %x %x\n",cid->hwrev, cid->fwrev);+ cid->hwrev = cid->fwrev = 0; /* null terminate string */+ printf("Product Name = %s\n",cid->name);+ printf("Serial Number = %02x%02x%02x\n",+ cid->sn[0], cid->sn[1], cid->sn[2]);+ printf("Month = %d\n",cid->month);+ printf("Year = %d\n",1997 + cid->year);+}++static void print_sd_cid(const struct sd_cid *cid)+{+ printf("Card Type: ");+ switch (card_type) {+ case CARDTYPE_NONE:+ printf("(None)\n");+ break;+ case CARDTYPE_MMC:+ printf("MMC\n");+ break;+ case CARDTYPE_SD:+ printf("SD\n");+ break;+ case CARDTYPE_SD20:+ printf("SD 2.0\n");+ break;+ case CARDTYPE_SDHC:+ printf("SD 2.0 SDHC\n");+ break;+ }+ printf("Manufacturer: 0x%02x, OEM \"%c%c\"\n",+ cid->mid, cid->oid_0, cid->oid_1);+ printf("Product name: \"%c%c%c%c%c\", revision %d.%d\n",+ cid->pnm_0, cid->pnm_1, cid->pnm_2, cid->pnm_3, cid->pnm_4,+ cid->prv >> 4, cid->prv & 15);+ printf("Serial number: %u\n",+ cid->psn_0 << 24 | cid->psn_1 << 16 | cid->psn_2 << 8 |+ cid->psn_3);+ printf("Manufacturing date: %d/%d\n",+ cid->mdt_1 & 15,+ 2000+((cid->mdt_0 & 15) << 4)+((cid->mdt_1 & 0xf0) >> 4));+/* printf("CRC: 0x%02x, b0 = %d\n",+ cid->crc >> 1, cid->crc & 1); */+}+++int mmc_init(int verbose)+{+ int retries = 14, rc = -ENODEV;+ int resp;+ u8 response[16];+ mmc_cid_t *mmc_cid = (mmc_cid_t *)response;+ struct sd_cid *sd_cid = (struct sd_cid *)response;+ u32 hcs = 0;++ card_type = CARDTYPE_NONE;++ /* enable engine */++ glamo_reg_write(GLAMO_CLOCK_MMC_EN_M9CLK |+ GLAMO_CLOCK_MMC_EN_TCLK |+ GLAMO_CLOCK_MMC_DG_M9CLK |+ GLAMO_CLOCK_MMC_DG_TCLK, GLAMO_REG_CLOCK_MMC);+ glamo_reg_write(glamo_reg_read(GLAMO_REG_HOSTBUS(2)) |+ GLAMO_HOSTBUS2_MMIO_EN_MMC, GLAMO_REG_HOSTBUS(2));++ /* controller reset */++ glamo_mci_reset();++ /* power the sdcard slot */++ pcf50633_reg_write(PCF50633_REG_HCLDOOUT, ldo_voltage(3300));+ udelay(10000);+ pcf50633_reg_write(PCF50633_REG_HCLDOOUT + 1,+ pcf50633_reg_read(PCF50633_REG_HCLDOOUT + 1) | 1); /* on */+ udelay(10000);++ /* start the clock -- slowly (50MHz / 250 == 195kHz */++ glamo_reg_write((glamo_reg_read(GLAMO_REG_CLOCK_GEN8) & 0xff00) | 250,+ GLAMO_REG_CLOCK_GEN8);++ /* enable clock to divider input */++ glamo_reg_write(glamo_reg_read(+ GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,+ GLAMO_REG_CLOCK_GEN5_1);++ udelay(100000);++ /* set bus width to 1 */++ glamo_reg_write((glamo_reg_read(GLAMO_REGOFS_MMC ++ GLAMO_REG_MMC_BASIC) &+ (~GLAMO_BASIC_MMC_EN_4BIT_DATA)),+ GLAMO_REGOFS_MMC + GLAMO_REG_MMC_BASIC);++ /* reset */++ resp = mmc_cmd(MMC_GO_IDLE_STATE, 0, MMC_CMD_BCR, 0, 0, 0,+ (u16 *)&response[0]);++ udelay(100000);+ udelay(100000);+ udelay(100000);++ /* SDHC card? */++ resp = mmc_cmd(SD_SEND_IF_COND, 0x000001aa,+ MMC_CMD_BCR | MMC_RSP_R7, 0, 0, 0,+ (u16 *)&response[0]);+ if (!resp && (response[0] == 0xaa)) {+ card_type = CARDTYPE_SD20; /* 2.0 SD, may not be SDHC */+ hcs = 0x40000000;+ }++ /* Well, either way let's say hello in SD card protocol */++ while (retries--) {++ udelay(100000);++ resp = mmc_cmd(MMC_APP_CMD, 0x00000000,+ MMC_CMD_AC | MMC_RSP_R1, 0, 0, 0,+ (u16 *)&response[0]);+ if (resp)+ continue;+ resp = mmc_cmd(SD_APP_OP_COND, hcs | 0x00300000,+ MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,+ (u16 *)&response[0]);+ if (resp)+ continue;++ if (response[3] & (1 << 6)) /* asserts block addressing */+ card_type = CARDTYPE_SDHC;++ if (response[3] & (1 << 7)) { /* not busy */+ if (card_type == CARDTYPE_NONE)+ card_type = CARDTYPE_SD;+ break;+ }+ }+ if (retries < 0)+ return 1;++ if (card_type == CARDTYPE_NONE) {+ retries = 10;+ printf("failed to detect SD Card, trying MMC\n");+ do {+ resp = mmc_cmd(MMC_SEND_OP_COND, 0x00ffc000,+ MMC_CMD_BCR | MMC_RSP_R3, 0, 0, 0,+ (u16 *)&response[0]);+ debug("resp %x %x\n", response[0], response[1]);+ udelay(50);+ } while (retries-- && !(response[3] & 0x80));+ if (retries >= 0)+ card_type = CARDTYPE_MMC;+ else+ return 1;+ }++ /* fill in device description */+ mmc_dev.if_type = IF_TYPE_MMC;+ mmc_dev.part_type = PART_TYPE_DOS;+ mmc_dev.dev = 0;+ mmc_dev.lun = 0;+ mmc_dev.type = 0;+ mmc_dev.removable = 0;+ mmc_dev.block_read = mmc_bread;+ mmc_dev.blksz = 512;+ mmc_dev.lba = 1 << 16; /* 64K x 512 blocks = 32MB default */++ /* try to get card id */+ resp = mmc_cmd(MMC_ALL_SEND_CID, hcs,+ MMC_CMD_BCR | MMC_RSP_R2, 0, 0, 0,+ (u16 *)&response[0]);+ if (resp)+ return 1;++ switch (card_type) {+ case CARDTYPE_MMC:+ /* TODO configure mmc driver depending on card+ attributes */++ if (verbose)+ print_mmc_cid(mmc_cid);+ sprintf((char *) mmc_dev.vendor,+ "Man %02x%02x%02x Snr %02x%02x%02x",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -