diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/omap.c | 88 |
1 files changed, 37 insertions, 51 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 0d3cd3c23f8f..c80cd58cfa07 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -983,52 +983,27 @@ static void mmc_omap_request(struct mmc_host *mmc, struct mmc_request *req) | |||
983 | mmc_omap_start_request(host, req); | 983 | mmc_omap_start_request(host, req); |
984 | } | 984 | } |
985 | 985 | ||
986 | static void innovator_fpga_socket_power(int on) | 986 | static void mmc_omap_set_power(struct mmc_omap_slot *slot, int power_on, |
987 | int vdd) | ||
987 | { | 988 | { |
988 | #if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) | 989 | struct mmc_omap_host *host; |
989 | if (on) { | ||
990 | fpga_write(fpga_read(OMAP1510_FPGA_POWER) | (1 << 3), | ||
991 | OMAP1510_FPGA_POWER); | ||
992 | } else { | ||
993 | fpga_write(fpga_read(OMAP1510_FPGA_POWER) & ~(1 << 3), | ||
994 | OMAP1510_FPGA_POWER); | ||
995 | } | ||
996 | #endif | ||
997 | } | ||
998 | 990 | ||
999 | /* | 991 | host = slot->host; |
1000 | * Turn the socket power on/off. Innovator uses FPGA, most boards | 992 | |
1001 | * probably use GPIO. | 993 | if (slot->pdata->set_power != NULL) |
1002 | */ | 994 | slot->pdata->set_power(mmc_dev(slot->mmc), slot->id, power_on, |
1003 | static void mmc_omap_power(struct mmc_omap_host *host, int on) | 995 | vdd); |
1004 | { | 996 | |
1005 | if (on) { | 997 | if (cpu_is_omap24xx()) { |
1006 | if (machine_is_omap_innovator()) | 998 | u16 w; |
1007 | innovator_fpga_socket_power(1); | 999 | |
1008 | else if (machine_is_omap_h2()) | 1000 | if (power_on) { |
1009 | tps65010_set_gpio_out_value(GPIO3, HIGH); | 1001 | w = OMAP_MMC_READ(host, CON); |
1010 | else if (machine_is_omap_h3()) | 1002 | OMAP_MMC_WRITE(host, CON, w | (1 << 11)); |
1011 | /* GPIO 4 of TPS65010 sends SD_EN signal */ | 1003 | } else { |
1012 | tps65010_set_gpio_out_value(GPIO4, HIGH); | 1004 | w = OMAP_MMC_READ(host, CON); |
1013 | else if (cpu_is_omap24xx()) { | 1005 | OMAP_MMC_WRITE(host, CON, w & ~(1 << 11)); |
1014 | u16 reg = OMAP_MMC_READ(host, CON); | 1006 | } |
1015 | OMAP_MMC_WRITE(host, CON, reg | (1 << 11)); | ||
1016 | } else | ||
1017 | if (host->power_pin >= 0) | ||
1018 | omap_set_gpio_dataout(host->power_pin, 1); | ||
1019 | } else { | ||
1020 | if (machine_is_omap_innovator()) | ||
1021 | innovator_fpga_socket_power(0); | ||
1022 | else if (machine_is_omap_h2()) | ||
1023 | tps65010_set_gpio_out_value(GPIO3, LOW); | ||
1024 | else if (machine_is_omap_h3()) | ||
1025 | tps65010_set_gpio_out_value(GPIO4, LOW); | ||
1026 | else if (cpu_is_omap24xx()) { | ||
1027 | u16 reg = OMAP_MMC_READ(host, CON); | ||
1028 | OMAP_MMC_WRITE(host, CON, reg & ~(1 << 11)); | ||
1029 | } else | ||
1030 | if (host->power_pin >= 0) | ||
1031 | omap_set_gpio_dataout(host->power_pin, 0); | ||
1032 | } | 1007 | } |
1033 | } | 1008 | } |
1034 | 1009 | ||
@@ -1067,23 +1042,31 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1067 | int i, dsor; | 1042 | int i, dsor; |
1068 | 1043 | ||
1069 | dsor = mmc_omap_calc_divisor(mmc, ios); | 1044 | dsor = mmc_omap_calc_divisor(mmc, ios); |
1070 | host->bus_mode = ios->bus_mode; | 1045 | |
1071 | host->hw_bus_mode = host->bus_mode; | 1046 | mmc_omap_select_slot(slot, 0); |
1047 | |||
1048 | if (ios->vdd != slot->vdd) | ||
1049 | slot->vdd = ios->vdd; | ||
1072 | 1050 | ||
1073 | switch (ios->power_mode) { | 1051 | switch (ios->power_mode) { |
1074 | case MMC_POWER_OFF: | 1052 | case MMC_POWER_OFF: |
1075 | mmc_omap_power(host, 0); | 1053 | mmc_omap_set_power(slot, 0, ios->vdd); |
1076 | break; | 1054 | break; |
1077 | case MMC_POWER_UP: | 1055 | case MMC_POWER_UP: |
1078 | /* Cannot touch dsor yet, just power up MMC */ | 1056 | /* Cannot touch dsor yet, just power up MMC */ |
1079 | mmc_omap_power(host, 1); | 1057 | mmc_omap_set_power(slot, 1, ios->vdd); |
1080 | return; | 1058 | goto exit; |
1081 | case MMC_POWER_ON: | 1059 | case MMC_POWER_ON: |
1082 | dsor |= 1 << 11; | 1060 | dsor |= 1 << 11; |
1083 | break; | 1061 | break; |
1084 | } | 1062 | } |
1085 | 1063 | ||
1086 | clk_enable(host->fclk); | 1064 | if (slot->bus_mode != ios->bus_mode) { |
1065 | if (slot->pdata->set_bus_mode != NULL) | ||
1066 | slot->pdata->set_bus_mode(mmc_dev(mmc), slot->id, | ||
1067 | ios->bus_mode); | ||
1068 | slot->bus_mode = ios->bus_mode; | ||
1069 | } | ||
1087 | 1070 | ||
1088 | /* On insanely high arm_per frequencies something sometimes | 1071 | /* On insanely high arm_per frequencies something sometimes |
1089 | * goes somehow out of sync, and the POW bit is not being set, | 1072 | * goes somehow out of sync, and the POW bit is not being set, |
@@ -1091,6 +1074,7 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1091 | * Writing to the CON register twice seems to do the trick. */ | 1074 | * Writing to the CON register twice seems to do the trick. */ |
1092 | for (i = 0; i < 2; i++) | 1075 | for (i = 0; i < 2; i++) |
1093 | OMAP_MMC_WRITE(host, CON, dsor); | 1076 | OMAP_MMC_WRITE(host, CON, dsor); |
1077 | slot->saved_con = dsor; | ||
1094 | if (ios->power_mode == MMC_POWER_ON) { | 1078 | if (ios->power_mode == MMC_POWER_ON) { |
1095 | /* Send clock cycles, poll completion */ | 1079 | /* Send clock cycles, poll completion */ |
1096 | OMAP_MMC_WRITE(host, IE, 0); | 1080 | OMAP_MMC_WRITE(host, IE, 0); |
@@ -1099,7 +1083,9 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1099 | while ((OMAP_MMC_READ(host, STAT) & 1) == 0); | 1083 | while ((OMAP_MMC_READ(host, STAT) & 1) == 0); |
1100 | OMAP_MMC_WRITE(host, STAT, 1); | 1084 | OMAP_MMC_WRITE(host, STAT, 1); |
1101 | } | 1085 | } |
1102 | clk_disable(host->fclk); | 1086 | |
1087 | exit: | ||
1088 | mmc_omap_release_slot(slot); | ||
1103 | } | 1089 | } |
1104 | 1090 | ||
1105 | static const struct mmc_host_ops mmc_omap_ops = { | 1091 | static const struct mmc_host_ops mmc_omap_ops = { |