mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-24 22:05:40 +00:00
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:
parent
15e5958560
commit
5ac25de695
3 changed files with 54 additions and 1 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue