Skip to content

Commit

Permalink
mmc: atmel-mci: add support for odd clock dividers
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ludovic Desroches authored and Chris Ball committed Apr 6, 2012
1 parent 33ab4bb commit faf8180
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
1 change: 1 addition & 0 deletions drivers/mmc/host/atmel-mci-regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
#define ATMCI_DTOR 0x0008 /* Data Timeout */
# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
Expand Down
48 changes: 29 additions & 19 deletions drivers/mmc/host/atmel-mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ struct atmel_mci_caps {
bool has_cstor_reg;
bool has_highspeed;
bool has_rwproof;
bool has_odd_clk_div;
};

struct atmel_mci_dma {
Expand Down Expand Up @@ -1134,16 +1135,27 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}

/* Calculate clock divider */
clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
if (clkdiv > 255) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (2 * 256));
clkdiv = 255;
if (host->caps.has_odd_clk_div) {
clkdiv = DIV_ROUND_UP(host->bus_hz, clock_min) - 2;
if (clkdiv > 511) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (511 + 2));
clkdiv = 511;
}
host->mode_reg = ATMCI_MR_CLKDIV(clkdiv >> 1)
| ATMCI_MR_CLKODD(clkdiv & 1);
} else {
clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1;
if (clkdiv > 255) {
dev_warn(&mmc->class_dev,
"clock %u too slow; using %lu\n",
clock_min, host->bus_hz / (2 * 256));
clkdiv = 255;
}
host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);
}

host->mode_reg = ATMCI_MR_CLKDIV(clkdiv);

/*
* WRPROOF and RDPROOF prevent overruns/underruns by
* stopping the clock when the FIFO is full/empty.
Expand Down Expand Up @@ -2014,37 +2026,35 @@ static void __init atmci_get_cap(struct atmel_mci *host)
"version: 0x%x\n", version);

host->caps.has_dma = 0;
host->caps.has_pdc = 0;
host->caps.has_pdc = 1;
host->caps.has_cfg_reg = 0;
host->caps.has_cstor_reg = 0;
host->caps.has_highspeed = 0;
host->caps.has_rwproof = 0;
host->caps.has_odd_clk_div = 0;

/* keep only major version number */
switch (version & 0xf00) {
case 0x100:
host->caps.has_pdc = 1;
break;
case 0x200:
host->caps.has_pdc = 1;
host->caps.has_rwproof = 1;
break;
case 0x300:
case 0x400:
case 0x500:
host->caps.has_odd_clk_div = 1;
case 0x400:
case 0x300:
#ifdef CONFIG_AT_HDMAC
host->caps.has_dma = 1;
#else
host->caps.has_dma = 0;
dev_info(&host->pdev->dev,
"has dma capability but dma engine is not selected, then use pio\n");
#endif
host->caps.has_pdc = 0;
host->caps.has_cfg_reg = 1;
host->caps.has_cstor_reg = 1;
host->caps.has_highspeed = 1;
case 0x200:
host->caps.has_rwproof = 1;
case 0x100:
break;
default:
host->caps.has_pdc = 0;
dev_warn(&host->pdev->dev,
"Unmanaged mci version, set minimum capabilities\n");
break;
Expand Down

0 comments on commit faf8180

Please sign in to comment.