blob: 47e94b0831a2a6463981c62c2427e825b47923c7 [file] [log] [blame]
Sridhar Parasuram5351efc2015-02-06 16:41:35 -08001/* Copyright (c) 2013-2015, 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 <string.h>
31#include <reg.h>
32#include <arch/defines.h>
33#include <sys/types.h>
34#include <stdlib.h>
35#include <endian.h>
36#include <ufs.h>
37#include <dme.h>
38#include <uic.h>
39#include <utp.h>
Sridhar Parasuram9374faa2014-10-23 19:56:12 -070040#include <ucs.h>
Channagoud Kadabi9fb0fce2015-04-22 11:17:36 -070041#include <crc32.h>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070042
43int dme_send_linkstartup_req(struct ufs_dev *dev)
44{
45 struct uic_cmd cmd;
46
47 cmd.uiccmd = UICCMDR_DME_LINKSTARTUP;
48 cmd.num_args = UICCMD_NO_ARGS;
49 cmd.timeout_msecs = DME_LINK_START_TIMEOUT;
50
51 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
52 goto dme_send_linkstartup_req_err;
53
54 return UFS_SUCCESS;
55
56dme_send_linkstartup_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080057 dprintf(CRITICAL, "%s:%d DME_LINKSTARTUP command failed.\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070058 return -UFS_FAILURE;
59}
60
61int dme_get_req(struct ufs_dev *dev, struct dme_get_req_type *req)
62{
63 struct uic_cmd cmd;
64
65 cmd.uiccmd = UICCMDR_DME_GET;
66 cmd.num_args = UICCMD_ONE_ARGS;
67 cmd.uiccmdarg1 = req->attribute << 16 | req->index;
68 cmd.timeout_msecs = INFINITE_TIME;
69
70 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
71 goto dme_get_req_err;
72
73 /* Return the result. */
74 *(req->mibval) = cmd.uiccmdarg3;
75
76 return UFS_SUCCESS;
77
78dme_get_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080079 dprintf(CRITICAL, "%s:%d DME_GET command failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070080 return -UFS_FAILURE;
81}
82
83static int dme_get_query_resp(struct ufs_dev *dev,
84 struct upiu_req_build_type *req_upiu,
85 addr_t buffer,
86 size_t buf_len)
87{
88 struct upiu_trans_mgmt_query_hdr *resp_upiu;
89
90 resp_upiu = (struct upiu_trans_mgmt_query_hdr *) req_upiu->resp_ptr;
91
92 if (resp_upiu->opcode != req_upiu->opcode)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080093 {
94 dprintf(CRITICAL, "%s:%d Opcode from respose does not match with Opcode from request\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070095 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080096 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070097 if (resp_upiu->basic_hdr.response != UPIU_QUERY_RESP_SUCCESS)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080098 {
99 dprintf(CRITICAL, "%s:%d UPIU Response is not SUCCESS\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700100 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800101 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700102
103 switch (resp_upiu->opcode)
104 {
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800105 case UPIU_QUERY_OP_READ_ATTRIBUTE:
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700106 case UPIU_QUERY_OP_READ_FLAG:
107 case UPIU_QUERY_OP_SET_FLAG:
108 if (buf_len < sizeof(uint32_t))
109 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800110 dprintf(CRITICAL, "%s:%d Insufficient buffer space.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700111 return -UFS_FAILURE;
112 }
113
114 *((uint32_t *) buffer) = resp_upiu->flag_value;
115 break;
116 case UPIU_QUERY_OP_TOGGLE_FLAG:
117 case UPIU_QUERY_OP_CLEAR_FLAG:
118 case UPIU_QUERY_OP_READ_DESCRIPTOR:
119 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800120 default:
121 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
122 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700123 }
124
125 return UFS_SUCCESS;
126}
127
128static int dme_send_query_upiu(struct ufs_dev *dev, struct utp_query_req_upiu_type *query)
129{
130 struct upiu_trans_mgmt_query_hdr resp_upiu;
131 struct upiu_req_build_type req_upiu;
132 int ret;
133
134 memset(&req_upiu, 0, sizeof(req_upiu));
135
136 req_upiu.opcode = query->opcode;
137 req_upiu.selector = query->selector;
138 req_upiu.index = query->index;
139 req_upiu.idn = query->idn;
140 req_upiu.trans_type = UPIU_TYPE_QUERY_REQ;
141 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
Sridhar Parasuram782645e2015-02-06 16:47:00 -0800142 req_upiu.resp_ptr = (struct upiu_basic_resp_hdr *) &resp_upiu;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700143 req_upiu.resp_len = sizeof(resp_upiu);
144 req_upiu.resp_data_ptr = query->buf;
145 req_upiu.timeout_msecs = UTP_GENERIC_CMD_TIMEOUT;
146
147 if (query->opcode == UPIU_QUERY_OP_READ_DESCRIPTOR)
148 {
149 req_upiu.resp_data_len = query->buf_len;
150 }
151
152 ret = utp_enqueue_upiu(dev, &req_upiu);
153 if (ret)
154 goto utp_send_query_upiu_err;
155
156 ret = dme_get_query_resp(dev, &req_upiu, query->buf, query->buf_len);
157 if (ret)
158 goto utp_send_query_upiu_err;
159
160utp_send_query_upiu_err:
161 return ret;
162}
163
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800164int dme_set_fpurgeenable(struct ufs_dev *dev)
165{
166 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
167 STACKBUF_DMA_ALIGN(status, sizeof(uint32_t));
168 uint32_t try_again = DME_BPURGESTATUS_RETRIES;
169 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
170 UFS_IDX_fPurgeEn,
171 0,
172 0,
173 (addr_t) result,
174 sizeof(uint32_t)};
175 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_ATTRIBUTE,
176 UFS_IDX_bPurgeStatus,
177 0,
178 0,
179 (addr_t)status,
180 sizeof(uint32_t)};
181
182 if (dme_send_query_upiu(dev, &set_query))
183 {
184 dprintf(CRITICAL, "%s:%d DME Purge Enable failed\n", __func__, __LINE__);
185 return -UFS_FAILURE;
186 }
187
188 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
189 dprintf(INFO, "%s:%d Purge enable status: %u\n", __func__,__LINE__, *result);
190
191 do {
192 *status = 0;
193 arch_invalidate_cache_range((addr_t) status, sizeof(uint32_t));
194 if (dme_send_query_upiu(dev, &read_query))
195 {
196 dprintf(CRITICAL, "%s:%d DME Purge Status Read failed\n", __func__, __LINE__);
197 return -UFS_FAILURE;
198 }
199
200 switch (*status)
201 {
202
203 case 0x0:
204#ifdef DEBUG_UFS
205 dprintf(INFO, "%s:%d Purge operation returning to ufs_erase. Purge Status 0x0\n", __func__, __LINE__);
206#endif
207 return UFS_SUCCESS;
208 case 0x3:
209#ifdef DEBUG_UFS
210 dprintf(INFO, "%s:%d Purge operation has completed. Purge Status:0x3\n", __func__, __LINE__);
211#endif
212 // next read of status will move to 0
213 continue;
214 case 0x1:
215#ifdef DEBUG_UFS
216 dprintf(INFO, "%s:%d Purge operation is still in progress.. Retrying\n", __func__, __LINE__);
217#endif
218 try_again--;
219 continue;
220 case 0x2:
221 dprintf(CRITICAL, "%s:%d Purge operation stopped prematurely\n", __func__, __LINE__);
222 return -UFS_FAILURE;
223 case 0x4:
224 dprintf(CRITICAL, "%s:%d Purge operation failed due to logical unit queue not empty\n", __func__, __LINE__);
225 return -UFS_FAILURE;
226 case 0x5:
227 dprintf(CRITICAL, "%s:%d Purge operation general failure\n", __func__, __LINE__);
228 return -UFS_FAILURE;
229 }
230 } while((*status == 0x1 || *status == 0x3) && try_again);
231
232 // should not come here
233 dprintf(CRITICAL, "%s:%d Purge operation timed out after checking status %d times\n", __func__, __LINE__, DME_BPURGESTATUS_RETRIES);
234 return -UFS_FAILURE;
235}
236
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700237int dme_set_fpoweronwpen(struct ufs_dev *dev)
238{
239 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
240 uint32_t try_again = DME_FPOWERONWPEN_RETRIES;
241 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
242 UFS_IDX_fPowerOnWPEn,
243 0,
244 0,
245 (addr_t) result,
246 sizeof(uint32_t)};
247 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
248 UFS_IDX_fPowerOnWPEn,
249 0,
250 0,
251 (addr_t) result,
252 sizeof(uint32_t)};
253
254
255 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800256 {
257 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700258 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800259 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700260
261 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
262
263 if (*result == 1)
264 goto utp_set_fpoweronwpen_done;
265
266 do
267 {
268 try_again--;
269 dprintf(CRITICAL, "Power on Write Protect request failed. Retrying again.\n");
270
271 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800272 {
273 dprintf(CRITICAL, "%s:%d DME Power On Write Set Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700274 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800275 }
276
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700277 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800278 {
279 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700280 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800281 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700282
283 if (*result == 1)
284 break;
285 } while (try_again);
286
287utp_set_fpoweronwpen_done:
288 dprintf(INFO,"Power on Write Protect status: %u\n", *result);
289 return UFS_SUCCESS;
290}
291
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700292int dme_set_fdeviceinit(struct ufs_dev *dev)
293{
294 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
295 uint32_t try_again = DME_FDEVICEINIT_RETRIES;
296 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
297 UFS_IDX_fDeviceInit,
298 0,
299 0,
300 (addr_t) result,
301 sizeof(uint32_t)};
302 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
303 UFS_IDX_fDeviceInit,
304 0,
305 0,
306 (addr_t) result,
307 sizeof(uint32_t)};
308
309
310 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800311 {
312 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700313 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800314 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700315
316 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
317
318 if (*result == 1)
319 goto utp_set_fdeviceinit_done;
320
321 do
322 {
323 try_again--;
324
325 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800326 {
327 dprintf(CRITICAL, "%s:%d DME Device Init Set request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700328 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800329 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700330
331 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800332 {
333 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700334 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800335 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700336
337 if (*result == 1)
338 break;
339 } while (try_again);
340
341utp_set_fdeviceinit_done:
342 return UFS_SUCCESS;
343}
344
345int dme_read_string_desc(struct ufs_dev *dev, uint8_t index, struct ufs_string_desc *desc)
346{
347 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
348 UFS_DESC_IDN_STRING,
349 index,
350 0,
351 (addr_t) desc,
352 sizeof(struct ufs_string_desc)};
353
354 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800355 {
356 dprintf(CRITICAL, "%s:%d DME Read String Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700357 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800358 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700359
360 if (desc->desc_len != 0)
361 return UFS_SUCCESS;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800362 dprintf(CRITICAL, "%s:%d DME Read String Descriptor is length 0\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700363 return -UFS_FAILURE;
364}
365
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700366static uint32_t dme_parse_serial_no(struct ufs_string_desc *desc)
367{
368 uint32_t serial_no=0;
Channagoud Kadabi9fb0fce2015-04-22 11:17:36 -0700369 int len=0;
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700370
371 if(desc->desc_len <= 0)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800372 {
373 dprintf(CRITICAL, "%s:%d Invalid string descriptor length\n", __func__, __LINE__);
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700374 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800375 }
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700376
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700377 len = (desc->desc_len-2)/2;
378
Channagoud Kadabi9fb0fce2015-04-22 11:17:36 -0700379 serial_no = crc32(~0L, desc->serial_num, len);
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700380
381 return serial_no;
382}
383
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700384int dme_read_device_desc(struct ufs_dev *dev)
385{
386 STACKBUF_DMA_ALIGN(dev_desc, sizeof(struct ufs_dev_desc));
387 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_string_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800388 struct ufs_dev_desc *device_desc = (struct ufs_dev_desc *) dev_desc;
389 struct ufs_string_desc *str_desc = (struct ufs_string_desc *) desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700390 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
391 UFS_DESC_IDN_DEVICE,
392 0,
393 0,
394 (addr_t) dev_desc,
395 sizeof(struct ufs_dev_desc)};
396
397 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800398 {
399 dprintf(CRITICAL, "%s:%d DME Read Device Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700400 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800401 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700402
403 /* Flush buffer. */
404 arch_invalidate_cache_range((addr_t) device_desc, sizeof(struct ufs_dev_desc));
405
406 /* Store all relevant data */
407 dev->num_lus = device_desc->num_lu;
408
409 /* Get serial number for the device based on the string index. */
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800410 if (dme_read_string_desc(dev, device_desc->serial_num, (struct ufs_string_desc *) desc))
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700411 return -UFS_FAILURE;
412
413 /* Flush buffer. */
414 arch_invalidate_cache_range((addr_t) str_desc, sizeof(struct ufs_string_desc));
415
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700416 dev->serial_num = dme_parse_serial_no(str_desc);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700417
418 return UFS_SUCCESS;
419}
420
421
422int dme_read_geo_desc(struct ufs_dev *dev)
423{
424 struct ufs_geometry_desc *desc;
425 STACKBUF_DMA_ALIGN(geometry_desc, sizeof(struct ufs_geometry_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800426 desc = (struct ufs_geometry_desc *) geometry_desc;
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700427 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
428 UFS_DESC_IDN_GEOMETRY,
429 0,
430 0,
431 (addr_t) geometry_desc,
432 sizeof(struct ufs_geometry_desc)};
433
434 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800435 {
436 dprintf(CRITICAL, "%s:%d DME Read Geometry Descriptor request failed\n", __func__, __LINE__);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700437 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800438 }
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700439
440 // Flush buffer.
441 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_geometry_desc));
442 dev->rpmb_rw_size = desc->rpmb_read_write_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700443 return UFS_SUCCESS;
444}
445
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700446int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700447{
448 STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800449 struct ufs_unit_desc *desc = (struct ufs_unit_desc *) unit_desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700450 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
451 UFS_DESC_IDN_UNIT,
452 index,
453 0,
454 (addr_t) unit_desc,
455 sizeof(struct ufs_unit_desc)};
456
457 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800458 {
459 dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700460 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800461 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700462 /* Flush buffer. */
463 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc));
464
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800465 dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700466
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800467 dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700468
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700469 // use only the lower 32 bits for rpmb partition size
470 if (index == UFS_WLUN_RPMB)
471 dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);
472
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700473 return UFS_SUCCESS;
474}
475
476int dme_read_config_desc(struct ufs_dev *dev)
477{
478 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_config_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800479 struct ufs_config_desc *config_desc = (struct ufs_config_desc *)desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700480 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
481 UFS_DESC_IDN_CONFIGURATION,
482 0,
483 0,
484 (addr_t) config_desc,
485 sizeof(struct ufs_config_desc)};
486
487 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800488 {
489 dprintf(CRITICAL, "%s:%d DME Read Config Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700490 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800491 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700492
493 /* Flush buffer. */
494 arch_invalidate_cache_range((addr_t) config_desc, sizeof(struct ufs_config_desc));
495
496 return UFS_SUCCESS;
497}
498
499int dme_send_nop_query(struct ufs_dev *dev)
500{
501 struct upiu_req_build_type req_upiu;
Sridhar Parasuram782645e2015-02-06 16:47:00 -0800502 struct upiu_basic_resp_hdr resp_upiu;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700503 int ret;
504 unsigned try_again;
505
506 ret = UFS_SUCCESS;
507 try_again = DME_NOP_NUM_RETRIES;
508
509 memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
510
511 req_upiu.trans_type = UPIU_TYPE_NOP_OUT;
512 req_upiu.flags = 0;
513 req_upiu.query_mgmt_func = 0;
514 req_upiu.cmd_type = UTRD_DEV_MGMT_FUNC;
515 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
516 req_upiu.resp_ptr = &resp_upiu;
517 req_upiu.resp_len = sizeof(struct upiu_basic_hdr);
518 req_upiu.timeout_msecs = DME_NOP_QUERY_TIMEOUT;
519
520 while (try_again)
521 {
522 try_again--;
523
524 ret = utp_enqueue_upiu(dev, &req_upiu);
525
526 if (ret == -UFS_RETRY)
527 {
528 continue;
529 }
530 else if (ret == -UFS_FAILURE)
531 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800532 dprintf(CRITICAL, "%s:%d Sending nop out failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700533 goto upiu_send_nop_out_err;
534 }
535
536 /* Check response UPIU */
537 if (resp_upiu.trans_type != UPIU_TYPE_NOP_IN)
538 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800539 dprintf(CRITICAL, "%s:%d Command failed. command = %x. Invalid response.\n",__func__,__LINE__, req_upiu.trans_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700540 ret = -UFS_FAILURE;
541 goto upiu_send_nop_out_err;
542 }
543 else
544 break;
545 }
546
547upiu_send_nop_out_err:
548 return ret;
549}
550
551int utp_build_query_req_upiu(struct upiu_trans_mgmt_query_hdr *req_upiu,
552 struct upiu_req_build_type *upiu_data)
553{
554 req_upiu->opcode = upiu_data->opcode;
555 req_upiu->idn = upiu_data->idn;
556 req_upiu->index = upiu_data->index;
557 req_upiu->selector = upiu_data->selector;
558 req_upiu->resp_len = BE16(upiu_data->resp_data_len);
559
560 switch (upiu_data->opcode)
561 {
562 case UPIU_QUERY_OP_READ_FLAG:
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800563 case UPIU_QUERY_OP_READ_ATTRIBUTE:
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700564 case UPIU_QUERY_OP_READ_DESCRIPTOR:
565 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_READ_REQ;
566 break;
567 case UPIU_QUERY_OP_TOGGLE_FLAG:
568 case UPIU_QUERY_OP_CLEAR_FLAG:
569 case UPIU_QUERY_OP_SET_FLAG:
570 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_WRITE_REQ;
571 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800572 default:
573 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
574 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700575 }
576
577 return UFS_SUCCESS;
578}