luckfox-pico-sdk/sysdrv/source/uboot/u-boot/drivers/ufs/ufs-rockchip-usbplug.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

586 lines
19 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Rockchip UFS Host Controller driver
*
* Copyright (C) 2024 Rockchip Electronics Co.Ltd.
*/
#include <charset.h>
#include <common.h>
#include <dm.h>
#include <log.h>
#include <dm/lists.h>
#include <dm/device-internal.h>
#include <malloc.h>
#include <hexdump.h>
#include <scsi.h>
#include <asm/io.h>
#include <asm/dma-mapping.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include "ufs-rockchip-usbplug.h"
#include "ufs.h"
/* Query request retries */
#define QUERY_REQ_RETRIES 3
/* Query request timeout */
#define QUERY_REQ_TIMEOUT 1500 /* 1.5 seconds */
#if defined(CONFIG_SUPPORT_USBPLUG)
int _ufs_start(struct ufs_hba *hba);
static void ufs_info_show_dev_desc(void *buf)
{
struct ufs_device_descriptor *dev = (struct ufs_device_descriptor *)buf;
printf("---------------------------\n");
printf("---UFS Device Descriptor---\n");
printf("---------------------------\n");
printf("bLength: 0x%x\n", dev->b_length);
printf("bDescriptorIDN: 0x%x\n", dev->b_descriptor_idn);
printf("bDevice: 0x%x\n", dev->b_device);
printf("bDeviceClass: 0x%x\n", dev->b_device_class);
printf("bDeviceSubClass: 0x%x\n", dev->b_device_sub_class);
printf("bProtocol: 0x%x\n", dev->b_protocol);
printf("bNumberLU: 0x%x\n", dev->b_number_lu);
printf("bNumberWLU: 0x%x\n", dev->b_number_wlu);
printf("bBootEnable: 0x%x\n", dev->b_boot_enable);
printf("bDescrAccessEn: 0x%x\n", dev->b_descr_access_en);
printf("bInitPowerMode: 0x%x\n", dev->b_init_power_mode);
printf("bHighPriorityLUN: 0x%x\n", dev->b_high_priority_lun);
printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
printf("bSecurityLU: 0x%x\n", dev->b_security_lu);
printf("bBackgroundOpsTermLat: 0x%x\n", dev->b_background_ops_term_lat);
printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
printf("wSpecVersion: 0x%x\n", to_bigendian16(dev->w_spec_version));
printf("wManufactureDate: 0x%x\n", to_bigendian16(dev->w_manufacture_date));
printf("iManufacturerName: 0x%x\n", dev->i_manufacturer_name);
printf("iProductName: 0x%x\n", dev->i_product_name);
printf("iSerialNumber: 0x%x\n", dev->i_serial_number);
printf("iOemID: 0x%x\n", dev->i_oem_id);
printf("wManufacturerID: 0x%x\n", to_bigendian16(dev->w_manufacturer_id));
printf("bUD0BaseOffset: 0x%x\n", dev->b_ud_0base_offset);
printf("bUDConfigPLength: 0x%x\n", dev->b_ud_config_plength);
printf("bDeviceRTTCap: 0x%x\n", dev->b_device_rtt_cap);
printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
printf("bUFSFeatureSupport: 0x%x\n", dev->b_ufs_feature_support);
printf("bFFUTimeout: 0x%x\n", dev->b_ffu_timeout);
printf("bQueueDepth: 0x%x\n", dev->b_queue_depth);
printf("wDeviceVersion: 0x%x\n", to_bigendian16(dev->w_device_version));
printf("bNumSecureWPArea: 0x%x\n", dev->b_num_secure_wp_area);
printf("dPSAMaxDataSize: 0x%x\n", to_bigendian32(dev->d_psa_max_data_size));
printf("bPSAStateTimeout: 0x%x\n", dev->b_psa_state_timeout);
printf("iProductRevisionLevel: 0x%x\n", dev->i_product_revision_level);
}
static void ufs_info_show_conf_desc(void *buf)
{
struct ufs_configuration_descriptor *c_desc = (struct ufs_configuration_descriptor *)buf;
struct ufs_dev_desc_configuration_param *dev;
struct ufs_unit_desc_configuration_param *unit;
int i;
dev = &c_desc->dev_desc_conf_param;
printf("----------------------------------------\n");
printf("---UFS Device Descriptor Config Param---\n");
printf("----------------------------------------\n");
printf("bLength: 0x%x\n", dev->b_length);
printf("bDescriptorIDN: 0x%x\n", dev->b_descriptor_idn);
printf("bConfDescContinue: 0x%x\n", dev->b_conf_desc_continue);
printf("bBootEnable: 0x%x\n", dev->b_boot_enable);
printf("bDescrAccessEn: 0x%x\n", dev->b_descr_access_en);
printf("bInitPowerMode: 0x%x\n", dev->b_init_power_mode);
printf("bHighPriorityLUN: 0x%x\n", dev->b_high_priority_lun);
printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
printf("bSecureRemovalType: 0x%x\n", dev->b_secure_removal_type);
printf("bInitActiveICCLevel: 0x%x\n", dev->b_init_active_icc_level);
printf("wPeriodicRTCUpdate: 0x%x\n", to_bigendian16(dev->w_periodic_rtc_update));
printf("bWB_EN: 0x%x\n", dev->b_write_booster_buffer_reserve_user_space_en);
printf("WB_TYPE: 0x%x\n", dev->b_write_booster_buffer_type);
printf("WB_alloc_units: 0x%x\n", to_bigendian32(dev->d_num_shared_write_booster_buffer_alloc_units));
for (i = 0; i < UNIT_DESCS_COUNT; i++) {
unit = &c_desc->unit_desc_conf_param[i];
printf("-----------------------------------------\n");
printf("---UFS Unit %d Descriptor Config Param---\n", i);
printf("-----------------------------------------\n");
printf("bLUEnable: 0x%x\n", unit->b_lu_enable);
printf("bBootLunID: 0x%x\n", unit->b_boot_lun_id);
printf("bLUWriteProtect: 0x%x\n", unit->b_lu_write_protect);
printf("bMemoryType: 0x%x\n", unit->b_memory_type);
printf("dNumAllocUnits: 0x%x\n", to_bigendian32(unit->d_num_alloc_units));
printf("bDataReliability: 0x%x\n", unit->b_data_reliability);
printf("bLogicalBlockSize: 0x%x\n", unit->b_logical_block_size);
printf("bProvisioningType: 0x%x\n", unit->b_provisioning_type);
printf("wContextCapabilities: 0x%x\n", to_bigendian16(unit->w_context_capabilities));
}
}
static int ufs_get_configuration_desc(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
{
u8 desc_buf[CONFIGURATION_DESC_V22_LENGTH];
u8 *buf = desc_buf;
int length = CONFIGURATION_DESC_V22_LENGTH;
int err;
if (CONFIGURATION_DESC_V31_LENGTH == hba->desc_size.conf_desc) {
buf = (u8 *)c_desc;
length = CONFIGURATION_DESC_V31_LENGTH;
} else if(CONFIGURATION_DESC_V22_LENGTH != hba->desc_size.conf_desc) {
return -EINVAL;
}
err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_CONFIGURATION, 0, 0, buf, length);
if (err) {
dev_err(hba->dev, "%s: Failed reading configuration Desc. err = %d\n",
__func__, err);
return err;
}
if (CONFIGURATION_DESC_V22_LENGTH == hba->desc_size.conf_desc) {
memcpy(&c_desc->dev_desc_conf_param, buf, 0x10);
buf += 0x10;
for (int i = 0; i < UNIT_DESCS_COUNT; i++) {
memcpy(&c_desc->unit_desc_conf_param[i], buf, 0x10);
buf += 0x10;
}
}
return err;
}
static int ufshcd_write_desc_param(struct ufs_hba *hba, enum desc_idn desc_id,
int desc_index, u8 param_offset, u8 *param_read_buf,
u8 param_size)
{
int ret;
u8 *desc_buf;
int buff_len;
/* Safety check */
if (desc_id >= QUERY_DESC_IDN_MAX || !param_size)
return -EINVAL;
/* Get the max length of descriptor from structure filled up at probe
* time.
*/
ret = ufshcd_map_desc_id_to_length(hba, desc_id, &buff_len);
/* Sanity checks */
if (ret || !buff_len) {
dev_err(hba->dev, "%s: Failed to get full descriptor length\n",
__func__);
return ret;
}
desc_buf = param_read_buf;
/* Request for full descriptor */
ret = ufshcd_query_descriptor_retry(hba, UPIU_QUERY_OPCODE_WRITE_DESC,
desc_id, desc_index, 0, desc_buf,
&buff_len);
if (ret)
dev_err(hba->dev, "%s: Failed write descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n",
__func__, desc_id, desc_index, param_offset, ret);
return ret;
}
static int ufs_write_configuration_desc(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
{
u8 desc_buf[CONFIGURATION_DESC_V22_LENGTH];
u8 *buf = desc_buf;
int length = CONFIGURATION_DESC_V22_LENGTH;
int err;
if (CONFIGURATION_DESC_V31_LENGTH == hba->desc_size.conf_desc) {
buf = (u8 *)c_desc;
length = CONFIGURATION_DESC_V31_LENGTH;
} else if(CONFIGURATION_DESC_V22_LENGTH == hba->desc_size.conf_desc) {
memcpy(buf, &c_desc->dev_desc_conf_param, 0x10);
buf += 0x10;
for (int i = 0; i < UNIT_DESCS_COUNT; i++) {
memcpy(buf, &c_desc->unit_desc_conf_param[i], 0x10);
buf += 0x10;
}
buf = desc_buf;
} else {
return -EINVAL;
}
err = ufshcd_write_desc_param(hba, QUERY_DESC_IDN_CONFIGURATION, 0, 0, buf, length);
if (err) {
dev_err(hba->dev, "%s: Failed reading configuration Desc. err = %d\n",
__func__, err);
return err;
}
return err;
}
static void ufs_lu_configuration(struct ufs_hba *hba, struct ufs_configuration_descriptor *c_desc)
{
uint32_t denominator = hba->geo_desc->b_allocation_unit_size * to_bigendian32(hba->geo_desc->d_segment_size);
struct ufs_dev_desc_configuration_param *dev;
struct ufs_unit_desc_configuration_param *unit;
uint32_t alloced_units = 0;
int i, cap_adj_fac;
uint64_t total_raw_device_capacity;
uint32_t max_wb_alloc_units = cpu_to_be32(hba->geo_desc->d_write_booster_buffer_max_alloc_units);
uint32_t wb_alloc_units;
cap_adj_fac = to_bigendian16(hba->geo_desc->w_enhanced1_cap_adj_fac) / 256;
total_raw_device_capacity = cpu_to_be64(hba->geo_desc->q_total_raw_device_capacity);
dev = &c_desc->dev_desc_conf_param;
dev->b_boot_enable = 0x1;
dev->b_descr_access_en = 0x0;
dev->b_init_power_mode = 0x1;
dev->b_high_priority_lun = 0x7F;
dev->b_secure_removal_type = 0x0;
dev->b_init_active_icc_level = 0x0;
dev->w_periodic_rtc_update = 0x0;
unit = &c_desc->unit_desc_conf_param[0];
/* lu 1: boot lu A 4MB */
unit[1].b_boot_lun_id = WELL_BOOT_LU_A; /* lu 0, boot a */
unit[1].b_memory_type = 0x3;
unit[1].d_num_alloc_units = (4 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
alloced_units += unit[1].d_num_alloc_units;
/* lu 2: boot lu B 4MB */
unit[2].b_boot_lun_id = WELL_BOOT_LU_B; /* lu 1, boot b */
unit[2].b_memory_type = 0x3; /* lu 0, Enhanced Memory */
unit[2].d_num_alloc_units = (4 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
alloced_units += unit[2].d_num_alloc_units;
/* lu 3: data lu 8MB */
unit[3].b_boot_lun_id = 0x0; /* lu 2 */
unit[3].b_memory_type = 0x3; /* lu 2, Enhanced Memory */
unit[3].d_num_alloc_units = (8 * 0x800 * cap_adj_fac + denominator - 1) / denominator;
alloced_units += unit[3].d_num_alloc_units;
if (max_wb_alloc_units) {
wb_alloc_units = max_wb_alloc_units;
if (wb_alloc_units > max_wb_alloc_units)
wb_alloc_units = max_wb_alloc_units;
dev->b_write_booster_buffer_reserve_user_space_en = 1;
dev->b_write_booster_buffer_type = 1;
dev->d_num_shared_write_booster_buffer_alloc_units = to_bigendian32(wb_alloc_units);
}
/* lu 0: data lu, max capacity*/
unit[0].b_boot_lun_id = 0x0; /* lu 3 */
unit[0].b_memory_type = 0x0; /* lu 3, Normal Memory */
unit[0].d_num_alloc_units = lower_32_bits(total_raw_device_capacity) / denominator - alloced_units;
for (i = 0; i <= 3; i++) { /* lu 0 - 3 */
unit[i].b_lu_enable = 0x1;
unit[i].b_lu_write_protect = 0x0;
unit[i].b_data_reliability = 0x1;
unit[i].b_logical_block_size = 0x0c;
unit[i].b_provisioning_type = 0x2;
unit[i].w_context_capabilities = 0x0;
unit[i].d_num_alloc_units = to_bigendian32(unit[i].d_num_alloc_units);
}
}
static int compair_conf_desp(struct ufs_configuration_descriptor *cda, struct ufs_configuration_descriptor *cdb)
{
struct ufs_dev_desc_configuration_param *dev_a, *dev_b;
struct ufs_unit_desc_configuration_param *unit_a, *unit_b;
int i, ret;
dev_a = &cda->dev_desc_conf_param;
dev_b = &cdb->dev_desc_conf_param;
if (dev_a->b_boot_enable != dev_b->b_boot_enable)
return 0x3;
if (dev_a->b_descr_access_en != dev_b->b_descr_access_en)
return 0x4;
if (dev_a->b_init_power_mode != dev_b->b_init_power_mode)
return 0x5;
if (dev_a->b_high_priority_lun != dev_b->b_high_priority_lun)
return 0x6;
if (dev_a->b_secure_removal_type != dev_b->b_secure_removal_type)
return 0x7;
if (dev_a->b_init_active_icc_level != dev_b->b_init_active_icc_level)
return 0x8;
if (dev_a->w_periodic_rtc_update != dev_b->w_periodic_rtc_update)
return 0x9;
if (dev_a->b_write_booster_buffer_reserve_user_space_en !=
dev_b->b_write_booster_buffer_reserve_user_space_en)
return 0xA;
if (dev_a->b_write_booster_buffer_type != dev_b->b_write_booster_buffer_type)
return 0xB;
if (dev_a->d_num_shared_write_booster_buffer_alloc_units !=
dev_b->d_num_shared_write_booster_buffer_alloc_units)
return 0xC;
for (i = 0; i < UNIT_DESCS_COUNT; i++) {
unit_a = &cda->unit_desc_conf_param[i];
unit_b = &cdb->unit_desc_conf_param[i];
ret = 0x10 * (i + 1);
if (unit_a->b_lu_enable != unit_b->b_lu_enable)
return ret;
if (unit_a->b_boot_lun_id != unit_b->b_boot_lun_id)
return ret + 0x1;
if (unit_a->b_lu_write_protect != unit_b->b_lu_write_protect)
return ret + 0x2;
if (unit_a->b_memory_type != unit_b->b_memory_type)
return ret + 0x3;
if (unit_a->d_num_alloc_units != unit_b->d_num_alloc_units)
return ret + 0x4;
if (unit_a->b_data_reliability != unit_b->b_data_reliability)
return ret + 0x8;
if (unit_a->b_logical_block_size != unit_b->b_logical_block_size)
return ret + 0x9;
if (unit_a->b_provisioning_type != unit_b->b_provisioning_type)
return ret + 0xA;
if (unit_a->w_context_capabilities != unit_b->w_context_capabilities)
return ret + 0xB;
}
return 0;
}
/**
* ufshcd_init_query() - init the query response and request parameters
*/
static inline void ufshcd_init_query(struct ufs_hba *hba,
struct ufs_query_req **request,
struct ufs_query_res **response,
enum query_opcode opcode,
u8 idn, u8 index, u8 selector)
{
*request = &hba->dev_cmd.query.request;
*response = &hba->dev_cmd.query.response;
memset(*request, 0, sizeof(struct ufs_query_req));
memset(*response, 0, sizeof(struct ufs_query_res));
(*request)->upiu_req.opcode = opcode;
(*request)->upiu_req.idn = idn;
(*request)->upiu_req.index = index;
(*request)->upiu_req.selector = selector;
}
/**
* ufshcd_query_flag() - API function for sending flag query requests
*/
static int ufshcd_query_attribute(struct ufs_hba *hba,enum query_opcode opcode,
enum attr_id idn, u8 index, u8 selector, u32 *value)
{
struct ufs_query_req *request = &hba->dev_cmd.query.request;
struct ufs_query_res *response = &hba->dev_cmd.query.response;
int err;
int timeout = QUERY_REQ_TIMEOUT;
memset(request, 0, sizeof(struct ufs_query_req));
memset(response, 0, sizeof(struct ufs_query_res));
request->upiu_req.opcode = opcode;
request->upiu_req.idn = idn;
request->upiu_req.index = 0;
request->upiu_req.selector = 0;
switch (opcode) {
case UPIU_QUERY_OPCODE_WRITE_ATTR:
request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
request->upiu_req.value = be32_to_cpu(*value);
break;
case UPIU_QUERY_OPCODE_READ_ATTR:
request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
break;
default:
dev_err(hba->dev,
"%s: Expected query flag opcode but got = %d\n",
__func__, opcode);
err = -EINVAL;
goto out;
}
err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, timeout);
if (err) {
dev_err(hba->dev,
"%s: Sending flag query for idn %d failed, err = %d\n",
__func__, idn, err);
goto out;
}
if (value)
*value = be32_to_cpu(response->upiu_res.value);
out:
return err;
}
static int ufshcd_query_attribute_retry(struct ufs_hba *hba, enum query_opcode opcode,
enum attr_id idn, u8 index, u8 selector, u32 *value)
{
int ret;
int retries;
for (retries = 0; retries < QUERY_REQ_RETRIES; retries++) {
ret = ufshcd_query_attribute(hba, opcode, idn, index, selector, value);
if (ret)
dev_dbg(hba->dev,
"%s: failed with error %d, retries %d\n",
__func__, ret, retries);
else
break;
}
if (ret)
dev_err(hba->dev,
"%s: query attribute, opcode %d, idn %d, failed with error %d after %d retires\n",
__func__, opcode, idn, ret, retries);
return ret;
}
static int read_attribute(struct ufs_hba *hba, enum attr_id idn, u8 index, u8 selector, u32 *value)
{
int ret;
ret = ufshcd_query_attribute_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR,
idn, index, 0, value);
return ret;
}
static int write_attribute(struct ufs_hba *hba, enum attr_id idn, u8 index, u8 selector, u32 *value)
{
int ret;
ret = ufshcd_query_attribute_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR,
idn, index, 0, value);
return ret;
}
static int set_boot_lu_enable(struct ufs_hba *hba)
{
uint32_t value = 0;
uint32_t target_value = DEFAULT_BOOT_LUN;
int ret;
ret = read_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
if (ret) {
printf("read bBootLunEn fail. ret = %d\n", ret);
return ret;
}
if (value != 0)
printf("UFS get boot W-LU-%c\n", (value == WELL_BOOT_LU_A) ? 'A' : 'B');
if (value == target_value)
return 0;
/* set default boot from Boot LU A */
value = target_value;
ret = write_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
if (ret) {
printf("write bBootLunEn attribute fail. ret = %d\n", ret);
return ret;
}
ret = read_attribute(hba, B_BOOT_LUNEN, 0, 0, &value);
if (ret) {
printf("read bBootLunEn fail. ret = %d\n", ret);
return ret;
}
if (target_value == value)
return 0;
printf("UFS set boot W-LU(%c) Fail value = %x\n", (value == WELL_BOOT_LU_A) ? 'A' : 'B', value);
return 0;
}
static int ufs_set_ref_clk(struct ufs_hba *hba)
{
uint32_t value;
int ret;
uint32_t target_ref_clk;
target_ref_clk = 1; /* 26 MHz */
ret = read_attribute(hba, B_REFCLK_FREQ, 0, 0, &value);
if (ret) {
printf("read bRefClkFreq fail. ret = %d\n", ret);
return ret;
}
printf("UFS get ref clock %d Mhz\n", (value == 1) ? 26 : 19);
if (target_ref_clk == value)
return 0;
/* set default boot from Boot LU A */
ret = write_attribute(hba, B_REFCLK_FREQ, 0, 0, &target_ref_clk);
if (ret) {
printf("write bRefClkFreq attribute fail. ret = %d\n", ret);
return ret;
}
ret = read_attribute(hba, B_REFCLK_FREQ, 0, 0, &value);
if (ret) {
printf("read bRefClkFreq fail. ret = %d\n", ret);
return ret;
}
if (target_ref_clk == value)
return 0;
printf("UFS set bRefClkFreq 26Mhz Fail\n");
return -EINVAL;
}
int ufs_create_partition_inventory(struct ufs_hba *hba)
{
int err, length;
length = (int)sizeof(struct ufs_geometry_descriptor);
if (length > hba->desc_size.geom_desc)
length = hba->desc_size.geom_desc;
err = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0, (u8 *)hba->geo_desc, length);
if (err) {
dev_err(hba->dev, "%s: Failed reading geometry Desc. err = %d\n", __func__, err);
return err;
}
dev_err(hba->dev, "%s: WB_max_alloc_units = %x\n", __func__,
hba->geo_desc->d_write_booster_buffer_max_alloc_units);
err = ufs_get_configuration_desc(hba, hba->rc_desc);
if (err) {
dev_err(hba->dev, "%s: Failed getting conf info. err = %d\n", __func__, err);
return err;
}
ufs_info_show_conf_desc(hba->rc_desc);
memset(hba->wc_desc, 0, sizeof(struct ufs_configuration_descriptor));
hba->wc_desc->dev_desc_conf_param.b_length = hba->rc_desc->dev_desc_conf_param.b_length;
hba->wc_desc->dev_desc_conf_param.b_descriptor_idn = hba->rc_desc->dev_desc_conf_param.b_descriptor_idn;
ufs_lu_configuration(hba, hba->wc_desc);
ufs_info_show_conf_desc(hba->wc_desc);
err = compair_conf_desp(hba->wc_desc, hba->rc_desc);
printf("compair_conf_desp: 0x%x\n", err);
if (!err)
goto out;
err = ufs_write_configuration_desc(hba, hba->wc_desc);
if (err)
dev_err(hba->dev, "%s: Failed write conf info. err = %d\n", __func__, err);
err = _ufs_start(hba);
if (err)
return err;
out:
ufs_info_show_dev_desc(hba->dev_desc);
ufs_set_ref_clk(hba);
return set_boot_lu_enable(hba);
}
#endif