2009-06-04 18:12:18

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 0/7] ASIC3 support for tmio_mmc

I've broken the long lines in patches 1-3 and merged the fix into patch 2:
[PATCH 1/7] MFD,mmc: tmio_mmc: make HCLK configurable (v2)
[PATCH 2/7] mmc: tmio_mmc: add bus_shift support (v2)
[PATCH 3/7] mmc: tmio_mmc: don't use set_irq_type (v2)
[PATCH 4/7] mmc: tmio_mmc: correct probe return value for num_resources != 3
Also I've added three new patches for your consideration. Patch 5 delays mapping
of the SD control registers because mfd_cell->enable has to enable the RAM first.
Patch 6 fixes a bug in the SDCLK divider calculation and patch 7 finally enables
compilation of tmio_mmc for ASIC3:
[PATCH 5/7] mmc: tmio_mmc: map SD control registers after enabling the MFD cell
[PATCH 6/7] mmc: tmio_mmc: fix SDCLK divider setting
[PATCH 7/7] mmc: tmio_mmc: allow compilation for ASIC3

regards
Philipp


2009-06-04 18:12:30

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 1/7] MFD,mmc: tmio_mmc: make HCLK configurable

The Toshiba parts all have a 24 MHz HCLK, but HTC ASIC3 has a 24.576 MHz HCLK
and AMD Imageon w228x's HCLK is 80 MHz. With this patch, the MFD driver
provides the HCLK frequency to tmio_mmc via mfd_cell->driver_data.

Signed-off-by: Philipp Zabel <[email protected]>
Acked-by: Ian Molton <[email protected]>
Cc: Samuel Ortiz <[email protected]>
Cc: Pierre Ossman <[email protected]>
---
drivers/mfd/t7l66xb.c | 5 +++++
drivers/mfd/tc6387xb.c | 5 +++++
drivers/mfd/tc6393xb.c | 5 +++++
drivers/mmc/host/tmio_mmc.c | 24 +++++++++++-------------
include/linux/mfd/tmio.h | 7 +++++++
5 files changed, 33 insertions(+), 13 deletions(-)

diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
index e9f4323..875f7a8 100644
--- a/drivers/mfd/t7l66xb.c
+++ b/drivers/mfd/t7l66xb.c
@@ -108,6 +108,10 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)

/*--------------------------------------------------------------------------*/

+static const struct tmio_mmc_data t7166xb_mmc_data = {
+ .hclk = 24000000,
+};
+
static const struct resource t7l66xb_mmc_resources[] = {
{
.start = 0x800,
@@ -149,6 +153,7 @@ static struct mfd_cell t7l66xb_cells[] = {
.name = "tmio-mmc",
.enable = t7l66xb_mmc_enable,
.disable = t7l66xb_mmc_disable,
+ .driver_data = &t7166xb_mmc_data,
.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
.resources = t7l66xb_mmc_resources,
},
diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
index 43222c1..c3993ac 100644
--- a/drivers/mfd/tc6387xb.c
+++ b/drivers/mfd/tc6387xb.c
@@ -75,6 +75,10 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc)

/*--------------------------------------------------------------------------*/

+const static struct tmio_mmc_data tc6387xb_mmc_data = {
+ .hclk = 24000000,
+};
+
static struct resource tc6387xb_mmc_resources[] = {
{
.start = 0x800,
@@ -98,6 +102,7 @@ static struct mfd_cell tc6387xb_cells[] = {
.name = "tmio-mmc",
.enable = tc6387xb_mmc_enable,
.disable = tc6387xb_mmc_disable,
+ .driver_data = &tc6387xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
.resources = tc6387xb_mmc_resources,
},
diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
index 77a12fc..9d2abb5 100644
--- a/drivers/mfd/tc6393xb.c
+++ b/drivers/mfd/tc6393xb.c
@@ -136,6 +136,10 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
return 0;
}

+const static struct tmio_mmc_data tc6393xb_mmc_data = {
+ .hclk = 24000000,
+};
+
static struct resource __devinitdata tc6393xb_nand_resources[] = {
{
.start = 0x1000,
@@ -351,6 +355,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
},
[TC6393XB_CELL_MMC] = {
.name = "tmio-mmc",
+ .driver_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
},
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 63fbd5b..49df71e 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -35,23 +35,14 @@

#include "tmio_mmc.h"

-/*
- * Fixme - documentation conflicts on what the clock values are for the
- * various dividers.
- * One document I have says that its a divisor of a 24MHz clock, another 33.
- * This probably depends on HCLK for a given platform, so we may need to
- * require HCLK be passed to us from the MFD core.
- *
- */
-
static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
{
void __iomem *cnf = host->cnf;
void __iomem *ctl = host->ctl;
- u32 clk = 0, clock;
+ u32 clk = 0, clock, f_min = host->mmc->f_min;

if (new_clock) {
- for (clock = 46875, clk = 0x100; new_clock >= (clock<<1); ) {
+ for (clock = f_min, clk = 0x100; new_clock >= (clock<<1); ) {
clock <<= 1;
clk >>= 1;
}
@@ -545,6 +536,7 @@ out:
static int __devinit tmio_mmc_probe(struct platform_device *dev)
{
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
+ struct tmio_mmc_data *pdata;
struct resource *res_ctl, *res_cnf;
struct tmio_mmc_host *host;
struct mmc_host *mmc;
@@ -560,6 +552,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
goto out;
}

+ pdata = cell->driver_data;
+ if (!pdata || !pdata->hclk) {
+ ret = -EINVAL;
+ goto out;
+ }
+
mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
if (!mmc)
goto out;
@@ -578,8 +576,8 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)

mmc->ops = &tmio_mmc_ops;
mmc->caps = MMC_CAP_4_BIT_DATA;
- mmc->f_min = 46875; /* 24000000 / 512 */
- mmc->f_max = 24000000;
+ mmc->f_max = pdata->hclk;
+ mmc->f_min = mmc->f_max / 512;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;

/* Enable the MMC/SD Control registers */
diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
index 516d955..c377118 100644
--- a/include/linux/mfd/tmio.h
+++ b/include/linux/mfd/tmio.h
@@ -19,6 +19,13 @@
} while (0)

/*
+ * data for the MMC controller
+ */
+struct tmio_mmc_data {
+ unsigned int hclk;
+};
+
+/*
* data for the NAND controller
*/
struct tmio_nand_data {
--
1.6.3.1

2009-06-04 18:12:41

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 2/7] mmc: tmio_mmc: add bus_shift support

Some ASIC3 devices in the wild are connected with the address bus shifted
by one line, so that its 16-bit registers appear 32-bit aligned in host
memory space.

Signed-off-by: Philipp Zabel <[email protected]>
Acked-by: Ian Molton <[email protected]>
Cc: Pierre Ossman <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 129 +++++++++++++++++++------------------------
drivers/mmc/host/tmio_mmc.h | 77 ++++++++++++++++++++++---
2 files changed, 125 insertions(+), 81 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 49df71e..01add9b 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -37,8 +37,6 @@

static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
{
- void __iomem *cnf = host->cnf;
- void __iomem *ctl = host->ctl;
u32 clk = 0, clock, f_min = host->mmc->f_min;

if (new_clock) {
@@ -50,45 +48,39 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
clk = 0x20000;

clk >>= 2;
- tmio_iowrite8((clk & 0x8000) ? 0 : 1, cnf + CNF_SD_CLK_MODE);
+ sd_config_write8(host, CNF_SD_CLK_MODE, (clk & 0x8000) ? 0 : 1);
clk |= 0x100;
}

- tmio_iowrite16(clk, ctl + CTL_SD_CARD_CLK_CTL);
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk);
}

static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
{
- void __iomem *ctl = host->ctl;
-
- tmio_iowrite16(0x0000, ctl + CTL_CLK_AND_WAIT_CTL);
+ sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
msleep(10);
- tmio_iowrite16(tmio_ioread16(ctl + CTL_SD_CARD_CLK_CTL) & ~0x0100,
- ctl + CTL_SD_CARD_CLK_CTL);
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
msleep(10);
}

static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
{
- void __iomem *ctl = host->ctl;
-
- tmio_iowrite16(tmio_ioread16(ctl + CTL_SD_CARD_CLK_CTL) | 0x0100,
- ctl + CTL_SD_CARD_CLK_CTL);
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
+ sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
msleep(10);
- tmio_iowrite16(0x0100, ctl + CTL_CLK_AND_WAIT_CTL);
+ sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
msleep(10);
}

static void reset(struct tmio_mmc_host *host)
{
- void __iomem *ctl = host->ctl;
-
/* FIXME - should we set stop clock reg here */
- tmio_iowrite16(0x0000, ctl + CTL_RESET_SD);
- tmio_iowrite16(0x0000, ctl + CTL_RESET_SDIO);
+ sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
+ sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
msleep(10);
- tmio_iowrite16(0x0001, ctl + CTL_RESET_SD);
- tmio_iowrite16(0x0001, ctl + CTL_RESET_SDIO);
+ sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
+ sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
msleep(10);
}

@@ -120,13 +112,12 @@ tmio_mmc_finish_request(struct tmio_mmc_host *host)
static int
tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
{
- void __iomem *ctl = host->ctl;
struct mmc_data *data = host->data;
int c = cmd->opcode;

/* Command 12 is handled by hardware */
if (cmd->opcode == 12 && !cmd->arg) {
- tmio_iowrite16(0x001, ctl + CTL_STOP_INTERNAL_ACTION);
+ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
return 0;
}

@@ -151,18 +142,18 @@ tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
if (data) {
c |= DATA_PRESENT;
if (data->blocks > 1) {
- tmio_iowrite16(0x100, ctl + CTL_STOP_INTERNAL_ACTION);
+ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
c |= TRANSFER_MULTI;
}
if (data->flags & MMC_DATA_READ)
c |= TRANSFER_READ;
}

- enable_mmc_irqs(ctl, TMIO_MASK_CMD);
+ enable_mmc_irqs(host, TMIO_MASK_CMD);

/* Fire off the command */
- tmio_iowrite32(cmd->arg, ctl + CTL_ARG_REG);
- tmio_iowrite16(c, ctl + CTL_SD_CMD);
+ sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
+ sd_ctrl_write16(host, CTL_SD_CMD, c);

return 0;
}
@@ -174,7 +165,6 @@ tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
*/
static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
{
- void __iomem *ctl = host->ctl;
struct mmc_data *data = host->data;
unsigned short *buf;
unsigned int count;
@@ -197,9 +187,9 @@ static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)

/* Transfer the data */
if (data->flags & MMC_DATA_READ)
- tmio_ioread16_rep(ctl + CTL_SD_DATA_PORT, buf, count >> 1);
+ sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
else
- tmio_iowrite16_rep(ctl + CTL_SD_DATA_PORT, buf, count >> 1);
+ sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);

host->sg_off += count;

@@ -213,7 +203,6 @@ static inline void tmio_mmc_pio_irq(struct tmio_mmc_host *host)

static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
{
- void __iomem *ctl = host->ctl;
struct mmc_data *data = host->data;
struct mmc_command *stop;

@@ -242,13 +231,13 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
*/

if (data->flags & MMC_DATA_READ)
- disable_mmc_irqs(ctl, TMIO_MASK_READOP);
+ disable_mmc_irqs(host, TMIO_MASK_READOP);
else
- disable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
+ disable_mmc_irqs(host, TMIO_MASK_WRITEOP);

if (stop) {
if (stop->opcode == 12 && !stop->arg)
- tmio_iowrite16(0x000, ctl + CTL_STOP_INTERNAL_ACTION);
+ sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
else
BUG();
}
@@ -259,9 +248,8 @@ static inline void tmio_mmc_data_irq(struct tmio_mmc_host *host)
static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
unsigned int stat)
{
- void __iomem *ctl = host->ctl, *addr;
struct mmc_command *cmd = host->cmd;
- int i;
+ int i, addr;

if (!host->cmd) {
pr_debug("Spurious CMD irq\n");
@@ -275,8 +263,8 @@ static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
* modify the order of the response for short response command types.
*/

- for (i = 3, addr = ctl + CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
- cmd->resp[i] = tmio_ioread32(addr);
+ for (i = 3, addr = CTL_RESPONSE ; i >= 0 ; i--, addr += 4)
+ cmd->resp[i] = sd_ctrl_read32(host, addr);

if (cmd->flags & MMC_RSP_136) {
cmd->resp[0] = (cmd->resp[0] << 8) | (cmd->resp[1] >> 24);
@@ -298,9 +286,9 @@ static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
*/
if (host->data && !cmd->error) {
if (host->data->flags & MMC_DATA_READ)
- enable_mmc_irqs(ctl, TMIO_MASK_READOP);
+ enable_mmc_irqs(host, TMIO_MASK_READOP);
else
- enable_mmc_irqs(ctl, TMIO_MASK_WRITEOP);
+ enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
} else {
tmio_mmc_finish_request(host);
}
@@ -312,20 +300,19 @@ static inline void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
static irqreturn_t tmio_mmc_irq(int irq, void *devid)
{
struct tmio_mmc_host *host = devid;
- void __iomem *ctl = host->ctl;
unsigned int ireg, irq_mask, status;

pr_debug("MMC IRQ begin\n");

- status = tmio_ioread32(ctl + CTL_STATUS);
- irq_mask = tmio_ioread32(ctl + CTL_IRQ_MASK);
+ status = sd_ctrl_read32(host, CTL_STATUS);
+ irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
ireg = status & TMIO_MASK_IRQ & ~irq_mask;

pr_debug_status(status);
pr_debug_status(ireg);

if (!ireg) {
- disable_mmc_irqs(ctl, status & ~irq_mask);
+ disable_mmc_irqs(host, status & ~irq_mask);

pr_debug("tmio_mmc: Spurious irq, disabling! "
"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
@@ -337,7 +324,7 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid)
while (ireg) {
/* Card insert / remove attempts */
if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
- ack_mmc_irqs(ctl, TMIO_STAT_CARD_INSERT |
+ ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
TMIO_STAT_CARD_REMOVE);
mmc_detect_change(host->mmc, 0);
}
@@ -349,25 +336,25 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid)

/* Command completion */
if (ireg & TMIO_MASK_CMD) {
- ack_mmc_irqs(ctl, TMIO_MASK_CMD);
+ ack_mmc_irqs(host, TMIO_MASK_CMD);
tmio_mmc_cmd_irq(host, status);
}

/* Data transfer */
if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
- ack_mmc_irqs(ctl, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
+ ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
tmio_mmc_pio_irq(host);
}

/* Data transfer completion */
if (ireg & TMIO_STAT_DATAEND) {
- ack_mmc_irqs(ctl, TMIO_STAT_DATAEND);
+ ack_mmc_irqs(host, TMIO_STAT_DATAEND);
tmio_mmc_data_irq(host);
}

/* Check status - keep going until we've handled it all */
- status = tmio_ioread32(ctl + CTL_STATUS);
- irq_mask = tmio_ioread32(ctl + CTL_IRQ_MASK);
+ status = sd_ctrl_read32(host, CTL_STATUS);
+ irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
ireg = status & TMIO_MASK_IRQ & ~irq_mask;

pr_debug("Status at end of loop: %08x\n", status);
@@ -382,8 +369,6 @@ out:
static int tmio_mmc_start_data(struct tmio_mmc_host *host,
struct mmc_data *data)
{
- void __iomem *ctl = host->ctl;
-
pr_debug("setup data transfer: blocksize %08x nr_blocks %d\n",
data->blksz, data->blocks);

@@ -398,8 +383,8 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host,
host->data = data;

/* Set transfer length / blocksize */
- tmio_iowrite16(data->blksz, ctl + CTL_SD_XFER_LEN);
- tmio_iowrite16(data->blocks, ctl + CTL_XFER_BLK_COUNT);
+ sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
+ sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);

return 0;
}
@@ -440,8 +425,6 @@ fail:
static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- void __iomem *cnf = host->cnf;
- void __iomem *ctl = host->ctl;

if (ios->clock)
tmio_mmc_set_clock(host, ios->clock);
@@ -449,12 +432,12 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* Power sequence - OFF -> ON -> UP */
switch (ios->power_mode) {
case MMC_POWER_OFF: /* power down SD bus */
- tmio_iowrite8(0x00, cnf + CNF_PWR_CTL_2);
+ sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
tmio_mmc_clk_stop(host);
break;
case MMC_POWER_ON: /* power up SD bus */

- tmio_iowrite8(0x02, cnf + CNF_PWR_CTL_2);
+ sd_config_write8(host, CNF_PWR_CTL_2, 0x02);
break;
case MMC_POWER_UP: /* start bus clock */
tmio_mmc_clk_start(host);
@@ -463,10 +446,10 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)

switch (ios->bus_width) {
case MMC_BUS_WIDTH_1:
- tmio_iowrite16(0x80e0, ctl + CTL_SD_MEM_CARD_OPT);
+ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
break;
case MMC_BUS_WIDTH_4:
- tmio_iowrite16(0x00e0, ctl + CTL_SD_MEM_CARD_OPT);
+ sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
break;
}

@@ -477,9 +460,8 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
static int tmio_mmc_get_ro(struct mmc_host *mmc)
{
struct tmio_mmc_host *host = mmc_priv(mmc);
- void __iomem *ctl = host->ctl;

- return (tmio_ioread16(ctl + CTL_STATUS) & TMIO_STAT_WRPROTECT) ? 0 : 1;
+ return (sd_ctrl_read16(host, CTL_STATUS) & TMIO_STAT_WRPROTECT) ? 0 : 1;
}

static struct mmc_host_ops tmio_mmc_ops = {
@@ -509,12 +491,12 @@ static int tmio_mmc_resume(struct platform_device *dev)
struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
struct mmc_host *mmc = platform_get_drvdata(dev);
struct tmio_mmc_host *host = mmc_priv(mmc);
- void __iomem *cnf = host->cnf;
int ret = 0;

/* Enable the MMC/SD Control registers */
- tmio_iowrite16(SDCREN, cnf + CNF_CMD);
- tmio_iowrite32(dev->resource[0].start & 0xfffe, cnf + CNF_CTL_BASE);
+ sd_config_write16(host, CNF_CMD, SDCREN);
+ sd_config_write32(host, CNF_CTL_BASE,
+ (dev->resource[0].start >> host->bus_shift) & 0xfffe);

/* Tell the MFD core we are ready to be enabled */
if (cell->enable) {
@@ -566,6 +548,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
host->mmc = mmc;
platform_set_drvdata(dev, mmc);

+ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
+ host->bus_shift = resource_size(res_ctl) >> 10;
+
host->ctl = ioremap(res_ctl->start, resource_size(res_ctl));
if (!host->ctl)
goto host_free;
@@ -581,9 +566,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;

/* Enable the MMC/SD Control registers */
- tmio_iowrite16(SDCREN, host->cnf + CNF_CMD);
- tmio_iowrite32(dev->resource[0].start & 0xfffe,
- host->cnf + CNF_CTL_BASE);
+ sd_config_write16(host, CNF_CMD, SDCREN);
+ sd_config_write32(host, CNF_CTL_BASE,
+ (dev->resource[0].start >> host->bus_shift) & 0xfffe);

/* Tell the MFD core we are ready to be enabled */
if (cell->enable) {
@@ -593,13 +578,13 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
}

/* Disable SD power during suspend */
- tmio_iowrite8(0x01, host->cnf + CNF_PWR_CTL_3);
+ sd_config_write8(host, CNF_PWR_CTL_3, 0x01);

/* The below is required but why? FIXME */
- tmio_iowrite8(0x1f, host->cnf + CNF_STOP_CLK_CTL);
+ sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f);

/* Power down SD bus*/
- tmio_iowrite8(0x0, host->cnf + CNF_PWR_CTL_2);
+ sd_config_write8(host, CNF_PWR_CTL_2, 0x00);

tmio_mmc_clk_stop(host);
reset(host);
@@ -610,7 +595,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
else
goto unmap_cnf;

- disable_mmc_irqs(host->ctl, TMIO_MASK_ALL);
+ disable_mmc_irqs(host, TMIO_MASK_ALL);

ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED, "tmio-mmc",
host);
@@ -625,7 +610,7 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
(unsigned long)host->ctl, host->irq);

/* Unmask the IRQs we want to know about */
- enable_mmc_irqs(host->ctl, TMIO_MASK_IRQ);
+ enable_mmc_irqs(host, TMIO_MASK_IRQ);

return 0;

diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 9c831ab..9fa9985 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -83,34 +83,36 @@
TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
#define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)

-#define enable_mmc_irqs(ctl, i) \
+
+#define enable_mmc_irqs(host, i) \
do { \
u32 mask;\
- mask = tmio_ioread32((ctl) + CTL_IRQ_MASK); \
+ mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \
mask &= ~((i) & TMIO_MASK_IRQ); \
- tmio_iowrite32(mask, (ctl) + CTL_IRQ_MASK); \
+ sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
} while (0)

-#define disable_mmc_irqs(ctl, i) \
+#define disable_mmc_irqs(host, i) \
do { \
u32 mask;\
- mask = tmio_ioread32((ctl) + CTL_IRQ_MASK); \
+ mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \
mask |= ((i) & TMIO_MASK_IRQ); \
- tmio_iowrite32(mask, (ctl) + CTL_IRQ_MASK); \
+ sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
} while (0)

-#define ack_mmc_irqs(ctl, i) \
+#define ack_mmc_irqs(host, i) \
do { \
u32 mask;\
- mask = tmio_ioread32((ctl) + CTL_STATUS); \
+ mask = sd_ctrl_read32((host), CTL_STATUS); \
mask &= ~((i) & TMIO_MASK_IRQ); \
- tmio_iowrite32(mask, (ctl) + CTL_STATUS); \
+ sd_ctrl_write32((host), CTL_STATUS, mask); \
} while (0)


struct tmio_mmc_host {
void __iomem *cnf;
void __iomem *ctl;
+ unsigned long bus_shift;
struct mmc_command *cmd;
struct mmc_request *mrq;
struct mmc_data *data;
@@ -123,6 +125,63 @@ struct tmio_mmc_host {
unsigned int sg_off;
};

+#include <linux/io.h>
+
+static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+ return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
+ u16 *buf, int count)
+{
+ readsw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr)
+{
+ return readw(host->ctl + (addr << host->bus_shift)) |
+ readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16;
+}
+
+static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr,
+ u16 val)
+{
+ writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
+ u16 *buf, int count)
+{
+ writesw(host->ctl + (addr << host->bus_shift), buf, count);
+}
+
+static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr,
+ u32 val)
+{
+ writew(val, host->ctl + (addr << host->bus_shift));
+ writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
+}
+
+static inline void sd_config_write8(struct tmio_mmc_host *host, int addr,
+ u8 val)
+{
+ writeb(val, host->cnf + (addr << host->bus_shift));
+}
+
+static inline void sd_config_write16(struct tmio_mmc_host *host, int addr,
+ u16 val)
+{
+ writew(val, host->cnf + (addr << host->bus_shift));
+}
+
+static inline void sd_config_write32(struct tmio_mmc_host *host, int addr,
+ u32 val)
+{
+ writew(val, host->cnf + (addr << host->bus_shift));
+ writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift));
+}
+
#include <linux/scatterlist.h>
#include <linux/blkdev.h>

--
1.6.3.1

2009-06-04 18:13:00

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 3/7] mmc: tmio_mmc: don't use set_irq_type (v2)

Use an IRQF_TRIGGER_ flag in request_irq instead.

Signed-off-by: Philipp Zabel <[email protected]>
Acked-by: Ian Molton <[email protected]>
Cc: Pierre Ossman <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 01add9b..bbcbd72 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -597,13 +597,11 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)

disable_mmc_irqs(host, TMIO_MASK_ALL);

- ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED, "tmio-mmc",
- host);
+ ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
+ IRQF_TRIGGER_FALLING, "tmio-mmc", host);
if (ret)
goto unmap_cnf;

- set_irq_type(host->irq, IRQ_TYPE_EDGE_FALLING);
-
mmc_add_host(mmc);

printk(KERN_INFO "%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
--
1.6.3.1

2009-06-04 18:13:32

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 4/7] mmc: tmio_mmc: correct probe return value for num_resources != 3

Signed-off-by: Philipp Zabel <[email protected]>
Acked-by: Ian Molton <[email protected]>
Cc: Pierre Ossman <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index bbcbd72..b576640 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -522,23 +522,21 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
struct resource *res_ctl, *res_cnf;
struct tmio_mmc_host *host;
struct mmc_host *mmc;
- int ret = -ENOMEM;
+ int ret = -EINVAL;

if (dev->num_resources != 3)
goto out;

res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1);
- if (!res_ctl || !res_cnf) {
- ret = -EINVAL;
+ if (!res_ctl || !res_cnf)
goto out;
- }

pdata = cell->driver_data;
- if (!pdata || !pdata->hclk) {
- ret = -EINVAL;
+ if (!pdata || !pdata->hclk)
goto out;
- }
+
+ ret = -ENOMEM;

mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
if (!mmc)
--
1.6.3.1

2009-06-04 18:14:21

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 7/7] mmc: tmio_mmc: allow compilation for ASIC3

Now tmio_mmc is able to drive the MMC/SD cell in ASIC3.

Signed-off-by: Philipp Zabel <[email protected]>
Cc: Pierre Ossman <[email protected]>
Cc: Ian Molton <[email protected]>
---
drivers/mmc/host/Kconfig | 4 ++--
drivers/mmc/host/tmio_mmc.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index b4cf691..9aae7f5 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -237,7 +237,7 @@ config MMC_SDRICOH_CS

config MMC_TMIO
tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
- depends on MFD_TMIO
+ depends on MFD_TMIO || MFD_ASIC3
help
This provides support for the SD/MMC cell found in TC6393XB,
- T7L66XB and also ipaq ASIC3
+ T7L66XB and also HTC ASIC3.
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 9f6e180..9f68c2f 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -10,7 +10,7 @@
*
* Driver for the MMC / SD / SDIO cell found in:
*
- * TC6393XB TC6391XB TC6387XB T7L66XB
+ * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
*
* This driver draws mainly on scattered spec sheets, Reverse engineering
* of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit
--
1.6.3.1

2009-06-04 18:13:56

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 6/7] mmc: tmio_mmc: fix SDCLK divider setting

Except for the SDCLK = HCLK (divider bypassed) case, the clock
setting resulted in double the requested frequency.
The smallest possible frequency (f_max/512) is configured with
a divider setting 0x80, not 0x40.

Signed-off-by: Philipp Zabel <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index fe6d2b6..9f6e180 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -44,10 +44,10 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
clock <<= 1;
clk >>= 1;
}
- if (clk & 0x1)
- clk = 0x20000;
+ if (clk == 0)
+ clk = 0x8000 << 1;

- clk >>= 2;
+ clk >>= 1;
sd_config_write8(host, CNF_SD_CLK_MODE, (clk & 0x8000) ? 0 : 1);
clk |= 0x100;
}
--
1.6.3.1

2009-06-04 18:13:43

by Philipp Zabel

[permalink] [raw]
Subject: [PATCH 5/7] mmc: tmio_mmc: map SD control registers after enabling the MFD cell

ASIC3 can disable the memory, so we need to wait for mfd_cell->enable
to enable the memory before we can map the SD control registers.

Signed-off-by: Philipp Zabel <[email protected]>
Cc: Pierre Ossman <[email protected]>
Cc: Ian Molton <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index b576640..fe6d2b6 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -493,11 +493,6 @@ static int tmio_mmc_resume(struct platform_device *dev)
struct tmio_mmc_host *host = mmc_priv(mmc);
int ret = 0;

- /* Enable the MMC/SD Control registers */
- sd_config_write16(host, CNF_CMD, SDCREN);
- sd_config_write32(host, CNF_CTL_BASE,
- (dev->resource[0].start >> host->bus_shift) & 0xfffe);
-
/* Tell the MFD core we are ready to be enabled */
if (cell->enable) {
ret = cell->enable(dev);
@@ -505,6 +500,11 @@ static int tmio_mmc_resume(struct platform_device *dev)
goto out;
}

+ /* Enable the MMC/SD Control registers */
+ sd_config_write16(host, CNF_CMD, SDCREN);
+ sd_config_write32(host, CNF_CTL_BASE,
+ (dev->resource[0].start >> host->bus_shift) & 0xfffe);
+
mmc_resume_host(mmc);

out:
@@ -563,11 +563,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
mmc->f_min = mmc->f_max / 512;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;

- /* Enable the MMC/SD Control registers */
- sd_config_write16(host, CNF_CMD, SDCREN);
- sd_config_write32(host, CNF_CTL_BASE,
- (dev->resource[0].start >> host->bus_shift) & 0xfffe);
-
/* Tell the MFD core we are ready to be enabled */
if (cell->enable) {
ret = cell->enable(dev);
@@ -575,6 +570,11 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
goto unmap_cnf;
}

+ /* Enable the MMC/SD Control registers */
+ sd_config_write16(host, CNF_CMD, SDCREN);
+ sd_config_write32(host, CNF_CTL_BASE,
+ (dev->resource[0].start >> host->bus_shift) & 0xfffe);
+
/* Disable SD power during suspend */
sd_config_write8(host, CNF_PWR_CTL_3, 0x01);

--
1.6.3.1

2009-06-04 22:53:26

by Samuel Ortiz

[permalink] [raw]
Subject: Re: [PATCH 1/7] MFD,mmc: tmio_mmc: make HCLK configurable

Hi Philip,

On Thu, Jun 04, 2009 at 08:12:31PM +0200, Philipp Zabel wrote:
> The Toshiba parts all have a 24 MHz HCLK, but HTC ASIC3 has a 24.576 MHz HCLK
> and AMD Imageon w228x's HCLK is 80 MHz. With this patch, the MFD driver
> provides the HCLK frequency to tmio_mmc via mfd_cell->driver_data.
Applied to my for-next branch, many thanks.


> Signed-off-by: Philipp Zabel <[email protected]>
> Acked-by: Ian Molton <[email protected]>
> Cc: Samuel Ortiz <[email protected]>
> Cc: Pierre Ossman <[email protected]>
> ---
> drivers/mfd/t7l66xb.c | 5 +++++
> drivers/mfd/tc6387xb.c | 5 +++++
> drivers/mfd/tc6393xb.c | 5 +++++
> drivers/mmc/host/tmio_mmc.c | 24 +++++++++++-------------
> include/linux/mfd/tmio.h | 7 +++++++
> 5 files changed, 33 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c
> index e9f4323..875f7a8 100644
> --- a/drivers/mfd/t7l66xb.c
> +++ b/drivers/mfd/t7l66xb.c
> @@ -108,6 +108,10 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
>
> /*--------------------------------------------------------------------------*/
>
> +static const struct tmio_mmc_data t7166xb_mmc_data = {
> + .hclk = 24000000,
> +};
> +
> static const struct resource t7l66xb_mmc_resources[] = {
> {
> .start = 0x800,
> @@ -149,6 +153,7 @@ static struct mfd_cell t7l66xb_cells[] = {
> .name = "tmio-mmc",
> .enable = t7l66xb_mmc_enable,
> .disable = t7l66xb_mmc_disable,
> + .driver_data = &t7166xb_mmc_data,
> .num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
> .resources = t7l66xb_mmc_resources,
> },
> diff --git a/drivers/mfd/tc6387xb.c b/drivers/mfd/tc6387xb.c
> index 43222c1..c3993ac 100644
> --- a/drivers/mfd/tc6387xb.c
> +++ b/drivers/mfd/tc6387xb.c
> @@ -75,6 +75,10 @@ static int tc6387xb_mmc_disable(struct platform_device *mmc)
>
> /*--------------------------------------------------------------------------*/
>
> +const static struct tmio_mmc_data tc6387xb_mmc_data = {
> + .hclk = 24000000,
> +};
> +
> static struct resource tc6387xb_mmc_resources[] = {
> {
> .start = 0x800,
> @@ -98,6 +102,7 @@ static struct mfd_cell tc6387xb_cells[] = {
> .name = "tmio-mmc",
> .enable = tc6387xb_mmc_enable,
> .disable = tc6387xb_mmc_disable,
> + .driver_data = &tc6387xb_mmc_data,
> .num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
> .resources = tc6387xb_mmc_resources,
> },
> diff --git a/drivers/mfd/tc6393xb.c b/drivers/mfd/tc6393xb.c
> index 77a12fc..9d2abb5 100644
> --- a/drivers/mfd/tc6393xb.c
> +++ b/drivers/mfd/tc6393xb.c
> @@ -136,6 +136,10 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
> return 0;
> }
>
> +const static struct tmio_mmc_data tc6393xb_mmc_data = {
> + .hclk = 24000000,
> +};
> +
> static struct resource __devinitdata tc6393xb_nand_resources[] = {
> {
> .start = 0x1000,
> @@ -351,6 +355,7 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
> },
> [TC6393XB_CELL_MMC] = {
> .name = "tmio-mmc",
> + .driver_data = &tc6393xb_mmc_data,
> .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
> .resources = tc6393xb_mmc_resources,
> },
> diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
> index 63fbd5b..49df71e 100644
> --- a/drivers/mmc/host/tmio_mmc.c
> +++ b/drivers/mmc/host/tmio_mmc.c
> @@ -35,23 +35,14 @@
>
> #include "tmio_mmc.h"
>
> -/*
> - * Fixme - documentation conflicts on what the clock values are for the
> - * various dividers.
> - * One document I have says that its a divisor of a 24MHz clock, another 33.
> - * This probably depends on HCLK for a given platform, so we may need to
> - * require HCLK be passed to us from the MFD core.
> - *
> - */
> -
> static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
> {
> void __iomem *cnf = host->cnf;
> void __iomem *ctl = host->ctl;
> - u32 clk = 0, clock;
> + u32 clk = 0, clock, f_min = host->mmc->f_min;
>
> if (new_clock) {
> - for (clock = 46875, clk = 0x100; new_clock >= (clock<<1); ) {
> + for (clock = f_min, clk = 0x100; new_clock >= (clock<<1); ) {
> clock <<= 1;
> clk >>= 1;
> }
> @@ -545,6 +536,7 @@ out:
> static int __devinit tmio_mmc_probe(struct platform_device *dev)
> {
> struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
> + struct tmio_mmc_data *pdata;
> struct resource *res_ctl, *res_cnf;
> struct tmio_mmc_host *host;
> struct mmc_host *mmc;
> @@ -560,6 +552,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
> goto out;
> }
>
> + pdata = cell->driver_data;
> + if (!pdata || !pdata->hclk) {
> + ret = -EINVAL;
> + goto out;
> + }
> +
> mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
> if (!mmc)
> goto out;
> @@ -578,8 +576,8 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
>
> mmc->ops = &tmio_mmc_ops;
> mmc->caps = MMC_CAP_4_BIT_DATA;
> - mmc->f_min = 46875; /* 24000000 / 512 */
> - mmc->f_max = 24000000;
> + mmc->f_max = pdata->hclk;
> + mmc->f_min = mmc->f_max / 512;
> mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
>
> /* Enable the MMC/SD Control registers */
> diff --git a/include/linux/mfd/tmio.h b/include/linux/mfd/tmio.h
> index 516d955..c377118 100644
> --- a/include/linux/mfd/tmio.h
> +++ b/include/linux/mfd/tmio.h
> @@ -19,6 +19,13 @@
> } while (0)
>
> /*
> + * data for the MMC controller
> + */
> +struct tmio_mmc_data {
> + unsigned int hclk;
> +};
> +
> +/*
> * data for the NAND controller
> */
> struct tmio_nand_data {
> --
> 1.6.3.1
>

--
Intel Open Source Technology Centre
http://oss.intel.com/

2009-06-12 21:36:42

by Ian molton

[permalink] [raw]
Subject: Re: [PATCH 5/7] mmc: tmio_mmc: map SD control registers after enabling the MFD cell

Philipp Zabel wrote:
> ASIC3 can disable the memory, so we need to wait for mfd_cell->enable
> to enable the memory before we can map the SD control registers.
>
> Signed-off-by: Philipp Zabel <[email protected]>
> Cc: Pierre Ossman <[email protected]>

Acked-by: Ian Molton <[email protected]>

2009-06-12 21:44:39

by Ian Molton

[permalink] [raw]
Subject: Re: [PATCH 6/7] mmc: tmio_mmc: fix SDCLK divider setting

Philipp Zabel wrote:
> Except for the SDCLK = HCLK (divider bypassed) case, the clock
> setting resulted in double the requested frequency.
> The smallest possible frequency (f_max/512) is configured with
> a divider setting 0x80, not 0x40.

I have (IMO) a better fix, which also removes some crap being written to
CTL_SD_CARD_CLK_CTL.

Pierre, please replace patch 6/7 from Philips set with this one.

From e69efa520b07a688643ce5f8e8d41bef753ff1ed Mon Sep 17 00:00:00 2001
From: Ian Molton <[email protected]>
Date: Fri, 12 Jun 2009 21:53:05 +0100
Subject: [PATCH] MMC: fix clock setup in tmio_mmc

This patch fixes the clock setup in tmio_mmc.

* Incorrect divider setting
* Cruft written to the clock registers (seemingly harmless but Not
Good (tm))

It also eliminates some unnecessary ifs and tidies the loop syntax.

Thanks to Philipp Zabel who discovered the divider issue, commenting

"Except for the SDCLK = HCLK (divider bypassed) case, the clock
setting resulted in double the requested frequency.
The smallest possible frequency (f_max/512) is configured with
a divider setting 0x80, not 0x40."

Signed-off-by: Ian Molton <[email protected]>
---
drivers/mmc/host/tmio_mmc.c | 15 +++++----------
1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index fe6d2b6..10951b7 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -37,22 +37,17 @@

static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
{
- u32 clk = 0, clock, f_min = host->mmc->f_min;
+ u32 clk = 0, clock;

if (new_clock) {
- for (clock = f_min, clk = 0x100; new_clock >= (clock<<1); ) {
+ for (clock = host->mmc->f_min, clk = 0x80000080;
+ new_clock >= (clock<<1); clk >>= 1)
clock <<= 1;
- clk >>= 1;
- }
- if (clk & 0x1)
- clk = 0x20000;
-
- clk >>= 2;
- sd_config_write8(host, CNF_SD_CLK_MODE, (clk & 0x8000) ? 0 : 1);
clk |= 0x100;
}

- sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk);
+ sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22);
+ sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
}

static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
--
1.6.3.1

2009-06-12 21:47:29

by Ian molton

[permalink] [raw]
Subject: Re: [PATCH 7/7] mmc: tmio_mmc: allow compilation for ASIC3

Does this patch actually _do_ anything? wont the asic3 driver need
modifying to use tmio_mmc before this patch is useful?

Is the idea that this patch go in and asic3 MFDs migrate gradually?

If so then I'll ack it.

Philipp Zabel wrote:
> Now tmio_mmc is able to drive the MMC/SD cell in ASIC3.
>
> Signed-off-by: Philipp Zabel <[email protected]>
> Cc: Pierre Ossman <[email protected]>
> Cc: Ian Molton <[email protected]>
> ---
> drivers/mmc/host/Kconfig | 4 ++--
> drivers/mmc/host/tmio_mmc.c | 2 +-
> 2 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
> index b4cf691..9aae7f5 100644
> --- a/drivers/mmc/host/Kconfig
> +++ b/drivers/mmc/host/Kconfig
> @@ -237,7 +237,7 @@ config MMC_SDRICOH_CS
>
> config MMC_TMIO
> tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
> - depends on MFD_TMIO
> + depends on MFD_TMIO || MFD_ASIC3
> help
> This provides support for the SD/MMC cell found in TC6393XB,
> - T7L66XB and also ipaq ASIC3
> + T7L66XB and also HTC ASIC3.
> diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
> index 9f6e180..9f68c2f 100644
> --- a/drivers/mmc/host/tmio_mmc.c
> +++ b/drivers/mmc/host/tmio_mmc.c
> @@ -10,7 +10,7 @@
> *
> * Driver for the MMC / SD / SDIO cell found in:
> *
> - * TC6393XB TC6391XB TC6387XB T7L66XB
> + * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
> *
> * This driver draws mainly on scattered spec sheets, Reverse engineering
> * of the toshiba e800 SD driver and some parts of the 2.4 ASIC3 driver (4 bit

2009-06-12 22:39:00

by Philipp Zabel

[permalink] [raw]
Subject: Re: [PATCH 7/7] mmc: tmio_mmc: allow compilation for ASIC3

On Fri, Jun 12, 2009 at 11:47 PM, Ian molton<[email protected]> wrote:
> Does this patch actually _do_ anything? wont the asic3 driver need modifying
> to use tmio_mmc before this patch is useful?

That's right, this patch only allows tmio-mmc to be compiled on ASIC3
based devices. The needed changes to ASIC3
(http://patchwork.kernel.org/patch/28000/ et al) are queued in the MFD
tree.

> Is the idea that this patch go in and asic3 MFDs migrate gradually?

The idea was that this patch is applied after tmio-mmc is ASIC3-ready,
so that it doesn't matter whether the MFD or MMC tree gets merged
first. If the ASIC3 MFD changes come first, at least tmio-mmc won't be
built (for CONFIG_MFD_ASIC3) until the tmio-mmc modifications are in.

> If so then I'll ack it.
>
> Philipp Zabel wrote:
>>
>> Now tmio_mmc is able to drive the MMC/SD cell in ASIC3.
>>
>> Signed-off-by: Philipp Zabel <[email protected]>
>> Cc: Pierre Ossman <[email protected]>
>> Cc: Ian Molton <[email protected]>
>> ---
>> ?drivers/mmc/host/Kconfig ? ?| ? ?4 ++--
>> ?drivers/mmc/host/tmio_mmc.c | ? ?2 +-
>> ?2 files changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
>> index b4cf691..9aae7f5 100644
>> --- a/drivers/mmc/host/Kconfig
>> +++ b/drivers/mmc/host/Kconfig
>> @@ -237,7 +237,7 @@ config MMC_SDRICOH_CS
>> ??config MMC_TMIO
>> ? ? ? ?tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function
>> support"
>> - ? ? ? depends on MFD_TMIO
>> + ? ? ? depends on MFD_TMIO || MFD_ASIC3
>> ? ? ? ?help
>> ? ? ? ? ?This provides support for the SD/MMC cell found in TC6393XB,
>> - ? ? ? ? T7L66XB and also ipaq ASIC3
>> + ? ? ? ? T7L66XB and also HTC ASIC3.
>> diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
>> index 9f6e180..9f68c2f 100644
>> --- a/drivers/mmc/host/tmio_mmc.c
>> +++ b/drivers/mmc/host/tmio_mmc.c
>> @@ -10,7 +10,7 @@
>> ?*
>> ?* Driver for the MMC / SD / SDIO cell found in:
>> ?*
>> - * TC6393XB TC6391XB TC6387XB T7L66XB
>> + * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
>> ?*
>> ?* This driver draws mainly on scattered spec sheets, Reverse engineering
>> ?* of the toshiba e800 ?SD driver and some parts of the 2.4 ASIC3 driver
>> (4 bit
>
>

regards
Philipp

2009-06-13 11:58:43

by Pierre Ossman

[permalink] [raw]
Subject: Re: [PATCH 0/7] ASIC3 support for tmio_mmc

On Thu, 4 Jun 2009 20:12:30 +0200
Philipp Zabel <[email protected]> wrote:

> I've broken the long lines in patches 1-3 and merged the fix into patch 2:
> [PATCH 1/7] MFD,mmc: tmio_mmc: make HCLK configurable (v2)
> [PATCH 2/7] mmc: tmio_mmc: add bus_shift support (v2)
> [PATCH 3/7] mmc: tmio_mmc: don't use set_irq_type (v2)
> [PATCH 4/7] mmc: tmio_mmc: correct probe return value for num_resources != 3
> Also I've added three new patches for your consideration. Patch 5 delays mapping
> of the SD control registers because mfd_cell->enable has to enable the RAM first.
> Patch 6 fixes a bug in the SDCLK divider calculation and patch 7 finally enables
> compilation of tmio_mmc for ASIC3:
> [PATCH 5/7] mmc: tmio_mmc: map SD control registers after enabling the MFD cell
> [PATCH 6/7] mmc: tmio_mmc: fix SDCLK divider setting
> [PATCH 7/7] mmc: tmio_mmc: allow compilation for ASIC3
>

I've queued up everything except patch 7 as I haven't seen Ian's
response on that yet.

Rgds
--
-- Pierre Ossman

WARNING: This correspondence is being monitored by the
Swedish government. Make sure your server uses encryption
for SMTP traffic and consider using PGP for end-to-end
encryption.


Attachments:
signature.asc (198.00 B)

2009-06-13 18:42:41

by Ian Molton

[permalink] [raw]
Subject: Re: [PATCH 0/7] ASIC3 support for tmio_mmc

Pierre Ossman wrote:

> I've queued up everything except patch 7 as I haven't seen Ian's
> response on that yet.

Is that using my replacement for patch 6 ? I didnt ack that one since
(whilst correct) My solution is simpler and fixes another bug as well.

Patch 7 is Acked-by me now that Philipp has explained the idea behind it.

2009-06-13 19:32:58

by Pierre Ossman

[permalink] [raw]
Subject: Re: [PATCH 0/7] ASIC3 support for tmio_mmc

On Sat, 13 Jun 2009 19:42:25 +0100
Ian Molton <[email protected]> wrote:

> Pierre Ossman wrote:
>
> > I've queued up everything except patch 7 as I haven't seen Ian's
> > response on that yet.
>
> Is that using my replacement for patch 6 ? I didnt ack that one since
> (whilst correct) My solution is simpler and fixes another bug as well.
>

I queued up your replacement, yes.

> Patch 7 is Acked-by me now that Philipp has explained the idea behind it.

Ok. I'll queue that up as well.

Rgds
--
-- Pierre Ossman

WARNING: This correspondence is being monitored by the
Swedish government. Make sure your server uses encryption
for SMTP traffic and consider using PGP for end-to-end
encryption.


Attachments:
signature.asc (198.00 B)

2009-06-13 19:58:10

by Ian Molton

[permalink] [raw]
Subject: Re: [PATCH 0/7] ASIC3 support for tmio_mmc

Pierre Ossman wrote:

> I queued up your replacement, yes.

Great,

>> Patch 7 is Acked-by me now that Philipp has explained the idea behind it.
>
> Ok. I'll queue that up as well.

Awesome, thanks,

-Ian