xref: /rk3399_rockchip-uboot/drivers/ufs/ufs-rockchip-usbplug.c (revision 1865a7e4c4aeeb4e7d66ace8020a852e57564e30)
12c3d2faaSYifeng Zhao // SPDX-License-Identifier: GPL-2.0+
22c3d2faaSYifeng Zhao /*
32c3d2faaSYifeng Zhao  * Rockchip UFS Host Controller driver
42c3d2faaSYifeng Zhao  *
52c3d2faaSYifeng Zhao  * Copyright (C) 2024 Rockchip Electronics Co.Ltd.
62c3d2faaSYifeng Zhao  */
72c3d2faaSYifeng Zhao 
82c3d2faaSYifeng Zhao #include <charset.h>
92c3d2faaSYifeng Zhao #include <common.h>
102c3d2faaSYifeng Zhao #include <dm.h>
112c3d2faaSYifeng Zhao #include <log.h>
122c3d2faaSYifeng Zhao #include <dm/lists.h>
132c3d2faaSYifeng Zhao #include <dm/device-internal.h>
142c3d2faaSYifeng Zhao #include <malloc.h>
152c3d2faaSYifeng Zhao #include <hexdump.h>
162c3d2faaSYifeng Zhao #include <scsi.h>
172c3d2faaSYifeng Zhao #include <asm/io.h>
182c3d2faaSYifeng Zhao #include <asm/dma-mapping.h>
192c3d2faaSYifeng Zhao #include <linux/bitops.h>
202c3d2faaSYifeng Zhao #include <linux/delay.h>
212c3d2faaSYifeng Zhao 
222c3d2faaSYifeng Zhao #include "ufs-rockchip-usbplug.h"
232c3d2faaSYifeng Zhao #include "ufs.h"
241e6560dfSYifeng Zhao /* Query request retries */
251e6560dfSYifeng Zhao #define QUERY_REQ_RETRIES 3
261e6560dfSYifeng Zhao /* Query request timeout */
271e6560dfSYifeng Zhao #define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */
282c3d2faaSYifeng Zhao 
292c3d2faaSYifeng Zhao #if defined(CONFIG_SUPPORT_USBPLUG)
302c3d2faaSYifeng Zhao int _ufs_start(struct ufs_hba *hba);
312c3d2faaSYifeng Zhao 
322c3d2faaSYifeng Zhao static void ufs_info_show_dev_desc(void *buf)
332c3d2faaSYifeng Zhao {
342c3d2faaSYifeng Zhao 	struct ufs_device_descriptor *dev = (struct ufs_device_descriptor *)buf;
352c3d2faaSYifeng Zhao 
362c3d2faaSYifeng Zhao 	printf("---------------------------\n");
372c3d2faaSYifeng Zhao 	printf("---UFS Device Descriptor---\n");
382c3d2faaSYifeng Zhao 	printf("---------------------------\n");
392c3d2faaSYifeng Zhao 	printf("bLength: 0x%x\n", dev->b_length);
402c3d2faaSYifeng Zhao 	printf("bDescriptorIDN: 0x%x\n", dev->b_descriptor_idn);
412c3d2faaSYifeng Zhao 	printf("bDevice: 0x%x\n", dev->b_device);
422c3d2faaSYifeng Zhao 	printf("bDeviceClass: 0x%x\n", dev->b_device_class);
432c3d2faaSYifeng Zhao 	printf("bDeviceSubClass: 0x%x\n", dev->b_device_sub_class);
442c3d2faaSYifeng Zhao 	printf("bProtocol: 0x%x\n", dev->b_protocol);
452c3d2faaSYifeng Zhao 	printf("bNumberLU: 0x%x\n", dev->b_number_lu);
462c3d2faaSYifeng Zhao 	printf("bNumberWLU: 0x%x\n", dev->b_number_wlu);
472c3d2faaSYifeng Zhao 	printf("bBootEnable: 0x%x\n", dev->b_boot_enable);
482c3d2faaSYifeng Zhao 	printf("bDescrAccessEn: 0x%x\n", dev->b_descr_access_en);
492c3d2faaSYifeng Zhao 	printf("bInitPowerMode: 0x%x\n", dev->b_init_power_mode);
502c3d2faaSYifeng Zhao 	printf("bHighPriorityLUN: 0x%x\n", dev->b_high_priority_lun);
512c3d2faaSYifeng Zhao 	printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
522c3d2faaSYifeng Zhao 	printf("bSecurityLU: 0x%x\n", dev->b_security_lu);
532c3d2faaSYifeng Zhao 	printf("bBackgroundOpsTermLat: 0x%x\n", dev->b_background_ops_term_lat);
542c3d2faaSYifeng Zhao 	printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
552c3d2faaSYifeng Zhao 	printf("wSpecVersion: 0x%x\n", to_bigendian16(dev->w_spec_version));
562c3d2faaSYifeng Zhao 	printf("wManufactureDate: 0x%x\n", to_bigendian16(dev->w_manufacture_date));
572c3d2faaSYifeng Zhao 	printf("iManufacturerName: 0x%x\n", dev->i_manufacturer_name);
582c3d2faaSYifeng Zhao 	printf("iProductName: 0x%x\n", dev->i_product_name);
592c3d2faaSYifeng Zhao 	printf("iSerialNumber: 0x%x\n", dev->i_serial_number);
602c3d2faaSYifeng Zhao 	printf("iOemID: 0x%x\n", dev->i_oem_id);
612c3d2faaSYifeng Zhao 	printf("wManufacturerID: 0x%x\n", to_bigendian16(dev->w_manufacturer_id));
622c3d2faaSYifeng Zhao 	printf("bUD0BaseOffset: 0x%x\n", dev->b_ud_0base_offset);
632c3d2faaSYifeng Zhao 	printf("bUDConfigPLength: 0x%x\n", dev->b_ud_config_plength);
642c3d2faaSYifeng Zhao 	printf("bDeviceRTTCap: 0x%x\n", dev->b_device_rtt_cap);
652c3d2faaSYifeng Zhao 	printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
662c3d2faaSYifeng Zhao 	printf("bUFSFeatureSupport: 0x%x\n", dev->b_ufs_feature_support);
672c3d2faaSYifeng Zhao 	printf("bFFUTimeout: 0x%x\n", dev->b_ffu_timeout);
682c3d2faaSYifeng Zhao 	printf("bQueueDepth: 0x%x\n", dev->b_queue_depth);
692c3d2faaSYifeng Zhao 	printf("wDeviceVersion: 0x%x\n", to_bigendian16(dev->w_device_version));
702c3d2faaSYifeng Zhao 	printf("bNumSecureWPArea: 0x%x\n", dev->b_num_secure_wp_area);
712c3d2faaSYifeng Zhao 	printf("dPSAMaxDataSize: 0x%x\n", to_bigendian32(dev->d_psa_max_data_size));
722c3d2faaSYifeng Zhao 	printf("bPSAStateTimeout: 0x%x\n", dev->b_psa_state_timeout);
732c3d2faaSYifeng Zhao 	printf("iProductRevisionLevel: 0x%x\n", dev->i_product_revision_level);
742c3d2faaSYifeng Zhao }
752c3d2faaSYifeng Zhao 
762c3d2faaSYifeng Zhao static void ufs_info_show_conf_desc(void *buf)
772c3d2faaSYifeng Zhao {
782c3d2faaSYifeng Zhao 	struct ufs_configuration_descriptor *c_desc = (struct ufs_configuration_descriptor *)buf;
792c3d2faaSYifeng Zhao 	struct ufs_dev_desc_configuration_param *dev;
802c3d2faaSYifeng Zhao 	struct ufs_unit_desc_configuration_param *unit;
812c3d2faaSYifeng Zhao 	int i;
822c3d2faaSYifeng Zhao 
832c3d2faaSYifeng Zhao 	dev = &c_desc->dev_desc_conf_param;
842c3d2faaSYifeng Zhao 	printf("----------------------------------------\n");
852c3d2faaSYifeng Zhao 	printf("---UFS Device Descriptor Config Param---\n");
862c3d2faaSYifeng Zhao 	printf("----------------------------------------\n");
872c3d2faaSYifeng Zhao 	printf("bLength: 0x%x\n", dev->b_length);
882c3d2faaSYifeng Zhao 	printf("bDescriptorIDN: 0x%x\n", dev->b_descriptor_idn);
892c3d2faaSYifeng Zhao 	printf("bConfDescContinue: 0x%x\n", dev->b_conf_desc_continue);
902c3d2faaSYifeng Zhao 	printf("bBootEnable: 0x%x\n", dev->b_boot_enable);
912c3d2faaSYifeng Zhao 	printf("bDescrAccessEn: 0x%x\n", dev->b_descr_access_en);
922c3d2faaSYifeng Zhao 	printf("bInitPowerMode: 0x%x\n", dev->b_init_power_mode);
932c3d2faaSYifeng Zhao 	printf("bHighPriorityLUN: 0x%x\n", dev->b_high_priority_lun);
942c3d2faaSYifeng Zhao 	printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
952c3d2faaSYifeng Zhao 	printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
962c3d2faaSYifeng Zhao 	printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
97*1865a7e4SYifeng Zhao 	printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
98*1865a7e4SYifeng Zhao 	printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
99*1865a7e4SYifeng Zhao 	printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
100*1865a7e4SYifeng Zhao 	printf("bWB_EN: 0x%x\n", dev->b_write_booster_buffer_reserve_user_space_en);
101*1865a7e4SYifeng Zhao 	printf("WB_TYPE: 0x%x\n", dev->b_write_booster_buffer_type);
102*1865a7e4SYifeng Zhao 	printf("WB_alloc_units: 0x%x\n", to_bigendian32(dev->d_num_shared_write_booster_buffer_alloc_units));
1032c3d2faaSYifeng Zhao 
1042c3d2faaSYifeng Zhao 	for (i = 0; i < UNIT_DESCS_COUNT; i++) {
1052c3d2faaSYifeng Zhao 		unit = &c_desc->unit_desc_conf_param[i];
1062c3d2faaSYifeng Zhao 
1072c3d2faaSYifeng Zhao 		printf("-----------------------------------------\n");
1082c3d2faaSYifeng Zhao 		printf("---UFS Unit %d Descriptor Config Param---\n", i);
1092c3d2faaSYifeng Zhao 		printf("-----------------------------------------\n");
1102c3d2faaSYifeng Zhao 		printf("bLUEnable: 0x%x\n", unit->b_lu_enable);
1112c3d2faaSYifeng Zhao 		printf("bBootLunID: 0x%x\n", unit->b_boot_lun_id);
1122c3d2faaSYifeng Zhao 		printf("bLUWriteProtect: 0x%x\n", unit->b_lu_write_protect);
1132c3d2faaSYifeng Zhao 		printf("bMemoryType: 0x%x\n", unit->b_memory_type);
1142c3d2faaSYifeng Zhao 		printf("dNumAllocUnits: 0x%x\n", to_bigendian32(unit->d_num_alloc_units));
1152c3d2faaSYifeng Zhao 		printf("bDataReliability: 0x%x\n", unit->b_data_reliability);
1162c3d2faaSYifeng Zhao 		printf("bLogicalBlockSize: 0x%x\n", unit->b_logical_block_size);
1172c3d2faaSYifeng Zhao 		printf("bProvisioningType: 0x%x\n", unit->b_provisioning_type);
1182c3d2faaSYifeng Zhao 		printf("wContextCapabilities: 0x%x\n", to_bigendian16(unit->w_context_capabilities));
1192c3d2faaSYifeng Zhao 	}
1202c3d2faaSYifeng Zhao }
1212c3d2faaSYifeng Zhao 
1222c3d2faaSYifeng Zhao static int ufs_get_configuration_desc(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
1232c3d2faaSYifeng Zhao {
1242c3d2faaSYifeng Zhao 	u8 desc_buf[CONFIGURATION_DESC_V22_LENGTH];
1252c3d2faaSYifeng Zhao 	u8 *buf = desc_buf;
1262c3d2faaSYifeng Zhao 	int length = CONFIGURATION_DESC_V22_LENGTH;
1272c3d2faaSYifeng Zhao 	int err;
1282c3d2faaSYifeng Zhao 
1292c3d2faaSYifeng Zhao 	if (CONFIGURATION_DESC_V31_LENGTH == hba->desc_size.conf_desc) {
1302c3d2faaSYifeng Zhao 		buf = (u8 *)c_desc;
1312c3d2faaSYifeng Zhao 		length = CONFIGURATION_DESC_V31_LENGTH;
1322c3d2faaSYifeng Zhao 	} else if(CONFIGURATION_DESC_V22_LENGTH != hba->desc_size.conf_desc) {
1332c3d2faaSYifeng Zhao 		return -EINVAL;
1342c3d2faaSYifeng Zhao 	}
1352c3d2faaSYifeng Zhao 
1362c3d2faaSYifeng Zhao 	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_CONFIGURATION, 0, 0, buf, length);
1372c3d2faaSYifeng Zhao 	if (err) {
1382c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed reading configuration Desc. err = %d\n",
1392c3d2faaSYifeng Zhao 			__func__, err);
1402c3d2faaSYifeng Zhao 		return err;
1412c3d2faaSYifeng Zhao 	}
1422c3d2faaSYifeng Zhao 
1432c3d2faaSYifeng Zhao 	if (CONFIGURATION_DESC_V22_LENGTH == hba->desc_size.conf_desc) {
1442c3d2faaSYifeng Zhao 		memcpy(&c_desc->dev_desc_conf_param, buf, 0x10);
1452c3d2faaSYifeng Zhao 		buf += 0x10;
1462c3d2faaSYifeng Zhao 		for (int i = 0; i < UNIT_DESCS_COUNT; i++) {
1472c3d2faaSYifeng Zhao 			memcpy(&c_desc->unit_desc_conf_param[i], buf,  0x10);
1482c3d2faaSYifeng Zhao 			buf += 0x10;
1492c3d2faaSYifeng Zhao 		}
1502c3d2faaSYifeng Zhao 	}
1512c3d2faaSYifeng Zhao 
1522c3d2faaSYifeng Zhao 	return err;
1532c3d2faaSYifeng Zhao }
1542c3d2faaSYifeng Zhao 
1552c3d2faaSYifeng Zhao static int ufshcd_write_desc_param(struct ufs_hba *hba, enum desc_idn desc_id,
1562c3d2faaSYifeng Zhao 			   int desc_index, u8 param_offset, u8 *param_read_buf,
1572c3d2faaSYifeng Zhao 			   u8 param_size)
1582c3d2faaSYifeng Zhao {
1592c3d2faaSYifeng Zhao 	int ret;
1602c3d2faaSYifeng Zhao 	u8 *desc_buf;
1612c3d2faaSYifeng Zhao 	int buff_len;
1622c3d2faaSYifeng Zhao 
1632c3d2faaSYifeng Zhao 	/* Safety check */
1642c3d2faaSYifeng Zhao 	if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
1652c3d2faaSYifeng Zhao 		return -EINVAL;
1662c3d2faaSYifeng Zhao 
1672c3d2faaSYifeng Zhao 	/* Get the max length of descriptor from structure filled up at probe
1682c3d2faaSYifeng Zhao 	 * time.
1692c3d2faaSYifeng Zhao 	 */
1702c3d2faaSYifeng Zhao 	ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
1712c3d2faaSYifeng Zhao 
1722c3d2faaSYifeng Zhao 	/* Sanity checks */
1732c3d2faaSYifeng Zhao 	if (ret || !buff_len) {
1742c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed to get full descriptor length\n",
1752c3d2faaSYifeng Zhao 			__func__);
1762c3d2faaSYifeng Zhao 		return ret;
1772c3d2faaSYifeng Zhao 	}
1782c3d2faaSYifeng Zhao 
1792c3d2faaSYifeng Zhao 	desc_buf = param_read_buf;
1802c3d2faaSYifeng Zhao 	/* Request for full descriptor */
1812c3d2faaSYifeng Zhao 	ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_WRITE_DESC,
1822c3d2faaSYifeng Zhao 					    desc_id, desc_index, 0, desc_buf,
1832c3d2faaSYifeng Zhao 					    &buff_len);
1842c3d2faaSYifeng Zhao 
1852c3d2faaSYifeng Zhao 	if (ret)
1862c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed write descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
1872c3d2faaSYifeng Zhao 			__func__, desc_id, desc_index, param_offset, ret);
1882c3d2faaSYifeng Zhao 
1892c3d2faaSYifeng Zhao 	return ret;
1902c3d2faaSYifeng Zhao }
1912c3d2faaSYifeng Zhao 
1922c3d2faaSYifeng Zhao static int ufs_write_configuration_desc(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
1932c3d2faaSYifeng Zhao {
1942c3d2faaSYifeng Zhao 	u8 desc_buf[CONFIGURATION_DESC_V22_LENGTH];
1952c3d2faaSYifeng Zhao 	u8 *buf = desc_buf;
1962c3d2faaSYifeng Zhao 	int length = CONFIGURATION_DESC_V22_LENGTH;
1972c3d2faaSYifeng Zhao 	int err;
1982c3d2faaSYifeng Zhao 
1992c3d2faaSYifeng Zhao 	if (CONFIGURATION_DESC_V31_LENGTH == hba->desc_size.conf_desc) {
2002c3d2faaSYifeng Zhao 		buf = (u8 *)c_desc;
2012c3d2faaSYifeng Zhao 		length = CONFIGURATION_DESC_V31_LENGTH;
2022c3d2faaSYifeng Zhao 	} else if(CONFIGURATION_DESC_V22_LENGTH == hba->desc_size.conf_desc) {
2032c3d2faaSYifeng Zhao 		memcpy(buf, &c_desc->dev_desc_conf_param, 0x10);
2042c3d2faaSYifeng Zhao 		buf += 0x10;
2052c3d2faaSYifeng Zhao 		for (int i = 0; i < UNIT_DESCS_COUNT; i++) {
2062c3d2faaSYifeng Zhao 			memcpy(buf, &c_desc->unit_desc_conf_param[i], 0x10);
2072c3d2faaSYifeng Zhao 			buf += 0x10;
2082c3d2faaSYifeng Zhao 		}
2092c3d2faaSYifeng Zhao 		buf = desc_buf;
2102c3d2faaSYifeng Zhao 	} else {
2112c3d2faaSYifeng Zhao 		return -EINVAL;
2122c3d2faaSYifeng Zhao 	}
2132c3d2faaSYifeng Zhao 
2142c3d2faaSYifeng Zhao 	err = ufshcd_write_desc_param(hba, QUERY_DESC_IDN_CONFIGURATION, 0, 0, buf, length);
2152c3d2faaSYifeng Zhao 	if (err) {
2162c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed reading configuration Desc. err = %d\n",
2172c3d2faaSYifeng Zhao 			__func__, err);
2182c3d2faaSYifeng Zhao 		return err;
2192c3d2faaSYifeng Zhao 	}
2202c3d2faaSYifeng Zhao 
2212c3d2faaSYifeng Zhao 	return err;
2222c3d2faaSYifeng Zhao }
2232c3d2faaSYifeng Zhao 
2242c3d2faaSYifeng Zhao static void ufs_lu_configuration(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
2252c3d2faaSYifeng Zhao {
2262c3d2faaSYifeng Zhao 	uint32_t denominator = hba->geo_desc->b_allocation_unit_size * to_bigendian32(hba->geo_desc->d_segment_size);
2272c3d2faaSYifeng Zhao 	struct ufs_dev_desc_configuration_param *dev;
2282c3d2faaSYifeng Zhao 	struct ufs_unit_desc_configuration_param *unit;
2292c3d2faaSYifeng Zhao 	uint32_t alloced_units = 0;
2302c3d2faaSYifeng Zhao 	int i, cap_adj_fac;
2312c3d2faaSYifeng Zhao 	uint64_t total_raw_device_capacity;
232*1865a7e4SYifeng Zhao 	uint32_t max_wb_alloc_units = cpu_to_be32(hba->geo_desc->d_write_booster_buffer_max_alloc_units);
233*1865a7e4SYifeng Zhao 	uint32_t wb_alloc_units;
2342c3d2faaSYifeng Zhao 
2352c3d2faaSYifeng Zhao 	cap_adj_fac = to_bigendian16(hba->geo_desc->w_enhanced1_cap_adj_fac) / 256;
2362c3d2faaSYifeng Zhao 	total_raw_device_capacity = cpu_to_be64(hba->geo_desc->q_total_raw_device_capacity);
2372c3d2faaSYifeng Zhao 
2382c3d2faaSYifeng Zhao 	dev = &c_desc->dev_desc_conf_param;
2392c3d2faaSYifeng Zhao 	dev->b_boot_enable = 0x1;
2402c3d2faaSYifeng Zhao 	dev->b_descr_access_en = 0x0;
2412c3d2faaSYifeng Zhao 	dev->b_init_power_mode = 0x1;
2422c3d2faaSYifeng Zhao 	dev->b_high_priority_lun = 0x7F;
2432c3d2faaSYifeng Zhao 	dev->b_secure_removal_type = 0x0;
2442c3d2faaSYifeng Zhao 	dev->b_init_active_icc_level = 0x0;
2452c3d2faaSYifeng Zhao 	dev->w_periodic_rtc_update = 0x0;
2462c3d2faaSYifeng Zhao 
2472c3d2faaSYifeng Zhao 	unit = &c_desc->unit_desc_conf_param[0];
2482c3d2faaSYifeng Zhao 	/* lu 1: boot lu A 4MB */
2492c3d2faaSYifeng Zhao 	unit[1].b_boot_lun_id = WELL_BOOT_LU_A; /* lu 0, boot a */
2502c3d2faaSYifeng Zhao 	unit[1].b_memory_type = 0x3;
2512c3d2faaSYifeng Zhao 	unit[1].d_num_alloc_units = (4 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
2522c3d2faaSYifeng Zhao 	alloced_units += unit[1].d_num_alloc_units;
2532c3d2faaSYifeng Zhao 	/* lu 2: boot lu B 4MB */
2542c3d2faaSYifeng Zhao 	unit[2].b_boot_lun_id = WELL_BOOT_LU_B; /* lu 1, boot b */
2552c3d2faaSYifeng Zhao 	unit[2].b_memory_type = 0x3; /* lu 0, Enhanced Memory */
2562c3d2faaSYifeng Zhao 	unit[2].d_num_alloc_units = (4 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
2572c3d2faaSYifeng Zhao 	alloced_units += unit[2].d_num_alloc_units;
2582c3d2faaSYifeng Zhao 	/* lu 3: data lu 8MB */
2592c3d2faaSYifeng Zhao 	unit[3].b_boot_lun_id = 0x0; /* lu 2 */
2602c3d2faaSYifeng Zhao 	unit[3].b_memory_type = 0x3; /* lu 2, Enhanced Memory */
2612c3d2faaSYifeng Zhao 	unit[3].d_num_alloc_units = (8 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
2622c3d2faaSYifeng Zhao 	alloced_units += unit[3].d_num_alloc_units;
2631e6560dfSYifeng Zhao 
264*1865a7e4SYifeng Zhao 	if (max_wb_alloc_units) {
265*1865a7e4SYifeng Zhao 		wb_alloc_units = max_wb_alloc_units;
266*1865a7e4SYifeng Zhao 		if (wb_alloc_units > max_wb_alloc_units)
267*1865a7e4SYifeng Zhao 			wb_alloc_units = max_wb_alloc_units;
268*1865a7e4SYifeng Zhao 		dev->b_write_booster_buffer_reserve_user_space_en = 1;
269*1865a7e4SYifeng Zhao 		dev->b_write_booster_buffer_type = 1;
270*1865a7e4SYifeng Zhao 		dev->d_num_shared_write_booster_buffer_alloc_units = to_bigendian32(wb_alloc_units);
271*1865a7e4SYifeng Zhao 	}
272*1865a7e4SYifeng Zhao 
2732c3d2faaSYifeng Zhao 	/* lu 0: data lu, max capacity*/
2742c3d2faaSYifeng Zhao 	unit[0].b_boot_lun_id = 0x0; /* lu 3 */
2752c3d2faaSYifeng Zhao 	unit[0].b_memory_type = 0x0; /* lu 3, Normal Memory */
2762c3d2faaSYifeng Zhao 	unit[0].d_num_alloc_units = lower_32_bits(total_raw_device_capacity) / denominator - alloced_units;
2772c3d2faaSYifeng Zhao 
2782c3d2faaSYifeng Zhao 	for (i = 0; i <= 3; i++) { /* lu 0 - 3 */
2792c3d2faaSYifeng Zhao 		unit[i].b_lu_enable = 0x1;
2802c3d2faaSYifeng Zhao 		unit[i].b_lu_write_protect = 0x0;
2812c3d2faaSYifeng Zhao 		unit[i].b_data_reliability = 0x1;
2822c3d2faaSYifeng Zhao 		unit[i].b_logical_block_size = 0x0c;
2832c3d2faaSYifeng Zhao 		unit[i].b_provisioning_type = 0x2;
2842c3d2faaSYifeng Zhao 		unit[i].w_context_capabilities = 0x0;
2852c3d2faaSYifeng Zhao 		unit[i].d_num_alloc_units = to_bigendian32(unit[i].d_num_alloc_units);
2862c3d2faaSYifeng Zhao 	}
2872c3d2faaSYifeng Zhao }
2882c3d2faaSYifeng Zhao 
2892c3d2faaSYifeng Zhao static int compair_conf_desp(struct ufs_configuration_descriptor *cda, struct ufs_configuration_descriptor *cdb)
2902c3d2faaSYifeng Zhao {
2912c3d2faaSYifeng Zhao 	struct ufs_dev_desc_configuration_param *dev_a, *dev_b;
2922c3d2faaSYifeng Zhao 	struct ufs_unit_desc_configuration_param *unit_a, *unit_b;
2932c3d2faaSYifeng Zhao 	int i, ret;
2942c3d2faaSYifeng Zhao 
2952c3d2faaSYifeng Zhao 	dev_a = &cda->dev_desc_conf_param;
2962c3d2faaSYifeng Zhao 	dev_b = &cdb->dev_desc_conf_param;
2972c3d2faaSYifeng Zhao 
2982c3d2faaSYifeng Zhao 	if (dev_a->b_boot_enable != dev_b->b_boot_enable)
2992c3d2faaSYifeng Zhao 		return 0x3;
3002c3d2faaSYifeng Zhao 	if (dev_a->b_descr_access_en != dev_b->b_descr_access_en)
3012c3d2faaSYifeng Zhao 		return 0x4;
3022c3d2faaSYifeng Zhao 	if (dev_a->b_init_power_mode != dev_b->b_init_power_mode)
3032c3d2faaSYifeng Zhao 		return 0x5;
3042c3d2faaSYifeng Zhao 	if (dev_a->b_high_priority_lun != dev_b->b_high_priority_lun)
3052c3d2faaSYifeng Zhao 		return 0x6;
3062c3d2faaSYifeng Zhao 	if (dev_a->b_secure_removal_type != dev_b->b_secure_removal_type)
3072c3d2faaSYifeng Zhao 		return 0x7;
3082c3d2faaSYifeng Zhao 	if (dev_a->b_init_active_icc_level != dev_b->b_init_active_icc_level)
3092c3d2faaSYifeng Zhao 		return 0x8;
3102c3d2faaSYifeng Zhao 	if (dev_a->w_periodic_rtc_update != dev_b->w_periodic_rtc_update)
3112c3d2faaSYifeng Zhao 		return 0x9;
312*1865a7e4SYifeng Zhao 	if (dev_a->b_write_booster_buffer_reserve_user_space_en !=
313*1865a7e4SYifeng Zhao 	    dev_b->b_write_booster_buffer_reserve_user_space_en)
314*1865a7e4SYifeng Zhao 		return 0xA;
315*1865a7e4SYifeng Zhao 	if (dev_a->b_write_booster_buffer_type != dev_b->b_write_booster_buffer_type)
316*1865a7e4SYifeng Zhao 		return 0xB;
317*1865a7e4SYifeng Zhao 	if (dev_a->d_num_shared_write_booster_buffer_alloc_units !=
318*1865a7e4SYifeng Zhao 	    dev_b->d_num_shared_write_booster_buffer_alloc_units)
319*1865a7e4SYifeng Zhao 		return 0xC;
3202c3d2faaSYifeng Zhao 
3212c3d2faaSYifeng Zhao 	for (i = 0; i < UNIT_DESCS_COUNT; i++) {
3222c3d2faaSYifeng Zhao 		unit_a = &cda->unit_desc_conf_param[i];
3232c3d2faaSYifeng Zhao 		unit_b = &cdb->unit_desc_conf_param[i];
3242c3d2faaSYifeng Zhao 
3252c3d2faaSYifeng Zhao 		ret = 0x10 * (i + 1);
3262c3d2faaSYifeng Zhao 		if (unit_a->b_lu_enable != unit_b->b_lu_enable)
3272c3d2faaSYifeng Zhao 			return ret;
3282c3d2faaSYifeng Zhao 		if (unit_a->b_boot_lun_id != unit_b->b_boot_lun_id)
3292c3d2faaSYifeng Zhao 			return ret + 0x1;
3302c3d2faaSYifeng Zhao 		if (unit_a->b_lu_write_protect != unit_b->b_lu_write_protect)
3312c3d2faaSYifeng Zhao 			return ret + 0x2;
3322c3d2faaSYifeng Zhao 		if (unit_a->b_memory_type != unit_b->b_memory_type)
3332c3d2faaSYifeng Zhao 			return ret + 0x3;
3342c3d2faaSYifeng Zhao 		if (unit_a->d_num_alloc_units != unit_b->d_num_alloc_units)
3352c3d2faaSYifeng Zhao 			return ret + 0x4;
3362c3d2faaSYifeng Zhao 		if (unit_a->b_data_reliability != unit_b->b_data_reliability)
3372c3d2faaSYifeng Zhao 			return ret + 0x8;
3382c3d2faaSYifeng Zhao 		if (unit_a->b_logical_block_size != unit_b->b_logical_block_size)
3392c3d2faaSYifeng Zhao 			return ret + 0x9;
3402c3d2faaSYifeng Zhao 		if (unit_a->b_provisioning_type != unit_b->b_provisioning_type)
3412c3d2faaSYifeng Zhao 			return ret + 0xA;
3422c3d2faaSYifeng Zhao 		if (unit_a->w_context_capabilities != unit_b->w_context_capabilities)
3432c3d2faaSYifeng Zhao 			return ret + 0xB;
3442c3d2faaSYifeng Zhao 	}
3452c3d2faaSYifeng Zhao 	return 0;
3462c3d2faaSYifeng Zhao }
3472c3d2faaSYifeng Zhao 
3482c3d2faaSYifeng Zhao 
3491e6560dfSYifeng Zhao /**
3501e6560dfSYifeng Zhao  * ufshcd_init_query() - init the query response and request parameters
3511e6560dfSYifeng Zhao  */
3521e6560dfSYifeng Zhao static inline void ufshcd_init_query(struct ufs_hba *hba,
3531e6560dfSYifeng Zhao 				     struct ufs_query_req **request,
3541e6560dfSYifeng Zhao 				     struct ufs_query_res **response,
3551e6560dfSYifeng Zhao 				     enum query_opcode opcode,
3561e6560dfSYifeng Zhao 				     u8 idn, u8 index, u8 selector)
3571e6560dfSYifeng Zhao {
3581e6560dfSYifeng Zhao 	*request = &hba->dev_cmd.query.request;
3591e6560dfSYifeng Zhao 	*response = &hba->dev_cmd.query.response;
3601e6560dfSYifeng Zhao 	memset(*request, 0, sizeof(struct ufs_query_req));
3611e6560dfSYifeng Zhao 	memset(*response, 0, sizeof(struct ufs_query_res));
3621e6560dfSYifeng Zhao 	(*request)->upiu_req.opcode = opcode;
3631e6560dfSYifeng Zhao 	(*request)->upiu_req.idn = idn;
3641e6560dfSYifeng Zhao 	(*request)->upiu_req.index = index;
3651e6560dfSYifeng Zhao 	(*request)->upiu_req.selector = selector;
3661e6560dfSYifeng Zhao }
3671e6560dfSYifeng Zhao 
3681e6560dfSYifeng Zhao /**
3691e6560dfSYifeng Zhao  * ufshcd_query_flag() - API function for sending flag query requests
3701e6560dfSYifeng Zhao  */
3711e6560dfSYifeng Zhao static int ufshcd_query_attribute(struct ufs_hba *hba,enum query_opcode opcode,
3721e6560dfSYifeng Zhao 				  enum attr_id idn, u8 index, u8 selector, u32 *value)
3731e6560dfSYifeng Zhao {
3741e6560dfSYifeng Zhao 	struct ufs_query_req *request = &hba->dev_cmd.query.request;
3751e6560dfSYifeng Zhao 	struct ufs_query_res *response = &hba->dev_cmd.query.response;
3761e6560dfSYifeng Zhao 	int err;
3771e6560dfSYifeng Zhao 	int timeout = QUERY_REQ_TIMEOUT;
3781e6560dfSYifeng Zhao 
3791e6560dfSYifeng Zhao 	memset(request, 0, sizeof(struct ufs_query_req));
3801e6560dfSYifeng Zhao 	memset(response, 0, sizeof(struct ufs_query_res));
3811e6560dfSYifeng Zhao 	request->upiu_req.opcode = opcode;
3821e6560dfSYifeng Zhao 	request->upiu_req.idn = idn;
3831e6560dfSYifeng Zhao 	request->upiu_req.index = 0;
3841e6560dfSYifeng Zhao 	request->upiu_req.selector = 0;
3851e6560dfSYifeng Zhao 
3861e6560dfSYifeng Zhao 	switch (opcode) {
3871e6560dfSYifeng Zhao 	case UPIU_QUERY_OPCODE_WRITE_ATTR:
3881e6560dfSYifeng Zhao 		request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
3891e6560dfSYifeng Zhao 		request->upiu_req.value = be32_to_cpu(*value);
3901e6560dfSYifeng Zhao 		break;
3911e6560dfSYifeng Zhao 	case UPIU_QUERY_OPCODE_READ_ATTR:
3921e6560dfSYifeng Zhao 		request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
3931e6560dfSYifeng Zhao 		break;
3941e6560dfSYifeng Zhao 	default:
3951e6560dfSYifeng Zhao 		dev_err(hba->dev,
3961e6560dfSYifeng Zhao 			"%s: Expected query flag opcode but got = %d\n",
3971e6560dfSYifeng Zhao 			__func__, opcode);
3981e6560dfSYifeng Zhao 		err = -EINVAL;
3991e6560dfSYifeng Zhao 		goto out;
4001e6560dfSYifeng Zhao 	}
4011e6560dfSYifeng Zhao 
4021e6560dfSYifeng Zhao 	err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
4031e6560dfSYifeng Zhao 
4041e6560dfSYifeng Zhao 	if (err) {
4051e6560dfSYifeng Zhao 		dev_err(hba->dev,
4061e6560dfSYifeng Zhao 			"%s: Sending flag query for idn %d failed, err = %d\n",
4071e6560dfSYifeng Zhao 			__func__, idn, err);
4081e6560dfSYifeng Zhao 		goto out;
4091e6560dfSYifeng Zhao 	}
4101e6560dfSYifeng Zhao 
4111e6560dfSYifeng Zhao 	if (value)
4121e6560dfSYifeng Zhao 		*value = be32_to_cpu(response->upiu_res.value);
4131e6560dfSYifeng Zhao 
4141e6560dfSYifeng Zhao out:
4151e6560dfSYifeng Zhao 	return err;
4161e6560dfSYifeng Zhao }
4171e6560dfSYifeng Zhao 
4181e6560dfSYifeng Zhao static int ufshcd_query_attribute_retry(struct ufs_hba *hba, enum query_opcode opcode,
4191e6560dfSYifeng Zhao 					enum attr_id idn, u8 index, u8 selector, u32 *value)
4201e6560dfSYifeng Zhao {
4211e6560dfSYifeng Zhao 	int ret;
4221e6560dfSYifeng Zhao 	int retries;
4231e6560dfSYifeng Zhao 
4241e6560dfSYifeng Zhao 	for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
4251e6560dfSYifeng Zhao 		ret = ufshcd_query_attribute(hba, opcode, idn, index, selector, value);
4261e6560dfSYifeng Zhao 		if (ret)
4271e6560dfSYifeng Zhao 			dev_dbg(hba->dev,
4281e6560dfSYifeng Zhao 				"%s: failed with error %d, retries %d\n",
4291e6560dfSYifeng Zhao 				__func__, ret, retries);
4301e6560dfSYifeng Zhao 		else
4311e6560dfSYifeng Zhao 			break;
4321e6560dfSYifeng Zhao 	}
4331e6560dfSYifeng Zhao 
4341e6560dfSYifeng Zhao 	if (ret)
4351e6560dfSYifeng Zhao 		dev_err(hba->dev,
4361e6560dfSYifeng Zhao 			"%s: query attribute, opcode %d, idn %d, failed with error %d after %d retires\n",
4371e6560dfSYifeng Zhao 			__func__, opcode, idn, ret, retries);
4382c3d2faaSYifeng Zhao 	return ret;
4392c3d2faaSYifeng Zhao }
4402c3d2faaSYifeng Zhao 
4411e6560dfSYifeng Zhao static int read_attribute(struct ufs_hba *hba, enum attr_id idn, u8 index, u8 selector, u32 *value)
4422c3d2faaSYifeng Zhao {
4431e6560dfSYifeng Zhao 	int ret;
4442c3d2faaSYifeng Zhao 
4451e6560dfSYifeng Zhao 	ret = ufshcd_query_attribute_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
4461e6560dfSYifeng Zhao 					    idn, index, 0, value);
4471e6560dfSYifeng Zhao 	return ret;
4481e6560dfSYifeng Zhao }
4491e6560dfSYifeng Zhao 
4501e6560dfSYifeng Zhao static int write_attribute(struct ufs_hba *hba, enum attr_id idn, u8 index, u8 selector, u32 *value)
4511e6560dfSYifeng Zhao {
4521e6560dfSYifeng Zhao 	int ret;
4531e6560dfSYifeng Zhao 
4541e6560dfSYifeng Zhao 	ret = ufshcd_query_attribute_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
4551e6560dfSYifeng Zhao 					    idn, index, 0, value);
4562c3d2faaSYifeng Zhao 	return ret;
4572c3d2faaSYifeng Zhao }
4582c3d2faaSYifeng Zhao 
4592c3d2faaSYifeng Zhao static int set_boot_lu_enable(struct ufs_hba *hba)
4602c3d2faaSYifeng Zhao {
4612c3d2faaSYifeng Zhao 	uint32_t value = 0;
4622c3d2faaSYifeng Zhao 	uint32_t target_value = DEFAULT_BOOT_LUN;
4632c3d2faaSYifeng Zhao 	int ret;
4642c3d2faaSYifeng Zhao 
4652c3d2faaSYifeng Zhao 	ret = read_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
4662c3d2faaSYifeng Zhao 	if (ret) {
4672c3d2faaSYifeng Zhao 		printf("read bBootLunEn fail. ret = %d\n", ret);
4682c3d2faaSYifeng Zhao 		return ret;
4692c3d2faaSYifeng Zhao 	}
4702c3d2faaSYifeng Zhao 
4712c3d2faaSYifeng Zhao 	if (value != 0)
4721e6560dfSYifeng Zhao 		printf("UFS get boot W-LU-%c\n", (value == WELL_BOOT_LU_A) ? 'A' : 'B');
4732c3d2faaSYifeng Zhao 
4742c3d2faaSYifeng Zhao 	if (value == target_value)
4752c3d2faaSYifeng Zhao 		return 0;
4762c3d2faaSYifeng Zhao 
4772c3d2faaSYifeng Zhao 	/* set default boot from Boot LU A */
4782c3d2faaSYifeng Zhao 	value = target_value;
4792c3d2faaSYifeng Zhao 	ret = write_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
4802c3d2faaSYifeng Zhao 	if (ret) {
4812c3d2faaSYifeng Zhao 		printf("write bBootLunEn attribute fail. ret = %d\n", ret);
4822c3d2faaSYifeng Zhao 		return ret;
4832c3d2faaSYifeng Zhao 	}
4842c3d2faaSYifeng Zhao 
4851e6560dfSYifeng Zhao 	ret = read_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
4861e6560dfSYifeng Zhao 	if (ret) {
4871e6560dfSYifeng Zhao 		printf("read bBootLunEn fail. ret = %d\n", ret);
4882c3d2faaSYifeng Zhao 		return ret;
4892c3d2faaSYifeng Zhao 	}
4902c3d2faaSYifeng Zhao 
4911e6560dfSYifeng Zhao 	if (target_value == value)
4921e6560dfSYifeng Zhao 		return 0;
4931e6560dfSYifeng Zhao 
4941e6560dfSYifeng Zhao 	printf("UFS set boot W-LU(%c) Fail value = %x\n", (value == WELL_BOOT_LU_A) ? 'A' : 'B', value);
4951e6560dfSYifeng Zhao 	return 0;
4961e6560dfSYifeng Zhao }
4971e6560dfSYifeng Zhao 
4981e6560dfSYifeng Zhao static int ufs_set_ref_clk(struct ufs_hba *hba)
4991e6560dfSYifeng Zhao {
5001e6560dfSYifeng Zhao 	uint32_t value;
5011e6560dfSYifeng Zhao 	int ret;
5021e6560dfSYifeng Zhao 	uint32_t target_ref_clk;
5031e6560dfSYifeng Zhao 
5041e6560dfSYifeng Zhao 	target_ref_clk = 1; /* 26 MHz */
5051e6560dfSYifeng Zhao 
5061e6560dfSYifeng Zhao 	ret = read_attribute(hba, B_REFCLK_FREQ, 0, 0, &value);
5071e6560dfSYifeng Zhao 	if (ret) {
5081e6560dfSYifeng Zhao 		printf("read bRefClkFreq fail. ret = %d\n", ret);
5091e6560dfSYifeng Zhao 		return ret;
5101e6560dfSYifeng Zhao 	}
5111e6560dfSYifeng Zhao 
5121e6560dfSYifeng Zhao 	printf("UFS get ref clock %d Mhz\n", (value == 1) ? 26 : 19);
5131e6560dfSYifeng Zhao 	if (target_ref_clk == value)
5141e6560dfSYifeng Zhao 		return 0;
5151e6560dfSYifeng Zhao 
5161e6560dfSYifeng Zhao 	/* set default boot from Boot LU A */
5171e6560dfSYifeng Zhao 	ret = write_attribute(hba, B_REFCLK_FREQ, 0, 0, &target_ref_clk);
5181e6560dfSYifeng Zhao 	if (ret) {
5191e6560dfSYifeng Zhao 		printf("write bRefClkFreq attribute fail. ret = %d\n", ret);
5201e6560dfSYifeng Zhao 		return ret;
5211e6560dfSYifeng Zhao 	}
5221e6560dfSYifeng Zhao 
5231e6560dfSYifeng Zhao 	ret = read_attribute(hba, B_REFCLK_FREQ, 0, 0, &value);
5241e6560dfSYifeng Zhao 	if (ret) {
5251e6560dfSYifeng Zhao 		printf("read bRefClkFreq fail. ret = %d\n", ret);
5261e6560dfSYifeng Zhao 		return ret;
5271e6560dfSYifeng Zhao 	}
5281e6560dfSYifeng Zhao 
5291e6560dfSYifeng Zhao 	if (target_ref_clk == value)
5301e6560dfSYifeng Zhao 		return 0;
5311e6560dfSYifeng Zhao 
5321e6560dfSYifeng Zhao 	printf("UFS set bRefClkFreq  26Mhz Fail\n");
5331e6560dfSYifeng Zhao 	return -EINVAL;
5341e6560dfSYifeng Zhao }
5351e6560dfSYifeng Zhao 
5362c3d2faaSYifeng Zhao int ufs_create_partition_inventory(struct ufs_hba *hba)
5372c3d2faaSYifeng Zhao {
5382c3d2faaSYifeng Zhao 	int err, length;
5392c3d2faaSYifeng Zhao 
5402c3d2faaSYifeng Zhao 	length = (int)sizeof(struct ufs_geometry_descriptor);
5412c3d2faaSYifeng Zhao 	if (length > hba->desc_size.geom_desc)
5422c3d2faaSYifeng Zhao 		length = hba->desc_size.geom_desc;
5432c3d2faaSYifeng Zhao 	err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0, (u8 *)hba->geo_desc, length);
5442c3d2faaSYifeng Zhao 	if (err) {
5452c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed reading geometry Desc. err = %d\n", __func__, err);
5462c3d2faaSYifeng Zhao 		return err;
5472c3d2faaSYifeng Zhao 	}
5482c3d2faaSYifeng Zhao 
549*1865a7e4SYifeng Zhao 	dev_err(hba->dev, "%s: WB_max_alloc_units = %x\n", __func__,
550*1865a7e4SYifeng Zhao 		hba->geo_desc->d_write_booster_buffer_max_alloc_units);
551*1865a7e4SYifeng Zhao 
5522c3d2faaSYifeng Zhao 	err = ufs_get_configuration_desc(hba, hba->rc_desc);
5532c3d2faaSYifeng Zhao 	if (err) {
5542c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed getting conf info. err = %d\n", __func__, err);
5552c3d2faaSYifeng Zhao 		return err;
5562c3d2faaSYifeng Zhao 	}
5572c3d2faaSYifeng Zhao 	ufs_info_show_conf_desc(hba->rc_desc);
5582c3d2faaSYifeng Zhao 
5592c3d2faaSYifeng Zhao 	memset(hba->wc_desc, 0, sizeof(struct ufs_configuration_descriptor));
5602c3d2faaSYifeng Zhao 	hba->wc_desc->dev_desc_conf_param.b_length = hba->rc_desc->dev_desc_conf_param.b_length;
5612c3d2faaSYifeng Zhao 	hba->wc_desc->dev_desc_conf_param.b_descriptor_idn = hba->rc_desc->dev_desc_conf_param.b_descriptor_idn;
5622c3d2faaSYifeng Zhao 	ufs_lu_configuration(hba, hba->wc_desc);
5632c3d2faaSYifeng Zhao 	ufs_info_show_conf_desc(hba->wc_desc);
5642c3d2faaSYifeng Zhao 
5652c3d2faaSYifeng Zhao 	err = compair_conf_desp(hba->wc_desc, hba->rc_desc);
5662c3d2faaSYifeng Zhao 	printf("compair_conf_desp: 0x%x\n", err);
5672c3d2faaSYifeng Zhao 
5682c3d2faaSYifeng Zhao 	if (!err)
5691e6560dfSYifeng Zhao 		goto out;
5702c3d2faaSYifeng Zhao 
5712c3d2faaSYifeng Zhao 	err = ufs_write_configuration_desc(hba, hba->wc_desc);
5722c3d2faaSYifeng Zhao 	if (err)
5732c3d2faaSYifeng Zhao 		dev_err(hba->dev, "%s: Failed write conf info. err = %d\n", __func__, err);
5742c3d2faaSYifeng Zhao 
5752c3d2faaSYifeng Zhao 	err =  _ufs_start(hba);
5762c3d2faaSYifeng Zhao         if (err)
5772c3d2faaSYifeng Zhao                 return err;
5781e6560dfSYifeng Zhao out:
5792c3d2faaSYifeng Zhao 	ufs_info_show_dev_desc(hba->dev_desc);
5802c3d2faaSYifeng Zhao 
5811e6560dfSYifeng Zhao 	ufs_set_ref_clk(hba);
5821e6560dfSYifeng Zhao 
5832c3d2faaSYifeng Zhao         return set_boot_lu_enable(hba);
5842c3d2faaSYifeng Zhao }
5852c3d2faaSYifeng Zhao #endif
586