diff options
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 125 |
1 files changed, 34 insertions, 91 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 38adc330c007..54bfd0cc106b 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <linux/mmc/core.h> | 35 | #include <linux/mmc/core.h> |
36 | #include <linux/mmc/mmc.h> | 36 | #include <linux/mmc/mmc.h> |
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/semaphore.h> | ||
39 | #include <linux/gpio.h> | 38 | #include <linux/gpio.h> |
40 | #include <linux/regulator/consumer.h> | 39 | #include <linux/regulator/consumer.h> |
41 | #include <linux/pm_runtime.h> | 40 | #include <linux/pm_runtime.h> |
@@ -44,7 +43,6 @@ | |||
44 | #include <plat/cpu.h> | 43 | #include <plat/cpu.h> |
45 | 44 | ||
46 | /* OMAP HSMMC Host Controller Registers */ | 45 | /* OMAP HSMMC Host Controller Registers */ |
47 | #define OMAP_HSMMC_SYSCONFIG 0x0010 | ||
48 | #define OMAP_HSMMC_SYSSTATUS 0x0014 | 46 | #define OMAP_HSMMC_SYSSTATUS 0x0014 |
49 | #define OMAP_HSMMC_CON 0x002C | 47 | #define OMAP_HSMMC_CON 0x002C |
50 | #define OMAP_HSMMC_BLK 0x0104 | 48 | #define OMAP_HSMMC_BLK 0x0104 |
@@ -161,8 +159,6 @@ struct omap_hsmmc_host { | |||
161 | unsigned int dma_sg_idx; | 159 | unsigned int dma_sg_idx; |
162 | unsigned char bus_mode; | 160 | unsigned char bus_mode; |
163 | unsigned char power_mode; | 161 | unsigned char power_mode; |
164 | u32 *buffer; | ||
165 | u32 bytesleft; | ||
166 | int suspended; | 162 | int suspended; |
167 | int irq; | 163 | int irq; |
168 | int use_dma, dma_ch; | 164 | int use_dma, dma_ch; |
@@ -171,7 +167,6 @@ struct omap_hsmmc_host { | |||
171 | int slot_id; | 167 | int slot_id; |
172 | int response_busy; | 168 | int response_busy; |
173 | int context_loss; | 169 | int context_loss; |
174 | int vdd; | ||
175 | int protect_card; | 170 | int protect_card; |
176 | int reqs_blocked; | 171 | int reqs_blocked; |
177 | int use_reg; | 172 | int use_reg; |
@@ -300,12 +295,12 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host) | |||
300 | struct regulator *reg; | 295 | struct regulator *reg; |
301 | int ocr_value = 0; | 296 | int ocr_value = 0; |
302 | 297 | ||
303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
304 | |||
305 | reg = regulator_get(host->dev, "vmmc"); | 298 | reg = regulator_get(host->dev, "vmmc"); |
306 | if (IS_ERR(reg)) { | 299 | if (IS_ERR(reg)) { |
307 | dev_dbg(host->dev, "vmmc regulator missing\n"); | 300 | dev_dbg(host->dev, "vmmc regulator missing\n"); |
301 | return PTR_ERR(reg); | ||
308 | } else { | 302 | } else { |
303 | mmc_slot(host).set_power = omap_hsmmc_set_power; | ||
309 | host->vcc = reg; | 304 | host->vcc = reg; |
310 | ocr_value = mmc_regulator_get_ocrmask(reg); | 305 | ocr_value = mmc_regulator_get_ocrmask(reg); |
311 | if (!mmc_slot(host).ocr_mask) { | 306 | if (!mmc_slot(host).ocr_mask) { |
@@ -495,7 +490,7 @@ static void omap_hsmmc_set_clock(struct omap_hsmmc_host *host) | |||
495 | unsigned long regval; | 490 | unsigned long regval; |
496 | unsigned long timeout; | 491 | unsigned long timeout; |
497 | 492 | ||
498 | dev_dbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); | 493 | dev_vdbg(mmc_dev(host->mmc), "Set clock to %uHz\n", ios->clock); |
499 | 494 | ||
500 | omap_hsmmc_stop_clock(host); | 495 | omap_hsmmc_stop_clock(host); |
501 | 496 | ||
@@ -579,21 +574,8 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
579 | if (host->context_loss == context_loss) | 574 | if (host->context_loss == context_loss) |
580 | return 1; | 575 | return 1; |
581 | 576 | ||
582 | /* Wait for hardware reset */ | 577 | if (!OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) |
583 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | 578 | return 1; |
584 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
585 | && time_before(jiffies, timeout)) | ||
586 | ; | ||
587 | |||
588 | /* Do software reset */ | ||
589 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); | ||
590 | timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); | ||
591 | while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE | ||
592 | && time_before(jiffies, timeout)) | ||
593 | ; | ||
594 | |||
595 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
596 | OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
597 | 579 | ||
598 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { | 580 | if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) { |
599 | if (host->power_mode != MMC_POWER_OFF && | 581 | if (host->power_mode != MMC_POWER_OFF && |
@@ -745,7 +727,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
745 | { | 727 | { |
746 | int cmdreg = 0, resptype = 0, cmdtype = 0; | 728 | int cmdreg = 0, resptype = 0, cmdtype = 0; |
747 | 729 | ||
748 | dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", | 730 | dev_vdbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n", |
749 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 731 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
750 | host->cmd = cmd; | 732 | host->cmd = cmd; |
751 | 733 | ||
@@ -934,7 +916,7 @@ static void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, u32 status) | |||
934 | buf += len; | 916 | buf += len; |
935 | } | 917 | } |
936 | 918 | ||
937 | dev_dbg(mmc_dev(host->mmc), "%s\n", res); | 919 | dev_vdbg(mmc_dev(host->mmc), "%s\n", res); |
938 | } | 920 | } |
939 | #else | 921 | #else |
940 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, | 922 | static inline void omap_hsmmc_dbg_report_irq(struct omap_hsmmc_host *host, |
@@ -981,72 +963,40 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
981 | __func__); | 963 | __func__); |
982 | } | 964 | } |
983 | 965 | ||
966 | static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, int err) | ||
967 | { | ||
968 | omap_hsmmc_reset_controller_fsm(host, SRC); | ||
969 | host->cmd->error = err; | ||
970 | |||
971 | if (host->data) { | ||
972 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
973 | omap_hsmmc_dma_cleanup(host, err); | ||
974 | } | ||
975 | |||
976 | } | ||
977 | |||
984 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) | 978 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) |
985 | { | 979 | { |
986 | struct mmc_data *data; | 980 | struct mmc_data *data; |
987 | int end_cmd = 0, end_trans = 0; | 981 | int end_cmd = 0, end_trans = 0; |
988 | 982 | ||
989 | if (!host->req_in_progress) { | ||
990 | do { | ||
991 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
992 | /* Flush posted write */ | ||
993 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
994 | } while (status & INT_EN_MASK); | ||
995 | return; | ||
996 | } | ||
997 | |||
998 | data = host->data; | 983 | data = host->data; |
999 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | 984 | dev_vdbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); |
1000 | 985 | ||
1001 | if (status & ERR) { | 986 | if (status & ERR) { |
1002 | omap_hsmmc_dbg_report_irq(host, status); | 987 | omap_hsmmc_dbg_report_irq(host, status); |
1003 | if ((status & CMD_TIMEOUT) || | 988 | if (status & (CMD_TIMEOUT | DATA_TIMEOUT)) |
1004 | (status & CMD_CRC)) { | 989 | hsmmc_command_incomplete(host, -ETIMEDOUT); |
1005 | if (host->cmd) { | 990 | else if (status & (CMD_CRC | DATA_CRC)) |
1006 | if (status & CMD_TIMEOUT) { | 991 | hsmmc_command_incomplete(host, -EILSEQ); |
1007 | omap_hsmmc_reset_controller_fsm(host, | 992 | |
1008 | SRC); | 993 | end_cmd = 1; |
1009 | host->cmd->error = -ETIMEDOUT; | 994 | if (host->data || host->response_busy) { |
1010 | } else { | 995 | end_trans = 1; |
1011 | host->cmd->error = -EILSEQ; | 996 | host->response_busy = 0; |
1012 | } | ||
1013 | end_cmd = 1; | ||
1014 | } | ||
1015 | if (host->data || host->response_busy) { | ||
1016 | if (host->data) | ||
1017 | omap_hsmmc_dma_cleanup(host, | ||
1018 | -ETIMEDOUT); | ||
1019 | host->response_busy = 0; | ||
1020 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
1021 | } | ||
1022 | } | ||
1023 | if ((status & DATA_TIMEOUT) || | ||
1024 | (status & DATA_CRC)) { | ||
1025 | if (host->data || host->response_busy) { | ||
1026 | int err = (status & DATA_TIMEOUT) ? | ||
1027 | -ETIMEDOUT : -EILSEQ; | ||
1028 | |||
1029 | if (host->data) | ||
1030 | omap_hsmmc_dma_cleanup(host, err); | ||
1031 | else | ||
1032 | host->mrq->cmd->error = err; | ||
1033 | host->response_busy = 0; | ||
1034 | omap_hsmmc_reset_controller_fsm(host, SRD); | ||
1035 | end_trans = 1; | ||
1036 | } | ||
1037 | } | ||
1038 | if (status & CARD_ERR) { | ||
1039 | dev_dbg(mmc_dev(host->mmc), | ||
1040 | "Ignoring card err CMD%d\n", host->cmd->opcode); | ||
1041 | if (host->cmd) | ||
1042 | end_cmd = 1; | ||
1043 | if (host->data) | ||
1044 | end_trans = 1; | ||
1045 | } | 997 | } |
1046 | } | 998 | } |
1047 | 999 | ||
1048 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
1049 | |||
1050 | if (end_cmd || ((status & CC) && host->cmd)) | 1000 | if (end_cmd || ((status & CC) && host->cmd)) |
1051 | omap_hsmmc_cmd_done(host, host->cmd); | 1001 | omap_hsmmc_cmd_done(host, host->cmd); |
1052 | if ((end_trans || (status & TC)) && host->mrq) | 1002 | if ((end_trans || (status & TC)) && host->mrq) |
@@ -1062,11 +1012,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | |||
1062 | int status; | 1012 | int status; |
1063 | 1013 | ||
1064 | status = OMAP_HSMMC_READ(host->base, STAT); | 1014 | status = OMAP_HSMMC_READ(host->base, STAT); |
1065 | do { | 1015 | while (status & INT_EN_MASK && host->req_in_progress) { |
1066 | omap_hsmmc_do_irq(host, status); | 1016 | omap_hsmmc_do_irq(host, status); |
1017 | |||
1067 | /* Flush posted write */ | 1018 | /* Flush posted write */ |
1019 | OMAP_HSMMC_WRITE(host->base, STAT, status); | ||
1068 | status = OMAP_HSMMC_READ(host->base, STAT); | 1020 | status = OMAP_HSMMC_READ(host->base, STAT); |
1069 | } while (status & INT_EN_MASK); | 1021 | } |
1070 | 1022 | ||
1071 | return IRQ_HANDLED; | 1023 | return IRQ_HANDLED; |
1072 | } | 1024 | } |
@@ -1501,12 +1453,10 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1501 | case MMC_POWER_OFF: | 1453 | case MMC_POWER_OFF: |
1502 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1454 | mmc_slot(host).set_power(host->dev, host->slot_id, |
1503 | 0, 0); | 1455 | 0, 0); |
1504 | host->vdd = 0; | ||
1505 | break; | 1456 | break; |
1506 | case MMC_POWER_UP: | 1457 | case MMC_POWER_UP: |
1507 | mmc_slot(host).set_power(host->dev, host->slot_id, | 1458 | mmc_slot(host).set_power(host->dev, host->slot_id, |
1508 | 1, ios->vdd); | 1459 | 1, ios->vdd); |
1509 | host->vdd = ios->vdd; | ||
1510 | break; | 1460 | break; |
1511 | case MMC_POWER_ON: | 1461 | case MMC_POWER_ON: |
1512 | do_send_init_stream = 1; | 1462 | do_send_init_stream = 1; |
@@ -1598,10 +1548,6 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) | |||
1598 | value = OMAP_HSMMC_READ(host->base, CAPA); | 1548 | value = OMAP_HSMMC_READ(host->base, CAPA); |
1599 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | 1549 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); |
1600 | 1550 | ||
1601 | /* Set the controller to AUTO IDLE mode */ | ||
1602 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
1603 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
1604 | |||
1605 | /* Set SD bus power bit */ | 1551 | /* Set SD bus power bit */ |
1606 | set_sd_bus_power(host); | 1552 | set_sd_bus_power(host); |
1607 | } | 1553 | } |
@@ -1659,8 +1605,6 @@ static int omap_hsmmc_regs_show(struct seq_file *s, void *data) | |||
1659 | 1605 | ||
1660 | pm_runtime_get_sync(host->dev); | 1606 | pm_runtime_get_sync(host->dev); |
1661 | 1607 | ||
1662 | seq_printf(s, "SYSCONFIG:\t0x%08x\n", | ||
1663 | OMAP_HSMMC_READ(host->base, SYSCONFIG)); | ||
1664 | seq_printf(s, "CON:\t\t0x%08x\n", | 1608 | seq_printf(s, "CON:\t\t0x%08x\n", |
1665 | OMAP_HSMMC_READ(host->base, CON)); | 1609 | OMAP_HSMMC_READ(host->base, CON)); |
1666 | seq_printf(s, "HCTL:\t\t0x%08x\n", | 1610 | seq_printf(s, "HCTL:\t\t0x%08x\n", |
@@ -2105,8 +2049,7 @@ static int omap_hsmmc_suspend(struct device *dev) | |||
2105 | if (ret) { | 2049 | if (ret) { |
2106 | host->suspended = 0; | 2050 | host->suspended = 0; |
2107 | if (host->pdata->resume) { | 2051 | if (host->pdata->resume) { |
2108 | ret = host->pdata->resume(dev, host->slot_id); | 2052 | if (host->pdata->resume(dev, host->slot_id)) |
2109 | if (ret) | ||
2110 | dev_dbg(dev, "Unmask interrupt failed\n"); | 2053 | dev_dbg(dev, "Unmask interrupt failed\n"); |
2111 | } | 2054 | } |
2112 | goto err; | 2055 | goto err; |