blob: f83ee93ff9d1f2dc7670258c7b5dcb177e55925f [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{
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700294 uint32_t result;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700295 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,
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700300 (addr_t) &result,
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700301 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,
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700306 (addr_t) &result,
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700307 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
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700316 if (result == 1)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700317 goto utp_set_fdeviceinit_done;
318
319 do
320 {
321 try_again--;
322
323 if (dme_send_query_upiu(dev, &set_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800324 {
325 dprintf(CRITICAL, "%s:%d DME Device Init Set request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700326 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800327 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700328
329 if (dme_send_query_upiu(dev, &read_query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800330 {
331 dprintf(CRITICAL, "%s:%d DME Device Init Read request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700332 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800333 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700334
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700335 if (result == 1)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700336 break;
337 } while (try_again);
338
339utp_set_fdeviceinit_done:
340 return UFS_SUCCESS;
341}
342
343int dme_read_string_desc(struct ufs_dev *dev, uint8_t index, struct ufs_string_desc *desc)
344{
345 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
346 UFS_DESC_IDN_STRING,
347 index,
348 0,
349 (addr_t) desc,
350 sizeof(struct ufs_string_desc)};
351
352 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800353 {
354 dprintf(CRITICAL, "%s:%d DME Read String Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700355 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800356 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700357
358 if (desc->desc_len != 0)
359 return UFS_SUCCESS;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800360 dprintf(CRITICAL, "%s:%d DME Read String Descriptor is length 0\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700361 return -UFS_FAILURE;
362}
363
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700364static uint32_t dme_parse_serial_no(struct ufs_string_desc *desc)
365{
366 uint32_t serial_no=0;
Channagoud Kadabi9fb0fce2015-04-22 11:17:36 -0700367 int len=0;
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700368
369 if(desc->desc_len <= 0)
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800370 {
371 dprintf(CRITICAL, "%s:%d Invalid string descriptor length\n", __func__, __LINE__);
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700372 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800373 }
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700374
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700375 len = (desc->desc_len-2)/2;
376
Channagoud Kadabi9fb0fce2015-04-22 11:17:36 -0700377 serial_no = crc32(~0L, desc->serial_num, len);
Sundarajan Srinivasanf7517cf2013-09-30 15:44:43 -0700378
379 return serial_no;
380}
381
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700382int dme_read_device_desc(struct ufs_dev *dev)
383{
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700384 struct ufs_dev_desc device_desc;
385 struct ufs_string_desc str_desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700386 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
387 UFS_DESC_IDN_DEVICE,
388 0,
389 0,
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700390 (addr_t) &device_desc,
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700391 sizeof(struct ufs_dev_desc)};
392
393 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800394 {
395 dprintf(CRITICAL, "%s:%d DME Read Device Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700396 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800397 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700398
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700399 /* Store all relevant data */
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700400 dev->num_lus = device_desc.num_lu;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700401
402 /* Get serial number for the device based on the string index. */
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700403 if (dme_read_string_desc(dev, device_desc.serial_num, (struct ufs_string_desc *) &str_desc))
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700404 return -UFS_FAILURE;
405
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700406 dev->serial_num = dme_parse_serial_no(&str_desc);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700407
408 return UFS_SUCCESS;
409}
410
411
412int dme_read_geo_desc(struct ufs_dev *dev)
413{
414 struct ufs_geometry_desc *desc;
415 STACKBUF_DMA_ALIGN(geometry_desc, sizeof(struct ufs_geometry_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800416 desc = (struct ufs_geometry_desc *) geometry_desc;
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700417 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
418 UFS_DESC_IDN_GEOMETRY,
419 0,
420 0,
421 (addr_t) geometry_desc,
422 sizeof(struct ufs_geometry_desc)};
423
424 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800425 {
426 dprintf(CRITICAL, "%s:%d DME Read Geometry Descriptor request failed\n", __func__, __LINE__);
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700427 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800428 }
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700429
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700430 dev->rpmb_rw_size = desc->rpmb_read_write_size;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700431 return UFS_SUCCESS;
432}
433
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700434int dme_read_unit_desc(struct ufs_dev *dev, uint8_t index)
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700435{
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700436 struct ufs_unit_desc unit_desc;
437 struct ufs_unit_desc *desc = (struct ufs_unit_desc *) &unit_desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700438 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
439 UFS_DESC_IDN_UNIT,
440 index,
441 0,
Channagoud Kadabicf3afe42015-08-07 16:08:08 -0700442 (addr_t) &unit_desc,
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700443 sizeof(struct ufs_unit_desc)};
444
445 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800446 {
447 dprintf(CRITICAL, "%s:%d DME Read Unit Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700448 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800449 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700450
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800451 dev->lun_cfg[index].logical_blk_cnt = BE64(desc->logical_blk_cnt);
Sundarajan Srinivasan54380a32013-10-25 17:38:38 -0700452
Sundarajan Srinivasan332ce6a2013-12-04 17:27:46 -0800453 dev->lun_cfg[index].erase_blk_size = BE32(desc->erase_blk_size);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700454
Sridhar Parasuram9374faa2014-10-23 19:56:12 -0700455 // use only the lower 32 bits for rpmb partition size
456 if (index == UFS_WLUN_RPMB)
457 dev->rpmb_num_blocks = BE32(desc->logical_blk_cnt >> 32);
458
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700459 return UFS_SUCCESS;
460}
461
462int dme_read_config_desc(struct ufs_dev *dev)
463{
464 STACKBUF_DMA_ALIGN(desc, sizeof(struct ufs_config_desc));
Sridhar Parasuramc02d1072014-11-06 12:55:42 -0800465 struct ufs_config_desc *config_desc = (struct ufs_config_desc *)desc;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700466 struct utp_query_req_upiu_type query = {UPIU_QUERY_OP_READ_DESCRIPTOR,
467 UFS_DESC_IDN_CONFIGURATION,
468 0,
469 0,
470 (addr_t) config_desc,
471 sizeof(struct ufs_config_desc)};
472
473 if (dme_send_query_upiu(dev, &query))
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800474 {
475 dprintf(CRITICAL, "%s:%d DME Read Config Descriptor request failed\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700476 return -UFS_FAILURE;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800477 }
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700478
479 /* Flush buffer. */
480 arch_invalidate_cache_range((addr_t) config_desc, sizeof(struct ufs_config_desc));
481
482 return UFS_SUCCESS;
483}
484
485int dme_send_nop_query(struct ufs_dev *dev)
486{
487 struct upiu_req_build_type req_upiu;
Sridhar Parasuram782645e2015-02-06 16:47:00 -0800488 struct upiu_basic_resp_hdr resp_upiu;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700489 int ret;
490 unsigned try_again;
491
492 ret = UFS_SUCCESS;
493 try_again = DME_NOP_NUM_RETRIES;
494
495 memset(&req_upiu, 0 , sizeof(struct upiu_req_build_type));
496
497 req_upiu.trans_type = UPIU_TYPE_NOP_OUT;
498 req_upiu.flags = 0;
499 req_upiu.query_mgmt_func = 0;
500 req_upiu.cmd_type = UTRD_DEV_MGMT_FUNC;
501 req_upiu.dd = UTRD_NO_DATA_TRANSFER;
502 req_upiu.resp_ptr = &resp_upiu;
503 req_upiu.resp_len = sizeof(struct upiu_basic_hdr);
504 req_upiu.timeout_msecs = DME_NOP_QUERY_TIMEOUT;
505
506 while (try_again)
507 {
508 try_again--;
509
510 ret = utp_enqueue_upiu(dev, &req_upiu);
511
512 if (ret == -UFS_RETRY)
513 {
514 continue;
515 }
516 else if (ret == -UFS_FAILURE)
517 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800518 dprintf(CRITICAL, "%s:%d Sending nop out failed.\n", __func__, __LINE__);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700519 goto upiu_send_nop_out_err;
520 }
521
522 /* Check response UPIU */
523 if (resp_upiu.trans_type != UPIU_TYPE_NOP_IN)
524 {
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800525 dprintf(CRITICAL, "%s:%d Command failed. command = %x. Invalid response.\n",__func__,__LINE__, req_upiu.trans_type);
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700526 ret = -UFS_FAILURE;
527 goto upiu_send_nop_out_err;
528 }
529 else
530 break;
531 }
532
533upiu_send_nop_out_err:
534 return ret;
535}
536
537int utp_build_query_req_upiu(struct upiu_trans_mgmt_query_hdr *req_upiu,
538 struct upiu_req_build_type *upiu_data)
539{
540 req_upiu->opcode = upiu_data->opcode;
541 req_upiu->idn = upiu_data->idn;
542 req_upiu->index = upiu_data->index;
543 req_upiu->selector = upiu_data->selector;
544 req_upiu->resp_len = BE16(upiu_data->resp_data_len);
545
546 switch (upiu_data->opcode)
547 {
548 case UPIU_QUERY_OP_READ_FLAG:
Sridhar Parasuram5351efc2015-02-06 16:41:35 -0800549 case UPIU_QUERY_OP_READ_ATTRIBUTE:
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700550 case UPIU_QUERY_OP_READ_DESCRIPTOR:
551 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_READ_REQ;
552 break;
553 case UPIU_QUERY_OP_TOGGLE_FLAG:
554 case UPIU_QUERY_OP_CLEAR_FLAG:
555 case UPIU_QUERY_OP_SET_FLAG:
556 req_upiu->basic_hdr.query_task_mgmt_func = UPIU_QUERY_FUNC_STD_WRITE_REQ;
557 break;
Sridhar Parasuram56d09f32014-11-05 15:58:30 -0800558 default:
559 dprintf(CRITICAL, "%s:%d UPIU query opcode not supported.\n", __func__, __LINE__);
560 return -UFS_FAILURE;
Deepa Dinamaniab9c2b92013-09-12 11:30:58 -0700561 }
562
563 return UFS_SUCCESS;
564}