aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorIan Molton <ian@mnementh.co.uk>2010-01-06 07:51:48 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2010-01-18 06:30:27 -0500
commit64e8867ba8098b69889c1af94997a5ba2348fb26 (patch)
tree3391806575ec3435a26043a22ba45c9d76f0b791 /drivers/mmc
parent6f2af72a2451b7491fba820b1d1b0b91c6a84027 (diff)
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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/tmio_mmc.c59
-rw-r--r--drivers/mmc/host/tmio_mmc.h46
2 files changed, 25 insertions, 80 deletions
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c
index 7cccc8523747..e22c3fa3516a 100644
--- a/drivers/mmc/host/tmio_mmc.c
+++ b/drivers/mmc/host/tmio_mmc.c
@@ -46,7 +46,9 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
46 clk |= 0x100; 46 clk |= 0x100;
47 } 47 }
48 48
49 sd_config_write8(host, CNF_SD_CLK_MODE, clk >> 22); 49 if (host->set_clk_div)
50 host->set_clk_div(host->pdev, (clk>>22) & 1);
51
50 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff); 52 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
51} 53}
52 54
@@ -427,12 +429,13 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
427 /* Power sequence - OFF -> ON -> UP */ 429 /* Power sequence - OFF -> ON -> UP */
428 switch (ios->power_mode) { 430 switch (ios->power_mode) {
429 case MMC_POWER_OFF: /* power down SD bus */ 431 case MMC_POWER_OFF: /* power down SD bus */
430 sd_config_write8(host, CNF_PWR_CTL_2, 0x00); 432 if (host->set_pwr)
433 host->set_pwr(host->pdev, 0);
431 tmio_mmc_clk_stop(host); 434 tmio_mmc_clk_stop(host);
432 break; 435 break;
433 case MMC_POWER_ON: /* power up SD bus */ 436 case MMC_POWER_ON: /* power up SD bus */
434 437 if (host->set_pwr)
435 sd_config_write8(host, CNF_PWR_CTL_2, 0x02); 438 host->set_pwr(host->pdev, 1);
436 break; 439 break;
437 case MMC_POWER_UP: /* start bus clock */ 440 case MMC_POWER_UP: /* start bus clock */
438 tmio_mmc_clk_start(host); 441 tmio_mmc_clk_start(host);
@@ -485,21 +488,15 @@ static int tmio_mmc_resume(struct platform_device *dev)
485{ 488{
486 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 489 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
487 struct mmc_host *mmc = platform_get_drvdata(dev); 490 struct mmc_host *mmc = platform_get_drvdata(dev);
488 struct tmio_mmc_host *host = mmc_priv(mmc);
489 int ret = 0; 491 int ret = 0;
490 492
491 /* Tell the MFD core we are ready to be enabled */ 493 /* Tell the MFD core we are ready to be enabled */
492 if (cell->enable) { 494 if (cell->resume) {
493 ret = cell->enable(dev); 495 ret = cell->resume(dev);
494 if (ret) 496 if (ret)
495 goto out; 497 goto out;
496 } 498 }
497 499
498 /* Enable the MMC/SD Control registers */
499 sd_config_write16(host, CNF_CMD, SDCREN);
500 sd_config_write32(host, CNF_CTL_BASE,
501 (dev->resource[0].start >> host->bus_shift) & 0xfffe);
502
503 mmc_resume_host(mmc); 500 mmc_resume_host(mmc);
504 501
505out: 502out:
@@ -514,17 +511,16 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
514{ 511{
515 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data; 512 struct mfd_cell *cell = (struct mfd_cell *)dev->dev.platform_data;
516 struct tmio_mmc_data *pdata; 513 struct tmio_mmc_data *pdata;
517 struct resource *res_ctl, *res_cnf; 514 struct resource *res_ctl;
518 struct tmio_mmc_host *host; 515 struct tmio_mmc_host *host;
519 struct mmc_host *mmc; 516 struct mmc_host *mmc;
520 int ret = -EINVAL; 517 int ret = -EINVAL;
521 518
522 if (dev->num_resources != 3) 519 if (dev->num_resources != 2)
523 goto out; 520 goto out;
524 521
525 res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0); 522 res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
526 res_cnf = platform_get_resource(dev, IORESOURCE_MEM, 1); 523 if (!res_ctl)
527 if (!res_ctl || !res_cnf)
528 goto out; 524 goto out;
529 525
530 pdata = cell->driver_data; 526 pdata = cell->driver_data;
@@ -539,8 +535,12 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
539 535
540 host = mmc_priv(mmc); 536 host = mmc_priv(mmc);
541 host->mmc = mmc; 537 host->mmc = mmc;
538 host->pdev = dev;
542 platform_set_drvdata(dev, mmc); 539 platform_set_drvdata(dev, mmc);
543 540
541 host->set_pwr = pdata->set_pwr;
542 host->set_clk_div = pdata->set_clk_div;
543
544 /* SD control register space size is 0x200, 0x400 for bus_shift=1 */ 544 /* SD control register space size is 0x200, 0x400 for bus_shift=1 */
545 host->bus_shift = resource_size(res_ctl) >> 10; 545 host->bus_shift = resource_size(res_ctl) >> 10;
546 546
@@ -548,10 +548,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
548 if (!host->ctl) 548 if (!host->ctl)
549 goto host_free; 549 goto host_free;
550 550
551 host->cnf = ioremap(res_cnf->start, resource_size(res_cnf));
552 if (!host->cnf)
553 goto unmap_ctl;
554
555 mmc->ops = &tmio_mmc_ops; 551 mmc->ops = &tmio_mmc_ops;
556 mmc->caps = MMC_CAP_4_BIT_DATA; 552 mmc->caps = MMC_CAP_4_BIT_DATA;
557 mmc->f_max = pdata->hclk; 553 mmc->f_max = pdata->hclk;
@@ -562,23 +558,9 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
562 if (cell->enable) { 558 if (cell->enable) {
563 ret = cell->enable(dev); 559 ret = cell->enable(dev);
564 if (ret) 560 if (ret)
565 goto unmap_cnf; 561 goto unmap_ctl;
566 } 562 }
567 563
568 /* Enable the MMC/SD Control registers */
569 sd_config_write16(host, CNF_CMD, SDCREN);
570 sd_config_write32(host, CNF_CTL_BASE,
571 (dev->resource[0].start >> host->bus_shift) & 0xfffe);
572
573 /* Disable SD power during suspend */
574 sd_config_write8(host, CNF_PWR_CTL_3, 0x01);
575
576 /* The below is required but why? FIXME */
577 sd_config_write8(host, CNF_STOP_CLK_CTL, 0x1f);
578
579 /* Power down SD bus*/
580 sd_config_write8(host, CNF_PWR_CTL_2, 0x00);
581
582 tmio_mmc_clk_stop(host); 564 tmio_mmc_clk_stop(host);
583 reset(host); 565 reset(host);
584 566
@@ -586,14 +568,14 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
586 if (ret >= 0) 568 if (ret >= 0)
587 host->irq = ret; 569 host->irq = ret;
588 else 570 else
589 goto unmap_cnf; 571 goto unmap_ctl;
590 572
591 disable_mmc_irqs(host, TMIO_MASK_ALL); 573 disable_mmc_irqs(host, TMIO_MASK_ALL);
592 574
593 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | 575 ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
594 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); 576 IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
595 if (ret) 577 if (ret)
596 goto unmap_cnf; 578 goto unmap_ctl;
597 579
598 mmc_add_host(mmc); 580 mmc_add_host(mmc);
599 581
@@ -605,8 +587,6 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev)
605 587
606 return 0; 588 return 0;
607 589
608unmap_cnf:
609 iounmap(host->cnf);
610unmap_ctl: 590unmap_ctl:
611 iounmap(host->ctl); 591 iounmap(host->ctl);
612host_free: 592host_free:
@@ -626,7 +606,6 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev)
626 mmc_remove_host(mmc); 606 mmc_remove_host(mmc);
627 free_irq(host->irq, host); 607 free_irq(host->irq, host);
628 iounmap(host->ctl); 608 iounmap(host->ctl);
629 iounmap(host->cnf);
630 mmc_free_host(mmc); 609 mmc_free_host(mmc);
631 } 610 }
632 611
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
index 9fa998594974..692dc23363b9 100644
--- a/drivers/mmc/host/tmio_mmc.h
+++ b/drivers/mmc/host/tmio_mmc.h
@@ -11,26 +11,6 @@
11 11
12#include <linux/highmem.h> 12#include <linux/highmem.h>
13 13
14#define CNF_CMD 0x04
15#define CNF_CTL_BASE 0x10
16#define CNF_INT_PIN 0x3d
17#define CNF_STOP_CLK_CTL 0x40
18#define CNF_GCLK_CTL 0x41
19#define CNF_SD_CLK_MODE 0x42
20#define CNF_PIN_STATUS 0x44
21#define CNF_PWR_CTL_1 0x48
22#define CNF_PWR_CTL_2 0x49
23#define CNF_PWR_CTL_3 0x4a
24#define CNF_CARD_DETECT_MODE 0x4c
25#define CNF_SD_SLOT 0x50
26#define CNF_EXT_GCLK_CTL_1 0xf0
27#define CNF_EXT_GCLK_CTL_2 0xf1
28#define CNF_EXT_GCLK_CTL_3 0xf9
29#define CNF_SD_LED_EN_1 0xfa
30#define CNF_SD_LED_EN_2 0xfe
31
32#define SDCREN 0x2 /* Enable access to MMC CTL regs. (flag in COMMAND_REG)*/
33
34#define CTL_SD_CMD 0x00 14#define CTL_SD_CMD 0x00
35#define CTL_ARG_REG 0x04 15#define CTL_ARG_REG 0x04
36#define CTL_STOP_INTERNAL_ACTION 0x08 16#define CTL_STOP_INTERNAL_ACTION 0x08
@@ -110,7 +90,6 @@
110 90
111 91
112struct tmio_mmc_host { 92struct tmio_mmc_host {
113 void __iomem *cnf;
114 void __iomem *ctl; 93 void __iomem *ctl;
115 unsigned long bus_shift; 94 unsigned long bus_shift;
116 struct mmc_command *cmd; 95 struct mmc_command *cmd;
@@ -119,10 +98,16 @@ struct tmio_mmc_host {
119 struct mmc_host *mmc; 98 struct mmc_host *mmc;
120 int irq; 99 int irq;
121 100
101 /* Callbacks for clock / power control */
102 void (*set_pwr)(struct platform_device *host, int state);
103 void (*set_clk_div)(struct platform_device *host, int state);
104
122 /* pio related stuff */ 105 /* pio related stuff */
123 struct scatterlist *sg_ptr; 106 struct scatterlist *sg_ptr;
124 unsigned int sg_len; 107 unsigned int sg_len;
125 unsigned int sg_off; 108 unsigned int sg_off;
109
110 struct platform_device *pdev;
126}; 111};
127 112
128#include <linux/io.h> 113#include <linux/io.h>
@@ -163,25 +148,6 @@ static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr,
163 writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); 148 writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift));
164} 149}
165 150
166static inline void sd_config_write8(struct tmio_mmc_host *host, int addr,
167 u8 val)
168{
169 writeb(val, host->cnf + (addr << host->bus_shift));
170}
171
172static inline void sd_config_write16(struct tmio_mmc_host *host, int addr,
173 u16 val)
174{
175 writew(val, host->cnf + (addr << host->bus_shift));
176}
177
178static inline void sd_config_write32(struct tmio_mmc_host *host, int addr,
179 u32 val)
180{
181 writew(val, host->cnf + (addr << host->bus_shift));
182 writew(val >> 16, host->cnf + ((addr + 2) << host->bus_shift));
183}
184
185#include <linux/scatterlist.h> 151#include <linux/scatterlist.h>
186#include <linux/blkdev.h> 152#include <linux/blkdev.h>
187 153