blob: 432f3a7b6e78b0be8acd40c2a898f391d2833e69 [file] [log] [blame]
Sridhar Parasuramb48afc72014-10-23 20:01:56 -07001/* Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -07002 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <stdlib.h>
31#include <endian.h>
32#include <string.h>
33#include <utp.h>
34
35static int ucs_do_request_sense(struct ufs_dev *dev);
36
37int ucs_do_scsi_cmd(struct ufs_dev *dev, struct scsi_req_build_type *req)
38{
39 struct upiu_req_build_type req_upiu;
40 struct upiu_basic_hdr resp_upiu;
41 int ret;
42
43 memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
44
45 req_upiu.cmd_set_type = UPIU_SCSI_CMD_SET;
46 req_upiu.trans_type = UPIU_TYPE_COMMAND;
47 req_upiu.data_buffer_addr = req->data_buffer_addr;
48 req_upiu.expected_data_len = req->data_len;
49 req_upiu.data_seg_len = 0;
50 req_upiu.ehs_len = 0;
51 req_upiu.flags = req->flags;
52 req_upiu.lun = req->lun;
53 req_upiu.query_mgmt_func = 0;
54 req_upiu.cdb = req->cdb;
55 req_upiu.cmd_type = UTRD_SCSCI_CMD;
56 req_upiu.dd = req->dd;
57 req_upiu.resp_ptr = &resp_upiu;
58 req_upiu.resp_len = sizeof(resp_upiu);
59 req_upiu.timeout_msecs = UTP_GENERIC_CMD_TIMEOUT;
60
61 if (utp_enqueue_upiu(dev, &req_upiu))
62 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -070063 dprintf(CRITICAL, "ucs_do_scsi_cmd: enqueue failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070064 return -UFS_FAILURE;
65 }
66
67 if (resp_upiu.status != SCSI_STATUS_GOOD)
68 {
69 if (resp_upiu.status == SCSI_STATUS_CHK_COND && (*((uint8_t *)(req->cdb)) != SCSI_CMD_SENSE_REQ))
70 {
71 ret = ucs_do_request_sense(dev);
72 if (ret)
73 dprintf(CRITICAL, "SCSI request sense failed.\n");
74 }
75
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -070076 dprintf(CRITICAL, "ucs_do_scsi_cmd failed status = %x\n", resp_upiu.status);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070077 return -UFS_FAILURE;
78 }
79
80 return UFS_SUCCESS;
81}
82
Sridhar Parasuramb48afc72014-10-23 20:01:56 -070083int ucs_do_scsi_rpmb_read(struct ufs_dev *dev, uint32_t *req_buf, uint32_t blk_cnt,
84 uint32_t *resp_buf, uint32_t *resp_len)
85{
86 // validate input parameters
87 ASSERT(req_buf);
88 ASSERT(resp_buf);
89 ASSERT(resp_len);
90
91 STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sec_protocol_cdb));
92 struct scsi_req_build_type req_upiu;
93 struct scsi_sec_protocol_cdb *cdb_out_param, *cdb_in_param;
94 uint32_t blks_remaining;
95 uint32_t blks_to_transfer;
96 uint64_t bytes_to_transfer;
97 uint32_t start_blk;
98 uint64_t max_size;
99 blks_remaining = blk_cnt;
100 blks_to_transfer = blks_remaining;
101 bytes_to_transfer = blks_to_transfer * RPMB_FRAME_SIZE;
102
103 // check if total bytes to transfer exceed max supported size
104 max_size = dev->rpmb_rw_size * RPMB_FRAME_SIZE * blk_cnt;
105 if (bytes_to_transfer > max_size)
106 {
107 dprintf(CRITICAL, "RPMB request transfer size %llu greater than max transfer size %llu\n", bytes_to_transfer, max_size);
108 return -UFS_FAILURE;
109 }
110#ifdef DEBUG_UFS
111 dprintf(INFO, "rpmb_read: req_buf: 0x%x blk_count: 0x%x\n", *req_buf, blk_cnt);
112 dprintf(INFO, "rpmb_read: bytes_to_transfer: 0x%x blks_to_transfer: 0x%x\n",
113 bytes_to_transfer, blks_to_transfer);
114#endif
115 // send the request
116 cdb_out_param = (struct scsi_sec_protocol_cdb*) cdb;
117 memset(cdb_out_param, 0, sizeof(struct scsi_sec_protocol_cdb));
118
119 cdb_out_param->opcode = SCSI_CMD_SECPROT_OUT;
120 cdb_out_param->cdb1 = SCSI_SEC_PROT;
121 cdb_out_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
122 cdb_out_param->alloc_tlen = BE32(bytes_to_transfer);
123
124 // Flush CDB to memory
125 dsb();
126 arch_clean_invalidate_cache_range((addr_t) cdb_out_param, sizeof(struct scsi_sec_protocol_cdb));
127
128 memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
129
130 req_upiu.cdb = (addr_t) cdb_out_param;
131 req_upiu.data_buffer_addr = req_buf;
132 req_upiu.data_len = bytes_to_transfer;
133 req_upiu.flags = UPIU_FLAGS_WRITE;
134 req_upiu.lun = UFS_WLUN_RPMB;
135 req_upiu.dd = UTRD_TARGET_TO_SYSTEM;
136
137#ifdef DEBUG_UFS
138 dprintf(INFO, "Sending RPMB Read request\n");
139#endif
140 if (ucs_do_scsi_cmd(dev, &req_upiu))
141 {
142 dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
143 return -UFS_FAILURE;
144 }
145#ifdef DEBUG_UFS
146 dprintf(INFO, "Sending RPMB Read request complete\n");
147#endif
148 // read the response
149 cdb_in_param = (struct scsi_sec_protocol_cdb*) cdb;
150 memset(cdb_in_param, 0, sizeof(struct scsi_sec_protocol_cdb));
151
152 cdb_in_param->opcode = SCSI_CMD_SECPROT_IN;
153 cdb_in_param->cdb1 = SCSI_SEC_PROT;
154 cdb_in_param->sec_protocol_specific = BE16(SCSI_SEC_UFS_PROT_ID);
155 cdb_in_param->alloc_tlen = BE32(bytes_to_transfer);
156
157 // Flush CDB to memory
158 dsb();
159 arch_clean_invalidate_cache_range((addr_t) cdb_in_param, sizeof(struct scsi_sec_protocol_cdb));
160
161 memset(&req_upiu, 0, sizeof(struct scsi_req_build_type));
162
163 req_upiu.cdb = (addr_t) cdb_in_param;
164 req_upiu.data_buffer_addr = resp_buf;
165 req_upiu.data_len = bytes_to_transfer;
166 req_upiu.flags = UPIU_FLAGS_READ;
167 req_upiu.lun = UFS_WLUN_RPMB;
168 req_upiu.dd = UTRD_SYSTEM_TO_TARGET;
169
170#ifdef DEBUG_UFS
171 dprintf(INFO, "Sending RPMB Read response\n");
172#endif
173 if (ucs_do_scsi_cmd(dev, &req_upiu))
174 {
175 dprintf(CRITICAL, "%s:%d ucs_do_scsi_rpmb_read: failed\n", __func__, __LINE__);
176 return -UFS_FAILURE;
177 }
178#ifdef DEBUG_UFS
179 dprintf(SPEW, "Sending RPMB Read response complete\n");
180#endif
181 *resp_len = bytes_to_transfer;
182 return UFS_SUCCESS;
183}
184
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700185int ucs_do_scsi_read(struct ufs_dev *dev, struct scsi_rdwr_req *req)
186{
187 STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_rdwr_cdb));
188 struct scsi_req_build_type req_upiu;
189 struct scsi_rdwr_cdb *cdb_param;
190 uint32_t blks_remaining;
191 uint16_t blks_to_transfer;
192 uint64_t bytes_to_transfer;
193 uint32_t start_blk;
194 uint32_t buf;
195
196 blks_remaining = req->num_blocks;
197 buf = req->data_buffer_base;
198 start_blk = req->start_lba;
199
200 cdb_param = (struct scsi_rdwr_cdb*) cdb;
201 while (blks_remaining)
202 {
203 if (blks_remaining <= SCSI_MAX_DATA_TRANS_BLK_LEN)
204 {
205 blks_to_transfer = blks_remaining;
206 blks_remaining = 0;
207 }
208 else
209 {
210 blks_to_transfer = SCSI_MAX_DATA_TRANS_BLK_LEN;
211 blks_remaining -= SCSI_MAX_DATA_TRANS_BLK_LEN;
212 }
213
214 bytes_to_transfer = blks_to_transfer * UFS_DEFAULT_SECTORE_SIZE;
215
216 memset(cdb_param, 0, sizeof(struct scsi_rdwr_cdb));
217 cdb_param->opcode = SCSI_CMD_READ10;
218 cdb_param->cdb1 = SCSI_READ_WRITE_10_CDB1(0, 0, 1, 0);
219 cdb_param->lba = BE32(start_blk);
220 cdb_param->trans_len = BE16(blks_to_transfer);
221
222
223 dsb();
224 arch_clean_invalidate_cache_range((addr_t) cdb_param, sizeof(struct scsi_rdwr_cdb));
225
226 memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));
227
228 req_upiu.cdb = (addr_t) cdb_param;
229 req_upiu.data_buffer_addr = buf;
230 req_upiu.data_len = bytes_to_transfer;
231 req_upiu.flags = UPIU_FLAGS_READ;
232 req_upiu.lun = req->lun;
233 req_upiu.dd = UTRD_TARGET_TO_SYSTEM;
234
235 if (ucs_do_scsi_cmd(dev, &req_upiu))
236 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700237 dprintf(CRITICAL, "ucs_do_scsi_read: failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700238 return -UFS_FAILURE;
239 }
240
241 buf += bytes_to_transfer;
242 start_blk += SCSI_MAX_DATA_TRANS_BLK_LEN;
243 }
244
245 return UFS_SUCCESS;
246}
247
248int ucs_do_scsi_write(struct ufs_dev *dev, struct scsi_rdwr_req *req)
249{
250 struct scsi_req_build_type req_upiu;
251 STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_rdwr_cdb));
252 struct scsi_rdwr_cdb *cdb_param;
253 uint32_t blks_remaining;
254 uint16_t blks_to_transfer;
255 uint64_t bytes_to_transfer;
256 uint32_t start_blk;
257 uint32_t buf;
258
259 blks_remaining = req->num_blocks;
260 buf = req->data_buffer_base;
261 start_blk = req->start_lba;
262
263 cdb_param = (struct scsi_rdwr_cdb*) cdb;
264 while (blks_remaining)
265 {
266 if (blks_remaining <= SCSI_MAX_DATA_TRANS_BLK_LEN)
267 {
268 blks_to_transfer = blks_remaining;
269 blks_remaining = 0;
270 }
271 else
272 {
273 blks_to_transfer = SCSI_MAX_DATA_TRANS_BLK_LEN;
274 blks_remaining -= SCSI_MAX_DATA_TRANS_BLK_LEN;
275 }
276
277 bytes_to_transfer = blks_to_transfer * UFS_DEFAULT_SECTORE_SIZE;
278
279 memset(cdb_param, 0, sizeof(struct scsi_rdwr_cdb));
280 cdb_param->opcode = SCSI_CMD_WRITE10;
281 cdb_param->cdb1 = SCSI_READ_WRITE_10_CDB1(0, 0, 1, 0);
282 cdb_param->lba = BE32(start_blk);
283 cdb_param->trans_len = BE16(blks_to_transfer);
284
285 /* Flush cdb to memory. */
286 dsb();
287 arch_clean_invalidate_cache_range((addr_t) cdb_param, sizeof(struct scsi_rdwr_cdb));
288
289 memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));
290
291 req_upiu.cdb = (addr_t) cdb_param;
292 req_upiu.data_buffer_addr = buf;
293 req_upiu.data_len = bytes_to_transfer;
294 req_upiu.flags = UPIU_FLAGS_WRITE;
295 req_upiu.lun = req->lun;
296 req_upiu.dd = UTRD_SYSTEM_TO_TARGET;
297
298 if (ucs_do_scsi_cmd(dev, &req_upiu))
299 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700300 dprintf(CRITICAL, "ucs_do_scsi_write: failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700301 return -UFS_FAILURE;
302 }
303
304 buf += bytes_to_transfer;
305 start_blk += SCSI_MAX_DATA_TRANS_BLK_LEN;
306 }
307
308 return UFS_SUCCESS;
309}
310
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700311int ucs_do_scsi_unmap(struct ufs_dev *dev, struct scsi_unmap_req *req)
312{
313 STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN);
314 STACKBUF_DMA_ALIGN(param, sizeof(struct unmap_param_list));
315 struct scsi_req_build_type req_upiu;
316 struct unmap_param_list *param_list;
317 struct unmap_blk_desc *blk_desc;
318
319 param_list = (struct unmap_param_list *)param;
320 param_list->data_len = (sizeof(struct unmap_param_list) - 1) << 0x8; /* n-1 */
321
322 param_list->blk_desc_data_len = sizeof(struct unmap_blk_desc) << 0x8;
323
324
325 blk_desc = &(param_list->blk_desc);
326
327 blk_desc->lba = BE64(req->start_lba);
328 blk_desc->num_blks = BE32(req->num_blocks);
329
330 memset((void*)cdb_param, 0, SCSI_CDB_PARAM_LEN);
331 cdb_param[0] = SCSI_CMD_UNMAP;
332 cdb_param[1] = 0; /*ANCHOR = 0 for UFS*/
333 cdb_param[6] = 0; /*Group No = 0*/
334 cdb_param[7] = 0; /* Param list length is 1, we erase 1 contiguous blk*/
335 cdb_param[8] = sizeof(struct unmap_param_list);
336 cdb_param[9] = 0;
337
338 /* Flush cdb to memory. */
339 dsb();
340 arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);
341
342 memset((void*)&req_upiu, 0 , sizeof(struct scsi_req_build_type));
343
344 req_upiu.cdb = (addr_t) cdb_param;
345 req_upiu.data_buffer_addr = (addr_t) param;
346 req_upiu.data_len = sizeof(struct unmap_param_list);
347 req_upiu.flags = UPIU_FLAGS_WRITE;
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800348 req_upiu.lun = req->lun;
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700349 req_upiu.dd = UTRD_SYSTEM_TO_TARGET;
350
351 if (ucs_do_scsi_cmd(dev, &req_upiu))
352 {
353 dprintf(CRITICAL, "Failed to send SCSI unmap command \n");
354 return -UFS_FAILURE;
355 }
356
357 /* Flush buffer. */
358 arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN);
359
360 return UFS_SUCCESS;
361}
362
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700363int ucs_scsi_send_inquiry(struct ufs_dev *dev)
364{
365 STACKBUF_DMA_ALIGN(cdb_param, SCSI_CDB_PARAM_LEN);
366 STACKBUF_DMA_ALIGN(param, SCSI_INQUIRY_LEN);
367 struct scsi_req_build_type req_upiu;
368
369 memset(cdb_param, 0, SCSI_CDB_PARAM_LEN);
370 cdb_param[0] = SCSI_CMD_INQUIRY;
371 cdb_param[3] = sizeof(param)>> 8;
372 cdb_param[4] = sizeof(param);
373
374 /* Flush cdb to memory. */
375 dsb();
376 arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);
377
378 memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));
379
380 req_upiu.cdb = (addr_t) cdb_param;
381 req_upiu.data_buffer_addr = (addr_t) param;
382 req_upiu.data_len = SCSI_INQUIRY_LEN;
383 req_upiu.flags = UPIU_FLAGS_READ;
384 req_upiu.lun = 0;
385 req_upiu.dd = UTRD_TARGET_TO_SYSTEM;
386
387 if (ucs_do_scsi_cmd(dev, &req_upiu))
388 {
389 dprintf(CRITICAL, "Failed to send SCSI inquiry\n");
390 return -UFS_FAILURE;
391 }
392
393 /* Flush buffer. */
394 arch_invalidate_cache_range((addr_t) param, SCSI_INQUIRY_LEN);
395
396 return UFS_SUCCESS;
397}
398
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700399void dump_sense_buffer(uint8_t *buf, int buf_len)
400{
401 int index=0;
402
403 dprintf(CRITICAL,"----Sense buffer----\n");
404 for(index=0; index < buf_len; index++)
405 dprintf(CRITICAL,"buf[%d] = %x\n",index, buf[index]);
406
407 dprintf(CRITICAL,"----end of buffer---\n");
408}
409
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700410static int ucs_do_request_sense(struct ufs_dev *dev)
411{
412 STACKBUF_DMA_ALIGN(cdb, sizeof(struct scsi_sense_cdb));
413 struct scsi_req_build_type req_upiu;
414 struct scsi_sense_cdb *cdb_param;
415 uint8_t buf[SCSI_SENSE_BUF_LEN];
416
417 cdb_param = cdb;
418
419 memset(cdb, 0, sizeof(struct scsi_sense_cdb));
420
421 cdb_param->opcode = SCSI_CMD_SENSE_REQ;
422 cdb_param->alloc_len = SCSI_SENSE_BUF_LEN;
423
424 /* Flush cdb to memory. */
425 dsb();
426 arch_invalidate_cache_range((addr_t) cdb_param, SCSI_CDB_PARAM_LEN);
427
428 memset(&req_upiu, 0 , sizeof(struct scsi_req_build_type));
429
430 req_upiu.cdb = (addr_t) cdb_param;
431 req_upiu.data_buffer_addr = (addr_t) buf;
432 req_upiu.data_len = SCSI_SENSE_BUF_LEN;
433 req_upiu.flags = UPIU_FLAGS_READ;
434 req_upiu.lun = 0;
435 req_upiu.dd = UTRD_TARGET_TO_SYSTEM;
436
437 if (ucs_do_scsi_cmd(dev, &req_upiu))
438 {
Sundarajan Srinivasan2fcaa982013-10-31 17:44:02 -0700439 dprintf(CRITICAL, "ucs_do_request_sense: failed\n");
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700440 return -UFS_FAILURE;
441 }
442
443 /* Flush buffer. */
444 arch_invalidate_cache_range((addr_t) buf, SCSI_INQUIRY_LEN);
445
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700446 dump_sense_buffer(buf, SCSI_SENSE_BUF_LEN);
447
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700448 return UFS_SUCCESS;
449}