blob: bac0cdb63be03df506910eec1c2fded76afcfcb8 [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>
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070041
42int dme_send_linkstartup_req(struct ufs_dev *dev)
43{
44 struct uic_cmd cmd;
45
46 cmd.uiccmd = UICCMDR_DME_LINKSTARTUP;
47 cmd.num_args = UICCMD_NO_ARGS;
48 cmd.timeout_msecs = DME_LINK_START_TIMEOUT;
49
50 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
51 goto dme_send_linkstartup_req_err;
52
53 return UFS_SUCCESS;
54
55dme_send_linkstartup_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080056 dprintf(CRITICAL, "%s:%d DME_LINKSTARTUP command failed.\n",__func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070057 return -UFS_FAILURE;
58}
59
60int dme_get_req(struct ufs_dev *dev, struct dme_get_req_type *req)
61{
62 struct uic_cmd cmd;
63
64 cmd.uiccmd = UICCMDR_DME_GET;
65 cmd.num_args = UICCMD_ONE_ARGS;
66 cmd.uiccmdarg1 = req->attribute << 16 | req->index;
67 cmd.timeout_msecs = INFINITE_TIME;
68
69 if (uic_send_cmd(dev, &cmd) || cmd.gen_err_code == UICCMD_FAILURE)
70 goto dme_get_req_err;
71
72 /* Return the result. */
73 *(req->mibval) = cmd.uiccmdarg3;
74
75 return UFS_SUCCESS;
76
77dme_get_req_err:
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080078 dprintf(CRITICAL, "%s:%d DME_GET command failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070079 return -UFS_FAILURE;
80}
81
82static int dme_get_query_resp(struct ufs_dev *dev,
83 struct upiu_req_build_type *req_upiu,
84 addr_t buffer,
85 size_t buf_len)
86{
87 struct upiu_trans_mgmt_query_hdr *resp_upiu;
88
89 resp_upiu = (struct upiu_trans_mgmt_query_hdr *) req_upiu->resp_ptr;
90
91 if (resp_upiu->opcode != req_upiu->opcode)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080092 {
93 dprintf(CRITICAL, "%s:%d Opcode from respose does not match with Opcode from request\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070094 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080095 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070096 if (resp_upiu->basic_hdr.response != UPIU_QUERY_RESP_SUCCESS)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -080097 {
98 dprintf(CRITICAL, "%s:%d UPIU Response is not SUCCESS\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -070099 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800100 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700101
102 switch (resp_upiu->opcode)
103 {
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800104 case UPIU_QUERY_OP_READ_ATTRIBUTE:
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700105 case UPIU_QUERY_OP_READ_FLAG:
106 case UPIU_QUERY_OP_SET_FLAG:
107 if (buf_len < sizeof(uint32_t))
108 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800109 dprintf(CRITICAL, "%s:%d Insufficient buffer space.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700110 return -UFS_FAILURE;
111 }
112
113 *((uint32_t *) buffer) = resp_upiu->flag_value;
114 break;
115 case UPIU_QUERY_OP_TOGGLE_FLAG:
116 case UPIU_QUERY_OP_CLEAR_FLAG:
117 case UPIU_QUERY_OP_READ_DESCRIPTOR:
118 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800119 default:
120 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
121 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700122 }
123
124 return UFS_SUCCESS;
125}
126
127static int dme_send_query_upiu(struct ufs_dev *dev, struct utp_query_req_upiu_type *query)
128{
129 struct upiu_trans_mgmt_query_hdr resp_upiu;
130 struct upiu_req_build_type req_upiu;
131 int ret;
132
133 memset(&req_upiu, 0, sizeof(req_upiu));
134
135 req_upiu.opcode = query->opcode;
136 req_upiu.selector = query->selector;
137 req_upiu.index = query->index;
138 req_upiu.idn = query->idn;
139 req_upiu.trans_type = UPIU_TYPE_QUERY_REQ;
140 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
141 req_upiu.resp_ptr = (struct upiu_basic_hdr *) &resp_upiu;
142 req_upiu.resp_len = sizeof(resp_upiu);
143 req_upiu.resp_data_ptr = query->buf;
144 req_upiu.timeout_msecs = UTP_GENERIC_CMD_TIMEOUT;
145
146 if (query->opcode == UPIU_QUERY_OP_READ_DESCRIPTOR)
147 {
148 req_upiu.resp_data_len = query->buf_len;
149 }
150
151 ret = utp_enqueue_upiu(dev, &req_upiu);
152 if (ret)
153 goto utp_send_query_upiu_err;
154
155 ret = dme_get_query_resp(dev, &req_upiu, query->buf, query->buf_len);
156 if (ret)
157 goto utp_send_query_upiu_err;
158
159utp_send_query_upiu_err:
160 return ret;
161}
162
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800163int dme_set_fpurgeenable(struct ufs_dev *dev)
164{
165 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
166 STACKBUF_DMA_ALIGN(status, sizeof(uint32_t));
167 uint32_t try_again = DME_BPURGESTATUS_RETRIES;
168 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
169 UFS_IDX_fPurgeEn,
170 0,
171 0,
172 (addr_t) result,
173 sizeof(uint32_t)};
174 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_ATTRIBUTE,
175 UFS_IDX_bPurgeStatus,
176 0,
177 0,
178 (addr_t)status,
179 sizeof(uint32_t)};
180
181 if (dme_send_query_upiu(dev, &set_query))
182 {
183 dprintf(CRITICAL, "%s:%d DME Purge Enable failed\n", __func__, __LINE__);
184 return -UFS_FAILURE;
185 }
186
187 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
188 dprintf(INFO, "%s:%d Purge enable status: %u\n", __func__,__LINE__, *result);
189
190 do {
191 *status = 0;
192 arch_invalidate_cache_range((addr_t) status, sizeof(uint32_t));
193 if (dme_send_query_upiu(dev, &read_query))
194 {
195 dprintf(CRITICAL, "%s:%d DME Purge Status Read failed\n", __func__, __LINE__);
196 return -UFS_FAILURE;
197 }
198
199 switch (*status)
200 {
201
202 case 0x0:
203#ifdef DEBUG_UFS
204 dprintf(INFO, "%s:%d Purge operation returning to ufs_erase. Purge Status 0x0\n", __func__, __LINE__);
205#endif
206 return UFS_SUCCESS;
207 case 0x3:
208#ifdef DEBUG_UFS
209 dprintf(INFO, "%s:%d Purge operation has completed. Purge Status:0x3\n", __func__, __LINE__);
210#endif
211 // next read of status will move to 0
212 continue;
213 case 0x1:
214#ifdef DEBUG_UFS
215 dprintf(INFO, "%s:%d Purge operation is still in progress.. Retrying\n", __func__, __LINE__);
216#endif
217 try_again--;
218 continue;
219 case 0x2:
220 dprintf(CRITICAL, "%s:%d Purge operation stopped prematurely\n", __func__, __LINE__);
221 return -UFS_FAILURE;
222 case 0x4:
223 dprintf(CRITICAL, "%s:%d Purge operation failed due to logical unit queue not empty\n", __func__, __LINE__);
224 return -UFS_FAILURE;
225 case 0x5:
226 dprintf(CRITICAL, "%s:%d Purge operation general failure\n", __func__, __LINE__);
227 return -UFS_FAILURE;
228 }
229 } while((*status == 0x1 || *status == 0x3) && try_again);
230
231 // should not come here
232 dprintf(CRITICAL, "%s:%d Purge operation timed out after checking status %d times\n", __func__, __LINE__, DME_BPURGESTATUS_RETRIES);
233 return -UFS_FAILURE;
234}
235
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700236int dme_set_fpoweronwpen(struct ufs_dev *dev)
237{
238 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
239 uint32_t try_again = DME_FPOWERONWPEN_RETRIES;
240 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
241 UFS_IDX_fPowerOnWPEn,
242 0,
243 0,
244 (addr_t) result,
245 sizeof(uint32_t)};
246 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
247 UFS_IDX_fPowerOnWPEn,
248 0,
249 0,
250 (addr_t) result,
251 sizeof(uint32_t)};
252
253
254 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800255 {
256 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700257 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800258 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700259
260 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
261
262 if (*result == 1)
263 goto utp_set_fpoweronwpen_done;
264
265 do
266 {
267 try_again--;
268 dprintf(CRITICAL, "Power on Write Protect request failed. Retrying again.\n");
269
270 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800271 {
272 dprintf(CRITICAL, "%s:%d DME Power On Write Set Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700273 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800274 }
275
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700276 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800277 {
278 dprintf(CRITICAL, "%s:%d DME Power On Write Read Request failed\n", __func__, __LINE__);
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700279 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800280 }
Sridhar Parasuram88bd9dd2014-09-23 15:15:05 -0700281
282 if (*result == 1)
283 break;
284 } while (try_again);
285
286utp_set_fpoweronwpen_done:
287 dprintf(INFO,"Power on Write Protect status: %u\n", *result);
288 return UFS_SUCCESS;
289}
290
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700291int dme_set_fdeviceinit(struct ufs_dev *dev)
292{
293 STACKBUF_DMA_ALIGN(result, sizeof(uint32_t));
294 uint32_t try_again = DME_FDEVICEINIT_RETRIES;
295 struct utp_query_req_upiu_type read_query = {UPIU_QUERY_OP_READ_FLAG,
296 UFS_IDX_fDeviceInit,
297 0,
298 0,
299 (addr_t) result,
300 sizeof(uint32_t)};
301 struct utp_query_req_upiu_type set_query = {UPIU_QUERY_OP_SET_FLAG,
302 UFS_IDX_fDeviceInit,
303 0,
304 0,
305 (addr_t) result,
306 sizeof(uint32_t)};
307
308
309 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800310 {
311 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700312 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800313 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700314
315 arch_invalidate_cache_range((addr_t) result, sizeof(uint32_t));
316
317 if (*result == 1)
318 goto utp_set_fdeviceinit_done;
319
320 do
321 {
322 try_again--;
323
324 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800325 {
326 dprintf(CRITICAL, "%s:%d DME Device Init Set request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700327 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800328 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700329
330 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800331 {
332 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700333 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800334 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700335
336 if (*result == 1)
337 break;
338 } while (try_again);
339
340utp_set_fdeviceinit_done:
341 return UFS_SUCCESS;
342}
343
344int dme_read_string_desc(struct ufs_dev *dev, uint8_t index, struct ufs_string_desc *desc)
345{
346 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
347 UFS_DESC_IDN_STRING,
348 index,
349 0,
350 (addr_t) desc,
351 sizeof(struct ufs_string_desc)};
352
353 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800354 {
355 dprintf(CRITICAL, "%s:%d DME Read String Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700356 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800357 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700358
359 if (desc->desc_len != 0)
360 return UFS_SUCCESS;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800361 dprintf(CRITICAL, "%s:%d DME Read String Descriptor is length 0\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700362 return -UFS_FAILURE;
363}
364
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700365static uint32_t dme_parse_serial_no(struct ufs_string_desc *desc)
366{
367 uint32_t serial_no=0;
368 uint16_t *ptr;
369 int index=0,len=0;
370
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
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800377 ptr = (uint16_t *) desc->serial_num;
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700378 len = (desc->desc_len-2)/2;
379
380 for(index=0; index<len; index++)
381 {
382 serial_no += *ptr;
383 ptr++;
384 }
385
386 return serial_no;
387}
388
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700389int dme_read_device_desc(struct ufs_dev *dev)
390{
391 STACKBUF_DMA_ALIGN(dev_desc, sizeof(struct ufs_dev_desc));
392 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_string_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800393 struct ufs_dev_desc *device_desc = (struct ufs_dev_desc *) dev_desc;
394 struct ufs_string_desc *str_desc = (struct ufs_string_desc *) desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700395 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
396 UFS_DESC_IDN_DEVICE,
397 0,
398 0,
399 (addr_t) dev_desc,
400 sizeof(struct ufs_dev_desc)};
401
402 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800403 {
404 dprintf(CRITICAL, "%s:%d DME Read Device Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700405 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800406 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700407
408 /* Flush buffer. */
409 arch_invalidate_cache_range((addr_t) device_desc, sizeof(struct ufs_dev_desc));
410
411 /* Store all relevant data */
412 dev->num_lus = device_desc->num_lu;
413
414 /* Get serial number for the device based on the string index. */
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800415 if (dme_read_string_desc(dev, device_desc->serial_num, (struct ufs_string_desc *) desc))
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700416 return -UFS_FAILURE;
417
418 /* Flush buffer. */
419 arch_invalidate_cache_range((addr_t) str_desc, sizeof(struct ufs_string_desc));
420
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700421 dev->serial_num = dme_parse_serial_no(str_desc);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700422
423 return UFS_SUCCESS;
424}
425
426
427int dme_read_geo_desc(struct ufs_dev *dev)
428{
429 struct ufs_geometry_desc *desc;
430 STACKBUF_DMA_ALIGN(geometry_desc, sizeof(struct ufs_geometry_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800431 desc = (struct ufs_geometry_desc *) geometry_desc;
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700432 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
433 UFS_DESC_IDN_GEOMETRY,
434 0,
435 0,
436 (addr_t) geometry_desc,
437 sizeof(struct ufs_geometry_desc)};
438
439 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800440 {
441 dprintf(CRITICAL, "%s:%d DME Read Geometry Descriptor request failed\n", __func__, __LINE__);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700442 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800443 }
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700444
445 // Flush buffer.
446 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_geometry_desc));
447 dev->rpmb_rw_size = desc->rpmb_read_write_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700448 return UFS_SUCCESS;
449}
450
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700451int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700452{
453 STACKBUF_DMA_ALIGN(unit_desc, sizeof(struct ufs_unit_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800454 struct ufs_unit_desc *desc = (struct ufs_unit_desc *) unit_desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700455 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
456 UFS_DESC_IDN_UNIT,
457 index,
458 0,
459 (addr_t) unit_desc,
460 sizeof(struct ufs_unit_desc)};
461
462 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800463 {
464 dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700465 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800466 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700467 /* Flush buffer. */
468 arch_invalidate_cache_range((addr_t) desc, sizeof(struct ufs_unit_desc));
469
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800470 dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700471
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800472 dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700473
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700474 // use only the lower 32 bits for rpmb partition size
475 if (index == UFS_WLUN_RPMB)
476 dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);
477
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700478 return UFS_SUCCESS;
479}
480
481int dme_read_config_desc(struct ufs_dev *dev)
482{
483 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_config_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800484 struct ufs_config_desc *config_desc = (struct ufs_config_desc *)desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700485 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
486 UFS_DESC_IDN_CONFIGURATION,
487 0,
488 0,
489 (addr_t) config_desc,
490 sizeof(struct ufs_config_desc)};
491
492 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800493 {
494 dprintf(CRITICAL, "%s:%d DME Read Config Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700495 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800496 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700497
498 /* Flush buffer. */
499 arch_invalidate_cache_range((addr_t) config_desc, sizeof(struct ufs_config_desc));
500
501 return UFS_SUCCESS;
502}
503
504int dme_send_nop_query(struct ufs_dev *dev)
505{
506 struct upiu_req_build_type req_upiu;
507 struct upiu_basic_hdr resp_upiu;
508 int ret;
509 unsigned try_again;
510
511 ret = UFS_SUCCESS;
512 try_again = DME_NOP_NUM_RETRIES;
513
514 memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
515
516 req_upiu.trans_type = UPIU_TYPE_NOP_OUT;
517 req_upiu.flags = 0;
518 req_upiu.query_mgmt_func = 0;
519 req_upiu.cmd_type = UTRD_DEV_MGMT_FUNC;
520 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
521 req_upiu.resp_ptr = &resp_upiu;
522 req_upiu.resp_len = sizeof(struct upiu_basic_hdr);
523 req_upiu.timeout_msecs = DME_NOP_QUERY_TIMEOUT;
524
525 while (try_again)
526 {
527 try_again--;
528
529 ret = utp_enqueue_upiu(dev, &req_upiu);
530
531 if (ret == -UFS_RETRY)
532 {
533 continue;
534 }
535 else if (ret == -UFS_FAILURE)
536 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800537 dprintf(CRITICAL, "%s:%d Sending nop out failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700538 goto upiu_send_nop_out_err;
539 }
540
541 /* Check response UPIU */
542 if (resp_upiu.trans_type != UPIU_TYPE_NOP_IN)
543 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800544 dprintf(CRITICAL, "%s:%d Command failed. command = %x. Invalid response.\n",__func__,__LINE__, req_upiu.trans_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700545 ret = -UFS_FAILURE;
546 goto upiu_send_nop_out_err;
547 }
548 else
549 break;
550 }
551
552upiu_send_nop_out_err:
553 return ret;
554}
555
556int utp_build_query_req_upiu(struct upiu_trans_mgmt_query_hdr *req_upiu,
557 struct upiu_req_build_type *upiu_data)
558{
559 req_upiu->opcode = upiu_data->opcode;
560 req_upiu->idn = upiu_data->idn;
561 req_upiu->index = upiu_data->index;
562 req_upiu->selector = upiu_data->selector;
563 req_upiu->resp_len = BE16(upiu_data->resp_data_len);
564
565 switch (upiu_data->opcode)
566 {
567 case UPIU_QUERY_OP_READ_FLAG:
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800568 case UPIU_QUERY_OP_READ_ATTRIBUTE:
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700569 case UPIU_QUERY_OP_READ_DESCRIPTOR:
570 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_READ_REQ;
571 break;
572 case UPIU_QUERY_OP_TOGGLE_FLAG:
573 case UPIU_QUERY_OP_CLEAR_FLAG:
574 case UPIU_QUERY_OP_SET_FLAG:
575 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_WRITE_REQ;
576 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800577 default:
578 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
579 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700580 }
581
582 return UFS_SUCCESS;
583}