From b3dc9566a46efa67951ff6ae28e4397da9db92af Mon Sep 17 00:00:00 2001 From: John Crispin Date: Thu, 25 Feb 2016 10:14:01 +0000 Subject: brcm2708: switch to linux 4.4 and update patches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As usual these patches were extracted from: https://github.com/raspberrypi/linux/commits/rpi-4.4.y Signed-off-by: Álvaro Fernández Rojas SVN-Revision: 48765 --- ...ost-Add-workaround-for-odd-behaviour-on-s.patch | 137 +++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch (limited to 'target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch') diff --git a/target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch b/target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch new file mode 100644 index 0000000000..bbfcbfa74c --- /dev/null +++ b/target/linux/brcm2708/patches-4.4/0136-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch @@ -0,0 +1,137 @@ +From f99bed36f644ebf32e90f49559aac7a663a9fa59 Mon Sep 17 00:00:00 2001 +From: Phil Elwell +Date: Tue, 19 Jan 2016 17:16:38 +0000 +Subject: [PATCH 136/156] bcm2835-sdhost: Add workaround for odd behaviour on + some cards + +For reasons not understood, the sdhost driver fails when reading +sectors very near the end of some SD cards. The problem could +be related to the similar issue that reading the final sector +of any card as part of a multiple read never completes, and the +workaround is an extension of the mechanism introduced to solve +that problem which ensures those sectors are always read singly. +--- + drivers/mmc/host/bcm2835-sdhost.c | 61 +++++++++++++++++++++++++++++++++------ + 1 file changed, 52 insertions(+), 9 deletions(-) + +--- a/drivers/mmc/host/bcm2835-sdhost.c ++++ b/drivers/mmc/host/bcm2835-sdhost.c +@@ -173,6 +173,9 @@ struct bcm2835_host { + u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */ + u32 overclock; /* Current frequency if overclocked, else zero */ + u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */ ++ ++ u32 sectors; /* Cached card size in sectors */ ++ u32 single_read_sectors[8]; + }; + + +@@ -277,6 +280,9 @@ static void bcm2835_sdhost_reset_interna + { + u32 temp; + ++ if (host->debug) ++ pr_info("%s: reset\n", mmc_hostname(host->mmc)); ++ + bcm2835_sdhost_set_power(host, false); + + bcm2835_sdhost_write(host, 0, SDCMD); +@@ -299,6 +305,8 @@ static void bcm2835_sdhost_reset_interna + bcm2835_sdhost_set_power(host, true); + mdelay(10); + host->clock = 0; ++ host->sectors = 0; ++ host->single_read_sectors[0] = ~0; + bcm2835_sdhost_write(host, host->hcfg, SDHCFG); + bcm2835_sdhost_write(host, host->cdiv, SDCDIV); + mmiowb(); +@@ -309,8 +317,6 @@ static void bcm2835_sdhost_reset(struct + { + struct bcm2835_host *host = mmc_priv(mmc); + unsigned long flags; +- if (host->debug) +- pr_info("%s: reset\n", mmc_hostname(mmc)); + spin_lock_irqsave(&host->lock, flags); + + bcm2835_sdhost_reset_internal(host); +@@ -676,6 +682,32 @@ static void bcm2835_sdhost_prepare_data( + host->flush_fifo = 0; + host->data->bytes_xfered = 0; + ++ if (!host->sectors && host->mmc->card) ++ { ++ struct mmc_card *card = host->mmc->card; ++ if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { ++ /* ++ * The EXT_CSD sector count is in number of 512 byte ++ * sectors. ++ */ ++ host->sectors = card->ext_csd.sectors; ++ pr_err("%s: using ext_csd!\n", mmc_hostname(host->mmc)); ++ } else { ++ /* ++ * The CSD capacity field is in units of read_blkbits. ++ * set_capacity takes units of 512 bytes. ++ */ ++ host->sectors = card->csd.capacity << ++ (card->csd.read_blkbits - 9); ++ } ++ host->single_read_sectors[0] = host->sectors - 65; ++ host->single_read_sectors[1] = host->sectors - 64; ++ host->single_read_sectors[2] = host->sectors - 33; ++ host->single_read_sectors[3] = host->sectors - 32; ++ host->single_read_sectors[4] = host->sectors - 1; ++ host->single_read_sectors[5] = ~0; /* Safety net */ ++ } ++ + host->use_dma = host->have_dma && (data->blocks > host->pio_limit); + if (!host->use_dma) { + int flags; +@@ -1246,6 +1278,10 @@ static u32 bcm2835_sdhost_block_irq(stru + + bcm2835_sdhost_finish_data(host); + } else { ++ /* Reset the timer */ ++ mod_timer(&host->pio_timer, ++ jiffies + host->pio_timeout); ++ + bcm2835_sdhost_transfer_pio(host); + + /* Reset the timer */ +@@ -1450,8 +1486,8 @@ void bcm2835_sdhost_set_clock(struct bcm + host->cdiv = div; + bcm2835_sdhost_write(host, host->cdiv, SDCDIV); + +- /* Set the timeout to 500ms */ +- bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT); ++ /* Set the timeout to 250ms */ ++ bcm2835_sdhost_write(host, host->mmc->actual_clock/4, SDTOUT); + + if (host->debug) + pr_info("%s: clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n", +@@ -1566,13 +1602,20 @@ static int bcm2835_sdhost_multi_io_quirk + reading the final sector of the card as part of a multiple read + problematic. Detect that case and shorten the read accordingly. + */ +- /* csd.capacity is in weird units - convert to sectors */ +- u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9)); ++ struct bcm2835_host *host; ++ ++ host = mmc_priv(card->host); + +- if ((direction == MMC_DATA_READ) && +- ((blk_pos + blk_size) == card_sectors)) +- blk_size--; ++ if (direction == MMC_DATA_READ) ++ { ++ int i; ++ int sector; ++ for (i = 0; blk_pos > (sector = host->single_read_sectors[i]); i++) ++ continue; + ++ if ((blk_pos + blk_size) > sector) ++ blk_size = (blk_pos == sector) ? 1 : (sector - blk_pos); ++ } + return blk_size; + } + -- cgit v1.2.3