Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/ufshci/ufshci_dev.c
- This file was added.
| /*- | |||||||||
| * SPDX-License-Identifier: BSD-2-Clause | |||||||||
| * | |||||||||
| * Copyright (c) 2025, Samsung Electronics Co., Ltd. | |||||||||
| * All rights reserved. | |||||||||
| * | |||||||||
| * Redistribution and use in source and binary forms, with or without | |||||||||
| * modification, are permitted provided that the following conditions | |||||||||
| * are met: | |||||||||
| * 1. Redistributions of source code must retain the above copyright | |||||||||
| * notice, this list of conditions and the following disclaimer. | |||||||||
| * 2. Redistributions in binary form must reproduce the above copyright | |||||||||
| * notice, this list of conditions and the following disclaimer in the | |||||||||
| * documentation and/or other materials provided with the distribution. | |||||||||
| * | |||||||||
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||||||||
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||||||||
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||||||||
| * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||||||||
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||||||||
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||||||||
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||||||||
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||||||||
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||||||||
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||||||||
| * SUCH DAMAGE. | |||||||||
| */ | |||||||||
| #include <sys/param.h> | |||||||||
| #include <sys/bus.h> | |||||||||
| #include <sys/conf.h> | |||||||||
| #include "ufshci_private.h" | |||||||||
| #include "ufshci_reg.h" | |||||||||
| static int | |||||||||
| ufshci_dev_read_descriptor(struct ufshci_controller *ctrlr, | |||||||||
| enum ufshci_descriptor_type desc_type, uint8_t index, uint8_t selector, | |||||||||
| void *desc, size_t desc_size) | |||||||||
| { | |||||||||
| struct ufshci_completion_poll_status status; | |||||||||
| struct ufshci_query_param param; | |||||||||
| param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST; | |||||||||
| param.opcode = UFSHCI_QUERY_OPCODE_READ_DESCRIPTOR; | |||||||||
| param.type = desc_type; | |||||||||
| param.index = index; | |||||||||
| param.selector = selector; | |||||||||
| param.value = 0; | |||||||||
| param.desc_size = desc_size; | |||||||||
| status.done = 0; | |||||||||
| ufshci_ctrl_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, | |||||||||
| &status, param); | |||||||||
| ufshci_completion_poll(&status); | |||||||||
| if (status.error) { | |||||||||
| ufshci_printf(ctrlr, "ufshci_dev_read_descriptor failed!\n"); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| memcpy(desc, status.cpl.response_upiu.query_response_upiu.command_data, | |||||||||
| desc_size); | |||||||||
| return (0); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_read_device_descriptor(struct ufshci_controller *ctrlr, | |||||||||
| struct ufshci_device_descriptor *desc) | |||||||||
| { | |||||||||
| return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_DEVICE, 0, 0, | |||||||||
| desc, sizeof(struct ufshci_device_descriptor))); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_read_geometry_descriptor(struct ufshci_controller *ctrlr, | |||||||||
| struct ufshci_geometry_descriptor *desc) | |||||||||
| { | |||||||||
| return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_GEOMETRY, 0, 0, | |||||||||
| desc, sizeof(struct ufshci_geometry_descriptor))); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_read_unit_descriptor(struct ufshci_controller *ctrlr, | |||||||||
| struct ufshci_unit_descriptor *desc, uint8_t index) | |||||||||
| { | |||||||||
| return (ufshci_dev_read_descriptor(ctrlr, UFSHCI_DESC_TYPE_UNIT, index, 0, | |||||||||
| desc, sizeof(struct ufshci_unit_descriptor))); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_read_flag(struct ufshci_controller *ctrlr, | |||||||||
| enum ufshci_flags flag_type, uint8_t *flag) | |||||||||
| { | |||||||||
| struct ufshci_completion_poll_status status; | |||||||||
| struct ufshci_query_param param; | |||||||||
| param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST; | |||||||||
| param.opcode = UFSHCI_QUERY_OPCODE_READ_FLAG; | |||||||||
| param.type = flag_type; | |||||||||
| param.index = 0; | |||||||||
| param.selector = 0; | |||||||||
| param.value = 0; | |||||||||
| status.done = 0; | |||||||||
| ufshci_ctrl_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, | |||||||||
| &status, param); | |||||||||
| ufshci_completion_poll(&status); | |||||||||
| if (status.error) { | |||||||||
| ufshci_printf(ctrlr, "ufshci_dev_read_flag failed!\n"); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| *flag = status.cpl.response_upiu.query_response_upiu.flag_value; | |||||||||
| return (0); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_set_flag(struct ufshci_controller *ctrlr, enum ufshci_flags flag_type) | |||||||||
| { | |||||||||
| struct ufshci_completion_poll_status status; | |||||||||
| struct ufshci_query_param param; | |||||||||
| param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST; | |||||||||
| param.opcode = UFSHCI_QUERY_OPCODE_SET_FLAG; | |||||||||
| param.type = flag_type; | |||||||||
| param.index = 0; | |||||||||
| param.selector = 0; | |||||||||
| param.value = 0; | |||||||||
| status.done = 0; | |||||||||
| ufshci_ctrl_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, | |||||||||
| &status, param); | |||||||||
| ufshci_completion_poll(&status); | |||||||||
| if (status.error) { | |||||||||
| ufshci_printf(ctrlr, "ufshci_dev_set_flag failed!\n"); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| return (0); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_read_attribute(struct ufshci_controller *ctrlr, | |||||||||
| enum ufshci_attributes attr_type, uint8_t index, uint8_t selector, | |||||||||
| uint64_t *attribute) | |||||||||
| { | |||||||||
| struct ufshci_completion_poll_status status; | |||||||||
| struct ufshci_query_param param; | |||||||||
| param.function = UFSHCI_QUERY_FUNC_STANDARD_READ_REQUEST; | |||||||||
| param.opcode = UFSHCI_QUERY_OPCODE_READ_ATTRIBUTE; | |||||||||
| param.type = attr_type; | |||||||||
| param.index = index; | |||||||||
| param.selector = selector; | |||||||||
| param.value = 0; | |||||||||
| status.done = 0; | |||||||||
| ufshci_ctrl_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, | |||||||||
| &status, param); | |||||||||
| ufshci_completion_poll(&status); | |||||||||
| if (status.error) { | |||||||||
| ufshci_printf(ctrlr, "ufshci_dev_read_attribute failed!\n"); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| *attribute = status.cpl.response_upiu.query_response_upiu.value_64; | |||||||||
| return (0); | |||||||||
| } | |||||||||
| static int | |||||||||
| ufshci_dev_write_attribute(struct ufshci_controller *ctrlr, | |||||||||
| enum ufshci_attributes attr_type, uint8_t index, uint8_t selector, | |||||||||
| uint64_t value) | |||||||||
| { | |||||||||
| struct ufshci_completion_poll_status status; | |||||||||
| struct ufshci_query_param param; | |||||||||
| param.function = UFSHCI_QUERY_FUNC_STANDARD_WRITE_REQUEST; | |||||||||
| param.opcode = UFSHCI_QUERY_OPCODE_WRITE_ATTRIBUTE; | |||||||||
| param.type = attr_type; | |||||||||
| param.index = index; | |||||||||
| param.selector = selector; | |||||||||
| param.value = value; | |||||||||
| status.done = 0; | |||||||||
| ufshci_ctrl_cmd_send_query_request(ctrlr, ufshci_completion_poll_cb, | |||||||||
| &status, param); | |||||||||
| ufshci_completion_poll(&status); | |||||||||
| if (status.error) { | |||||||||
| ufshci_printf(ctrlr, "ufshci_dev_write_attribute failed!\n"); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_init(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| int timeout = ticks + MSEC_2_TICKS(ctrlr->device_init_timeout_in_ms); | |||||||||
| sbintime_t delta_t = SBT_1US; | |||||||||
| uint8_t flag; | |||||||||
| int error; | |||||||||
| const uint8_t device_init_completed = 0; | |||||||||
| error = ufshci_dev_set_flag(ctrlr, UFSHCI_FLAG_F_DEVICE_INIT); | |||||||||
| if (error) | |||||||||
| return (error); | |||||||||
| /* Wait for the UFSHCI_FLAG_F_DEVICE_INIT flag to change */ | |||||||||
| while (1) { | |||||||||
| error = ufshci_dev_read_flag(ctrlr, UFSHCI_FLAG_F_DEVICE_INIT, | |||||||||
| &flag); | |||||||||
| if (error) | |||||||||
| return (error); | |||||||||
| if (flag == device_init_completed) | |||||||||
| break; | |||||||||
| if(timeout - ticks < 0) { | |||||||||
| ufshci_printf(ctrlr, "device init did not become %d " | |||||||||
jrtc27Unsubmitted Done Inline Actions
jrtc27: | |||||||||
| "within %d ms\n", device_init_completed, | |||||||||
| ctrlr->device_init_timeout_in_ms); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| pause_sbt("ufshciinit", delta_t, 0, C_PREL(1)); | |||||||||
| delta_t = min(SBT_1MS, delta_t * 3 / 2); | |||||||||
| } | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_reset(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| if (ufshci_uic_send_dme_endpoint_reset(ctrlr)) | |||||||||
| return (ENXIO); | |||||||||
| return (ufshci_dev_init(ctrlr)); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_init_reference_clock(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| int error; | |||||||||
| uint64_t ref_clk; | |||||||||
| uint8_t index, selector; | |||||||||
| index = 0; /* bRefClkFreq is device type attribute */ | |||||||||
| selector = 0; /* bRefClkFreq is device type attribute */ | |||||||||
| /* | |||||||||
| * We need to determine what reference clock the host interface uses and | |||||||||
| * set it. The reference clocks for each manufacturer are as follows. | |||||||||
| * - Intel UFSHCI reference clock = 19.2MHz | |||||||||
| */ | |||||||||
| ref_clk = UFSHCI_ATTR_REF_CLOCK_19_2MHz; | |||||||||
| error = ufshci_dev_write_attribute(ctrlr, UFSHCI_ATTR_B_REF_CLK_FREQ, | |||||||||
| index, selector, ref_clk); | |||||||||
| if (error) | |||||||||
| return (error); | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_init_unipro(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| uint32_t value; | |||||||||
| /* | |||||||||
| * Unipro Version: | |||||||||
| * 7~15 = Above 2.0, 6 = 2.0, 5 = 1.8, 4 = 1.61, 3 = 1.6, 2 = 1.41, | |||||||||
| * 1 = 1.40, 0 = Reserved | |||||||||
| */ | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_LocalVerInfo, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ctrlr->unipro_version = value; | |||||||||
| ufshci_printf(ctrlr, "Controller Unipro version = %d\n", value); | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_RemoteVerInfo, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ctrlr->ufs_dev.unipro_version = value; | |||||||||
| ufshci_printf(ctrlr, "Device Unipro version = %d\n", value); | |||||||||
| /* | |||||||||
| * PA_TActivate: | |||||||||
| * UniPro automatically sets timing information such as PA_TActivate | |||||||||
| * through the PACP_CAP_EXT1_ind command during Link Startup operation. | |||||||||
| */ | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_TActivate, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ufshci_printf(ctrlr, "Controller PA_TActivate = %d\n", value); | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_TActivate, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ufshci_printf(ctrlr, "Device PA_TActivate = %d\n", value); | |||||||||
| /* | |||||||||
| * TODO: Intel Lake-field UFSHCI quirk | |||||||||
| * Intel Lake-field UFSHCI has a quirk. We need to add 200us to the | |||||||||
| * PEER's PA_TActivate. | |||||||||
| */ | |||||||||
| /* | |||||||||
| * PA_Granularity: 100us (1=1us, 2=4us, 3=8us, 4=16us, 5=32us, 6=100us) | |||||||||
| */ | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_Granularity, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ufshci_printf(ctrlr, "Controller PA_Granularity = %d\n", value); | |||||||||
| if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, &value)) | |||||||||
| return (ENXIO); | |||||||||
| ufshci_printf(ctrlr, "Device PA_Granularity = %d\n", value); | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| /* Update lanes with available TX/RX lanes */ | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_AvailTxDataLanes, &ctrlr->max_tx_lanes)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_AvailRxDataLanes, &ctrlr->max_rx_lanes)) | |||||||||
| return (ENXIO); | |||||||||
| /* Get max HS-GEAR value */ | |||||||||
| if (ufshci_uic_send_dme_get(ctrlr, PA_MaxRxHSGear, &ctrlr->max_rx_hs_gear)) | |||||||||
| return (ENXIO); | |||||||||
| /* Set the data lane to max */ | |||||||||
| ctrlr->tx_lanes = ctrlr->max_tx_lanes; | |||||||||
| ctrlr->rx_lanes = ctrlr->max_rx_lanes; | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveTxDataLanes, ctrlr->tx_lanes)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveRxDataLanes, ctrlr->rx_lanes)) | |||||||||
| return (ENXIO); | |||||||||
| /* Set HS-GEAR to max gear */ | |||||||||
| ctrlr->hs_gear = ctrlr->max_rx_hs_gear; | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveTxDataLanes, ctrlr->hs_gear)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_ActiveRxDataLanes, ctrlr->hs_gear)) | |||||||||
| return (ENXIO); | |||||||||
| /* | |||||||||
| * Set termination | |||||||||
| * HS-MODE = ON / LS-MODE = OFF | |||||||||
| */ | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_TxTermination, true)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_RxTermination, false)) | |||||||||
| return (ENXIO); | |||||||||
| /* Set HSSerise (A = 1, B = 2) */ | |||||||||
| const uint32_t hs_series = 2; | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_HSSeries, hs_series)) | |||||||||
| return (ENXIO); | |||||||||
| /* Set Timeout values */ | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData0, DL_FC0ProtectionTimeOutVal_Default)) | |||||||||
Done Inline ActionsStart of the block jrtc27: Start of the block | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData1, DL_TC0ReplayTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData2, DL_AFC0ReqTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData3, DL_FC0ProtectionTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData4, DL_TC0ReplayTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRModeUserData5, DL_AFC0ReqTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, DME_LocalFC0ProtectionTimeOutVal, DL_FC0ProtectionTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, DME_LocalTC0ReplayTimeOutVal, DL_TC0ReplayTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, DME_LocalAFC0ReqTimeOutVal, DL_AFC0ReqTimeOutVal_Default)) | |||||||||
| return (ENXIO); | |||||||||
| /* | |||||||||
| * Set TX/RX PWRMode | |||||||||
| * TX[3:0], RX[7:4] | |||||||||
| * Fast_Mode=1, Slow_Mode=2, FastAuto_Mode=4, SlowAuto_Mode=5 | |||||||||
| */ | |||||||||
| const uint32_t fast_mode = 1; | |||||||||
| const uint32_t rx_bit_shift = 4; | |||||||||
| const uint32_t power_mode = fast_mode << rx_bit_shift | fast_mode; | |||||||||
| if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, power_mode)) | |||||||||
| return (ENXIO); | |||||||||
Done Inline ActionsStart of the block jrtc27: Start of the block | |||||||||
| /* Wait for power mode changed. */ | |||||||||
Done Inline ActionsParens please jrtc27: Parens please | |||||||||
| if (ufshci_uic_power_mode_ready(ctrlr)) | |||||||||
| return (ENXIO); | |||||||||
| /* Clear 'Power Mode completion status' */ | |||||||||
| ufshci_mmio_write_4(ctrlr, is, UFSHCIM(UFSHCI_IS_REG_UPMS)); | |||||||||
| /* | |||||||||
| * Intel Lake-field UFSHCI has a quirk. | |||||||||
| * We need to wait 1250us and clear dme error. | |||||||||
| */ | |||||||||
| pause_sbt("ufshci", 1250 * SBT_1US, 0, C_PREL(1)); | |||||||||
| /* Test with dme_peer_get to make sure there are no errors. */ | |||||||||
| if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, NULL)) | |||||||||
| return (ENXIO); | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_init_ufs_power_mode(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| /* TODO: Need to implement */ | |||||||||
| return (0); | |||||||||
| } | |||||||||
| int | |||||||||
| ufshci_dev_get_descriptor(struct ufshci_controller *ctrlr) | |||||||||
| { | |||||||||
| struct ufshci_device *device = &ctrlr->ufs_dev; | |||||||||
| uint32_t ver; | |||||||||
| int error; | |||||||||
| error = ufshci_dev_read_device_descriptor(ctrlr, &device->dev_desc); | |||||||||
| if (error) | |||||||||
| return (error); | |||||||||
| // For debug | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bLength=%d\n", device->dev_desc.bLength); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDescriptorIDN=%d\n", device->dev_desc.bDescriptorIDN); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDevice=%d\n", device->dev_desc.bDevice); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDeviceClass=%d\n", device->dev_desc.bDeviceClass); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDeviceSubClass=%d\n", device->dev_desc.bDeviceSubClass); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bProtocol=%d\n", device->dev_desc.bProtocol); | |||||||||
Done Inline ActionsPresumably this is not intended to be committed? jrtc27: Presumably this is not intended to be committed? | |||||||||
Done Inline ActionsYes, this printf is for debugging purposes and will be removed before commit. jaeyoon: Yes, this printf is for debugging purposes and will be removed before commit. | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bNumberLU=%d\n", device->dev_desc.bNumberLU); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bNumberWLU=%d\n", device->dev_desc.bNumberWLU); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bBootEnable=%d\n", device->dev_desc.bBootEnable); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDescrAccessEn=%d\n", device->dev_desc.bDescrAccessEn); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bInitPowerMode=%d\n", device->dev_desc.bInitPowerMode); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bHighPriorityLUN=%d\n", device->dev_desc.bHighPriorityLUN); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bSecureRemovalType=%d\n", device->dev_desc.bSecureRemovalType); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bSecurityLU=%d\n", device->dev_desc.bSecurityLU); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bBackgroundOpsTermLat=%d\n", device->dev_desc.bBackgroundOpsTermLat); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bInitActiveICCLevel=%d\n", device->dev_desc.bInitActiveICCLevel); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: wSpecVersion=%d\n", device->dev_desc.wSpecVersion); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: wManufactureDate=%d\n", device->dev_desc.wManufactureDate); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: iManufacturerName=%d\n", device->dev_desc.iManufacturerName); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: iProductName=%d\n", device->dev_desc.iProductName); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: iSerialNumber=%d\n", device->dev_desc.iSerialNumber); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: iOemID=%d\n", device->dev_desc.iOemID); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: wManufacturerID=%d\n", device->dev_desc.wManufacturerID); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bUD0BaseOffset=%d\n", device->dev_desc.bUD0BaseOffset); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bUDConfigPLength=%d\n", device->dev_desc.bUDConfigPLength); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bDeviceRTTCap=%d\n", device->dev_desc.bDeviceRTTCap); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: wPeriodicRTCUpdate=%d\n", device->dev_desc.wPeriodicRTCUpdate); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bUfsFeaturesSupport=%d\n", device->dev_desc.bUfsFeaturesSupport); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bFFUTimeout=%d\n", device->dev_desc.bFFUTimeout); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bQueueDepth=%d\n", device->dev_desc.bQueueDepth); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: wDeviceVersion=%d\n", device->dev_desc.wDeviceVersion); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bNumSecureWPArea=%d\n", device->dev_desc.bNumSecureWPArea); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: dPSAMaxDataSize=%d\n", device->dev_desc.dPSAMaxDataSize); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bPSAStateTimeout=%d\n", device->dev_desc.bPSAStateTimeout); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: iProductRevisionLevel=%d\n", device->dev_desc.iProductRevisionLevel); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: dExtendedUfsFeaturesSupport=%d\n", device->dev_desc.dExtendedUfsFeaturesSupport); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bWriteBoosterBufferPreserveUserSpaceEn=%d\n", device->dev_desc.bWriteBoosterBufferPreserveUserSpaceEn); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: bWriteBoosterBufferType=%d\n", device->dev_desc.bWriteBoosterBufferType); | |||||||||
| ufshci_printf(ctrlr, "DEVICE_DESC: dNumSharedWriteBoosterBufferAllocUnits=%d\n", device->dev_desc.dNumSharedWriteBoosterBufferAllocUnits); | |||||||||
| ver = device->dev_desc.wSpecVersion; | |||||||||
| ufshci_printf(ctrlr, "UFS device spec version %u.%u%u\n", UFSHCIV(UFSHCI_VER_REG_MJR, ver), | |||||||||
| UFSHCIV(UFSHCI_VER_REG_MNR, ver), UFSHCIV(UFSHCI_VER_REG_VS, ver)); | |||||||||
| ufshci_printf(ctrlr, "%u enabled LUNs found\n", device->dev_desc.bNumberLU); | |||||||||
| error = ufshci_dev_read_geometry_descriptor(ctrlr, &device->geo_desc); | |||||||||
| if (error) | |||||||||
| return (error); | |||||||||
| if (device->geo_desc.bMaxNumberLU == 0) { | |||||||||
| device->max_lun_count = 8; | |||||||||
| } else if (device->geo_desc.bMaxNumberLU == 1) { | |||||||||
| device->max_lun_count = 32; | |||||||||
| } else { | |||||||||
| ufshci_printf(ctrlr, "Invalid Geometry Descriptor bMaxNumberLU value=%d\n", | |||||||||
| device->geo_desc.bMaxNumberLU); | |||||||||
| return (ENXIO); | |||||||||
| } | |||||||||
| ctrlr->max_lun_count = device->max_lun_count; | |||||||||
| /* | |||||||||
| * The kDeviceDensityUnit is defined in the spec as 512. | |||||||||
| * qTotalRawDeviceCapacity use big-endian byte ordering. | |||||||||
| */ | |||||||||
| const uint32_t device_density_unit = 512; | |||||||||
| // For debug | |||||||||
| ufshci_printf(ctrlr, "UFS device total size is %lu bytes\n", | |||||||||
| be64toh(device->geo_desc.qTotalRawDeviceCapacity) * device_density_unit); | |||||||||
| return (0); | |||||||||
Done Inline ActionsAs with the other const variable below jrtc27: As with the other const variable below | |||||||||
| } | |||||||||
| No newline at end of file | |||||||||
Done Inline ActionsShould be fixed jrtc27: Should be fixed | |||||||||