drivers:ufs: fix hynix ufs bug with quirk on hi36xx SoC

Hynix ufs has deviations on hi36xx platform which will result
in ufs bursts transfer failures at a very low probability.

To fix the problem, the Hynix device must set the register
VS_DebugSaveConfigTime to 0x10, which will set time reference
for SaveConfigTime is 250 ns. The time reference for SaveConfigTime
is 40 ns by default.

Signed-off-by: fengbaopeng <fengbaopeng@hisilicon.com>
This commit is contained in:
fengbaopeng 2018-02-12 20:53:54 +08:00 committed by wei li
parent 15e5958560
commit 5ac25de695
3 changed files with 54 additions and 1 deletions

View File

@ -97,10 +97,21 @@ static int dwufs_phy_set_pwr_mode(ufs_params_t *params)
int result;
unsigned int data, tx_lanes, rx_lanes;
uintptr_t base;
unsigned int flags;
assert((params != NULL) && (params->reg_base != 0));
base = params->reg_base;
flags = params->flags;
if ((flags & UFS_FLAGS_VENDOR_SKHYNIX) != 0U) {
NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n");
/* VS_DebugSaveConfigTime */
result = ufshc_dme_set(0xd0a0, 0x0, 0x10);
assert(result == 0);
/* sync length */
result = ufshc_dme_set(0x1556, 0x0, 0x48);
assert(result == 0);
}
result = ufshc_dme_get(PA_TACTIVATE_OFFSET, 0, &data);
assert(result == 0);

View File

@ -705,11 +705,27 @@ static void ufs_enum(void)
}
}
static void ufs_get_device_info(struct ufs_dev_desc *card_data)
{
uint8_t desc_buf[DESC_DEVICE_MAX_SIZE];
ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0,
(uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE);
/*
* getting vendor (manufacturerID) and Bank Index in big endian
* format
*/
card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) |
(desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1]));
}
int ufs_init(const ufs_ops_t *ops, ufs_params_t *params)
{
int result;
unsigned int data;
uic_cmd_t cmd;
struct ufs_dev_desc card = {0};
assert((params != NULL) &&
(params->reg_base != 0) &&
@ -750,10 +766,17 @@ int ufs_init(const ufs_ops_t *ops, ufs_params_t *params)
ops->phy_init(&ufs_params);
result = ufshc_link_startup(ufs_params.reg_base);
assert(result == 0);
ufs_enum();
ufs_get_device_info(&card);
if (card.wmanufacturerid == UFS_VENDOR_SKHYNIX) {
ufs_params.flags |= UFS_FLAGS_VENDOR_SKHYNIX;
}
ops->phy_set_pwr_mode(&ufs_params);
}
ufs_enum();
(void)result;
return 0;
}

View File

@ -7,6 +7,8 @@
#ifndef __UFS_H__
#define __UFS_H__
#include <utils_def.h>
/* register map of UFSHCI */
/* Controller Capabilities */
#define CAP 0x00
@ -214,6 +216,9 @@
#define DESC_TYPE_INTERCONNECT 0x04
#define DESC_TYPE_STRING 0x05
#define DESC_DEVICE_MAX_SIZE 0x1F
#define DEVICE_DESC_PARAM_MANF_ID 0x18
#define ATTR_CUR_PWR_MODE 0x02 /* bCurrentPowerMode */
#define ATTR_ACTIVECC 0x03 /* bActiveICCLevel */
@ -246,8 +251,22 @@
#define FLAG_DEVICE_INIT 0x01
#define UFS_VENDOR_SKHYNIX U(0x1AD)
#define MAX_MODEL_LEN 16
/**
* ufs_dev_desc - ufs device details from the device descriptor
* @wmanufacturerid: card details
* @model: card model
*/
struct ufs_dev_desc {
uint16_t wmanufacturerid;
int8_t model[MAX_MODEL_LEN + 1];
};
/* UFS Driver Flags */
#define UFS_FLAGS_SKIPINIT (1 << 0)
#define UFS_FLAGS_VENDOR_SKHYNIX (U(1) << 2)
typedef struct sense_data {
uint8_t resp_code : 7;