Merge tag 'v4.4-rc7'
[firefly-linux-kernel-4.4.55.git] / drivers / mmc / host / rk_sdmmc_ops.c
1 /*
2  *  linux/drivers/mmchost/rkemmc_ops.c
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or (at
7  * your option) any later version.
8  */
9
10 #include <linux/mmc/core.h>
11 #include <linux/mmc/card.h>
12 #include <linux/mmc/host.h>
13 #include <linux/mmc/mmc.h>
14 #include <linux/slab.h>
15
16 #include <linux/scatterlist.h>
17 #include <linux/swap.h>         /* For nr_free_buffer_pages() */
18 #include <linux/list.h>
19
20 #include <linux/debugfs.h>
21 #include <linux/uaccess.h>
22 #include <linux/seq_file.h>
23 #include <linux/mutex.h>
24 #include <linux/miscdevice.h>
25
26 #define BLKSZ           512
27
28 struct mmc_card *this_card = NULL;
29 /*
30  * Fill in the mmc_request structure given a set of transfer parameters.
31  */
32 static void rk_emmc_prepare_mrq(struct mmc_request *mrq, struct scatterlist *sg, 
33                 unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
34 {
35         BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
36
37         if (blocks > 1) {
38                 mrq->cmd->opcode = write ?
39                         MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
40         } else {
41                 mrq->cmd->opcode = write ?
42                         MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
43         }
44
45         mrq->cmd->arg = dev_addr;
46         if (!mmc_card_blockaddr(this_card))
47                 mrq->cmd->arg <<= 9;
48
49         mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
50
51         if (blocks == 1)
52                 mrq->stop = NULL;
53         else {
54                 mrq->stop->opcode = MMC_STOP_TRANSMISSION;
55                 mrq->stop->arg = 0;
56                 mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
57         }
58
59         mrq->data->blksz = blksz;
60         mrq->data->blocks = blocks;
61         mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
62         mrq->data->sg = sg;
63         mrq->data->sg_len = sg_len;
64         mmc_set_data_timeout(mrq->data, this_card);
65 }
66
67 static int rk_emmc_busy(struct mmc_command *cmd)
68 {
69         return !(cmd->resp[0] & R1_READY_FOR_DATA) ||
70                 (R1_CURRENT_STATE(cmd->resp[0]) == 7);
71 }
72
73 /*
74  * Wait for the card to finish the busy state
75  */
76 static int rk_emmc_wait_busy(void)
77 {
78         int ret, busy;
79         struct mmc_command cmd = {0};
80
81         busy = 0;
82         do {
83                 memset(&cmd, 0, sizeof(struct mmc_command));
84
85                 cmd.opcode = MMC_SEND_STATUS;
86                 cmd.arg = this_card->rca << 16;
87                 cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
88
89                 ret = mmc_wait_for_cmd(this_card->host, &cmd, 0);
90                 if (ret)
91                         break;
92
93                 if (!busy && rk_emmc_busy(&cmd)) {
94                         busy = 1;
95                         if (this_card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
96                                 pr_info("%s: Warning: Host did not "
97                                         "wait for busy state to end.\n",
98                                         mmc_hostname(this_card->host));
99                 }
100         } while (rk_emmc_busy(&cmd));
101
102         return ret;
103 }
104
105 /*
106  * Transfer a single sector of kernel addressable data
107  */
108 int rk_emmc_transfer(u8 *buffer, unsigned addr, unsigned blksz, int write)
109 {
110         int ret = 0;
111
112         struct mmc_request mrq = {0};
113         struct mmc_command cmd = {0};
114         struct mmc_command stop = {0};
115         struct mmc_data data = {0};
116
117         struct scatterlist sg;
118
119         if(!this_card)
120                 return -EIO;
121
122         mrq.cmd = &cmd;
123         mrq.data = &data;
124         mrq.stop = &stop;
125
126         sg_init_one(&sg, buffer, blksz);
127
128         rk_emmc_prepare_mrq(&mrq, &sg, 1, addr, 1, blksz, write);
129
130         mmc_claim_host(this_card->host);
131         mmc_wait_for_req(this_card->host, &mrq);
132
133         if (cmd.error){
134                 ret = cmd.error;
135                 goto exit;
136         }
137         if (data.error){
138                 ret =  data.error;
139                 goto exit;
140         }
141
142         ret = rk_emmc_wait_busy();
143 exit:
144         mmc_release_host(this_card->host);
145         return ret;
146 }
147 EXPORT_SYMBOL(rk_emmc_transfer);