Deleted Added
full compact
54c54
< __FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 183542 2008-10-02 07:06:59Z imp $");
---
> __FBSDID("$FreeBSD: head/sys/dev/mmc/mmc.c 183704 2008-10-08 17:35:41Z mav $");
63a64
> #include <sys/endian.h>
84a86,87
> uint32_t raw_scr[2]; /* Raw bits of the SCR */
> uint8_t raw_ext_csd[512]; /* Raw bits of the EXT_CSD */
88a92
> struct mmc_scr scr; /* scr decoded */
89a94,98
> u_char bus_width; /* Bus width to use */
> u_char timing; /* Bus timing support */
> u_char high_cap; /* High Capacity card */
> uint32_t tran_speed; /* Max speed in normal mode */
> uint32_t hs_tran_speed; /* Max speed in high speed mode */
113a123,127
> static int mmc_select_card(struct mmc_softc *sc, uint16_t rca);
> static int mmc_set_bus_width(struct mmc_softc *sc, uint16_t rca, int width);
> static int mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr);
> static void mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr);
> static int mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd);
175a190
> struct mmc_ivars *ivar;
198,199c213
< mmc_wait_for_command(sc, MMC_SELECT_CARD, rca << 16,
< MMC_RSP_R1 | MMC_CMD_AC, NULL, CMD_RETRIES);
---
> mmc_select_card(sc, rca);
200a215,223
> /* Prepare bus width for the new card. */
> ivar = device_get_ivars(dev);
> device_printf(busdev,
> "setting bus width to %d bits\n",
> (ivar->bus_width == bus_width_4)?4:
> (ivar->bus_width == bus_width_8)?8:1);
> mmc_set_bus_width(sc, rca, ivar->bus_width);
> mmcbr_set_bus_width(busdev, ivar->bus_width);
> mmcbr_update_ios(busdev);
202d224
< /* XXX should set bus width here? */
208,209c230
< mmc_wait_for_command(sc, MMC_SELECT_CARD, 0,
< MMC_RSP_R1 | MMC_CMD_AC, NULL, CMD_RETRIES);
---
> mmc_select_card(sc, 0);
212d232
< /* XXX should set bus width here? */
446a467,482
> static int
> mmc_send_if_cond(struct mmc_softc *sc, uint8_t vhs)
> {
> struct mmc_command cmd;
> int err;
>
> memset(&cmd, 0, sizeof(cmd));
> cmd.opcode = SD_SEND_IF_COND;
> cmd.arg = (vhs << 8) + 0xAA;
> cmd.flags = MMC_RSP_R7 | MMC_CMD_BCR;
> cmd.data = NULL;
>
> err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
> return (err);
> }
>
462a499
> mmcbr_set_timing(dev, bus_timing_normal);
477a515
> mmcbr_set_timing(dev, bus_timing_normal);
480a519,715
> static int
> mmc_select_card(struct mmc_softc *sc, uint16_t rca)
> {
> return (mmc_wait_for_command(sc, MMC_SELECT_CARD, ((uint32_t)rca) << 16,
> MMC_RSP_R1B | MMC_CMD_AC, NULL, CMD_RETRIES));
> }
>
> static int
> mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
> {
> struct mmc_command cmd;
> int err;
>
> cmd.opcode = MMC_SWITCH_FUNC;
> cmd.arg = (MMC_SWITCH_FUNC_WR << 24) |
> (index << 16) |
> (value << 8) |
> set;
> cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
> cmd.data = NULL;
> err = mmc_wait_for_cmd(sc, &cmd, 0);
> return (err);
> }
>
> static int
> mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res)
> {
> int err;
> struct mmc_command cmd;
> struct mmc_data data;
>
> memset(&cmd, 0, sizeof(struct mmc_command));
> memset(&data, 0, sizeof(struct mmc_data));
>
> memset(res, 0, 64);
> cmd.opcode = SD_SWITCH_FUNC;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.arg = mode << 31;
> cmd.arg |= 0x00FFFFFF;
> cmd.arg &= ~(0xF << grp);
> cmd.arg |= value << grp;
> cmd.data = &data;
>
> data.data = res;
> data.len = 64;
> data.flags = MMC_DATA_READ;
>
> err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
> return (err);
> }
>
> static int
> mmc_set_bus_width(struct mmc_softc *sc, uint16_t rca, int width)
> {
> int err;
>
> if (mmcbr_get_mode(sc->dev) == mode_sd) {
> struct mmc_command cmd;
>
> memset(&cmd, 0, sizeof(struct mmc_command));
> cmd.opcode = ACMD_SET_BUS_WIDTH;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
> switch (width) {
> case bus_width_1:
> cmd.arg = SD_BUS_WIDTH_1;
> break;
> case bus_width_4:
> cmd.arg = SD_BUS_WIDTH_4;
> break;
> default:
> return (MMC_ERR_INVALID);
> }
> err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
> } else {
> uint8_t value;
>
> switch (width) {
> case bus_width_1:
> value = EXT_CSD_BUS_WIDTH_1;
> break;
> case bus_width_4:
> value = EXT_CSD_BUS_WIDTH_4;
> break;
> case bus_width_8:
> value = EXT_CSD_BUS_WIDTH_8;
> break;
> default:
> return (MMC_ERR_INVALID);
> }
> err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, value);
> }
> return (err);
> }
>
> static int
> mmc_set_timing(struct mmc_softc *sc, int timing)
> {
> int err;
> uint8_t value;
>
> switch (timing) {
> case bus_timing_normal:
> value = 0;
> break;
> case bus_timing_hs:
> value = 1;
> break;
> default:
> return (MMC_ERR_INVALID);
> }
> if (mmcbr_get_mode(sc->dev) == mode_sd) {
> u_char switch_res[64];
>
> err = mmc_sd_switch(sc, 1, 0, value, switch_res);
> } else {
> err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL,
> EXT_CSD_HS_TIMING, value);
> }
> return (err);
> }
>
> static int
> mmc_test_bus_width(struct mmc_softc *sc)
> {
> struct mmc_command cmd;
> struct mmc_data data;
> int err;
> uint8_t buf[8];
> uint8_t p8[8] = { 0x55, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
> uint8_t p8ok[8] = { 0xAA, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
> uint8_t p4[4] = { 0x5A, 0x00, 0x00, 0x00, };
> uint8_t p4ok[4] = { 0xA5, 0x00, 0x00, 0x00, };
>
> if (mmcbr_get_caps(sc->dev) & MMC_CAP_8_BIT_DATA) {
> mmcbr_set_bus_width(sc->dev, bus_width_8);
> mmcbr_update_ios(sc->dev);
>
> cmd.opcode = MMC_BUSTEST_W;
> cmd.arg = 0;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.data = &data;
>
> data.data = p8;
> data.len = 8;
> data.flags = MMC_DATA_WRITE;
> mmc_wait_for_cmd(sc, &cmd, 0);
>
> cmd.opcode = MMC_BUSTEST_R;
> cmd.arg = 0;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.data = &data;
>
> data.data = buf;
> data.len = 8;
> data.flags = MMC_DATA_READ;
> err = mmc_wait_for_cmd(sc, &cmd, 0);
>
> mmcbr_set_bus_width(sc->dev, bus_width_1);
> mmcbr_update_ios(sc->dev);
>
> if (err == MMC_ERR_NONE && memcmp(buf, p8ok, 8) == 0)
> return (bus_width_8);
> }
>
> if (mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) {
> mmcbr_set_bus_width(sc->dev, bus_width_4);
> mmcbr_update_ios(sc->dev);
>
> cmd.opcode = MMC_BUSTEST_W;
> cmd.arg = 0;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.data = &data;
>
> data.data = p4;
> data.len = 4;
> data.flags = MMC_DATA_WRITE;
> mmc_wait_for_cmd(sc, &cmd, 0);
>
> cmd.opcode = MMC_BUSTEST_R;
> cmd.arg = 0;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.data = &data;
>
> data.data = buf;
> data.len = 4;
> data.flags = MMC_DATA_READ;
> err = mmc_wait_for_cmd(sc, &cmd, 0);
>
> mmcbr_set_bus_width(sc->dev, bus_width_1);
> mmcbr_update_ios(sc->dev);
>
> if (err == MMC_ERR_NONE && memcmp(buf, p4ok, 4) == 0)
> return (bus_width_4);
> }
> return (bus_width_1);
> }
>
509,510c744,751
< /* XXX write me */
< panic("write mmc cid decoder");
---
> cid->mid = mmc_get_bits(raw_cid, 120, 8);
> cid->oid = mmc_get_bits(raw_cid, 104, 8);
> for (i = 0; i < 6; i++)
> cid->pnm[i] = mmc_get_bits(raw_cid, 96 - i * 8, 8);
> cid->prv = mmc_get_bits(raw_cid, 48, 8);
> cid->psn = mmc_get_bits(raw_cid, 16, 32);
> cid->mdt_month = mmc_get_bits(raw_cid, 12, 4);
> cid->mdt_year = mmc_get_bits(raw_cid, 8, 4) + 1997;
566c807,828
< panic("Write SDHC CSD parser");
---
> m = mmc_get_bits(raw_csd, 115, 4);
> e = mmc_get_bits(raw_csd, 112, 3);
> csd->tacc = exp[e] * mant[m] + 9 / 10;
> csd->nsac = mmc_get_bits(raw_csd, 104, 8) * 100;
> m = mmc_get_bits(raw_csd, 99, 4);
> e = mmc_get_bits(raw_csd, 96, 3);
> csd->tran_speed = exp[e] * 10000 * mant[m];
> csd->ccc = mmc_get_bits(raw_csd, 84, 12);
> csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 80, 4);
> csd->read_bl_partial = mmc_get_bits(raw_csd, 79, 1);
> csd->write_blk_misalign = mmc_get_bits(raw_csd, 78, 1);
> csd->read_blk_misalign = mmc_get_bits(raw_csd, 77, 1);
> csd->dsr_imp = mmc_get_bits(raw_csd, 76, 1);
> csd->capacity = ((uint64_t)mmc_get_bits(raw_csd, 48, 22) + 1) *
> 512 * 1024;
> csd->erase_blk_en = mmc_get_bits(raw_csd, 46, 1);
> csd->sector_size = mmc_get_bits(raw_csd, 39, 7);
> csd->wp_grp_size = mmc_get_bits(raw_csd, 32, 7);
> csd->wp_grp_enable = mmc_get_bits(raw_csd, 31, 1);
> csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 26, 3);
> csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 22, 4);
> csd->write_bl_partial = mmc_get_bits(raw_csd, 21, 1);
570c832,860
< panic("Write a MMC CSD parser");
---
> csd->csd_structure = mmc_get_bits(raw_csd, 126, 2);
> csd->spec_vers = mmc_get_bits(raw_csd, 122, 4);
> m = mmc_get_bits(raw_csd, 115, 4);
> e = mmc_get_bits(raw_csd, 112, 3);
> csd->tacc = exp[e] * mant[m] + 9 / 10;
> csd->nsac = mmc_get_bits(raw_csd, 104, 8) * 100;
> m = mmc_get_bits(raw_csd, 99, 4);
> e = mmc_get_bits(raw_csd, 96, 3);
> csd->tran_speed = exp[e] * 10000 * mant[m];
> csd->ccc = mmc_get_bits(raw_csd, 84, 12);
> csd->read_bl_len = 1 << mmc_get_bits(raw_csd, 80, 4);
> csd->read_bl_partial = mmc_get_bits(raw_csd, 79, 1);
> csd->write_blk_misalign = mmc_get_bits(raw_csd, 78, 1);
> csd->read_blk_misalign = mmc_get_bits(raw_csd, 77, 1);
> csd->dsr_imp = mmc_get_bits(raw_csd, 76, 1);
> csd->vdd_r_curr_min = cur_min[mmc_get_bits(raw_csd, 59, 3)];
> csd->vdd_r_curr_max = cur_max[mmc_get_bits(raw_csd, 56, 3)];
> csd->vdd_w_curr_min = cur_min[mmc_get_bits(raw_csd, 53, 3)];
> csd->vdd_w_curr_max = cur_max[mmc_get_bits(raw_csd, 50, 3)];
> m = mmc_get_bits(raw_csd, 62, 12);
> e = mmc_get_bits(raw_csd, 47, 3);
> csd->capacity = ((1 + m) << (e + 2)) * csd->read_bl_len;
> // csd->erase_blk_en = mmc_get_bits(raw_csd, 46, 1);
> // csd->sector_size = mmc_get_bits(raw_csd, 39, 7);
> csd->wp_grp_size = mmc_get_bits(raw_csd, 32, 5);
> csd->wp_grp_enable = mmc_get_bits(raw_csd, 31, 1);
> csd->r2w_factor = 1 << mmc_get_bits(raw_csd, 26, 3);
> csd->write_bl_len = 1 << mmc_get_bits(raw_csd, 22, 4);
> csd->write_bl_partial = mmc_get_bits(raw_csd, 21, 1);
573a864,884
> static void
> mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr)
> {
> unsigned int scr_struct;
> uint32_t tmp[4];
>
> tmp[3] = raw_scr[1];
> tmp[2] = raw_scr[0];
>
> memset(scr, 0, sizeof(*scr));
>
> scr_struct = mmc_get_bits(tmp, 60, 4);
> if (scr_struct != 0) {
> printf("Unrecognised SCR structure version %d\n",
> scr_struct);
> return;
> }
> scr->sda_vsn = mmc_get_bits(tmp, 56, 4);
> scr->bus_widths = mmc_get_bits(tmp, 48, 4);
> }
>
604a916,979
> mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr)
> {
> int err;
> struct mmc_command cmd;
> struct mmc_data data;
>
> memset(&cmd, 0, sizeof(struct mmc_command));
> memset(&data, 0, sizeof(struct mmc_data));
>
> memset(rawscr, 0, 8);
> cmd.opcode = ACMD_SEND_SCR;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.arg = 0;
> cmd.data = &data;
>
> data.data = rawscr;
> data.len = 8;
> data.flags = MMC_DATA_READ;
>
> err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
> rawscr[0] = be32toh(rawscr[0]);
> rawscr[1] = be32toh(rawscr[1]);
> return (err);
> }
>
> static int
> mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd)
> {
> int err;
> struct mmc_command cmd;
> struct mmc_data data;
>
> memset(&cmd, 0, sizeof(struct mmc_command));
> memset(&data, 0, sizeof(struct mmc_data));
>
> memset(rawextcsd, 0, 512);
> cmd.opcode = MMC_SEND_EXT_CSD;
> cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
> cmd.arg = 0;
> cmd.data = &data;
>
> data.data = rawextcsd;
> data.len = 512;
> data.flags = MMC_DATA_READ;
>
> err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
> return (err);
> }
>
> static int
> mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp)
> {
> struct mmc_command cmd;
> int err;
>
> cmd.opcode = MMC_SET_RELATIVE_ADDR;
> cmd.arg = resp << 16;
> cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
> cmd.data = NULL;
> err = mmc_wait_for_cmd(sc, &cmd, 0);
> return (err);
> }
>
> static int
625a1001,1002
> uint16_t rca = 2;
> u_char switch_res[64];
639,640c1016,1020
< if (mmcbr_get_mode(sc->dev) == mode_sd) {
< ivar->mode = mode_sd;
---
> if (mmcbr_get_ro(sc->dev))
> ivar->read_only = 1;
> ivar->bus_width = bus_width_1;
> ivar->mode = mmcbr_get_mode(sc->dev);
> if (ivar->mode == mode_sd) {
644,645c1024
< if (mmcbr_get_ro(sc->dev))
< ivar->read_only = 1;
---
> /* Get card CSD. */
648,649c1027,1048
< printf("SD CARD: %lld bytes\n", (long long)
< ivar->csd.capacity);
---
> if (ivar->csd.csd_structure > 0)
> ivar->high_cap = 1;
> ivar->tran_speed = ivar->csd.tran_speed;
> /* Get card SCR. Card must be selected to fetch it. */
> mmc_select_card(sc, ivar->rca);
> mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
> mmc_app_decode_scr(ivar->raw_scr, &ivar->scr);
> /* Get card switch capabilities. */
> if ((ivar->scr.sda_vsn >= 1) &&
> (ivar->csd.ccc & (1<<10))) {
> mmc_sd_switch(sc, 0, 0, 0xF, switch_res);
> if (switch_res[13] & 2) {
> ivar->timing = bus_timing_hs;
> ivar->hs_tran_speed = 50000000;
> }
> }
> mmc_select_card(sc, 0);
> /* Find max supported bus width. */
> if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
> (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
> ivar->bus_width = bus_width_4;
> /* Add device. */
654c1053,1084
< panic("Write MMC card code here");
---
> mmc_decode_cid(0, ivar->raw_cid, &ivar->cid);
> ivar->rca = rca++;
> mmc_set_relative_addr(sc, ivar->rca);
> /* Get card CSD. */
> mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
> mmc_decode_csd(0, ivar->raw_csd, &ivar->csd);
> ivar->tran_speed = ivar->csd.tran_speed;
> /* Only MMC >= 4.x cards support EXT_CSD. */
> if (ivar->csd.spec_vers >= 4) {
> /* Card must be selected to fetch EXT_CSD. */
> mmc_select_card(sc, ivar->rca);
> mmc_send_ext_csd(sc, ivar->raw_ext_csd);
> /* Get card speed in high speed mode. */
> ivar->timing = bus_timing_hs;
> if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE]
> & EXT_CSD_CARD_TYPE_52)
> ivar->hs_tran_speed = 52000000;
> else if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE]
> & EXT_CSD_CARD_TYPE_26)
> ivar->hs_tran_speed = 26000000;
> else
> ivar->hs_tran_speed = ivar->tran_speed;
> /* Find max supported bus width. */
> ivar->bus_width = mmc_test_bus_width(sc);
> mmc_select_card(sc, 0);
> } else {
> ivar->bus_width = bus_width_1;
> ivar->timing = bus_timing_normal;
> }
> /* Add device. */
> child = device_add_child(sc->dev, NULL, -1);
> device_set_ivars(child, ivar);
663a1094
> int err;
674c1105,1107
< if (mmc_send_app_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) {
---
> err = mmc_send_if_cond(sc, 1);
> if (mmc_send_app_op_cond(sc, err?0:MMC_OCR_CCS, &ocr) !=
> MMC_ERR_NONE) {
700,702c1133,1137
< if (mmcbr_get_mode(dev) == mode_sd)
< mmc_send_app_op_cond(sc, mmcbr_get_ocr(dev), NULL);
< else
---
> if (mmcbr_get_mode(dev) == mode_sd) {
> err = mmc_send_if_cond(sc, 1);
> mmc_send_app_op_cond(sc,
> (err?0:MMC_OCR_CCS)|mmcbr_get_ocr(dev), NULL);
> } else
715c1150
< int max_dtr = 0;
---
> int max_dtr, max_hs_dtr, max_timing;
717a1153
> struct mmc_ivars *ivar;
721c1157,1161
< max_dtr = f_max;
---
> max_dtr = max_hs_dtr = f_max;
> if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED))
> max_timing = bus_timing_hs;
> else
> max_timing = bus_timing_normal;
724,726c1164,1180
< for (i = 0; i < nkid; i++)
< if (mmc_get_tran_speed(kids[i]) < max_dtr)
< max_dtr = mmc_get_tran_speed(kids[i]);
---
> for (i = 0; i < nkid; i++) {
> ivar = device_get_ivars(kids[i]);
> if (ivar->timing < max_timing)
> max_timing = ivar->timing;
> if (ivar->tran_speed < max_dtr)
> max_dtr = ivar->tran_speed;
> if (ivar->hs_tran_speed < max_dtr)
> max_hs_dtr = ivar->hs_tran_speed;
> }
> for (i = 0; i < nkid; i++) {
> ivar = device_get_ivars(kids[i]);
> if (ivar->timing == bus_timing_normal)
> continue;
> mmc_select_card(sc, ivar->rca);
> mmc_set_timing(sc, max_timing);
> }
> mmc_select_card(sc, 0);
728,730c1182,1190
< device_printf(sc->dev, "setting transfer rate to %d.%03dMHz\n",
< max_dtr / 1000000, (max_dtr / 1000) % 1000);
< return (max_dtr);
---
> if (max_timing == bus_timing_hs)
> max_dtr = max_hs_dtr;
> device_printf(sc->dev, "setting transfer rate to %d.%03dMHz%s\n",
> max_dtr / 1000000, (max_dtr / 1000) % 1000,
> (max_timing == bus_timing_hs)?" with high speed timing":"");
> mmcbr_set_timing(sc->dev, max_timing);
> mmcbr_set_clock(sc->dev, max_dtr);
> mmcbr_update_ios(sc->dev);
> return max_dtr;
744,745c1204
< mmcbr_set_clock(dev, mmc_calculate_clock(sc));
< mmcbr_update_ios(dev);
---
> mmc_calculate_clock(sc);
776a1236,1238
> case MMC_IVAR_HIGH_CAP:
> *(int *)result = ivar->high_cap;
> break;