aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2012-03-21 11:41:23 -0400
committerChris Ball <cjb@laptop.org>2012-04-05 20:32:22 -0400
commitfaf8180b20882b52145b96d6d4ed082d41908f90 (patch)
tree457276f731216938caa2b82d851c770cf3b7dd1e /drivers/mmc
parent33ab4bbbdf6c60a8c196b5a28215a93aa2a4ed2e (diff)
mmc: atmel-mci: add support for odd clock dividers
Add an odd clock divider capability available from v5xx. It also involves changing the clock divider calculation, and changing the switch-case statement to use top-down fallthrough. Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h1
-rw-r--r--drivers/mmc/host/atmel-mci.c48
2 files changed, 30 insertions, 19 deletions
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
index 000b3ad0f5ca..787aba1682bb 100644
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ b/drivers/mmc/host/atmel-mci-regs.h
@@ -31,6 +31,7 @@
31# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */ 31# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
32# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */ 32# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
33# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */ 33# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
34# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
34#define ATMCI_DTOR 0x0008 /* Data Timeout */ 35#define ATMCI_DTOR 0x0008 /* Data Timeout */
35# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */ 36# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
36# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */ 37# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index c56edc4a8e26..e94476beca18 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -77,6 +77,7 @@ struct atmel_mci_caps {
77 bool has_cstor_reg; 77 bool has_cstor_reg;
78 bool has_highspeed; 78 bool has_highspeed;
79 bool has_rwproof; 79 bool has_rwproof;
80 bool has_odd_clk_div;
80}; 81};
81 82
82struct atmel_mci_dma { 83struct atmel_mci_dma {
@@ -1134,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
1134 } 1135 }
1135 1136
1136 /* Calculate clock divider */ 1137 /* Calculate clock divider */
1137 clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; 1138 if (host->caps.has_odd_clk_div) {
1138 if (clkdiv > 255) { 1139 clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
1139 dev_warn(&mmc->class_dev, 1140 if (clkdiv > 511) {
1140 "clock %u too slow; using %lu\n", 1141 dev_warn(&mmc->class_dev,
1141 clock_min, host->bus_hz / (2 * 256)); 1142 "clock %u too slow; using %lu\n",
1142 clkdiv = 255; 1143 clock_min, host->bus_hz / (511 + 2));
1144 clkdiv = 511;
1145 }
1146 host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
1147 | ATMCI_MR_CLKODD(clkdiv & 1);
1148 } else {
1149 clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
1150 if (clkdiv > 255) {
1151 dev_warn(&mmc->class_dev,
1152 "clock %u too slow; using %lu\n",
1153 clock_min, host->bus_hz / (2 * 256));
1154 clkdiv = 255;
1155 }
1156 host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
1143 } 1157 }
1144 1158
1145 host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
1146
1147 /* 1159 /*
1148 * WRPROOF and RDPROOF prevent overruns/underruns by 1160 * WRPROOF and RDPROOF prevent overruns/underruns by
1149 * stopping the clock when the FIFO is full/empty. 1161 * stopping the clock when the FIFO is full/empty.
@@ -2014,37 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host)
2014 "version: 0x%x\n", version); 2026 "version: 0x%x\n", version);
2015 2027
2016 host->caps.has_dma = 0; 2028 host->caps.has_dma = 0;
2017 host->caps.has_pdc = 0; 2029 host->caps.has_pdc = 1;
2018 host->caps.has_cfg_reg = 0; 2030 host->caps.has_cfg_reg = 0;
2019 host->caps.has_cstor_reg = 0; 2031 host->caps.has_cstor_reg = 0;
2020 host->caps.has_highspeed = 0; 2032 host->caps.has_highspeed = 0;
2021 host->caps.has_rwproof = 0; 2033 host->caps.has_rwproof = 0;
2034 host->caps.has_odd_clk_div = 0;
2022 2035
2023 /* keep only major version number */ 2036 /* keep only major version number */
2024 switch (version & 0xf00) { 2037 switch (version & 0xf00) {
2025 case 0x100:
2026 host->caps.has_pdc = 1;
2027 break;
2028 case 0x200:
2029 host->caps.has_pdc = 1;
2030 host->caps.has_rwproof = 1;
2031 break;
2032 case 0x300:
2033 case 0x400:
2034 case 0x500: 2038 case 0x500:
2039 host->caps.has_odd_clk_div = 1;
2040 case 0x400:
2041 case 0x300:
2035#ifdef CONFIG_AT_HDMAC 2042#ifdef CONFIG_AT_HDMAC
2036 host->caps.has_dma = 1; 2043 host->caps.has_dma = 1;
2037#else 2044#else
2038 host->caps.has_dma = 0;
2039 dev_info(&host->pdev->dev, 2045 dev_info(&host->pdev->dev,
2040 "has dma capability but dma engine is not selected, then use pio\n"); 2046 "has dma capability but dma engine is not selected, then use pio\n");
2041#endif 2047#endif
2048 host->caps.has_pdc = 0;
2042 host->caps.has_cfg_reg = 1; 2049 host->caps.has_cfg_reg = 1;
2043 host->caps.has_cstor_reg = 1; 2050 host->caps.has_cstor_reg = 1;
2044 host->caps.has_highspeed = 1; 2051 host->caps.has_highspeed = 1;
2052 case 0x200:
2045 host->caps.has_rwproof = 1; 2053 host->caps.has_rwproof = 1;
2054 case 0x100:
2046 break; 2055 break;
2047 default: 2056 default:
2057 host->caps.has_pdc = 0;
2048 dev_warn(&host->pdev->dev, 2058 dev_warn(&host->pdev->dev,
2049 "Unmanaged mci version, set minimum capabilities\n"); 2059 "Unmanaged mci version, set minimum capabilities\n");
2050 break; 2060 break;