/* Attribute idn for Query requests */
enum attr_idn {
+ QUERY_ATTR_IDN_BOOT_LU_EN = 0x00,
+ QUERY_ATTR_IDN_RESERVED = 0x01,
+ QUERY_ATTR_IDN_POWER_MODE = 0x02,
QUERY_ATTR_IDN_ACTIVE_ICC_LVL = 0x03,
+ QUERY_ATTR_IDN_OOO_DATA_EN = 0x04,
QUERY_ATTR_IDN_BKOPS_STATUS = 0x05,
+ QUERY_ATTR_IDN_PURGE_STATUS = 0x06,
+ QUERY_ATTR_IDN_MAX_DATA_IN = 0x07,
+ QUERY_ATTR_IDN_MAX_DATA_OUT = 0x08,
+ QUERY_ATTR_IDN_DYN_CAP_NEEDED = 0x09,
+ QUERY_ATTR_IDN_REF_CLK_FREQ = 0x0A,
+ QUERY_ATTR_IDN_CONF_DESC_LOCK = 0x0B,
+ QUERY_ATTR_IDN_MAX_NUM_OF_RTT = 0x0C,
QUERY_ATTR_IDN_EE_CONTROL = 0x0D,
QUERY_ATTR_IDN_EE_STATUS = 0x0E,
+ QUERY_ATTR_IDN_SECONDS_PASSED = 0x0F,
+ QUERY_ATTR_IDN_CNTX_CONF = 0x10,
+ QUERY_ATTR_IDN_CORR_PRG_BLK_NUM = 0x11,
};
/* Descriptor idn for Query requests */
QUERY_DESC_IDN_RFU_1 = 0x6,
QUERY_DESC_IDN_GEOMETRY = 0x7,
QUERY_DESC_IDN_POWER = 0x8,
+ QUERY_DESC_IDN_HEALTH = 0x9,
+ QUERY_DESC_IDN_RFU_2 = 0xA,
QUERY_DESC_IDN_MAX,
};
QUERY_RESULT_GENERAL_FAILURE = 0xFF,
};
+enum health_device_desc_param {
+ HEALTH_DEVICE_DESC_PARAM_LEN = 0x0,
+ HEALTH_DEVICE_DESC_PARAM_IDN =0x1,
+ HEALTH_DEVICE_DESC_PARAM_INFO =0x2,
+ HEALTH_DEVICE_DESC_PARAM_LIFETIMEA =0x3,
+ HEALTH_DEVICE_DESC_PARAM_LIFETIMEB =0x4,
+ HEALTH_DEVICE_DESC_PARAM_RESERVED =0x5,
+};
+
/* UTP Transfer Request Command Type (CT) */
enum {
UPIU_COMMAND_SET_TYPE_SCSI = 0x0,
--- /dev/null
+/*
+ * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "ufshcd.h"
+#include "ufs_quirks.h"
+
+#ifndef UFS_VENDOR_ID_SAMSUNG
+#define UFS_VENDOR_ID_SAMSUNG 0x1ce
+#endif
+
+#define SERIAL_NUM_SIZE 6
+#define TOSHIBA_SERIAL_NUM_SIZE 10
+
+
+/*UN policy
+* 16 digits : mandate + serial number(6byte, hex raw data)
+* 18 digits : manid + mandate + serial number(sec, hynix : 6byte hex,
+* toshiba : 10byte + 00, ascii)
+*/
+void ufs_set_sec_unique_number(struct ufs_hba *hba, u8 *str_desc_buf, u8 *desc_buf)
+{
+ u8 manid;
+ u8 snum_buf[UFS_UN_MAX_DIGITS];
+
+ manid = hba->manufacturer_id & 0xFF;
+ memset(hba->unique_number, 0, sizeof(hba->unique_number));
+ memset(snum_buf, 0, sizeof(snum_buf));
+
+#if defined(CONFIG_UFS_UN_18DIGITS)
+
+ memcpy(snum_buf, str_desc_buf + QUERY_DESC_HDR_SIZE, SERIAL_NUM_SIZE);
+
+ sprintf(hba->unique_number, "%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ manid,
+ desc_buf[DEVICE_DESC_PARAM_MANF_DATE], desc_buf[DEVICE_DESC_PARAM_MANF_DATE+1],
+ snum_buf[0], snum_buf[1], snum_buf[2], snum_buf[3], snum_buf[4], snum_buf[5]);
+
+ /* Null terminate the unique number string */
+ hba->unique_number[UFS_UN_18_DIGITS] = '\0';
+
+#else
+ /*default is 16 DIGITS UN*/
+ memcpy(snum_buf, str_desc_buf + QUERY_DESC_HDR_SIZE, SERIAL_NUM_SIZE);
+
+ sprintf(hba->unique_number, "%02x%02x%02x%02x%02x%02x%02x%02x",
+ desc_buf[DEVICE_DESC_PARAM_MANF_DATE], desc_buf[DEVICE_DESC_PARAM_MANF_DATE+1],
+ snum_buf[0], snum_buf[1], snum_buf[2], snum_buf[3], snum_buf[4], snum_buf[5]);
+
+ /* Null terminate the unique number string */
+ hba->unique_number[UFS_UN_16_DIGITS] = '\0';
+#endif
+}
+
+
#include "ufshcd.h"
#include "ufs_quirks.h"
#include "unipro.h"
+#include "ufs-exynos.h"
+#include "ufs_quirks.h"
#define CREATE_TRACE_POINTS
#include <trace/events/ufs.h>
goto out;
}
+ /*
+ * While reading variable size descriptors (like string descriptor),
+ * some UFS devices may report the "LENGTH" (field in "Transaction
+ * Specific fields" of Query Response UPIU) same as what was requested
+ * in Query Request UPIU instead of reporting the actual size of the
+ * variable size descriptor.
+ * Although it's safe to ignore the "LENGTH" field for variable size
+ * descriptors as we can always derive the length of the descriptor from
+ * the descriptor header fields. Hence this change impose the length
+ * match check only for fixed size descriptors (for which we always
+ * request the correct size as part of Query Request UPIU).
+ */
+ if ((desc_id != QUERY_DESC_IDN_STRING) &&
+ (buff_len != desc_buf[QUERY_DESC_LENGTH_OFFSET])) {
+ dev_err(hba->dev, "%s: desc_buf length mismatch: buff_len %d, buff_len(desc_header) %d",
+ __func__, buff_len, desc_buf[QUERY_DESC_LENGTH_OFFSET]);
+ ret = -EINVAL;
+ goto out;
+ }
/* Check wherher we will not copy more data, than available */
if (is_kmalloc && param_size > buff_len)
param_size = buff_len;
param_offset, param_read_buf, param_size);
}
+int ufshcd_read_health_desc(struct ufs_hba *hba, u8 *buf, u32 size)
+{
+ int err = 0;
+
+ err = ufshcd_read_desc(hba,
+ QUERY_DESC_IDN_HEALTH, 0, buf, size);
+
+ if (err)
+ dev_err(hba->dev, "%s: reading Device Health Desc failed. err = %d\n",
+ __func__, err);
+
+ return err;
+}
+
/**
* ufshcd_memory_alloc - allocate memory for host memory space data structures
* @hba: per adapter instance
hba->vops->dbg_register_dump(hba);
}
+int ufshcd_read_health_desc(struct ufs_hba *hba, u8 *buf, u32 size);
#endif /* End of Header */