~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/mmc/host/sh_mmcif.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <linux/mmc/sh_mmcif.h>
30
30
#include <linux/pagemap.h>
31
31
#include <linux/platform_device.h>
 
32
#include <linux/pm_runtime.h>
 
33
#include <linux/spinlock.h>
32
34
 
33
35
#define DRIVER_NAME     "sh_mmcif"
34
36
#define DRIVER_VERSION  "2010-04-28"
153
155
#define CLKDEV_MMC_DATA         20000000 /* 20MHz */
154
156
#define CLKDEV_INIT             400000   /* 400 KHz */
155
157
 
 
158
enum mmcif_state {
 
159
        STATE_IDLE,
 
160
        STATE_REQUEST,
 
161
        STATE_IOS,
 
162
};
 
163
 
156
164
struct sh_mmcif_host {
157
165
        struct mmc_host *mmc;
158
166
        struct mmc_data *data;
164
172
        long timeout;
165
173
        void __iomem *addr;
166
174
        struct completion intr_wait;
 
175
        enum mmcif_state state;
 
176
        spinlock_t lock;
 
177
        bool power;
167
178
 
168
179
        /* DMA support */
169
180
        struct dma_chan         *chan_rx;
798
809
static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
799
810
{
800
811
        struct sh_mmcif_host *host = mmc_priv(mmc);
 
812
        unsigned long flags;
 
813
 
 
814
        spin_lock_irqsave(&host->lock, flags);
 
815
        if (host->state != STATE_IDLE) {
 
816
                spin_unlock_irqrestore(&host->lock, flags);
 
817
                mrq->cmd->error = -EAGAIN;
 
818
                mmc_request_done(mmc, mrq);
 
819
                return;
 
820
        }
 
821
 
 
822
        host->state = STATE_REQUEST;
 
823
        spin_unlock_irqrestore(&host->lock, flags);
801
824
 
802
825
        switch (mrq->cmd->opcode) {
803
826
        /* MMCIF does not support SD/SDIO command */
804
827
        case SD_IO_SEND_OP_COND:
805
828
        case MMC_APP_CMD:
 
829
                host->state = STATE_IDLE;
806
830
                mrq->cmd->error = -ETIMEDOUT;
807
831
                mmc_request_done(mmc, mrq);
808
832
                return;
809
833
        case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
810
834
                if (!mrq->data) {
811
835
                        /* send_if_cond cmd (not support) */
 
836
                        host->state = STATE_IDLE;
812
837
                        mrq->cmd->error = -ETIMEDOUT;
813
838
                        mmc_request_done(mmc, mrq);
814
839
                        return;
830
855
        sh_mmcif_start_cmd(host, mrq, mrq->cmd);
831
856
        host->data = NULL;
832
857
 
833
 
        if (mrq->cmd->error != 0) {
834
 
                mmc_request_done(mmc, mrq);
835
 
                return;
836
 
        }
837
 
        if (mrq->stop)
 
858
        if (!mrq->cmd->error && mrq->stop)
838
859
                sh_mmcif_stop_cmd(host, mrq, mrq->stop);
 
860
        host->state = STATE_IDLE;
839
861
        mmc_request_done(mmc, mrq);
840
862
}
841
863
 
843
865
{
844
866
        struct sh_mmcif_host *host = mmc_priv(mmc);
845
867
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
 
868
        unsigned long flags;
 
869
 
 
870
        spin_lock_irqsave(&host->lock, flags);
 
871
        if (host->state != STATE_IDLE) {
 
872
                spin_unlock_irqrestore(&host->lock, flags);
 
873
                return;
 
874
        }
 
875
 
 
876
        host->state = STATE_IOS;
 
877
        spin_unlock_irqrestore(&host->lock, flags);
846
878
 
847
879
        if (ios->power_mode == MMC_POWER_UP) {
848
880
                if (p->set_pwr)
849
881
                        p->set_pwr(host->pd, ios->power_mode);
 
882
                if (!host->power) {
 
883
                        /* See if we also get DMA */
 
884
                        sh_mmcif_request_dma(host, host->pd->dev.platform_data);
 
885
                        pm_runtime_get_sync(&host->pd->dev);
 
886
                        host->power = true;
 
887
                }
850
888
        } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
851
889
                /* clock stop */
852
890
                sh_mmcif_clock_control(host, 0);
853
 
                if (ios->power_mode == MMC_POWER_OFF && p->down_pwr)
854
 
                        p->down_pwr(host->pd);
 
891
                if (ios->power_mode == MMC_POWER_OFF) {
 
892
                        if (host->power) {
 
893
                                pm_runtime_put(&host->pd->dev);
 
894
                                sh_mmcif_release_dma(host);
 
895
                                host->power = false;
 
896
                        }
 
897
                        if (p->down_pwr)
 
898
                                p->down_pwr(host->pd);
 
899
                }
 
900
                host->state = STATE_IDLE;
855
901
                return;
856
902
        }
857
903
 
859
905
                sh_mmcif_clock_control(host, ios->clock);
860
906
 
861
907
        host->bus_width = ios->bus_width;
 
908
        host->state = STATE_IDLE;
862
909
}
863
910
 
864
911
static int sh_mmcif_get_cd(struct mmc_host *mmc)
925
972
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
926
973
                err = 1;
927
974
        } else {
928
 
                dev_dbg(&host->pd->dev, "Not support int\n");
 
975
                dev_dbg(&host->pd->dev, "Unsupported interrupt: 0x%x\n", state);
929
976
                sh_mmcif_writel(host->addr, MMCIF_CE_INT, ~state);
930
977
                sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state);
931
978
                err = 1;
996
1043
        host->pd = pdev;
997
1044
 
998
1045
        init_completion(&host->intr_wait);
 
1046
        spin_lock_init(&host->lock);
999
1047
 
1000
1048
        mmc->ops = &sh_mmcif_ops;
1001
1049
        mmc->f_max = host->clk;
1020
1068
        sh_mmcif_sync_reset(host);
1021
1069
        platform_set_drvdata(pdev, host);
1022
1070
 
1023
 
        /* See if we also get DMA */
1024
 
        sh_mmcif_request_dma(host, pd);
 
1071
        pm_runtime_enable(&pdev->dev);
 
1072
        host->power = false;
 
1073
 
 
1074
        ret = pm_runtime_resume(&pdev->dev);
 
1075
        if (ret < 0)
 
1076
                goto clean_up2;
1025
1077
 
1026
1078
        mmc_add_host(mmc);
1027
1079
 
 
1080
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
1081
 
1028
1082
        ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host);
1029
1083
        if (ret) {
1030
1084
                dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
1031
 
                goto clean_up2;
 
1085
                goto clean_up3;
1032
1086
        }
1033
1087
        ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host);
1034
1088
        if (ret) {
1035
1089
                free_irq(irq[0], host);
1036
1090
                dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
1037
 
                goto clean_up2;
 
1091
                goto clean_up3;
1038
1092
        }
1039
1093
 
1040
 
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
1041
1094
        sh_mmcif_detect(host->mmc);
1042
1095
 
1043
1096
        dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
1045
1098
                sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
1046
1099
        return ret;
1047
1100
 
 
1101
clean_up3:
 
1102
        mmc_remove_host(mmc);
 
1103
        pm_runtime_suspend(&pdev->dev);
1048
1104
clean_up2:
 
1105
        pm_runtime_disable(&pdev->dev);
1049
1106
        clk_disable(host->hclk);
1050
1107
clean_up1:
1051
1108
        mmc_free_host(mmc);
1060
1117
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
1061
1118
        int irq[2];
1062
1119
 
 
1120
        pm_runtime_get_sync(&pdev->dev);
 
1121
 
1063
1122
        mmc_remove_host(host->mmc);
1064
 
        sh_mmcif_release_dma(host);
 
1123
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
1065
1124
 
1066
1125
        if (host->addr)
1067
1126
                iounmap(host->addr);
1068
1127
 
1069
 
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
1070
 
 
1071
1128
        irq[0] = platform_get_irq(pdev, 0);
1072
1129
        irq[1] = platform_get_irq(pdev, 1);
1073
1130
 
1078
1135
 
1079
1136
        clk_disable(host->hclk);
1080
1137
        mmc_free_host(host->mmc);
 
1138
        pm_runtime_put_sync(&pdev->dev);
 
1139
        pm_runtime_disable(&pdev->dev);
1081
1140
 
1082
1141
        return 0;
1083
1142
}
1084
1143
 
 
1144
#ifdef CONFIG_PM
 
1145
static int sh_mmcif_suspend(struct device *dev)
 
1146
{
 
1147
        struct platform_device *pdev = to_platform_device(dev);
 
1148
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 
1149
        int ret = mmc_suspend_host(host->mmc);
 
1150
 
 
1151
        if (!ret) {
 
1152
                sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
1153
                clk_disable(host->hclk);
 
1154
        }
 
1155
 
 
1156
        return ret;
 
1157
}
 
1158
 
 
1159
static int sh_mmcif_resume(struct device *dev)
 
1160
{
 
1161
        struct platform_device *pdev = to_platform_device(dev);
 
1162
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
 
1163
 
 
1164
        clk_enable(host->hclk);
 
1165
 
 
1166
        return mmc_resume_host(host->mmc);
 
1167
}
 
1168
#else
 
1169
#define sh_mmcif_suspend        NULL
 
1170
#define sh_mmcif_resume         NULL
 
1171
#endif  /* CONFIG_PM */
 
1172
 
 
1173
static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
 
1174
        .suspend = sh_mmcif_suspend,
 
1175
        .resume = sh_mmcif_resume,
 
1176
};
 
1177
 
1085
1178
static struct platform_driver sh_mmcif_driver = {
1086
1179
        .probe          = sh_mmcif_probe,
1087
1180
        .remove         = sh_mmcif_remove,
1088
1181
        .driver         = {
1089
1182
                .name   = DRIVER_NAME,
 
1183
                .pm     = &sh_mmcif_dev_pm_ops,
1090
1184
        },
1091
1185
};
1092
1186