Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F161203750
D32704.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D32704.id.diff
View Options
diff --git a/sys/dev/sdhci/sdhci.h b/sys/dev/sdhci/sdhci.h
--- a/sys/dev/sdhci/sdhci.h
+++ b/sys/dev/sdhci/sdhci.h
@@ -431,6 +431,7 @@
int sdhci_cleanup_slot(struct sdhci_slot *slot);
int sdhci_generic_suspend(struct sdhci_slot *slot);
int sdhci_generic_resume(struct sdhci_slot *slot);
+void sdhci_generic_reset(device_t brdev, struct sdhci_slot *slot, uint8_t mask);
int sdhci_generic_update_ios(device_t brdev, device_t reqdev);
int sdhci_generic_tune(device_t brdev, device_t reqdev, bool hs400);
int sdhci_generic_switch_vccq(device_t brdev, device_t reqdev);
diff --git a/sys/dev/sdhci/sdhci.c b/sys/dev/sdhci/sdhci.c
--- a/sys/dev/sdhci/sdhci.c
+++ b/sys/dev/sdhci/sdhci.c
@@ -106,7 +106,6 @@
static void sdhci_read_block_pio(struct sdhci_slot *slot);
static void sdhci_req_done(struct sdhci_slot *slot);
static void sdhci_req_wakeup(struct mmc_request *req);
-static void sdhci_reset(struct sdhci_slot *slot, uint8_t mask);
static void sdhci_retune(void *arg);
static void sdhci_set_clock(struct sdhci_slot *slot, uint32_t clock);
static void sdhci_set_power(struct sdhci_slot *slot, u_char power);
@@ -370,66 +369,6 @@
return (0);
}
-static void
-sdhci_reset(struct sdhci_slot *slot, uint8_t mask)
-{
- int timeout;
- uint32_t clock;
-
- if (slot->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
- if (!SDHCI_GET_CARD_PRESENT(slot->bus, slot))
- return;
- }
-
- /* Some controllers need this kick or reset won't work. */
- if ((mask & SDHCI_RESET_ALL) == 0 &&
- (slot->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)) {
- /* This is to force an update */
- clock = slot->clock;
- slot->clock = 0;
- sdhci_set_clock(slot, clock);
- }
-
- if (mask & SDHCI_RESET_ALL) {
- slot->clock = 0;
- slot->power = 0;
- }
-
- WR1(slot, SDHCI_SOFTWARE_RESET, mask);
-
- if (slot->quirks & SDHCI_QUIRK_WAITFOR_RESET_ASSERTED) {
- /*
- * Resets on TI OMAPs and AM335x are incompatible with SDHCI
- * specification. The reset bit has internal propagation delay,
- * so a fast read after write returns 0 even if reset process is
- * in progress. The workaround is to poll for 1 before polling
- * for 0. In the worst case, if we miss seeing it asserted the
- * time we spent waiting is enough to ensure the reset finishes.
- */
- timeout = 10000;
- while ((RD1(slot, SDHCI_SOFTWARE_RESET) & mask) != mask) {
- if (timeout <= 0)
- break;
- timeout--;
- DELAY(1);
- }
- }
-
- /* Wait max 100 ms */
- timeout = 10000;
- /* Controller clears the bits when it's done */
- while (RD1(slot, SDHCI_SOFTWARE_RESET) & mask) {
- if (timeout <= 0) {
- slot_printf(slot, "Reset 0x%x never completed.\n",
- mask);
- sdhci_dumpregs(slot);
- return;
- }
- timeout--;
- DELAY(10);
- }
-}
-
static uint32_t
sdhci_tuning_intmask(const struct sdhci_slot *slot)
{
@@ -449,7 +388,7 @@
sdhci_init(struct sdhci_slot *slot)
{
- sdhci_reset(slot, SDHCI_RESET_ALL);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_ALL);
/* Enable interrupts. */
slot->intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
@@ -1256,7 +1195,7 @@
device_delete_child(slot->bus, d);
SDHCI_LOCK(slot);
- sdhci_reset(slot, SDHCI_RESET_ALL);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_ALL);
SDHCI_UNLOCK(slot);
if (slot->opt & SDHCI_HAVE_DMA)
sdhci_dma_free(slot);
@@ -1283,7 +1222,7 @@
callout_drain(&slot->retune_callout);
SDHCI_LOCK(slot);
slot->opt &= ~SDHCI_TUNING_ENABLED;
- sdhci_reset(slot, SDHCI_RESET_ALL);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_ALL);
SDHCI_UNLOCK(slot);
return (0);
@@ -1300,6 +1239,67 @@
return (0);
}
+void
+sdhci_generic_reset(device_t brdev __unused, struct sdhci_slot *slot,
+ uint8_t mask)
+{
+ int timeout;
+ uint32_t clock;
+
+ if (slot->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
+ if (!SDHCI_GET_CARD_PRESENT(slot->bus, slot))
+ return;
+ }
+
+ /* Some controllers need this kick or reset won't work. */
+ if ((mask & SDHCI_RESET_ALL) == 0 &&
+ (slot->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET)) {
+ /* This is to force an update */
+ clock = slot->clock;
+ slot->clock = 0;
+ sdhci_set_clock(slot, clock);
+ }
+
+ if (mask & SDHCI_RESET_ALL) {
+ slot->clock = 0;
+ slot->power = 0;
+ }
+
+ WR1(slot, SDHCI_SOFTWARE_RESET, mask);
+
+ if (slot->quirks & SDHCI_QUIRK_WAITFOR_RESET_ASSERTED) {
+ /*
+ * Resets on TI OMAPs and AM335x are incompatible with SDHCI
+ * specification. The reset bit has internal propagation delay,
+ * so a fast read after write returns 0 even if reset process is
+ * in progress. The workaround is to poll for 1 before polling
+ * for 0. In the worst case, if we miss seeing it asserted the
+ * time we spent waiting is enough to ensure the reset finishes.
+ */
+ timeout = 10000;
+ while ((RD1(slot, SDHCI_SOFTWARE_RESET) & mask) != mask) {
+ if (timeout <= 0)
+ break;
+ timeout--;
+ DELAY(1);
+ }
+ }
+
+ /* Wait max 100 ms */
+ timeout = 10000;
+ /* Controller clears the bits when it's done */
+ while (RD1(slot, SDHCI_SOFTWARE_RESET) & mask) {
+ if (timeout <= 0) {
+ slot_printf(slot, "Reset 0x%x never completed.\n",
+ mask);
+ sdhci_dumpregs(slot);
+ return;
+ }
+ timeout--;
+ DELAY(10);
+ }
+}
+
uint32_t
sdhci_generic_min_freq(device_t brdev __unused, struct sdhci_slot *slot)
{
@@ -1391,7 +1391,8 @@
SDHCI_SET_UHS_TIMING(brdev, slot);
/* Some controllers like reset after bus changes. */
if (slot->quirks & SDHCI_QUIRK_RESET_ON_IOS)
- sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot,
+ SDHCI_RESET_CMD | SDHCI_RESET_DATA);
SDHCI_UNLOCK(slot);
return (0);
@@ -1634,7 +1635,7 @@
slot_printf(slot, "Tuning failed, using fixed sampling clock\n");
WR2(slot, SDHCI_HOST_CONTROL2, hostctrl2 & ~(SDHCI_CTRL2_EXEC_TUNING |
SDHCI_CTRL2_SAMPLING_CLOCK));
- sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
return (EIO);
}
@@ -1703,7 +1704,8 @@
if (slot->curcmd != NULL) {
slot_printf(slot, "Controller timeout\n");
sdhci_dumpregs(slot);
- sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot,
+ SDHCI_RESET_CMD | SDHCI_RESET_DATA);
slot->curcmd->error = MMC_ERR_TIMEOUT;
sdhci_req_done(slot);
} else {
@@ -1881,8 +1883,8 @@
if (slot->curcmd->error) {
if (slot->curcmd->error == MMC_ERR_BADCRC)
slot->retune_req |= SDHCI_RETUNE_REQ_RESET;
- sdhci_reset(slot, SDHCI_RESET_CMD);
- sdhci_reset(slot, SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_DATA);
sdhci_start(slot);
return;
}
@@ -2041,8 +2043,8 @@
if (slot->curcmd->error) {
if (slot->curcmd->error == MMC_ERR_BADCRC)
slot->retune_req |= SDHCI_RETUNE_REQ_RESET;
- sdhci_reset(slot, SDHCI_RESET_CMD);
- sdhci_reset(slot, SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_DATA);
sdhci_start(slot);
return;
}
@@ -2084,8 +2086,8 @@
slot_printf(slot, "result: %d\n", mmcio->cmd.error);
if (mmcio->cmd.error == 0 &&
(slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
- sdhci_reset(slot, SDHCI_RESET_CMD);
- sdhci_reset(slot, SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_DATA);
}
sdhci_req_done(slot);
@@ -2117,8 +2119,8 @@
((slot->curcmd == req->stop &&
(slot->quirks & SDHCI_QUIRK_BROKEN_AUTO_STOP)) ||
(slot->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
- sdhci_reset(slot, SDHCI_RESET_CMD);
- sdhci_reset(slot, SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_DATA);
}
sdhci_req_done(slot);
@@ -2343,7 +2345,7 @@
return;
}
slot_printf(slot, "Got AutoCMD12 error 0x%04x\n", acmd_err);
- sdhci_reset(slot, SDHCI_RESET_CMD);
+ SDHCI_RESET(slot->bus, slot, SDHCI_RESET_CMD);
}
void
@@ -2849,7 +2851,8 @@
WR1(slot, SDHCI_HOST_CONTROL, slot->hostctrl);
/* Some controllers like reset after bus changes. */
if(slot->quirks & SDHCI_QUIRK_RESET_ON_IOS)
- sdhci_reset(slot, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
+ SDHCI_RESET(slot->bus, slot,
+ SDHCI_RESET_CMD | SDHCI_RESET_DATA);
SDHCI_UNLOCK(slot);
return (0);
diff --git a/sys/dev/sdhci/sdhci_if.m b/sys/dev/sdhci/sdhci_if.m
--- a/sys/dev/sdhci/sdhci_if.m
+++ b/sys/dev/sdhci/sdhci_if.m
@@ -164,3 +164,9 @@
device_t brdev;
struct sdhci_slot *slot;
} DEFAULT null_set_uhs_timing;
+
+METHOD void reset {
+ device_t brdev;
+ struct sdhci_slot *slot;
+ uint8_t mask;
+} DEFAULT sdhci_generic_reset;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Jul 2, 2:54 PM (16 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34598287
Default Alt Text
D32704.id.diff (8 KB)
Attached To
Mode
D32704: sdhci: Provide devmethod for software reset
Attached
Detach File
Event Timeline
Log In to Comment