xref: /OK3568_Linux_fs/kernel/drivers/mmc/host/rk_sdmmc_ops.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 #include <linux/pm.h>
26 #include <linux/pm_runtime.h>
27 #include "../core/block.h"
28 #include "../core/card.h"
29 #include "../core/core.h"
30 #include "../core/mmc_ops.h"
31 #include "rk_sdmmc_ops.h"
32 
33 #define BLKSZ		512
34 
35 enum emmc_area_type {
36 	MMC_DATA_AREA_MAIN,
37 	MMC_DATA_AREA_BOOT1,
38 	MMC_DATA_AREA_BOOT2,
39 	MMC_DATA_AREA_RPMB,
40 };
41 
rk_emmc_set_areatype(enum emmc_area_type areatype)42 static int rk_emmc_set_areatype(enum emmc_area_type areatype)
43 {
44 	int err;
45 	u8 part_config;
46 
47 	part_config = this_card->ext_csd.part_config;
48 	part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK;
49 	part_config |= (u8)areatype;
50 	err = mmc_switch(this_card, EXT_CSD_CMD_SET_NORMAL,
51 			 EXT_CSD_PART_CONFIG, part_config,
52 			 this_card->ext_csd.part_time);
53 
54 	return err;
55 }
56 
57 /*
58  * Fill in the mmc_request structure given a set of transfer parameters.
59  */
rk_emmc_prepare_mrq(struct mmc_request * mrq,struct scatterlist * sg,unsigned sg_len,unsigned dev_addr,unsigned blocks,unsigned blksz,int write)60 static void rk_emmc_prepare_mrq(struct mmc_request *mrq, struct scatterlist *sg,
61 		unsigned sg_len, unsigned dev_addr, unsigned blocks, unsigned blksz, int write)
62 {
63 	BUG_ON(!mrq || !mrq->cmd || !mrq->data || !mrq->stop);
64 
65 	if (blocks > 1) {
66 		mrq->cmd->opcode = write ?
67 			MMC_WRITE_MULTIPLE_BLOCK : MMC_READ_MULTIPLE_BLOCK;
68 	} else {
69 		mrq->cmd->opcode = write ?
70 			MMC_WRITE_BLOCK : MMC_READ_SINGLE_BLOCK;
71 	}
72 
73 	mrq->cmd->arg = dev_addr;
74 	if (!mmc_card_blockaddr(this_card))
75 		mrq->cmd->arg <<= 9;
76 
77 	mrq->cmd->flags = MMC_RSP_R1 | MMC_CMD_ADTC;
78 
79 	if (blocks == 1)
80 		mrq->stop = NULL;
81 	else {
82 		mrq->stop->opcode = MMC_STOP_TRANSMISSION;
83 		mrq->stop->arg = 0;
84 		mrq->stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
85 	}
86 
87 	mrq->data->blksz = blksz;
88 	mrq->data->blocks = blocks;
89 	mrq->data->flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
90 	mrq->data->sg = sg;
91 	mrq->data->sg_len = sg_len;
92 	mmc_set_data_timeout(mrq->data, this_card);
93 }
94 
rk_emmc_busy(struct mmc_command * cmd)95 static int rk_emmc_busy(struct mmc_command *cmd)
96 {
97 	return !(cmd->resp[0] & R1_READY_FOR_DATA) ||
98 		(R1_CURRENT_STATE(cmd->resp[0]) == 7);
99 }
100 
101 /*
102  * Wait for the card to finish the busy state
103  */
rk_emmc_wait_busy(void)104 static int rk_emmc_wait_busy(void)
105 {
106 	int ret, busy;
107 	struct mmc_command cmd = {0};
108 
109 	busy = 0;
110 	do {
111 		memset(&cmd, 0, sizeof(struct mmc_command));
112 
113 		cmd.opcode = MMC_SEND_STATUS;
114 		cmd.arg = this_card->rca << 16;
115 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
116 
117 		ret = mmc_wait_for_cmd(this_card->host, &cmd, 0);
118 		if (ret)
119 			break;
120 
121 		if (!busy && rk_emmc_busy(&cmd)) {
122 			busy = 1;
123 			if (this_card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
124 				pr_info("%s: Warning: Host did not "
125 					"wait for busy state to end.\n",
126 					mmc_hostname(this_card->host));
127 		}
128 	} while (rk_emmc_busy(&cmd));
129 
130 	return ret;
131 }
132 
133 /*
134  * Transfer a single sector of kernel addressable data
135  */
rk_emmc_transfer(u8 * buffer,unsigned int addr,unsigned int datasz,int write)136 int rk_emmc_transfer(u8 *buffer, unsigned int addr, unsigned int datasz, int write)
137 {
138 	int ret = 0;
139 	enum emmc_area_type areatype;
140 
141 	struct mmc_request mrq = {0};
142 	struct mmc_command cmd = {0};
143 	struct mmc_command stop = {0};
144 	struct mmc_data data = {0};
145 
146 	struct scatterlist sg;
147 
148 	if(!this_card)
149 		return -EIO;
150 
151 	mrq.cmd = &cmd;
152 	mrq.data = &data;
153 	mrq.stop = &stop;
154 
155 	sg_init_one(&sg, buffer, datasz);
156 
157 	rk_emmc_prepare_mrq(&mrq, &sg, 1, addr, datasz / BLKSZ, BLKSZ, write);
158 
159 	pm_runtime_get_sync(&this_card->dev);
160 	mmc_claim_host(this_card->host);
161 
162 	if (this_card->ext_csd.cmdq_en) {
163 		ret = mmc_cmdq_disable(this_card);
164 		if (ret)
165 			goto exit;
166 	}
167 
168 	areatype = (enum emmc_area_type)this_card->ext_csd.part_config
169 		    & EXT_CSD_PART_CONFIG_ACC_MASK;
170 	if (areatype != MMC_DATA_AREA_MAIN) {
171 		ret = rk_emmc_set_areatype(MMC_DATA_AREA_MAIN);
172 		if (ret) {
173 			pr_err("rk_emmc_set_areatype error!.\n");
174 			goto exit;
175 		}
176 	}
177 
178 	mmc_wait_for_req(this_card->host, &mrq);
179 
180 	if (cmd.error){
181 		ret = cmd.error;
182 		goto exit;
183 	}
184 	if (data.error){
185 		ret =  data.error;
186 		goto exit;
187 	}
188 
189 	ret = rk_emmc_wait_busy();
190 
191 	if (areatype != MMC_DATA_AREA_MAIN) {
192 		ret = rk_emmc_set_areatype(areatype);
193 		if (ret)
194 			pr_err("rk_emmc_set_areatype error!.\n");
195 	}
196 
197 exit:
198 	if (this_card->reenable_cmdq && !this_card->ext_csd.cmdq_en)
199 		mmc_cmdq_enable(this_card);
200 
201 	mmc_release_host(this_card->host);
202 	pm_runtime_put(&this_card->dev);
203 
204 	return ret;
205 }
206 EXPORT_SYMBOL(rk_emmc_transfer);
207 
208 MODULE_LICENSE("GPL");
209