aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/rtsx_pci_sdmmc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 20:17:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-08-07 20:17:39 -0400
commit54c72d5987ff9f3cf59529d5d4f5cf19eae3f695 (patch)
tree3fee972d54926627895aa07684ddb2e2388e4614 /drivers/mmc/host/rtsx_pci_sdmmc.c
parent66bb0aa077978dbb76e6283531eb3cc7a878de38 (diff)
parent7caa79917ad4c1f91366b11f18e48623554aaa52 (diff)
Merge tag 'mfd-for-linus-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
Pull MFD update from Lee Jones: "Changes to existing drivers: - checkpatch fixes throughout the subsystem - use Regmap to handle IRQs in max77686, extcon-max77693 and mc13xxx-core - use DMA in rtsx_pcr - restrict building on unsupported architectures on timberdale, cs5535 - SPI hardening in cros_ec_spi - more robust error handing in asic3, cros_ec, ab8500-debugfs, max77686 and pcf50633-core - reorder PM runtime and regulator handing during shutdown in arizona - enable wakeup in cros_ec_spi - unused variable/code clean-up in pm8921-core, cros_ec, htc-i2cpld, tps65912-spi, wm5110-tables and ab8500-debugfs - add regulator handing into suspend() in sec-core - remove pointless wrapper functions in extcon-max77693 and i2c-cros-ec-tunnel - use cross-architecture friendly data sizes in stmpe-i2c, arizona, max77686 and tps65910 - devicetree documentation updates throughout - provide power management support in max77686 - few OF clean-ups in max77686 - use manged resources in tps6105x New drivers/supported devices: - add support for s2mpu02 to sec-core - add support for Allwinner A32 to sun6i-prcm - add support for Maxim 77802 in max77686 - add support for DA9063 AD in da9063 - new driver for Intel PMICs (generic) and specifically Crystal Cove (Re-)moved drivers == - move out keyboard functionality cros_ec ==> input/keyboard/cros_ec_keyb" * tag 'mfd-for-linus-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (101 commits) MAINTAINERS: Update MFD repo location mfd: omap-usb-host: Fix improper mask use. mfd: arizona: Only free the CTRLIF_ERR IRQ if we requested it mfd: arizona: Add missing handling for ISRC3 under/overclocked mfd: wm5110: Add new interrupt register definitions mfd: arizona: Rename thermal shutdown interrupt mfd: wm5110: Add in the output done interrupts mfd: wm5110: Remove non-existant interrupts mfd: tps65912-spi: Remove unused variable mfd: htc-i2cpld: Remove unused code mfd: da9063: Add support for AD silicon variant mfd: arizona: Map MICVDD from extcon device to the Arizona core mfd: arizona: Add MICVDD to mapped regulators for wm8997 mfd: max77686: Ensure device type IDs are architecture agnostic mfd: max77686: Add Maxim 77802 PMIC support mfd: tps6105x: Use managed resources when allocating memory mfd: wm8997-tables: Suppress 'line over 80 chars' warnings mfd: kempld-core: Correct a variety of checkpatch warnings mfd: ipaq-micro: Fix coding style errors/warnings reported by checkpatch mfd: si476x-cmd: Remedy checkpatch style complains ...
Diffstat (limited to 'drivers/mmc/host/rtsx_pci_sdmmc.c')
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c133
1 files changed, 127 insertions, 6 deletions
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 0d519649b575..dfde4a210238 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -24,6 +24,7 @@
24#include <linux/highmem.h> 24#include <linux/highmem.h>
25#include <linux/delay.h> 25#include <linux/delay.h>
26#include <linux/platform_device.h> 26#include <linux/platform_device.h>
27#include <linux/workqueue.h>
27#include <linux/mmc/host.h> 28#include <linux/mmc/host.h>
28#include <linux/mmc/mmc.h> 29#include <linux/mmc/mmc.h>
29#include <linux/mmc/sd.h> 30#include <linux/mmc/sd.h>
@@ -36,7 +37,10 @@ struct realtek_pci_sdmmc {
36 struct rtsx_pcr *pcr; 37 struct rtsx_pcr *pcr;
37 struct mmc_host *mmc; 38 struct mmc_host *mmc;
38 struct mmc_request *mrq; 39 struct mmc_request *mrq;
40 struct workqueue_struct *workq;
41#define SDMMC_WORKQ_NAME "rtsx_pci_sdmmc_workq"
39 42
43 struct work_struct work;
40 struct mutex host_mutex; 44 struct mutex host_mutex;
41 45
42 u8 ssc_depth; 46 u8 ssc_depth;
@@ -48,6 +52,11 @@ struct realtek_pci_sdmmc {
48 int power_state; 52 int power_state;
49#define SDMMC_POWER_ON 1 53#define SDMMC_POWER_ON 1
50#define SDMMC_POWER_OFF 0 54#define SDMMC_POWER_OFF 0
55
56 unsigned int sg_count;
57 s32 cookie;
58 unsigned int cookie_sg_count;
59 bool using_cookie;
51}; 60};
52 61
53static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host) 62static inline struct device *sdmmc_dev(struct realtek_pci_sdmmc *host)
@@ -86,6 +95,77 @@ static void sd_print_debug_regs(struct realtek_pci_sdmmc *host)
86#define sd_print_debug_regs(host) 95#define sd_print_debug_regs(host)
87#endif /* DEBUG */ 96#endif /* DEBUG */
88 97
98/*
99 * sd_pre_dma_transfer - do dma_map_sg() or using cookie
100 *
101 * @pre: if called in pre_req()
102 * return:
103 * 0 - do dma_map_sg()
104 * 1 - using cookie
105 */
106static int sd_pre_dma_transfer(struct realtek_pci_sdmmc *host,
107 struct mmc_data *data, bool pre)
108{
109 struct rtsx_pcr *pcr = host->pcr;
110 int read = data->flags & MMC_DATA_READ;
111 int count = 0;
112 int using_cookie = 0;
113
114 if (!pre && data->host_cookie && data->host_cookie != host->cookie) {
115 dev_err(sdmmc_dev(host),
116 "error: data->host_cookie = %d, host->cookie = %d\n",
117 data->host_cookie, host->cookie);
118 data->host_cookie = 0;
119 }
120
121 if (pre || data->host_cookie != host->cookie) {
122 count = rtsx_pci_dma_map_sg(pcr, data->sg, data->sg_len, read);
123 } else {
124 count = host->cookie_sg_count;
125 using_cookie = 1;
126 }
127
128 if (pre) {
129 host->cookie_sg_count = count;
130 if (++host->cookie < 0)
131 host->cookie = 1;
132 data->host_cookie = host->cookie;
133 } else {
134 host->sg_count = count;
135 }
136
137 return using_cookie;
138}
139
140static void sdmmc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
141 bool is_first_req)
142{
143 struct realtek_pci_sdmmc *host = mmc_priv(mmc);
144 struct mmc_data *data = mrq->data;
145
146 if (data->host_cookie) {
147 dev_err(sdmmc_dev(host),
148 "error: reset data->host_cookie = %d\n",
149 data->host_cookie);
150 data->host_cookie = 0;
151 }
152
153 sd_pre_dma_transfer(host, data, true);
154 dev_dbg(sdmmc_dev(host), "pre dma sg: %d\n", host->cookie_sg_count);
155}
156
157static void sdmmc_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
158 int err)
159{
160 struct realtek_pci_sdmmc *host = mmc_priv(mmc);
161 struct rtsx_pcr *pcr = host->pcr;
162 struct mmc_data *data = mrq->data;
163 int read = data->flags & MMC_DATA_READ;
164
165 rtsx_pci_dma_unmap_sg(pcr, data->sg, data->sg_len, read);
166 data->host_cookie = 0;
167}
168
89static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt, 169static int sd_read_data(struct realtek_pci_sdmmc *host, u8 *cmd, u16 byte_cnt,
90 u8 *buf, int buf_len, int timeout) 170 u8 *buf, int buf_len, int timeout)
91{ 171{
@@ -415,7 +495,7 @@ static int sd_rw_multi(struct realtek_pci_sdmmc *host, struct mmc_request *mrq)
415 495
416 rtsx_pci_send_cmd_no_wait(pcr); 496 rtsx_pci_send_cmd_no_wait(pcr);
417 497
418 err = rtsx_pci_transfer_data(pcr, data->sg, data->sg_len, read, 10000); 498 err = rtsx_pci_dma_transfer(pcr, data->sg, host->sg_count, read, 10000);
419 if (err < 0) { 499 if (err < 0) {
420 sd_clear_error(host); 500 sd_clear_error(host);
421 return err; 501 return err;
@@ -640,12 +720,24 @@ static int sd_tuning_rx(struct realtek_pci_sdmmc *host, u8 opcode)
640 return 0; 720 return 0;
641} 721}
642 722
643static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) 723static inline int sd_rw_cmd(struct mmc_command *cmd)
644{ 724{
645 struct realtek_pci_sdmmc *host = mmc_priv(mmc); 725 return mmc_op_multi(cmd->opcode) ||
726 (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
727 (cmd->opcode == MMC_WRITE_BLOCK);
728}
729
730static void sd_request(struct work_struct *work)
731{
732 struct realtek_pci_sdmmc *host = container_of(work,
733 struct realtek_pci_sdmmc, work);
646 struct rtsx_pcr *pcr = host->pcr; 734 struct rtsx_pcr *pcr = host->pcr;
735
736 struct mmc_host *mmc = host->mmc;
737 struct mmc_request *mrq = host->mrq;
647 struct mmc_command *cmd = mrq->cmd; 738 struct mmc_command *cmd = mrq->cmd;
648 struct mmc_data *data = mrq->data; 739 struct mmc_data *data = mrq->data;
740
649 unsigned int data_size = 0; 741 unsigned int data_size = 0;
650 int err; 742 int err;
651 743
@@ -677,13 +769,13 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
677 if (mrq->data) 769 if (mrq->data)
678 data_size = data->blocks * data->blksz; 770 data_size = data->blocks * data->blksz;
679 771
680 if (!data_size || mmc_op_multi(cmd->opcode) || 772 if (!data_size || sd_rw_cmd(cmd)) {
681 (cmd->opcode == MMC_READ_SINGLE_BLOCK) ||
682 (cmd->opcode == MMC_WRITE_BLOCK)) {
683 sd_send_cmd_get_rsp(host, cmd); 773 sd_send_cmd_get_rsp(host, cmd);
684 774
685 if (!cmd->error && data_size) { 775 if (!cmd->error && data_size) {
686 sd_rw_multi(host, mrq); 776 sd_rw_multi(host, mrq);
777 if (!host->using_cookie)
778 sdmmc_post_req(host->mmc, host->mrq, 0);
687 779
688 if (mmc_op_multi(cmd->opcode) && mrq->stop) 780 if (mmc_op_multi(cmd->opcode) && mrq->stop)
689 sd_send_cmd_get_rsp(host, mrq->stop); 781 sd_send_cmd_get_rsp(host, mrq->stop);
@@ -712,6 +804,21 @@ finish:
712 mmc_request_done(mmc, mrq); 804 mmc_request_done(mmc, mrq);
713} 805}
714 806
807static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
808{
809 struct realtek_pci_sdmmc *host = mmc_priv(mmc);
810 struct mmc_data *data = mrq->data;
811
812 mutex_lock(&host->host_mutex);
813 host->mrq = mrq;
814 mutex_unlock(&host->host_mutex);
815
816 if (sd_rw_cmd(mrq->cmd))
817 host->using_cookie = sd_pre_dma_transfer(host, data, false);
818
819 queue_work(host->workq, &host->work);
820}
821
715static int sd_set_bus_width(struct realtek_pci_sdmmc *host, 822static int sd_set_bus_width(struct realtek_pci_sdmmc *host,
716 unsigned char bus_width) 823 unsigned char bus_width)
717{ 824{
@@ -1146,6 +1253,8 @@ out:
1146} 1253}
1147 1254
1148static const struct mmc_host_ops realtek_pci_sdmmc_ops = { 1255static const struct mmc_host_ops realtek_pci_sdmmc_ops = {
1256 .pre_req = sdmmc_pre_req,
1257 .post_req = sdmmc_post_req,
1149 .request = sdmmc_request, 1258 .request = sdmmc_request,
1150 .set_ios = sdmmc_set_ios, 1259 .set_ios = sdmmc_set_ios,
1151 .get_ro = sdmmc_get_ro, 1260 .get_ro = sdmmc_get_ro,
@@ -1224,10 +1333,16 @@ static int rtsx_pci_sdmmc_drv_probe(struct platform_device *pdev)
1224 return -ENOMEM; 1333 return -ENOMEM;
1225 1334
1226 host = mmc_priv(mmc); 1335 host = mmc_priv(mmc);
1336 host->workq = create_singlethread_workqueue(SDMMC_WORKQ_NAME);
1337 if (!host->workq) {
1338 mmc_free_host(mmc);
1339 return -ENOMEM;
1340 }
1227 host->pcr = pcr; 1341 host->pcr = pcr;
1228 host->mmc = mmc; 1342 host->mmc = mmc;
1229 host->pdev = pdev; 1343 host->pdev = pdev;
1230 host->power_state = SDMMC_POWER_OFF; 1344 host->power_state = SDMMC_POWER_OFF;
1345 INIT_WORK(&host->work, sd_request);
1231 platform_set_drvdata(pdev, host); 1346 platform_set_drvdata(pdev, host);
1232 pcr->slots[RTSX_SD_CARD].p_dev = pdev; 1347 pcr->slots[RTSX_SD_CARD].p_dev = pdev;
1233 pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event; 1348 pcr->slots[RTSX_SD_CARD].card_event = rtsx_pci_sdmmc_card_event;
@@ -1255,6 +1370,8 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
1255 pcr->slots[RTSX_SD_CARD].card_event = NULL; 1370 pcr->slots[RTSX_SD_CARD].card_event = NULL;
1256 mmc = host->mmc; 1371 mmc = host->mmc;
1257 1372
1373 cancel_work_sync(&host->work);
1374
1258 mutex_lock(&host->host_mutex); 1375 mutex_lock(&host->host_mutex);
1259 if (host->mrq) { 1376 if (host->mrq) {
1260 dev_dbg(&(pdev->dev), 1377 dev_dbg(&(pdev->dev),
@@ -1273,6 +1390,10 @@ static int rtsx_pci_sdmmc_drv_remove(struct platform_device *pdev)
1273 mmc_remove_host(mmc); 1390 mmc_remove_host(mmc);
1274 host->eject = true; 1391 host->eject = true;
1275 1392
1393 flush_workqueue(host->workq);
1394 destroy_workqueue(host->workq);
1395 host->workq = NULL;
1396
1276 mmc_free_host(mmc); 1397 mmc_free_host(mmc);
1277 1398
1278 dev_dbg(&(pdev->dev), 1399 dev_dbg(&(pdev->dev),