コード例 #1
0
ファイル: mmc.c プロジェクト: sparkmbox/GT-I8160_HD-Kernel
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
                         struct mmc_card *oldcard)
{
    struct mmc_card *card;
    int err, ddr = 0;
    u32 cid[4];
    unsigned int max_dtr;

    BUG_ON(!host);
    WARN_ON(!host->claimed);

    /*
     * Since we're changing the OCR value, we seem to
     * need to tell some cards to go back to the idle
     * state.  We wait 1ms to give cards time to
     * respond.
     */
    mmc_go_idle(host);

    /* The extra bit indicates that we support high capacity */
    err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
    if (err)
        goto err;

    /*
     * For SPI, enable CRC as appropriate.
     */
    if (mmc_host_is_spi(host)) {
        err = mmc_spi_set_crc(host, use_spi_crc);
        if (err)
            goto err;
    }

    /*
     * Fetch CID from card.
     */
    if (mmc_host_is_spi(host))
        err = mmc_send_cid(host, cid);
    else
        err = mmc_all_send_cid(host, cid);
    if (err)
        goto err;

    if (oldcard) {
        if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
            err = -ENOENT;
            goto err;
        }

        card = oldcard;
    } else {
        /*
         * Allocate card structure.
         */
        card = mmc_alloc_card(host, &mmc_type);
        if (IS_ERR(card)) {
            err = PTR_ERR(card);
            goto err;
        }

        card->type = MMC_TYPE_MMC;
        card->rca = 1;
        memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
    }

    /*
     * For native busses:  set card RCA and quit open drain mode.
     */
    if (!mmc_host_is_spi(host)) {
        err = mmc_set_relative_addr(card);
        if (err)
            goto free_card;

        mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
    }

    if (!oldcard) {
        /*
         * Fetch CSD from card.
         */
        err = mmc_send_csd(card, card->raw_csd);
        if (err)
            goto free_card;

        err = mmc_decode_csd(card);
        if (err)
            goto free_card;
        err = mmc_decode_cid(card);
        if (err)
            goto free_card;
    }

    /*
     * Select card, as all following commands rely on that.
     */
    if (!mmc_host_is_spi(host)) {
        err = mmc_select_card(card);
        if (err)
            goto free_card;
    }

    if (!oldcard) {
        /*
         * Fetch and process extended CSD.
         */
        err = mmc_read_ext_csd(card);
        if (err)
            goto free_card;
    }

    /*
     * Activate high speed (if supported)
     */
    if ((card->ext_csd.hs_max_dtr != 0) &&
            (host->caps & MMC_CAP_MMC_HIGHSPEED)) {
        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                         EXT_CSD_HS_TIMING, 1);
        if (err && err != -EBADMSG)
            goto free_card;

        if (err) {
            printk(KERN_WARNING "%s: switch to highspeed failed\n",
                   mmc_hostname(card->host));
            err = 0;
        } else {
            mmc_card_set_highspeed(card);
            mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
        }
    }

    /*
     * Compute bus speed.
     */
    max_dtr = (unsigned int)-1;

    if (mmc_card_highspeed(card)) {
        if (max_dtr > card->ext_csd.hs_max_dtr)
            max_dtr = card->ext_csd.hs_max_dtr;
    } else if (max_dtr > card->csd.max_dtr) {
        max_dtr = card->csd.max_dtr;
    }

    mmc_set_clock(host, max_dtr);

    /*
     * Indicate DDR mode (if supported).
     */
    if (mmc_card_highspeed(card)) {
        if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
                && (host->caps & (MMC_CAP_1_8V_DDR)))
            ddr = MMC_1_8V_DDR_MODE;
        else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
                 && (host->caps & (MMC_CAP_1_2V_DDR)))
            ddr = MMC_1_2V_DDR_MODE;
    }

    /*
     * Activate wide bus and DDR (if supported).
     */
    if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
            (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
        unsigned ext_csd_bit, bus_width;

        if (host->caps & MMC_CAP_8_BIT_DATA) {
            if (ddr)
                ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8;
            else
                ext_csd_bit = EXT_CSD_BUS_WIDTH_8;
            bus_width = MMC_BUS_WIDTH_8;
        } else {
            if (ddr)
                ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4;
            else
                ext_csd_bit = EXT_CSD_BUS_WIDTH_4;
            bus_width = MMC_BUS_WIDTH_4;
        }

        err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
                         EXT_CSD_BUS_WIDTH, ext_csd_bit);

        if (err && err != -EBADMSG)
            goto free_card;

        if (err) {
            printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
                   "failed\n", mmc_hostname(card->host),
                   1 << bus_width, ddr);
            err = 0;
        } else {
            if (ddr)
                mmc_card_set_ddr_mode(card);
            else
                ddr = MMC_SDR_MODE;

            mmc_set_bus_width_ddr(card->host, bus_width, ddr);
        }
    }

    if (!oldcard)
        host->card = card;

    return 0;

free_card:
    if (!oldcard)
        mmc_remove_card(card);
err:

    return err;
}
コード例 #2
0
ファイル: core.c プロジェクト: FreeProjectAce/i8160-kernel
/*
 * Change data bus width of a host.
 */
void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
{
	mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE);
}
コード例 #3
0
/*
 * Change data bus width of a host.
 */
void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
{
	mmc_set_bus_width_ddr(host, width, 0);
}
コード例 #4
0
ファイル: mmc.c プロジェクト: LittleForker/linux-2.6
/*
 * Handle the detection and initialisation of a card.
 *
 * In the case of a resume, "oldcard" will contain the card
 * we're trying to reinitialise.
 */
static int mmc_init_card(struct mmc_host *host, u32 ocr,
	struct mmc_card *oldcard)
{
	struct mmc_card *card;
	int err, ddr = 0;
	u32 cid[4];
	unsigned int max_dtr;
	u32 rocr;

	BUG_ON(!host);
	WARN_ON(!host->claimed);

	/*
	 * Since we're changing the OCR value, we seem to
	 * need to tell some cards to go back to the idle
	 * state.  We wait 1ms to give cards time to
	 * respond.
	 */
	mmc_go_idle(host);

	/* The extra bit indicates that we support high capacity */
	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
	if (err)
		goto err;

	/*
	 * For SPI, enable CRC as appropriate.
	 */
	if (mmc_host_is_spi(host)) {
		err = mmc_spi_set_crc(host, use_spi_crc);
		if (err)
			goto err;
	}

	/*
	 * Fetch CID from card.
	 */
	if (mmc_host_is_spi(host))
		err = mmc_send_cid(host, cid);
	else
		err = mmc_all_send_cid(host, cid);
	if (err)
		goto err;

	if (oldcard) {
		if (memcmp(cid, oldcard->raw_cid, sizeof(cid)) != 0) {
			err = -ENOENT;
			goto err;
		}

		card = oldcard;
	} else {
		/*
		 * Allocate card structure.
		 */
		card = mmc_alloc_card(host, &mmc_type);
		if (IS_ERR(card)) {
			err = PTR_ERR(card);
			goto err;
		}

		card->type = MMC_TYPE_MMC;
		card->rca = 1;
		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
	}

	/*
	 * For native busses:  set card RCA and quit open drain mode.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_set_relative_addr(card);
		if (err)
			goto free_card;

		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
	}

	if (!oldcard) {
		/*
		 * Fetch CSD from card.
		 */
		err = mmc_send_csd(card, card->raw_csd);
		if (err)
			goto free_card;

		err = mmc_decode_csd(card);
		if (err)
			goto free_card;
		err = mmc_decode_cid(card);
		if (err)
			goto free_card;
	}

	/*
	 * Select card, as all following commands rely on that.
	 */
	if (!mmc_host_is_spi(host)) {
		err = mmc_select_card(card);
		if (err)
			goto free_card;
	}

	if (!oldcard) {
		/*
		 * Fetch and process extended CSD.
		 */
		err = mmc_read_ext_csd(card);
		if (err)
			goto free_card;

		/* If doing byte addressing, check if required to do sector
		 * addressing.  Handle the case of <2GB cards needing sector
		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
		 * ocr register has bit 30 set for sector addressing.
		 */
		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
			mmc_card_set_blockaddr(card);

		/* Erase size depends on CSD and Extended CSD */
		mmc_set_erase_size(card);
	}

	/*
	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
	 * bit.  This bit will be lost everytime after a reset or power off.
	 */
	if (card->ext_csd.enhanced_area_en) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
				EXT_CSD_ERASE_GROUP_DEF, 1);

		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			err = 0;
			/*
			 * Just disable enhanced area off & sz
			 * will try to enable ERASE_GROUP_DEF
			 * during next time reinit
			 */
			card->ext_csd.enhanced_area_offset = -EINVAL;
			card->ext_csd.enhanced_area_size = -EINVAL;
		} else {
			card->ext_csd.erase_group_def = 1;
			/*
			 * enable ERASE_GRP_DEF successfully.
			 * This will affect the erase size, so
			 * here need to reset erase size
			 */
			mmc_set_erase_size(card);
		}
	}

	/*
	 * Activate high speed (if supported)
	 */
	if ((card->ext_csd.hs_max_dtr != 0) &&
		(host->caps & MMC_CAP_MMC_HIGHSPEED)) {
		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
			EXT_CSD_HS_TIMING, 1);
		if (err && err != -EBADMSG)
			goto free_card;

		if (err) {
			printk(KERN_WARNING "%s: switch to highspeed failed\n",
			       mmc_hostname(card->host));
			err = 0;
		} else {
			mmc_card_set_highspeed(card);
			mmc_set_timing(card->host, MMC_TIMING_MMC_HS);
		}
	}

	/*
	 * Compute bus speed.
	 */
	max_dtr = (unsigned int)-1;

	if (mmc_card_highspeed(card)) {
		if (max_dtr > card->ext_csd.hs_max_dtr)
			max_dtr = card->ext_csd.hs_max_dtr;
	} else if (max_dtr > card->csd.max_dtr) {
		max_dtr = card->csd.max_dtr;
	}

	mmc_set_clock(host, max_dtr);

	/*
	 * Indicate DDR mode (if supported).
	 */
	if (mmc_card_highspeed(card)) {
		if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V)
			&& (host->caps & (MMC_CAP_1_8V_DDR)))
				ddr = MMC_1_8V_DDR_MODE;
		else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V)
			&& (host->caps & (MMC_CAP_1_2V_DDR)))
				ddr = MMC_1_2V_DDR_MODE;
	}

	/*
	 * Activate wide bus and DDR (if supported).
	 */
	if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) &&
	    (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) {
		static unsigned ext_csd_bits[][2] = {
			{ EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 },
			{ EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 },
			{ EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 },
		};
		static unsigned bus_widths[] = {
			MMC_BUS_WIDTH_8,
			MMC_BUS_WIDTH_4,
			MMC_BUS_WIDTH_1
		};
		unsigned idx, bus_width = 0;

		if (host->caps & MMC_CAP_8_BIT_DATA)
			idx = 0;
		else
			idx = 1;
		for (; idx < ARRAY_SIZE(bus_widths); idx++) {
			bus_width = bus_widths[idx];
			if (bus_width == MMC_BUS_WIDTH_1)
				ddr = 0; /* no DDR for 1-bit width */
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					 EXT_CSD_BUS_WIDTH,
					 ext_csd_bits[idx][0]);
			if (!err) {
				mmc_set_bus_width_ddr(card->host,
						      bus_width, MMC_SDR_MODE);
				/*
				 * If controller can't handle bus width test,
				 * use the highest bus width to maintain
				 * compatibility with previous MMC behavior.
				 */
				if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST))
					break;
				err = mmc_bus_test(card, bus_width);
				if (!err)
					break;
			}
		}

		if (!err && ddr) {
			err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
					EXT_CSD_BUS_WIDTH,
					ext_csd_bits[idx][1]);
		}
		if (err) {
			printk(KERN_WARNING "%s: switch to bus width %d ddr %d "
				"failed\n", mmc_hostname(card->host),
				1 << bus_width, ddr);
			goto free_card;
		} else if (ddr) {
			mmc_card_set_ddr_mode(card);
			mmc_set_bus_width_ddr(card->host, bus_width, ddr);
		}
	}

	if (!oldcard)
		host->card = card;

	return 0;

free_card:
	if (!oldcard)
		mmc_remove_card(card);
err:

	return err;
}