diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-07 23:14:19 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-09-07 23:14:19 -0400 |
commit | 8de4651abe61c6b6a94a70a57ef163020fed05ee (patch) | |
tree | a2455b59b7df7239a5819b9cf2248e27eef483c4 /drivers/mmc | |
parent | 327fff3e1391a27dcc89de6e0481689a865361c9 (diff) | |
parent | 9c31e8840836de447e1e508a6d756af419790ed6 (diff) |
Merge tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next
Pull MFD (multi-function device) updates from Samuel Ortiz:
"For the 3.12 merge window we have one new driver for the DA9063 PMIC
from Dialog Semiconductor.
Besides that driver we also have:
- Device tree support for the s2mps11 driver
- More devm_* conversion for the pm8921, max89xx, menelaus, tps65010,
wl1273 and pcf50633-adc drivers.
- A conversion to threaded IRQ and IRQ domain for the twl6030 driver.
- A fairly big update for the rtsx driver: Better power saving
support, better vendor settings handling, and a few fixes.
- Support for a couple more boards (COMe-bHL6 and COMe-cTH6) for the
Kontron driver.
- A conversion to the dev_get_platdata() API for all MFD drivers.
- A removal of non-DT (legacy) support for the twl6040 driver.
- A few fixes and additions (Mic detect level) to the wm5110 register
tables.
- Regmap support for the davinci_voicecodec driver.
- The usual bunch of minor cleanups and janitorial fixes"
* tag 'mfd-3.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/mfd-next: (81 commits)
mfd: ucb1x00-core: Rewrite ucb1x00_add_dev()
mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for event name
mfd: ab8500-debugfs: Apply a check for -ENOMEM after allocating memory for sysfs
mfd: timberdale: Use module_pci_driver
mfd: timberdale: Remove redundant break
mfd: timberdale: Staticize local variables
mfd: ab8500-debugfs: Staticize local variables
mfd: db8500-prcmu: Staticize clk_mgt
mfd: db8500-prcmu: Use ANSI function declaration
mfd: omap-usb-host: Staticize usbhs_driver_name
mfd: 88pm805: Fix potential NULL pdata dereference
mfd: 88pm800: Fix potential NULL pdata dereference
mfd: twl6040: Use regmap for register cache
mfd: davinci_voicecodec: Provide a regmap for register I/O
mfd: davinci_voicecodec: Remove unused read and write functions
mmc: memstick: rtsx: Modify copyright comments
mmc: rtsx: Clear SD_CLK toggle enable bit if switching voltage fail
mfd: mmc: rtsx: Change default tx phase
mfd: pcf50633-adc: Use devm_*() functions
mfd: rtsx: Copyright modifications
...
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/rtsx_pci_sdmmc.c | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 82a35b91cdbc..375a880e0c5f 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* Realtek PCI-Express SD/MMC Card Interface driver | 1 | /* Realtek PCI-Express SD/MMC Card Interface driver |
2 | * | 2 | * |
3 | * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. | 3 | * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License as published by the | 6 | * under the terms of the GNU General Public License as published by the |
@@ -17,7 +17,6 @@ | |||
17 | * | 17 | * |
18 | * Author: | 18 | * Author: |
19 | * Wei WANG <wei_wang@realsil.com.cn> | 19 | * Wei WANG <wei_wang@realsil.com.cn> |
20 | * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China | ||
21 | */ | 20 | */ |
22 | 21 | ||
23 | #include <linux/module.h> | 22 | #include <linux/module.h> |
@@ -56,7 +55,6 @@ struct realtek_pci_sdmmc { | |||
56 | bool double_clk; | 55 | bool double_clk; |
57 | bool eject; | 56 | bool eject; |
58 | bool initial_mode; | 57 | bool initial_mode; |
59 | bool ddr_mode; | ||
60 | int power_state; | 58 | int power_state; |
61 | #define SDMMC_POWER_ON 1 | 59 | #define SDMMC_POWER_ON 1 |
62 | #define SDMMC_POWER_OFF 0 | 60 | #define SDMMC_POWER_OFF 0 |
@@ -228,6 +226,7 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
228 | int stat_idx = 0; | 226 | int stat_idx = 0; |
229 | u8 rsp_type; | 227 | u8 rsp_type; |
230 | int rsp_len = 5; | 228 | int rsp_len = 5; |
229 | bool clock_toggled = false; | ||
231 | 230 | ||
232 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", | 231 | dev_dbg(sdmmc_dev(host), "%s: SD/MMC CMD %d, arg = 0x%08x\n", |
233 | __func__, cmd_idx, arg); | 232 | __func__, cmd_idx, arg); |
@@ -271,6 +270,8 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
271 | 0xFF, SD_CLK_TOGGLE_EN); | 270 | 0xFF, SD_CLK_TOGGLE_EN); |
272 | if (err < 0) | 271 | if (err < 0) |
273 | goto out; | 272 | goto out; |
273 | |||
274 | clock_toggled = true; | ||
274 | } | 275 | } |
275 | 276 | ||
276 | rtsx_pci_init_cmd(pcr); | 277 | rtsx_pci_init_cmd(pcr); |
@@ -351,6 +352,10 @@ static void sd_send_cmd_get_rsp(struct realtek_pci_sdmmc *host, | |||
351 | 352 | ||
352 | out: | 353 | out: |
353 | cmd->error = err; | 354 | cmd->error = err; |
355 | |||
356 | if (err && clock_toggled) | ||
357 | rtsx_pci_write_register(pcr, SD_BUS_STAT, | ||
358 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); | ||
354 | } | 359 | } |
355 | 360 | ||
356 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) | 361 | static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq) |
@@ -475,18 +480,24 @@ static void sd_normal_rw(struct realtek_pci_sdmmc *host, | |||
475 | kfree(buf); | 480 | kfree(buf); |
476 | } | 481 | } |
477 | 482 | ||
478 | static int sd_change_phase(struct realtek_pci_sdmmc *host, u8 sample_point) | 483 | static int sd_change_phase(struct realtek_pci_sdmmc *host, |
484 | u8 sample_point, bool rx) | ||
479 | { | 485 | { |
480 | struct rtsx_pcr *pcr = host->pcr; | 486 | struct rtsx_pcr *pcr = host->pcr; |
481 | int err; | 487 | int err; |
482 | 488 | ||
483 | dev_dbg(sdmmc_dev(host), "%s: sample_point = %d\n", | 489 | dev_dbg(sdmmc_dev(host), "%s(%s): sample_point = %d\n", |
484 | __func__, sample_point); | 490 | __func__, rx ? "RX" : "TX", sample_point); |
485 | 491 | ||
486 | rtsx_pci_init_cmd(pcr); | 492 | rtsx_pci_init_cmd(pcr); |
487 | 493 | ||
488 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK); | 494 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, CHANGE_CLK, CHANGE_CLK); |
489 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPRX_CTL, 0x1F, sample_point); | 495 | if (rx) |
496 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
497 | SD_VPRX_CTL, 0x1F, sample_point); | ||
498 | else | ||
499 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, | ||
500 | SD_VPTX_CTL, 0x1F, sample_point); | ||
490 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); | 501 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, PHASE_NOT_RESET, 0); |
491 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, | 502 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL, |
492 | PHASE_NOT_RESET, PHASE_NOT_RESET); | 503 | PHASE_NOT_RESET, PHASE_NOT_RESET); |
@@ -602,7 +613,7 @@ static int sd_tuning_rx_cmd(struct realtek_pci_sdmmc *host, | |||
602 | int err; | 613 | int err; |
603 | u8 cmd[5] = {0}; | 614 | u8 cmd[5] = {0}; |
604 | 615 | ||
605 | err = sd_change_phase(host, sample_point); | 616 | err = sd_change_phase(host, sample_point, true); |
606 | if (err < 0) | 617 | if (err < 0) |
607 | return err; | 618 | return err; |
608 | 619 | ||
@@ -664,7 +675,7 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode) | |||
664 | if (final_phase == 0xFF) | 675 | if (final_phase == 0xFF) |
665 | return -EINVAL; | 676 | return -EINVAL; |
666 | 677 | ||
667 | err = sd_change_phase(host, final_phase); | 678 | err = sd_change_phase(host, final_phase, true); |
668 | if (err < 0) | 679 | if (err < 0) |
669 | return err; | 680 | return err; |
670 | } else { | 681 | } else { |
@@ -833,14 +844,11 @@ static int sd_set_power_mode(struct realtek_pci_sdmmc *host, | |||
833 | return err; | 844 | return err; |
834 | } | 845 | } |
835 | 846 | ||
836 | static int sd_set_timing(struct realtek_pci_sdmmc *host, | 847 | static int sd_set_timing(struct realtek_pci_sdmmc *host, unsigned char timing) |
837 | unsigned char timing, bool *ddr_mode) | ||
838 | { | 848 | { |
839 | struct rtsx_pcr *pcr = host->pcr; | 849 | struct rtsx_pcr *pcr = host->pcr; |
840 | int err = 0; | 850 | int err = 0; |
841 | 851 | ||
842 | *ddr_mode = false; | ||
843 | |||
844 | rtsx_pci_init_cmd(pcr); | 852 | rtsx_pci_init_cmd(pcr); |
845 | 853 | ||
846 | switch (timing) { | 854 | switch (timing) { |
@@ -857,8 +865,6 @@ static int sd_set_timing(struct realtek_pci_sdmmc *host, | |||
857 | break; | 865 | break; |
858 | 866 | ||
859 | case MMC_TIMING_UHS_DDR50: | 867 | case MMC_TIMING_UHS_DDR50: |
860 | *ddr_mode = true; | ||
861 | |||
862 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, | 868 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_CFG1, |
863 | 0x0C | SD_ASYNC_FIFO_NOT_RST, | 869 | 0x0C | SD_ASYNC_FIFO_NOT_RST, |
864 | SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); | 870 | SD_DDR_MODE | SD_ASYNC_FIFO_NOT_RST); |
@@ -926,7 +932,7 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
926 | 932 | ||
927 | sd_set_bus_width(host, ios->bus_width); | 933 | sd_set_bus_width(host, ios->bus_width); |
928 | sd_set_power_mode(host, ios->power_mode); | 934 | sd_set_power_mode(host, ios->power_mode); |
929 | sd_set_timing(host, ios->timing, &host->ddr_mode); | 935 | sd_set_timing(host, ios->timing); |
930 | 936 | ||
931 | host->vpclk = false; | 937 | host->vpclk = false; |
932 | host->double_clk = true; | 938 | host->double_clk = true; |
@@ -1121,11 +1127,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1121 | goto out; | 1127 | goto out; |
1122 | } | 1128 | } |
1123 | 1129 | ||
1130 | out: | ||
1124 | /* Stop toggle SD clock in idle */ | 1131 | /* Stop toggle SD clock in idle */ |
1125 | err = rtsx_pci_write_register(pcr, SD_BUS_STAT, | 1132 | err = rtsx_pci_write_register(pcr, SD_BUS_STAT, |
1126 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); | 1133 | SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0); |
1127 | 1134 | ||
1128 | out: | ||
1129 | mutex_unlock(&pcr->pcr_mutex); | 1135 | mutex_unlock(&pcr->pcr_mutex); |
1130 | 1136 | ||
1131 | return err; | 1137 | return err; |
@@ -1148,9 +1154,35 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
1148 | 1154 | ||
1149 | rtsx_pci_start_run(pcr); | 1155 | rtsx_pci_start_run(pcr); |
1150 | 1156 | ||
1151 | if (!host->ddr_mode) | 1157 | /* Set initial TX phase */ |
1152 | err = sd_tuning_rx(host, MMC_SEND_TUNING_BLOCK); | 1158 | switch (mmc->ios.timing) { |
1159 | case MMC_TIMING_UHS_SDR104: | ||
1160 | err = sd_change_phase(host, SDR104_TX_PHASE(pcr), false); | ||
1161 | break; | ||
1162 | |||
1163 | case MMC_TIMING_UHS_SDR50: | ||
1164 | err = sd_change_phase(host, SDR50_TX_PHASE(pcr), false); | ||
1165 | break; | ||
1166 | |||
1167 | case MMC_TIMING_UHS_DDR50: | ||
1168 | err = sd_change_phase(host, DDR50_TX_PHASE(pcr), false); | ||
1169 | break; | ||
1170 | |||
1171 | default: | ||
1172 | err = 0; | ||
1173 | } | ||
1153 | 1174 | ||
1175 | if (err) | ||
1176 | goto out; | ||
1177 | |||
1178 | /* Tuning RX phase */ | ||
1179 | if ((mmc->ios.timing == MMC_TIMING_UHS_SDR104) || | ||
1180 | (mmc->ios.timing == MMC_TIMING_UHS_SDR50)) | ||
1181 | err = sd_tuning_rx(host, opcode); | ||
1182 | else if (mmc->ios.timing == MMC_TIMING_UHS_DDR50) | ||
1183 | err = sd_change_phase(host, DDR50_RX_PHASE(pcr), true); | ||
1184 | |||
1185 | out: | ||
1154 | mutex_unlock(&pcr->pcr_mutex); | 1186 | mutex_unlock(&pcr->pcr_mutex); |
1155 | 1187 | ||
1156 | return err; | 1188 | return err; |