Commit fe64454d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-2.6:
  mfd: Unlock mc13783 before subsystems initialisation, at probe time.
  mfd: WM835x GPIO direction register is not locked
  mfd: tmio_mmc hardware abstraction for CNF area
  mfd: WM8350 off by one bug
  mfd: Correct WM835x ISINK ramp time defines
parents 8888be69 1e02b2c3
...@@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o ...@@ -11,9 +11,9 @@ obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o
obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o
obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o
obj-$(CONFIG_MFD_WM8400) += wm8400-core.o obj-$(CONFIG_MFD_WM8400) += wm8400-core.o
wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o wm831x-objs := wm831x-core.o wm831x-irq.o wm831x-otp.o
......
...@@ -80,6 +80,7 @@ struct asic3 { ...@@ -80,6 +80,7 @@ struct asic3 {
u16 irq_bothedge[4]; u16 irq_bothedge[4];
struct gpio_chip gpio; struct gpio_chip gpio;
struct device *dev; struct device *dev;
void __iomem *tmio_cnf;
struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)]; struct asic3_clk clocks[ARRAY_SIZE(asic3_clk_init)];
}; };
...@@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = { ...@@ -685,8 +686,24 @@ static struct mfd_cell asic3_cell_ds1wm = {
.resources = ds1wm_resources, .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 = { 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[] = { static struct resource asic3_mmc_resources[] = {
...@@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = { ...@@ -695,11 +712,6 @@ static struct resource asic3_mmc_resources[] = {
.end = ASIC3_SD_CTRL_BASE + 0x3ff, .end = ASIC3_SD_CTRL_BASE + 0x3ff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{
.start = ASIC3_SD_CONFIG_BASE,
.end = ASIC3_SD_CONFIG_BASE + 0x1ff,
.flags = IORESOURCE_MEM,
},
{ {
.start = 0, .start = 0,
.end = 0, .end = 0,
...@@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev) ...@@ -743,6 +755,10 @@ static int asic3_mmc_enable(struct platform_device *pdev)
asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF), asic3_set_register(asic, ASIC3_OFFSET(SDHWCTRL, SDCONF),
ASIC3_SDHWCTRL_SDPWR, 1); 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; return 0;
} }
...@@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev, ...@@ -797,10 +813,15 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm); asic3_cell_ds1wm.data_size = sizeof(asic3_cell_ds1wm);
/* MMC */ /* 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].start >>= asic->bus_shift;
asic3_mmc_resources[0].end >>= 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.platform_data = &asic3_cell_mmc;
asic3_cell_mmc.data_size = sizeof(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, ...@@ -820,7 +841,10 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
static void asic3_mfd_remove(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); mfd_remove_devices(&pdev->dev);
iounmap(asic->tmio_cnf);
} }
/* Core */ /* Core */
......
...@@ -619,6 +619,8 @@ static int mc13783_probe(struct spi_device *spi) ...@@ -619,6 +619,8 @@ static int mc13783_probe(struct spi_device *spi)
} }
/* This should go away (END) */ /* This should go away (END) */
mc13783_unlock(mc13783);
if (pdata->flags & MC13783_USE_ADC) if (pdata->flags & MC13783_USE_ADC)
mc13783_add_subdevice(mc13783, "mc13783-adc"); mc13783_add_subdevice(mc13783, "mc13783-adc");
...@@ -641,8 +643,6 @@ static int mc13783_probe(struct spi_device *spi) ...@@ -641,8 +643,6 @@ static int mc13783_probe(struct spi_device *spi)
if (pdata->flags & MC13783_USE_TOUCHSCREEN) if (pdata->flags & MC13783_USE_TOUCHSCREEN)
mc13783_add_subdevice(mc13783, "mc13783-ts"); mc13783_add_subdevice(mc13783, "mc13783-ts");
mc13783_unlock(mc13783);
return 0; return 0;
} }
......
...@@ -38,6 +38,19 @@ enum { ...@@ -38,6 +38,19 @@ enum {
T7L66XB_CELL_MMC, 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_REVID 0x08 /* b Revision ID */
#define SCR_IMR 0x42 /* b Interrupt Mask */ #define SCR_IMR 0x42 /* b Interrupt Mask */
#define SCR_DEV_CTL 0xe0 /* b Device control */ #define SCR_DEV_CTL 0xe0 /* b Device control */
...@@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc) ...@@ -83,6 +96,9 @@ static int t7l66xb_mmc_enable(struct platform_device *mmc)
spin_unlock_irqrestore(&t7l66xb->lock, flags); spin_unlock_irqrestore(&t7l66xb->lock, flags);
tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
t7l66xb_mmc_resources[0].start & 0xfffe);
return 0; return 0;
} }
...@@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc) ...@@ -106,28 +122,28 @@ static int t7l66xb_mmc_disable(struct platform_device *mmc)
return 0; 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 = { static struct tmio_mmc_data t7166xb_mmc_data = {
.hclk = 24000000, .hclk = 24000000,
}; .set_pwr = t7l66xb_mmc_pwr,
.set_clk_div = t7l66xb_mmc_clk_div,
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,
},
}; };
static const struct resource t7l66xb_nand_resources[] = { static const struct resource t7l66xb_nand_resources[] = {
...@@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev) ...@@ -282,6 +298,9 @@ static int t7l66xb_resume(struct platform_device *dev)
if (pdata && pdata->resume) if (pdata && pdata->resume)
pdata->resume(dev); pdata->resume(dev);
tmio_core_mmc_enable(t7l66xb->scr + 0x200, 0,
t7l66xb_mmc_resources[0].start & 0xfffe);
return 0; return 0;
} }
#else #else
......
...@@ -22,28 +22,52 @@ enum { ...@@ -22,28 +22,52 @@ enum {
TC6387XB_CELL_MMC, 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 #ifdef CONFIG_PM
static int tc6387xb_suspend(struct platform_device *dev, pm_message_t state) 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; struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
if (pdata && pdata->suspend) if (pdata && pdata->suspend)
pdata->suspend(dev); pdata->suspend(dev);
clk_disable(clk32k); clk_disable(tc6387xb->clk32k);
return 0; return 0;
} }
static int tc6387xb_resume(struct platform_device *dev) 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; struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
clk_enable(clk32k); clk_enable(tc6387xb->clk32k);
if (pdata && pdata->resume) if (pdata && pdata->resume)
pdata->resume(dev); pdata->resume(dev);
tmio_core_mmc_resume(tc6387xb->scr + 0x200, 0,
tc6387xb_mmc_resources[0].start & 0xfffe);
return 0; return 0;
} }
#else #else
...@@ -53,12 +77,32 @@ static int tc6387xb_resume(struct platform_device *dev) ...@@ -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) static int tc6387xb_mmc_enable(struct platform_device *mmc)
{ {
struct platform_device *dev = to_platform_device(mmc->dev.parent); 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(tc6387xb->clk32k);
clk_enable(clk32k); tmio_core_mmc_enable(tc6387xb->scr + 0x200, 0,
tc6387xb_mmc_resources[0].start & 0xfffe);
return 0; return 0;
} }
...@@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc) ...@@ -66,36 +110,20 @@ static int tc6387xb_mmc_enable(struct platform_device *mmc)
static int tc6387xb_mmc_disable(struct platform_device *mmc) static int tc6387xb_mmc_disable(struct platform_device *mmc)
{ {
struct platform_device *dev = to_platform_device(mmc->dev.parent); 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; return 0;
} }
/*--------------------------------------------------------------------------*/
static struct tmio_mmc_data tc6387xb_mmc_data = { static struct tmio_mmc_data tc6387xb_mmc_data = {
.hclk = 24000000, .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[] = { static struct mfd_cell tc6387xb_cells[] = {
[TC6387XB_CELL_MMC] = { [TC6387XB_CELL_MMC] = {
...@@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = { ...@@ -111,8 +139,9 @@ static struct mfd_cell tc6387xb_cells[] = {
static int tc6387xb_probe(struct platform_device *dev) static int tc6387xb_probe(struct platform_device *dev)
{ {
struct tc6387xb_platform_data *pdata = dev->dev.platform_data; struct tc6387xb_platform_data *pdata = dev->dev.platform_data;
struct resource *iomem; struct resource *iomem, *rscr;
struct clk *clk32k; struct clk *clk32k;
struct tc6387xb *tc6387xb;
int irq, ret; int irq, ret;
iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); iomem = platform_get_resource(dev, IORESOURCE_MEM, 0);
...@@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev) ...@@ -120,18 +149,40 @@ static int tc6387xb_probe(struct platform_device *dev)
return -EINVAL; return -EINVAL;
} }
tc6387xb = kzalloc(sizeof *tc6387xb, GFP_KERNEL);
if (!tc6387xb)
return -ENOMEM;
ret = platform_get_irq(dev, 0); ret = platform_get_irq(dev, 0);
if (ret >= 0) if (ret >= 0)
irq = ret; irq = ret;
else else
goto err_resource; goto err_no_irq;
clk32k = clk_get(&dev->dev, "CLK_CK32K"); clk32k = clk_get(&dev->dev, "CLK_CK32K");
if (IS_ERR(clk32k)) { if (IS_ERR(clk32k)) {
ret = PTR_ERR(clk32k); ret = PTR_ERR(clk32k);
goto err_no_clk;
}
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; goto err_resource;
tc6387xb->scr = ioremap(rscr->start, rscr->end - rscr->start + 1);
if (!tc6387xb->scr) {
ret = -ENOMEM;
goto err_ioremap;
} }
platform_set_drvdata(dev, clk32k);
tc6387xb->clk32k = clk32k;
platform_set_drvdata(dev, tc6387xb);
if (pdata && pdata->enable) if (pdata && pdata->enable)
pdata->enable(dev); pdata->enable(dev);
...@@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev) ...@@ -149,8 +200,13 @@ static int tc6387xb_probe(struct platform_device *dev)
if (!ret) if (!ret)
return 0; return 0;
clk_put(clk32k); err_ioremap:
release_resource(&tc6387xb->rscr);
err_resource: err_resource:
clk_put(clk32k);
err_no_clk:
err_no_irq:
kfree(tc6387xb);
return ret; return ret;
} }
...@@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver"); ...@@ -195,3 +251,4 @@ MODULE_DESCRIPTION("Toshiba TC6387XB core driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Ian Molton"); MODULE_AUTHOR("Ian Molton");
MODULE_ALIAS("platform:tc6387xb"); MODULE_ALIAS("platform:tc6387xb");
...@@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand) ...@@ -136,10 +136,6 @@ static int tc6393xb_nand_enable(struct platform_device *nand)
return 0; return 0;
} }
static struct tmio_mmc_data tc6393xb_mmc_data = {
.hclk = 24000000,
};
static struct resource __devinitdata tc6393xb_nand_resources[] = { static struct resource __devinitdata tc6393xb_nand_resources[] = {
{ {
.start = 0x1000, .start = 0x1000,
...@@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = { ...@@ -164,11 +160,6 @@ static struct resource __devinitdata tc6393xb_mmc_resources[] = {
.end = 0x9ff, .end = 0x9ff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
{
.start = 0x200,
.end = 0x2ff,
.flags = IORESOURCE_MEM,
},
{ {
.start = IRQ_TC6393_MMC, .start = IRQ_TC6393_MMC,
.end = IRQ_TC6393_MMC, .end = IRQ_TC6393_MMC,
...@@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb, ...@@ -346,6 +337,50 @@ int tc6393xb_lcd_mode(struct platform_device *fb,
} }
EXPORT_SYMBOL(tc6393xb_lcd_mode); 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[] = { static struct mfd_cell __devinitdata tc6393xb_cells[] = {
[TC6393XB_CELL_NAND] = { [TC6393XB_CELL_NAND] = {
.name = "tmio-nand", .name = "tmio-nand",
...@@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = { ...@@ -355,6 +390,8 @@ static struct mfd_cell __devinitdata tc6393xb_cells[] = {
}, },
[TC6393XB_CELL_MMC] = { [TC6393XB_CELL_MMC] = {
.name = "tmio-mmc", .name = "tmio-mmc",
.enable = tc6393xb_mmc_enable,
.resume = tc6393xb_mmc_resume,
.driver_data = &tc6393xb_mmc_data, .driver_data = &tc6393xb_mmc_data,
.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources), .num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
.resources = tc6393xb_mmc_resources, .resources = tc6393xb_mmc_resources,
...@@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2"); ...@@ -836,3 +873,4 @@ MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer"); MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov and Dirk Opfer");
MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller"); MODULE_DESCRIPTION("tc6393xb Toshiba Mobile IO Controller");
MODULE_ALIAS("platform:tc6393xb"); MODULE_ALIAS("platform:tc6393xb");
/*
* 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);
...@@ -134,8 +134,7 @@ static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg) ...@@ -134,8 +134,7 @@ static inline int is_reg_locked(struct wm8350 *wm8350, u8 reg)
wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY) wm8350->reg_cache[WM8350_SECURITY] == WM8350_UNLOCK_KEY)
return 0; return 0;
if ((reg == WM8350_GPIO_CONFIGURATION_I_O) || if ((reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
(reg >= WM8350_GPIO_FUNCTION_SELECT_1 &&
reg <= WM8350_GPIO_FUNCTION_SELECT_4) || reg <= WM8350_GPIO_FUNCTION_SELECT_4) ||
(reg >= WM8350_BATTERY_CHARGER_CONTROL_1 && (reg >= WM8350_BATTERY_CHARGER_CONTROL_1 &&
reg <= WM8350_BATTERY_CHARGER_CONTROL_3)) reg <= WM8350_BATTERY_CHARGER_CONTROL_3))
......
...@@ -434,7 +434,7 @@ int wm8350_register_irq(struct wm8350 *wm8350, int irq, ...@@ -434,7 +434,7 @@ int wm8350_register_irq(struct wm8350 *wm8350, int irq,
irq_handler_t handler, unsigned long flags, irq_handler_t handler, unsigned long flags,
const char *name, void *data) const char *name, void *data)
{ {
if (irq < 0 || irq > WM8350_NUM_IRQ || !handler) if (irq < 0 || irq >= WM8350_NUM_IRQ || !handler)
return -EINVAL; return -EINVAL;
if (wm8350->irq[irq].handler) if (wm8350->irq[irq].handler)
...@@ -453,7 +453,7 @@ EXPORT_SYMBOL_GPL(wm8350_register_irq); ...@@ -453,7 +453,7 @@ EXPORT_SYMBOL_GPL(wm8350_register_irq);
int wm8350_free_irq(struct wm8350 *wm8350, int irq) int wm8350_free_irq(struct wm8350 *wm8350, int irq)
{ {
if (irq < 0 || irq > WM8350_NUM_IRQ) if (irq < 0 || irq >= WM8350_NUM_IRQ)
return -EINVAL; return -EINVAL;
wm8350_mask_irq(wm8350, irq); wm8350_mask_irq(wm8350, irq);
......
...@@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) ...@@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
clk |= 0x100; 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); 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) ...@@ -427,12 +429,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
/* Power sequence - OFF -> ON -> UP */ /* Power sequence - OFF -> ON -> UP */
switch (ios->power_mode) { switch (ios->power_mode) {
case MMC_POWER_OFF: /* power down SD bus */ 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); tmio_mmc_clk_stop(host);
break; break;
case MMC_POWER_ON: /* power up SD bus */ case MMC_POWER_ON: /* power up SD bus */
if (host->set_pwr)
sd_config_write8(host, CNF_PWR_CTL_2, 0x02); host->set_pwr(host->pdev, 1);
break; break;
case MMC_POWER_UP: /* start bus clock */ case MMC_POWER_UP: /* start bus clock */
tmio_mmc_clk_start(host); tmio_mmc_clk_start(host);
...@@ -485,21 +488,15 @@ static int tmio_mmc_resume(struct platform_device *dev) ...@@ -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 mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
struct mmc_host *mmc = platform_get_drvdata(dev); struct mmc_host *mmc = platform_get_drvdata(dev);
struct tmio_mmc_host *host = mmc_priv(mmc);
int ret = 0; int ret = 0;
/* Tell the MFD core we are ready to be enabled */ /* Tell the MFD core we are ready to be enabled */
if (cell->enable) { if (cell->resume) {
ret = cell->enable(dev); ret = cell->resume(dev);
if (ret) if (ret)
goto out; 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); mmc_resume_host(mmc);
out: out:
...@@ -514,17 +511,16 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -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 mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
struct tmio_mmc_data *pdata; struct tmio_mmc_data *pdata;
struct resource *res_ctl, *res_cnf; struct resource *res_ctl;
struct tmio_mmc_host *host; struct tmio_mmc_host *host;
struct mmc_host *mmc; struct mmc_host *mmc;
int ret = -EINVAL; int ret = -EINVAL;
if (dev->num_resources != 3) if (dev->num_resources != 2)
goto out; goto out;
res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0); res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1); if (!res_ctl)
if (!res_ctl || !res_cnf)
goto out; goto out;
pdata = cell->driver_data; pdata = cell->driver_data;
...@@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; host->mmc = mmc;
host->pdev = dev;
platform_set_drvdata(dev, mmc); 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 */ /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
host->bus_shift = resource_size(res_ctl) >> 10; host->bus_shift = resource_size(res_ctl) >> 10;
...@@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (!host->ctl) if (!host->ctl)
goto host_free; 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->ops = &tmio_mmc_ops;
mmc->caps = MMC_CAP_4_BIT_DATA; mmc->caps = MMC_CAP_4_BIT_DATA;
mmc->f_max = pdata->hclk; mmc->f_max = pdata->hclk;
...@@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (cell->enable) { if (cell->enable) {
ret = cell->enable(dev); ret = cell->enable(dev);
if (ret) 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); tmio_mmc_clk_stop(host);
reset(host); reset(host);
...@@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
if (ret >= 0) if (ret >= 0)
host->irq = ret; host->irq = ret;
else else
goto unmap_cnf; goto unmap_ctl;
disable_mmc_irqs(host, TMIO_MASK_ALL); disable_mmc_irqs(host, TMIO_MASK_ALL);
ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
if (ret) if (ret)
goto unmap_cnf; goto unmap_ctl;
mmc_add_host(mmc); mmc_add_host(mmc);
...@@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) ...@@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
return 0; return 0;
unmap_cnf:
iounmap(host->cnf);
unmap_ctl: unmap_ctl:
iounmap(host->ctl); iounmap(host->ctl);
host_free: host_free:
...@@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) ...@@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev)
mmc_remove_host(mmc); mmc_remove_host(mmc);
free_irq(host->irq, host); free_irq(host->irq, host);
iounmap(host->ctl); iounmap(host->ctl);
iounmap(host->cnf);
mmc_free_host(mmc); mmc_free_host(mmc);
} }
......
...@@ -11,26 +11,6 @@ ...@@ -11,26 +11,6 @@
#include <linux/highmem.h> #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_SD_CMD 0x00
#define CTL_ARG_REG 0x04 #define CTL_ARG_REG 0x04
#define CTL_STOP_INTERNAL_ACTION 0x08 #define CTL_STOP_INTERNAL_ACTION 0x08
...@@ -110,7 +90,6 @@ ...@@ -110,7 +90,6 @@
struct tmio_mmc_host { struct tmio_mmc_host {
void __iomem *cnf;
void __iomem *ctl; void __iomem *ctl;
unsigned long bus_shift; unsigned long bus_shift;
struct mmc_command *cmd; struct mmc_command *cmd;
...@@ -119,10 +98,16 @@ struct tmio_mmc_host { ...@@ -119,10 +98,16 @@ struct tmio_mmc_host {
struct mmc_host *mmc; struct mmc_host *mmc;
int irq; 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 */ /* pio related stuff */
struct scatterlist *sg_ptr; struct scatterlist *sg_ptr;
unsigned int sg_len; unsigned int sg_len;
unsigned int sg_off; unsigned int sg_off;
struct platform_device *pdev;
}; };
#include <linux/io.h> #include <linux/io.h>
...@@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, ...@@ -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)); 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/scatterlist.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
#define MFD_TMIO_H #define MFD_TMIO_H
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#define tmio_ioread8(addr) readb(addr) #define tmio_ioread8(addr) readb(addr)
#define tmio_ioread16(addr) readw(addr) #define tmio_ioread16(addr) readw(addr)
...@@ -18,11 +20,48 @@ ...@@ -18,11 +20,48 @@
writew((val) >> 16, (addr) + 2); \ writew((val) >> 16, (addr) + 2); \
} while (0) } 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 * data for the MMC controller
*/ */
struct tmio_mmc_data { struct tmio_mmc_data {
const unsigned int hclk; const unsigned int hclk;
void (*set_pwr)(struct platform_device *host, int state);
void (*set_clk_div)(struct platform_device *host, int state);
}; };
/* /*
......
...@@ -666,20 +666,20 @@ ...@@ -666,20 +666,20 @@
#define WM8350_ISINK_FLASH_DUR_64MS (1 << 8) #define WM8350_ISINK_FLASH_DUR_64MS (1 << 8)
#define WM8350_ISINK_FLASH_DUR_96MS (2 << 8) #define WM8350_ISINK_FLASH_DUR_96MS (2 << 8)
#define WM8350_ISINK_FLASH_DUR_1024MS (3 << 8) #define WM8350_ISINK_FLASH_DUR_1024MS (3 << 8)
#define WM8350_ISINK_FLASH_ON_INSTANT (0 << 4) #define WM8350_ISINK_FLASH_ON_INSTANT (0 << 0)
#define WM8350_ISINK_FLASH_ON_0_25S (1 << 4) #define WM8350_ISINK_FLASH_ON_0_25S (1 << 0)
#define WM8350_ISINK_FLASH_ON_0_50S (2 << 4) #define WM8350_ISINK_FLASH_ON_0_50S (2 << 0)
#define WM8350_ISINK_FLASH_ON_1_00S (3 << 4) #define WM8350_ISINK_FLASH_ON_1_00S (3 << 0)
#define WM8350_ISINK_FLASH_ON_1_95S (1 << 4) #define WM8350_ISINK_FLASH_ON_1_95S (1 << 0)
#define WM8350_ISINK_FLASH_ON_3_91S (2 << 4) #define WM8350_ISINK_FLASH_ON_3_91S (2 << 0)
#define WM8350_ISINK_FLASH_ON_7_80S (3 << 4) #define WM8350_ISINK_FLASH_ON_7_80S (3 << 0)
#define WM8350_ISINK_FLASH_OFF_INSTANT (0 << 0) #define WM8350_ISINK_FLASH_OFF_INSTANT (0 << 4)
#define WM8350_ISINK_FLASH_OFF_0_25S (1 << 0) #define WM8350_ISINK_FLASH_OFF_0_25S (1 << 4)
#define WM8350_ISINK_FLASH_OFF_0_50S (2 << 0) #define WM8350_ISINK_FLASH_OFF_0_50S (2 << 4)
#define WM8350_ISINK_FLASH_OFF_1_00S (3 << 0) #define WM8350_ISINK_FLASH_OFF_1_00S (3 << 4)
#define WM8350_ISINK_FLASH_OFF_1_95S (1 << 0) #define WM8350_ISINK_FLASH_OFF_1_95S (1 << 4)
#define WM8350_ISINK_FLASH_OFF_3_91S (2 << 0) #define WM8350_ISINK_FLASH_OFF_3_91S (2 << 4)
#define WM8350_ISINK_FLASH_OFF_7_80S (3 << 0) #define WM8350_ISINK_FLASH_OFF_7_80S (3 << 4)
/* /*
* Regulator Interrupts. * Regulator Interrupts.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment