Commit cd60ebd430ab0aa5e2ed6afeb28c1ed4b2d01388

Authored by Bo Shen
Committed by Pantelis Antoniou
1 parent 6ace153d13

MMC: atmel_mci: refactor setting the mode register

The mode register is different between MCI IP version.
So, according to MCI IP version to set the mode register.

Signed-off-by: Bo Shen <voice.shen@atmel.com>
Acked-by: Pantelis Antoniou <panto@antoniou-consulting.com>

Showing 2 changed files with 46 additions and 14 deletions Side-by-side Diff

drivers/mmc/gen_atmel_mci.c
... ... @@ -58,30 +58,58 @@
58 58 atmel_mci_t *mci = mmc->priv;
59 59 u32 bus_hz = get_mci_clk_rate();
60 60 u32 clkdiv = 255;
  61 + unsigned int version = atmel_mci_get_version(mci);
  62 + u32 clkodd = 0;
  63 + u32 mr;
61 64  
62 65 debug("mci: bus_hz is %u, setting clock %u Hz, block size %u\n",
63 66 bus_hz, hz, blklen);
64 67 if (hz > 0) {
65   - /* find lowest clkdiv yielding a rate <= than requested */
66   - for (clkdiv=0; clkdiv<255; clkdiv++) {
67   - if ((bus_hz / (clkdiv+1) / 2) <= hz)
68   - break;
  68 + if (version >= 0x500) {
  69 + clkdiv = DIV_ROUND_UP(bus_hz, hz) - 2;
  70 + if (clkdiv > 511)
  71 + clkdiv = 511;
  72 +
  73 + clkodd = clkdiv & 1;
  74 + clkdiv >>= 1;
  75 +
  76 + printf("mci: setting clock %u Hz, block size %u\n",
  77 + bus_hz / (clkdiv * 2 + clkodd + 2), blklen);
  78 + } else {
  79 + /* find clkdiv yielding a rate <= than requested */
  80 + for (clkdiv = 0; clkdiv < 255; clkdiv++) {
  81 + if ((bus_hz / (clkdiv + 1) / 2) <= hz)
  82 + break;
  83 + }
  84 + printf("mci: setting clock %u Hz, block size %u\n",
  85 + (bus_hz / (clkdiv + 1)) / 2, blklen);
  86 +
69 87 }
70 88 }
71   - printf("mci: setting clock %u Hz, block size %u\n",
72   - (bus_hz / (clkdiv+1)) / 2, blklen);
73 89  
74 90 blklen &= 0xfffc;
75   - /* On some platforms RDPROOF and WRPROOF are ignored */
76   - writel((MMCI_BF(CLKDIV, clkdiv)
77   - | MMCI_BF(BLKLEN, blklen)
78   - | MMCI_BIT(RDPROOF)
79   - | MMCI_BIT(WRPROOF)), &mci->mr);
  91 +
  92 + mr = MMCI_BF(CLKDIV, clkdiv);
  93 +
  94 + /* MCI IP version >= 0x200 has R/WPROOF */
  95 + if (version >= 0x200)
  96 + mr |= MMCI_BIT(RDPROOF) | MMCI_BIT(WRPROOF);
  97 +
80 98 /*
81   - * On some new platforms BLKLEN in mci->mr is ignored.
82   - * Should use the BLKLEN in the block register.
  99 + * MCI IP version >= 0x500 use bit 16 as clkodd.
  100 + * MCI IP version < 0x500 use upper 16 bits for blklen.
83 101 */
84   - writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
  102 + if (version >= 0x500)
  103 + mr |= MMCI_BF(CLKODD, clkodd);
  104 + else
  105 + mr |= MMCI_BF(BLKLEN, blklen);
  106 +
  107 + writel(mr, &mci->mr);
  108 +
  109 + /* MCI IP version >= 0x200 has blkr */
  110 + if (version >= 0x200)
  111 + writel(MMCI_BF(BLKLEN, blklen), &mci->blkr);
  112 +
85 113 initialized = 1;
86 114 }
87 115  
... ... @@ -67,6 +67,10 @@
67 67 #define MMCI_PDCPADV_SIZE 1
68 68 #define MMCI_PDCMODE_OFFSET 15
69 69 #define MMCI_PDCMODE_SIZE 1
  70 +/* MCI IP version >= 0x500, MR bit 16 used for CLKODD */
  71 +#define MMCI_CLKODD_OFFSET 16
  72 +#define MMCI_CLKODD_SIZE 1
  73 +/* MCI IP version < 0x200, MR higher 16bits for BLKLEN */
70 74 #define MMCI_BLKLEN_OFFSET 16
71 75 #define MMCI_BLKLEN_SIZE 16
72 76