aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/omap.c88
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
986static void innovator_fpga_socket_power(int on) 986static 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,
1003static 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
1087exit:
1088 mmc_omap_release_slot(slot);
1103} 1089}
1104 1090
1105static const struct mmc_host_ops mmc_omap_ops = { 1091static const struct mmc_host_ops mmc_omap_ops = {