brcm2708: update linux 4.4 patches to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0134-bcm2835-sdhost-Add-workaround-for-odd-behaviour-on-s.patch
1 From 3162c03da716f865fb9b766c8bd7d1dac0386f88 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Tue, 19 Jan 2016 17:16:38 +0000
4 Subject: [PATCH 134/381] bcm2835-sdhost: Add workaround for odd behaviour on
5 some cards
6
7 For reasons not understood, the sdhost driver fails when reading
8 sectors very near the end of some SD cards. The problem could
9 be related to the similar issue that reading the final sector
10 of any card as part of a multiple read never completes, and the
11 workaround is an extension of the mechanism introduced to solve
12 that problem which ensures those sectors are always read singly.
13 ---
14 drivers/mmc/host/bcm2835-sdhost.c | 61 +++++++++++++++++++++++++++++++++------
15 1 file changed, 52 insertions(+), 9 deletions(-)
16
17 --- a/drivers/mmc/host/bcm2835-sdhost.c
18 +++ b/drivers/mmc/host/bcm2835-sdhost.c
19 @@ -173,6 +173,9 @@ struct bcm2835_host {
20 u32 overclock_50; /* frequency to use when 50MHz is requested (in MHz) */
21 u32 overclock; /* Current frequency if overclocked, else zero */
22 u32 pio_limit; /* Maximum block count for PIO (0 = always DMA) */
23 +
24 + u32 sectors; /* Cached card size in sectors */
25 + u32 single_read_sectors[8];
26 };
27
28
29 @@ -277,6 +280,9 @@ static void bcm2835_sdhost_reset_interna
30 {
31 u32 temp;
32
33 + if (host->debug)
34 + pr_info("%s: reset\n", mmc_hostname(host->mmc));
35 +
36 bcm2835_sdhost_set_power(host, false);
37
38 bcm2835_sdhost_write(host, 0, SDCMD);
39 @@ -299,6 +305,8 @@ static void bcm2835_sdhost_reset_interna
40 bcm2835_sdhost_set_power(host, true);
41 mdelay(10);
42 host->clock = 0;
43 + host->sectors = 0;
44 + host->single_read_sectors[0] = ~0;
45 bcm2835_sdhost_write(host, host->hcfg, SDHCFG);
46 bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
47 mmiowb();
48 @@ -309,8 +317,6 @@ static void bcm2835_sdhost_reset(struct
49 {
50 struct bcm2835_host *host = mmc_priv(mmc);
51 unsigned long flags;
52 - if (host->debug)
53 - pr_info("%s: reset\n", mmc_hostname(mmc));
54 spin_lock_irqsave(&host->lock, flags);
55
56 bcm2835_sdhost_reset_internal(host);
57 @@ -676,6 +682,32 @@ static void bcm2835_sdhost_prepare_data(
58 host->flush_fifo = 0;
59 host->data->bytes_xfered = 0;
60
61 + if (!host->sectors && host->mmc->card)
62 + {
63 + struct mmc_card *card = host->mmc->card;
64 + if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) {
65 + /*
66 + * The EXT_CSD sector count is in number of 512 byte
67 + * sectors.
68 + */
69 + host->sectors = card->ext_csd.sectors;
70 + pr_err("%s: using ext_csd!\n", mmc_hostname(host->mmc));
71 + } else {
72 + /*
73 + * The CSD capacity field is in units of read_blkbits.
74 + * set_capacity takes units of 512 bytes.
75 + */
76 + host->sectors = card->csd.capacity <<
77 + (card->csd.read_blkbits - 9);
78 + }
79 + host->single_read_sectors[0] = host->sectors - 65;
80 + host->single_read_sectors[1] = host->sectors - 64;
81 + host->single_read_sectors[2] = host->sectors - 33;
82 + host->single_read_sectors[3] = host->sectors - 32;
83 + host->single_read_sectors[4] = host->sectors - 1;
84 + host->single_read_sectors[5] = ~0; /* Safety net */
85 + }
86 +
87 host->use_dma = host->have_dma && (data->blocks > host->pio_limit);
88 if (!host->use_dma) {
89 int flags;
90 @@ -1246,6 +1278,10 @@ static u32 bcm2835_sdhost_block_irq(stru
91
92 bcm2835_sdhost_finish_data(host);
93 } else {
94 + /* Reset the timer */
95 + mod_timer(&host->pio_timer,
96 + jiffies + host->pio_timeout);
97 +
98 bcm2835_sdhost_transfer_pio(host);
99
100 /* Reset the timer */
101 @@ -1450,8 +1486,8 @@ void bcm2835_sdhost_set_clock(struct bcm
102 host->cdiv = div;
103 bcm2835_sdhost_write(host, host->cdiv, SDCDIV);
104
105 - /* Set the timeout to 500ms */
106 - bcm2835_sdhost_write(host, host->mmc->actual_clock/2, SDTOUT);
107 + /* Set the timeout to 250ms */
108 + bcm2835_sdhost_write(host, host->mmc->actual_clock/4, SDTOUT);
109
110 if (host->debug)
111 pr_info("%s: clock=%d -> max_clk=%d, cdiv=%x (actual clock %d)\n",
112 @@ -1566,13 +1602,20 @@ static int bcm2835_sdhost_multi_io_quirk
113 reading the final sector of the card as part of a multiple read
114 problematic. Detect that case and shorten the read accordingly.
115 */
116 - /* csd.capacity is in weird units - convert to sectors */
117 - u32 card_sectors = (card->csd.capacity << (card->csd.read_blkbits - 9));
118 + struct bcm2835_host *host;
119 +
120 + host = mmc_priv(card->host);
121
122 - if ((direction == MMC_DATA_READ) &&
123 - ((blk_pos + blk_size) == card_sectors))
124 - blk_size--;
125 + if (direction == MMC_DATA_READ)
126 + {
127 + int i;
128 + int sector;
129 + for (i = 0; blk_pos > (sector = host->single_read_sectors[i]); i++)
130 + continue;
131
132 + if ((blk_pos + blk_size) > sector)
133 + blk_size = (blk_pos == sector) ? 1 : (sector - blk_pos);
134 + }
135 return blk_size;
136 }
137