mfd: tmio_mmc hardware abstraction for CNF area

This patch abstracts out the CNF area code from tmio_mmc which
is not present in all hardware that can use this driver. This
is required so that we can support non-toshiba based hardware.

ASIC3 support by Philipp Zabel

Signed-off-by: Ian Molton <ian@mnementh.co.uk>
Signed-off-by: Magnus Damm <damm@opensource.se>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
This commit is contained in:
Ian Molton 2010-01-06 13:51:48 +01:00 committed by Samuel Ortiz
parent 6f2af72a24
commit 64e8867ba8
9 changed files with 324 additions and 150 deletions

View File

@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o

View File

@ -80,6 +80,7 @@ struct asic3 {
u16 irq_bothedge[4];
struct gpio_chip gpio;
struct device *dev;
void __iomem *tmio_cnf;
struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
};
@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = {
.resources = ds1wm_resources,
};
static void asic3_mmc_pwr(struct platform_device *pdev, int state)
{
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
tmio_core_mmc_pwr(asic->tmio_cnf, 1 - asic->bus_shift, state);
}
static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
{
struct asic3 *asic = dev_get_drvdata(pdev->dev.parent);
tmio_core_mmc_clk_div(asic->tmio_cnf, 1 - asic->bus_shift, state);
}
static struct tmio_mmc_data asic3_mmc_data = {
.hclk = 24576000,
.hclk = 24576000,
.set_pwr = asic3_mmc_pwr,
.set_clk_div = asic3_mmc_clk_div,
};
static struct resource asic3_mmc_resources[] = {
@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = {
.end = ASIC3_SD_CTRL_BASE + 0x3ff,
.flags = IORESOURCE_MEM,
},
{
.start = ASIC3_SD_CONFIG_BASE,
.end = ASIC3_SD_CONFIG_BASE + 0x1ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0,
.end = 0,
@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev)
asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
ASIC3_SDHWCTRL_SDPWR, 1);
/* ASIC3_SD_CTRL_BASE assumes 32-bit addressing, TMIO is 16-bit */
tmio_core_mmc_enable(asic->tmio_cnf, 1 - asic->bus_shift,
ASIC3_SD_CTRL_BASE >> 1);
return 0;
}
@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
/* MMC */
asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
mem_sdio->start, 0x400 >> asic->bus_shift);
if (!asic->tmio_cnf) {
ret = -ENOMEM;
dev_dbg(asic->dev, "Couldn't ioremap SD_CONFIG\n");
goto out;
}
asic3_mmc_resources[0].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= asic->bus_shift;
asic3_mmc_resources[1].start >>= asic->bus_shift;
asic3_mmc_resources[1].end >>= asic->bus_shift;
asic3_cell_mmc.platform_data = &asic3_cell_mmc;
asic3_cell_mmc.data_size = sizeof(asic3_cell_mmc);
@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
static void asic3_mfd_remove(struct platform_device *pdev)
{
struct asic3 *asic = platform_get_drvdata(pdev);
mfd_remove_devices(&pdev->dev);
iounmap(asic->tmio_cnf);
}
/* Core */

View File

@ -38,6 +38,19 @@ enum {
T7L66XB_CELL_MMC,
};
static const struct resource t7l66xb_mmc_resources[] = {
{
.start = 0x800,
.end = 0x9ff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_T7L66XB_MMC,
.end = IRQ_T7L66XB_MMC,
.flags = IORESOURCE_IRQ,
},
};
#define SCR_REVID 0x08 /* b Revision ID */
#define SCR_IMR 0x42 /* b Interrupt Mask */
#define SCR_DEV_CTL 0xe0 /* b Device control */
@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
spin_unlock_irqrestore(&t7l66xb->lock, flags);
tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
t7l66xb_mmc_resources[0].start & 0xfffe);
return 0;
}
@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
return 0;
}
static void t7l66xb_mmc_pwr(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
tmio_core_mmc_pwr(t7l66xb->scr + 0x200, 0, state);
}
static void t7l66xb_mmc_clk_div(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct t7l66xb *t7l66xb = platform_get_drvdata(dev);
tmio_core_mmc_clk_div(t7l66xb->scr + 0x200, 0, state);
}
/*--------------------------------------------------------------------------*/
static struct tmio_mmc_data t7166xb_mmc_data = {
.hclk = 24000000,
};
static const struct resource t7l66xb_mmc_resources[] = {
{
.start = 0x800,
.end = 0x9ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0x200,
.end = 0x2ff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_T7L66XB_MMC,
.end = IRQ_T7L66XB_MMC,
.flags = IORESOURCE_IRQ,
},
.set_pwr = t7l66xb_mmc_pwr,
.set_clk_div = t7l66xb_mmc_clk_div,
};
static const struct resource t7l66xb_nand_resources[] = {
@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev)
if (pdata && pdata->resume)
pdata->resume(dev);
tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
t7l66xb_mmc_resources[0].start & 0xfffe);
return 0;
}
#else

View File

@ -22,28 +22,52 @@ enum {
TC6387XB_CELL_MMC,
};
struct tc6387xb {
void __iomem *scr;
struct clk *clk32k;
struct resource rscr;
};
static struct resource tc6387xb_mmc_resources[] = {
{
.start = 0x800,
.end = 0x9ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0,
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
/*--------------------------------------------------------------------------*/
#ifdef CONFIG_PM
static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state)
{
struct clk *clk32k = platform_get_drvdata(dev);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
if (pdata && pdata->suspend)
pdata->suspend(dev);
clk_disable(clk32k);
clk_disable(tc6387xb->clk32k);
return 0;
}
static int tc6387xb_resume(struct platform_device *dev)
{
struct clk *clk32k = platform_get_drvdata(dev);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
clk_enable(clk32k);
clk_enable(tc6387xb->clk32k);
if (pdata && pdata->resume)
pdata->resume(dev);
tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0,
tc6387xb_mmc_resources[0].start & 0xfffe);
return 0;
}
#else
@ -53,12 +77,32 @@ static int tc6387xb_resume(struct platform_device *dev)
/*--------------------------------------------------------------------------*/
static void tc6387xb_mmc_pwr(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
tmio_core_mmc_pwr(tc6387xb->scr + 0x200, 0, state);
}
static void tc6387xb_mmc_clk_div(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
tmio_core_mmc_clk_div(tc6387xb->scr + 0x200, 0, state);
}
static int tc6387xb_mmc_enable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct clk *clk32k = platform_get_drvdata(dev);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
clk_enable(clk32k);
clk_enable(tc6387xb->clk32k);
tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
tc6387xb_mmc_resources[0].start & 0xfffe);
return 0;
}
@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
static int tc6387xb_mmc_disable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct clk *clk32k = platform_get_drvdata(dev);
struct tc6387xb *tc6387xb = platform_get_drvdata(dev);
clk_disable(clk32k);
clk_disable(tc6387xb->clk32k);
return 0;
}
/*--------------------------------------------------------------------------*/
static struct tmio_mmc_data tc6387xb_mmc_data = {
.hclk = 24000000,
.set_pwr = tc6387xb_mmc_pwr,
.set_clk_div = tc6387xb_mmc_clk_div,
};
static struct resource tc6387xb_mmc_resources[] = {
{
.start = 0x800,
.end = 0x9ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0x200,
.end = 0x2ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0,
.end = 0,
.flags = IORESOURCE_IRQ,
},
};
/*--------------------------------------------------------------------------*/
static struct mfd_cell tc6387xb_cells[] = {
[TC6387XB_CELL_MMC] = {
@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = {
static int tc6387xb_probe(struct platform_device *dev)
{
struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
struct resource *iomem;
struct resource *iomem, *rscr;
struct clk *clk32k;
struct tc6387xb *tc6387xb;
int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev)
return -EINVAL;
}
tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
if (!tc6387xb)
return -ENOMEM;
ret = platform_get_irq(dev, 0);
if (ret >= 0)
irq = ret;
else
goto err_resource;
goto err_no_irq;
clk32k = clk_get(&dev->dev, "CLK_CK32K");
if (IS_ERR(clk32k)) {
ret = PTR_ERR(clk32k);
goto err_resource;
goto err_no_clk;
}
platform_set_drvdata(dev, clk32k);
rscr = &tc6387xb->rscr;
rscr->name = "tc6387xb-core";
rscr->start = iomem->start;
rscr->end = iomem->start + 0xff;
rscr->flags = IORESOURCE_MEM;
ret = request_resource(iomem, rscr);
if (ret)
goto err_resource;
tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
if (!tc6387xb->scr) {
ret = -ENOMEM;
goto err_ioremap;
}
tc6387xb->clk32k = clk32k;
platform_set_drvdata(dev, tc6387xb);
if (pdata && pdata->enable)
pdata->enable(dev);
@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev)
if (!ret)
return 0;
clk_put(clk32k);
err_ioremap:
release_resource(&tc6387xb->rscr);
err_resource:
clk_put(clk32k);
err_no_clk:
err_no_irq:
kfree(tc6387xb);
return ret;
}
@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Ian Molton");
MODULE_ALIAS("platform:tc6387xb");

View File

@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
return 0;
}
static struct tmio_mmc_data tc6393xb_mmc_data = {
.hclk = 24000000,
};
static struct resource __devinitdata tc6393xb_nand_resources[] = {
{
.start = 0x1000,
@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
.end = 0x9ff,
.flags = IORESOURCE_MEM,
},
{
.start = 0x200,
.end = 0x2ff,
.flags = IORESOURCE_MEM,
},
{
.start = IRQ_TC6393_MMC,
.end = IRQ_TC6393_MMC,
@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb,
}
EXPORT_SYMBOL(tc6393xb_lcd_mode);
static int tc6393xb_mmc_enable(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
tmio_core_mmc_enable(tc6393xb->scr + 0x200, 0,
tc6393xb_mmc_resources[0].start & 0xfffe);
return 0;
}
static int tc6393xb_mmc_resume(struct platform_device *mmc)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
tmio_core_mmc_resume(tc6393xb->scr + 0x200, 0,
tc6393xb_mmc_resources[0].start & 0xfffe);
return 0;
}
static void tc6393xb_mmc_pwr(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
tmio_core_mmc_pwr(tc6393xb->scr + 0x200, 0, state);
}
static void tc6393xb_mmc_clk_div(struct platform_device *mmc, int state)
{
struct platform_device *dev = to_platform_device(mmc->dev.parent);
struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
tmio_core_mmc_clk_div(tc6393xb->scr + 0x200, 0, state);
}
static struct tmio_mmc_data tc6393xb_mmc_data = {
.hclk = 24000000,
.set_pwr = tc6393xb_mmc_pwr,
.set_clk_div = tc6393xb_mmc_clk_div,
};
static struct mfd_cell __devinitdata tc6393xb_cells[] = {
[TC6393XB_CELL_NAND] = {
.name = "tmio-nand",
@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
},
[TC6393XB_CELL_MMC] = {
.name = "tmio-mmc",
.enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume,
.driver_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources,
@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
MODULE_ALIAS("platform:tc6393xb");

52
drivers/mfd/tmio_core.c Normal file
View File

@ -0,0 +1,52 @@
/*
* Copyright(c) 2009 Ian Molton <spyro@f2s.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/mfd/tmio.h>
int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base)
{
/* Enable the MMC/SD Control registers */
sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
/* Disable SD power during suspend */
sd_config_write8(cnf, shift, CNF_PWR_CTL_3, 0x01);
/* The below is required but why? FIXME */
sd_config_write8(cnf, shift, CNF_STOP_CLK_CTL, 0x1f);
/* Power down SD bus */
sd_config_write8(cnf, shift, CNF_PWR_CTL_2, 0x00);
return 0;
}
EXPORT_SYMBOL(tmio_core_mmc_enable);
int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base)
{
/* Enable the MMC/SD Control registers */
sd_config_write16(cnf, shift, CNF_CMD, SDCREN);
sd_config_write32(cnf, shift, CNF_CTL_BASE, base & 0xfffe);
return 0;
}
EXPORT_SYMBOL(tmio_core_mmc_resume);
void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state)
{
sd_config_write8(cnf, shift, CNF_PWR_CTL_2, state ? 0x02 : 0x00);
}
EXPORT_SYMBOL(tmio_core_mmc_pwr);
void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state)
{
sd_config_write8(cnf, shift, CNF_SD_CLK_MODE, state ? 1 : 0);
}
EXPORT_SYMBOL(tmio_core_mmc_clk_div);

View File

@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
clk |= 0x100;
}
sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22);
if (host->set_clk_div)
host->set_clk_div(host->pdev, (clk>>22) & 1);
sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
}
@ -427,12 +429,13 @@ 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 */
sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
if (host->set_pwr)
host->set_pwr(host->pdev, 0);
tmio_mmc_clk_stop(host);
break;
case MMC_POWER_ON: /* power up SD bus */
sd_config_write8(host, CNF_PWR_CTL_2, 0x02);
if (host->set_pwr)
host->set_pwr(host->pdev, 1);
break;
case MMC_POWER_UP: /* start bus clock */
tmio_mmc_clk_start(host);
@ -485,21 +488,15 @@ 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);
int ret = 0;
/* Tell the MFD core we are ready to be enabled */
if (cell->enable) {
ret = cell->enable(dev);
if (cell->resume) {
ret = cell->resume(dev);
if (ret)
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:
@ -514,17 +511,16 @@ 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 resource *res_ctl;
struct tmio_mmc_host *host;
struct mmc_host *mmc;
int ret = -EINVAL;
if (dev->num_resources != 3)
if (dev->num_resources != 2)
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)
if (!res_ctl)
goto out;
pdata = cell->driver_data;
@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = dev;
platform_set_drvdata(dev, mmc);
host->set_pwr = pdata->set_pwr;
host->set_clk_div = pdata->set_clk_div;
/* SD control register space size is 0x200, 0x400 for bus_shift=1 */
host->bus_shift = resource_size(res_ctl) >> 10;
@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (!host->ctl)
goto host_free;
host->cnf = ioremap(res_cnf->start, resource_size(res_cnf));
if (!host->cnf)
goto unmap_ctl;
mmc->ops = &tmio_mmc_ops;
mmc->caps = MMC_CAP_4_BIT_DATA;
mmc->f_max = pdata->hclk;
@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (cell->enable) {
ret = cell->enable(dev);
if (ret)
goto unmap_cnf;
goto unmap_ctl;
}
/* 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);
/* The below is required but why? FIXME */
sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f);
/* Power down SD bus*/
sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
tmio_mmc_clk_stop(host);
reset(host);
@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (ret >= 0)
host->irq = ret;
else
goto unmap_cnf;
goto unmap_ctl;
disable_mmc_irqs(host, TMIO_MASK_ALL);
ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
if (ret)
goto unmap_cnf;
goto unmap_ctl;
mmc_add_host(mmc);
@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
return 0;
unmap_cnf:
iounmap(host->cnf);
unmap_ctl:
iounmap(host->ctl);
host_free:
@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev)
mmc_remove_host(mmc);
free_irq(host->irq, host);
iounmap(host->ctl);
iounmap(host->cnf);
mmc_free_host(mmc);
}

View File

@ -11,26 +11,6 @@
#include <linux/highmem.h>
#define CNF_CMD 0x04
#define CNF_CTL_BASE 0x10
#define CNF_INT_PIN 0x3d
#define CNF_STOP_CLK_CTL 0x40
#define CNF_GCLK_CTL 0x41
#define CNF_SD_CLK_MODE 0x42
#define CNF_PIN_STATUS 0x44
#define CNF_PWR_CTL_1 0x48
#define CNF_PWR_CTL_2 0x49
#define CNF_PWR_CTL_3 0x4a
#define CNF_CARD_DETECT_MODE 0x4c
#define CNF_SD_SLOT 0x50
#define CNF_EXT_GCLK_CTL_1 0xf0
#define CNF_EXT_GCLK_CTL_2 0xf1
#define CNF_EXT_GCLK_CTL_3 0xf9
#define CNF_SD_LED_EN_1 0xfa
#define CNF_SD_LED_EN_2 0xfe
#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
#define CTL_SD_CMD 0x00
#define CTL_ARG_REG 0x04
#define CTL_STOP_INTERNAL_ACTION 0x08
@ -110,7 +90,6 @@
struct tmio_mmc_host {
void __iomem *cnf;
void __iomem *ctl;
unsigned long bus_shift;
struct mmc_command *cmd;
@ -119,10 +98,16 @@ struct tmio_mmc_host {
struct mmc_host *mmc;
int irq;
/* Callbacks for clock / power control */
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
/* pio related stuff */
struct scatterlist *sg_ptr;
unsigned int sg_len;
unsigned int sg_off;
struct platform_device *pdev;
};
#include <linux/io.h>
@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr,
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>

View File

@ -2,6 +2,8 @@
#define MFD_TMIO_H
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#define tmio_ioread8(addr) readb(addr)
#define tmio_ioread16(addr) readw(addr)
@ -18,11 +20,48 @@
writew((val) >> 16, (addr) + 2); \
} while (0)
#define CNF_CMD 0x04
#define CNF_CTL_BASE 0x10
#define CNF_INT_PIN 0x3d
#define CNF_STOP_CLK_CTL 0x40
#define CNF_GCLK_CTL 0x41
#define CNF_SD_CLK_MODE 0x42
#define CNF_PIN_STATUS 0x44
#define CNF_PWR_CTL_1 0x48
#define CNF_PWR_CTL_2 0x49
#define CNF_PWR_CTL_3 0x4a
#define CNF_CARD_DETECT_MODE 0x4c
#define CNF_SD_SLOT 0x50
#define CNF_EXT_GCLK_CTL_1 0xf0
#define CNF_EXT_GCLK_CTL_2 0xf1
#define CNF_EXT_GCLK_CTL_3 0xf9
#define CNF_SD_LED_EN_1 0xfa
#define CNF_SD_LED_EN_2 0xfe
#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
#define sd_config_write8(base, shift, reg, val) \
tmio_iowrite8((val), (base) + ((reg) << (shift)))
#define sd_config_write16(base, shift, reg, val) \
tmio_iowrite16((val), (base) + ((reg) << (shift)))
#define sd_config_write32(base, shift, reg, val) \
do { \
tmio_iowrite16((val), (base) + ((reg) << (shift))); \
tmio_iowrite16((val) >> 16, (base) + ((reg + 2) << (shift))); \
} while (0)
int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
int tmio_core_mmc_resume(void __iomem *cnf, int shift, unsigned long base);
void tmio_core_mmc_pwr(void __iomem *cnf, int shift, int state);
void tmio_core_mmc_clk_div(void __iomem *cnf, int shift, int state);
/*
* data for the MMC controller
*/
struct tmio_mmc_data {
const unsigned int hclk;
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
};
/*