Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sdio: high-speed support

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>

+49 -3
+49 -3
drivers/mmc/core/sdio.c
··· 165 165 } 166 166 167 167 /* 168 + * Test if the card supports high-speed mode and, if so, switch to it. 169 + */ 170 + static int sdio_enable_hs(struct mmc_card *card) 171 + { 172 + int ret; 173 + u8 speed; 174 + 175 + if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) 176 + return 0; 177 + 178 + if (!card->cccr.high_speed) 179 + return 0; 180 + 181 + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); 182 + if (ret) 183 + return ret; 184 + 185 + speed |= SDIO_SPEED_EHS; 186 + 187 + ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); 188 + if (ret) 189 + return ret; 190 + 191 + mmc_card_set_highspeed(card); 192 + mmc_set_timing(card->host, MMC_TIMING_SD_HS); 193 + 194 + return 0; 195 + } 196 + 197 + /* 168 198 * Host is being removed. Free up the current card. 169 199 */ 170 200 static void mmc_sdio_remove(struct mmc_host *host) ··· 363 333 goto remove; 364 334 365 335 /* 366 - * No support for high-speed yet, so just set 367 - * the card's maximum speed. 336 + * Switch to high-speed (if supported). 368 337 */ 369 - mmc_set_clock(host, card->cis.max_dtr); 338 + err = sdio_enable_hs(card); 339 + if (err) 340 + goto remove; 341 + 342 + /* 343 + * Change to the card's maximum speed. 344 + */ 345 + if (mmc_card_highspeed(card)) { 346 + /* 347 + * The SDIO specification doesn't mention how 348 + * the CIS transfer speed register relates to 349 + * high-speed, but it seems that 50 MHz is 350 + * mandatory. 351 + */ 352 + mmc_set_clock(host, 50000000); 353 + } else { 354 + mmc_set_clock(host, card->cis.max_dtr); 355 + } 370 356 371 357 /* 372 358 * Switch to wider bus (if supported).