diff --git a/drivers/synopsys/ufs/dw_ufs.c b/drivers/synopsys/ufs/dw_ufs.c index d8ed5b6..b0ea3e7 100644 --- a/drivers/synopsys/ufs/dw_ufs.c +++ b/drivers/synopsys/ufs/dw_ufs.c @@ -97,10 +97,21 @@ 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); diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index d513d0a..254866f 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -705,11 +705,27 @@ } } +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 @@ 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; } diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h index 3a4f1c7..88dedc5 100644 --- a/include/drivers/ufs.h +++ b/include/drivers/ufs.h @@ -7,6 +7,8 @@ #ifndef __UFS_H__ #define __UFS_H__ +#include + /* 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;