📄 sdio.patch
字号:
+ continue;+ if (newrca == 0) {+ mmc_card_set_dead(c);+ }+ else {+ c->rca = newrca;+ DBG("FOUND: SDIO only card: RCA = 0x%04x\n", c->rca);+ } } } @@ -908,7 +1089,7 @@ { struct mmc_card *card; - list_for_each_entry(card, &host->cards, node) {+ list_for_each_entry(card, &host->mem_cards, mem_node) { struct mmc_command cmd; int err; @@ -943,7 +1124,7 @@ struct scatterlist sg; - list_for_each_entry(card, &host->cards, node) {+ list_for_each_entry(card, &host->mem_cards, mem_node) { if (card->state & (MMC_STATE_DEAD|MMC_STATE_PRESENT)) continue; if (!mmc_card_sd(card))@@ -1006,15 +1187,57 @@ mmc_deselect_cards(host); } +static void sdio_read_cias(struct mmc_host *host)+{+ struct mmc_card *card;+ + list_for_each_entry(card, &host->sdio_cards, sdio_node) {+ int err = MMC_ERR_NONE;+ if ((card->state & MMC_STATE_DEAD) != 0) {+ continue;+ }+ err = sdio_card_read_cia(host, card->sd_card);+ if (err != MMC_ERR_NONE) {+ mmc_card_set_dead(card);+ }+ }+}++inline+unsigned int mmc_calc_max_dtr(unsigned char clock) {+ return (tran_exp[clock & 0x07] * tran_mant[(clock >> 3) & 0x0F]);+}++EXPORT_SYMBOL(mmc_calc_max_dtr);+ static unsigned int mmc_calculate_clock(struct mmc_host *host) { struct mmc_card *card; unsigned int max_dtr = host->f_max;+ unsigned int max_dtr_card = 0; - list_for_each_entry(card, &host->cards, node)- if (!mmc_card_dead(card) && max_dtr > card->csd.max_dtr)- max_dtr = card->csd.max_dtr;-+ list_for_each_entry(card, &host->cards, node) {+ if (card->sd_card != NULL) {+ /* SDIO card */+ max_dtr_card = card->sd_card->max_dtr;+ }+ else {+ /* Memory card */+ max_dtr_card = card->csd.max_dtr;+ }+ if (max_dtr_card == 0) {+ /* Invalid max DTR */+ mmc_card_set_dead(card);+ continue;+ }+ if (mmc_card_dead(card)) {+ continue;+ }+ if (max_dtr > max_dtr_card) {+ max_dtr = max_dtr_card;+ }+ }+ DBG("MMC: selected %d.%03dMHz transfer rate\n", max_dtr / 1000000, (max_dtr / 1000) % 1000); @@ -1032,14 +1255,15 @@ static void mmc_check_cards(struct mmc_host *host) { struct list_head *l, *n;-+ + mmc_claim_host(host); mmc_deselect_cards(host);-- list_for_each_safe(l, n, &host->cards) {- struct mmc_card *card = mmc_list_to_card(l);+ + list_for_each_safe(l, n, &host->mem_cards) {+ struct mmc_card *card = mmc_list_to_card(l, mem_node); struct mmc_command cmd; int err;-+ cmd.opcode = MMC_SEND_STATUS; cmd.arg = card->rca << 16; cmd.flags = MMC_RSP_R1;@@ -1047,47 +1271,142 @@ err = mmc_wait_for_cmd(host, &cmd, CMD_RETRIES); if (err == MMC_ERR_NONE) continue;-+ mmc_card_set_dead(card); }+ + list_for_each_safe(l, n, &host->sdio_cards) {+ /* If the card is selectable, it is still there. */+ struct mmc_card *card = mmc_list_to_card(l, sdio_node);+ int err = MMC_ERR_NONE;+ + err = mmc_select_card(card->host, card);+ if (err != MMC_ERR_NONE) {+ mmc_card_set_dead(card);+ continue;+ }+ mmc_deselect_cards(card->host);+ }+ + mmc_release_host(host); } static void mmc_setup(struct mmc_host *host) {+ int err = MMC_ERR_NONE;+ + mmc_claim_host(host);+ if (host->ios.power_mode != MMC_POWER_ON) {- int err;- u32 ocr;-+ u32 r4 = 0;+ u32 ocr = 0;+ host->mode = MMC_MODE_MMC; mmc_power_up(host);+ + /*+ * Searching for SDIO cards.+ */+ err = sdio_send_op_cond(host, 0, &r4);+ if (err == MMC_ERR_NONE) {+ /* SDIO card found */+ struct mmc_card* card = NULL;+ struct sd_card* sd_card = NULL;+ u32 u32_temp = 0;+ uint uint_temp = 0;+ + host->mode = MMC_MODE_SD;+ + /* Alloc card */+ card = mmc_alloc_card(host, &u32_temp, &uint_temp);+ if (card == NULL) {+ err = MMC_ERR_INVALID;+ DBG("SDIO card: No MMC memory\n");+ }+ else {+ sd_card = sdio_card_alloc(host);+ if (sd_card == NULL) {+ mmc_free_card(card);+ card = NULL;+ err = MMC_ERR_INVALID;+ DBG("SDIO card: No SDIO memory\n");+ }+ }+ if (err == MMC_ERR_NONE) {+ card->sd_card = sd_card;+ sd_card->mmc_card = card;+ sdio_card_decode_buffer(host,+ sd_card,+ &r4,+ SDIO_BUFFER_TYPE_R4);+ host->ocr = mmc_select_voltage(host,+ sd_card->ocr);+ list_add(&card->node, &host->cards);+ list_add(&card->sdio_node, &host->sdio_cards);+ if (card->sd_card->func == 0) {+ /* No SDIO function */+ err = MMC_ERR_INVALID;+ DBG("SDIO card: No SDIO function\n");+ }+ else if (host->ocr == 0) {+ /* OCR invalid */+ err = MMC_ERR_INVALID;+ DBG("SDIO card: OCR invalid\n");+ }+ else {+ err = sdio_send_op_cond(host,+ host->ocr,+ NULL);+ if (err != MMC_ERR_NONE) {+ DBG("SDIO card: Not ready to operate\n");+ }+ }+ if (err != MMC_ERR_NONE) {+ mmc_card_set_dead(card);+ }+ }+ }+ mmc_idle_cards(host);-- err = mmc_send_op_cond(host, 0, &ocr); /*- * If we fail to detect any cards then try- * searching for SD cards.+ * Searching for SD memory cards. */- if (err != MMC_ERR_NONE)- {- err = mmc_send_app_op_cond(host, 0, &ocr);- if (err != MMC_ERR_NONE)- return;-+ err = mmc_send_app_op_cond(host, 0, &ocr);+ if (err == MMC_ERR_NONE) { host->mode = MMC_MODE_SD; }-- host->ocr = mmc_select_voltage(host, ocr);-+ /*- * 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.+ * Searching for MMC cards. */- if (host->ocr)- mmc_idle_cards(host);+ if (err != MMC_ERR_NONE) {+ /* No SD memory card, searching for MMC cards */+ err = mmc_send_op_cond(host, 0, &ocr);+ if (err == MMC_ERR_NONE) {+ host->mode = MMC_MODE_MMC;+ }+ }+ + if (err == MMC_ERR_NONE) {+ /* Memory card found */+ host->ocr = mmc_select_voltage(host, ocr);+ + if (host->ocr == 0) {+ /* OCR invalid */+ err = MMC_ERR_INVALID;+ }+ else {+ /*+ * 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_idle_cards(host);+ }+ } } else { host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.clock = host->f_min;@@ -1107,22 +1426,25 @@ * they drop off the bus. */ }-- if (host->ocr == 0)- return;-- /*- * Send the selected OCR multiple times... until the cards- * all get the idea that they should be ready for CMD2.- * (My SanDisk card seems to need this.)- */- if (host->mode == MMC_MODE_SD)- mmc_send_app_op_cond(host, host->ocr, NULL);- else- mmc_send_op_cond(host, host->ocr, NULL);-- mmc_discover_cards(host);-+ + if (err == MMC_ERR_NONE) {+ /* Memory card */+ + /*+ * Send the selected OCR multiple times... until the cards+ * all get the idea that they should be ready for CMD2.+ * (My SanDisk card seems to need this.)+ */+ if (host->mode == MMC_MODE_SD)+ mmc_send_app_op_cond(host, host->ocr, NULL);+ else+ mmc_send_op_cond(host, host->ocr, NULL);+ + mmc_discover_cards(host);+ }+ + sdio_assign_rca(host);+ /* * Ok, now switch to push-pull mode. */@@ -1133,6 +1455,10 @@ if (host->mode == MMC_MODE_SD) mmc_read_scrs(host);+ + mmc_release_host(host);+ + sdio_read_cias(host); } @@ -1156,46 +1482,79 @@ struct mmc_host *host = data; struct list_head *l, *n; - mmc_claim_host(host);-- if (host->ios.power_mode == MMC_POWER_ON)+ if (host->ios.power_mode == MMC_POWER_ON) { mmc_check_cards(host);-+ }+ mmc_setup(host);-+ if (!list_empty(&host->cards)) { /* * (Re-)calculate the fastest clock rate which the * attached cards and the host support. */+ mmc_claim_host(host); host->ios.clock = mmc_calculate_clock(host); host->ops->set_ios(host, &host->ios);+ mmc_release_host(host); }-- mmc_release_host(host);-- list_for_each_safe(l, n, &host->cards) {- struct mmc_card *card = mmc_list_to_card(l);-+ + list_for_each_safe(l, n, &host->mem_cards) {+ struct mmc_card *card = mmc_list_to_card(l, mem_node);+ /* * If this is a new and good card, register it. */ if (!mmc_card_present(card) && !mmc_card_dead(card)) {- if (mmc_register_card(card))+ if (mmc_register_card(card)) { mmc_card_set_dead(card);- else+ }+ else { mmc_card_set_present(card);+ } }-+ /* * If this card is dead, destroy it. */ if (mmc_card_dead(card)) { list_del(&card->node);- mmc_remove_card(card);+ list_del(&card->mem_node);+ if (mmc_card_present(card)) {+ mmc_unregister_card(card);+ }+ mmc_free_card(card); } }-+ + list_for_each_safe(l, n, &host->sdio_cards) {+ struct mmc_card *card = mmc_list_to_card(l, sdio_node);+ + /*+ * If this is a new and good card, register it.+ */+ if (!mmc_card_present(card) && !mmc_card_dead(card)) {+ if (sdio_card_register(host, card->sd_card)) {+ mmc_card_set_dead(card);+ }+ else {+ mmc_card_set_present(card);+ }+ }+ + /*+ * If this card is dead, destroy it.+ */+ if (mmc_card_dead(card)) {+ list_del(&card->node);+ list_del(&card->sdio_node);+ if (mmc_card_present(card)) {+ sdio_card_unregister(host, card->sd_card);+ }+ sdio_card_free(host, card->sd_card);+ }+ }+ /* * If we discover that there are no cards on the * bus, turn off the clock and power down.@@ -1223,6 +1582,8 @@ spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_LIST_HEAD(&host->cards);+ INIT_LIST_HEAD(&host->mem_cards);+ INIT_LIST_HEAD(&host->sdio_cards); INIT_WORK(&host->detect, mmc_rescan, host); host->dev = dev;@@ -1271,13 +1632,29 @@ void mmc_remove_host(struct mmc_host *host) { struct list_head *l, *n;-- list_for_each_safe(l, n, &host->cards) {- struct mmc_card *card = mmc_list_to_card(l);-- mmc_remove_card(card);+ + list_for_each_safe(l, n, &host->mem_cards) {+ struct mmc_card *card = mmc_list_to_card(l, mem_node);+ + list_del(&card->node);+ list_del(&card->mem_node);+ if (mmc_card_present(card)) {+ mmc_unregister_card(card);+ }+ mmc_free_card(card); }-+ + list_for_each_safe(l, n, &host->sdio_cards) {+ struct mmc_card *card = mmc_list_to_card(l, sdio_node);+ + list_del(&card->node);+ list_del(&card->sdio_node);+ if (mmc_card_present(card)) {+ sdio_card_unregister(host, card->sd_card);+ }+ sdio_card_free(host, card->sd_card);+ }+ mmc_power_off(host); } diff -Naur -x '.*' -x '*~' -x '*.o' -x '*.ko' -x '*.mod.c' -x '*.cmd' linux26-cvs.BOM/drivers/mmc/mmc.h linux26-cvs.sdio/drivers/mmc/mmc.h--- linux26-cvs.BOM/drivers/mmc/mmc.h 2005-10-20 18:17:10.000000000 +0200+++ linux26-cvs.sdio/drivers/mmc/mmc.h 2005-10-20 18:21:30.000000000 +0200@@ -3,14 +3,35 @@ * * Copyright (C) 2003 Russell King, All Rights Reserved. *+ * SDIO support: Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.+ * by Robert Richter+ * * 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. */ #ifndef _MMC_H #define _MMC_H++#define UNSTUFF_BITS(resp,start,size) \+ ({ \+ const int __size = size; \+ const u32 __mask = (__size < 32 ? 1 << __size : 0) - 1; \+ const int __off = 3 - ((start) / 32); \+ const int __shft = (start) & 31; \+ u32 __res; \+ \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -