diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/ufs/ufs-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-debugfs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-debugfs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-debugfs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-ice.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom-ice.h | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.c | 10 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.h | 71 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.h~HEAD | 258 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs.h | 493 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs_quirks.c | 4 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufs_test.c | 4 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd-pci.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd-pltfrm.c | 1 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 1143 | ||||
-rw-r--r-- | drivers/scsi/ufs/unipro.h | 235 |
17 files changed, 2192 insertions, 43 deletions
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c index 1567797d8796..d719f7b5fcae 100644 --- a/drivers/scsi/ufs/ufs-debugfs.c +++ b/drivers/scsi/ufs/ufs-debugfs.c @@ -19,7 +19,7 @@ #include <linux/random.h> #include "ufs-debugfs.h" -#include <linux/scsi/ufs/unipro.h> +#include "unipro.h" #include "ufshci.h" enum field_width { diff --git a/drivers/scsi/ufs/ufs-debugfs.h b/drivers/scsi/ufs/ufs-debugfs.h index cf82be23fb47..f576571ee4db 100644 --- a/drivers/scsi/ufs/ufs-debugfs.h +++ b/drivers/scsi/ufs/ufs-debugfs.h @@ -21,7 +21,7 @@ #define _UFS_DEBUGFS_H #include <linux/debugfs.h> -#include <linux/scsi/ufs/ufshcd.h> +#include "ufshcd.h" #ifdef CONFIG_DEBUG_FS void ufsdbg_add_debugfs(struct ufs_hba *hba); diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.c b/drivers/scsi/ufs/ufs-qcom-debugfs.c index f2ae82532da6..0368f9805b8c 100644 --- a/drivers/scsi/ufs/ufs-qcom-debugfs.c +++ b/drivers/scsi/ufs/ufs-qcom-debugfs.c @@ -13,7 +13,7 @@ */ #include <linux/debugfs.h> -#include <linux/scsi/ufs/ufs-qcom.h> +#include "ufs-qcom.h" #include "ufs-qcom-debugfs.h" #include "ufs-debugfs.h" diff --git a/drivers/scsi/ufs/ufs-qcom-debugfs.h b/drivers/scsi/ufs/ufs-qcom-debugfs.h index 03341711e11e..b693bfa84a71 100644 --- a/drivers/scsi/ufs/ufs-qcom-debugfs.h +++ b/drivers/scsi/ufs/ufs-qcom-debugfs.h @@ -15,7 +15,7 @@ #ifndef QCOM_DEBUGFS_H_ #define QCOM_DEBUGFS_H_ -#include <linux/scsi/ufs/ufshcd.h> +#include "ufshcd.h" #ifdef CONFIG_DEBUG_FS void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root); diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c index 2fe52b9e98b7..84a6cff5f97a 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.c +++ b/drivers/scsi/ufs/ufs-qcom-ice.c @@ -15,11 +15,11 @@ #include <linux/of.h> #include <linux/async.h> #include <linux/blkdev.h> -#include <linux/scsi/ufs/ufshcd.h> #include <crypto/ice.h> #include "ufs-qcom-ice.h" #include "ufs-qcom-debugfs.h" +#include "ufshcd.h" #define UFS_QCOM_CRYPTO_LABEL "ufs-qcom-crypto" /* Timeout waiting for ICE initialization, that requires TZ access */ diff --git a/drivers/scsi/ufs/ufs-qcom-ice.h b/drivers/scsi/ufs/ufs-qcom-ice.h index ae78a5120426..adadbe0b218b 100644 --- a/drivers/scsi/ufs/ufs-qcom-ice.h +++ b/drivers/scsi/ufs/ufs-qcom-ice.h @@ -17,7 +17,7 @@ #include <scsi/scsi_cmnd.h> -#include <linux/scsi/ufs/ufs-qcom.h> +#include "ufs-qcom.h" /* * UFS host controller ICE registers. There are n [0..31] diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 7e6a22930e5e..970e0cfa4e21 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c @@ -12,23 +12,15 @@ * */ -#include <linux/io.h> -#include <linux/kernel.h> -#include <linux/module.h> #include <linux/time.h> -#include <linux/clk.h> #include <linux/of.h> #include <linux/iopoll.h> #include <linux/platform_device.h> - #include <linux/msm-bus.h> #include <soc/qcom/scm.h> #include <linux/phy/phy.h> - -#include <linux/scsi/ufs/ufshcd.h> -#include <linux/scsi/ufs/unipro.h> -#include <linux/scsi/ufs/ufs-qcom.h> #include <linux/phy/phy-qcom-ufs.h> + #include "ufshcd.h" #include "ufshcd-pltfrm.h" #include "unipro.h" diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 36249b35f858..e734574c150a 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h @@ -14,6 +14,9 @@ #ifndef UFS_QCOM_H_ #define UFS_QCOM_H_ +#include <linux/phy/phy.h> +#include "ufshcd.h" + #define MAX_UFS_QCOM_HOSTS 1 #define MAX_U32 (~(u32)0) #define MPHY_TX_FSM_STATE 0x41 @@ -64,15 +67,6 @@ enum { UFS_TEST_BUS_CTRL_2 = 0xF4, UFS_UNIPRO_CFG = 0xF8, - /* - * QCOM UFS host controller vendor specific registers - * added in HW Version 3.0.0 - */ - UFS_AH8_CFG = 0xFC, -}; - -/* QCOM UFS host controller vendor specific debug registers */ -enum { UFS_DBG_RD_REG_UAWM = 0x100, UFS_DBG_RD_REG_UARM = 0x200, UFS_DBG_RD_REG_TXUC = 0x300, @@ -88,9 +82,6 @@ enum { UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, }; -#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x) -#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x) - /* bit definitions for REG_UFS_CFG1 register */ #define QUNIPRO_SEL UFS_BIT(0) #define TEST_BUS_EN BIT(18) @@ -192,6 +183,33 @@ struct ufs_qcom_bus_vote { struct device_attribute max_bus_bw; }; +/** + * struct ufs_qcom_ice_data - ICE related information + * @vops: pointer to variant operations of ICE + * @async_done: completion for supporting ICE's driver asynchronous nature + * @pdev: pointer to the proper ICE platform device + * @state: UFS-ICE interface's internal state (see + * ufs-qcom-ice.h for possible internal states) + * @quirks: UFS-ICE interface related quirks + * @crypto_engine_err: crypto engine errors + */ +struct ufs_qcom_ice_data { + struct qcom_ice_variant_ops *vops; + struct completion async_done; + struct platform_device *pdev; + int state; + + /* + * If UFS host controller should handle cryptographic engine's + * errors, enables this quirk. + */ + #define UFS_QCOM_ICE_QUIRK_HANDLE_CRYPTO_ENGINE_ERRORS UFS_BIT(0) + + u16 quirks; + + bool crypto_engine_err; +}; + /* Host controller hardware version: major.minor.step */ struct ufs_hw_version { u16 step; @@ -199,6 +217,18 @@ struct ufs_hw_version { u8 major; }; +#ifdef CONFIG_DEBUG_FS +struct qcom_debugfs_files { + struct dentry *debugfs_root; + struct dentry *dbg_print_en; + struct dentry *testbus; + struct dentry *testbus_en; + struct dentry *testbus_cfg; + struct dentry *testbus_bus; + struct dentry *dbg_regs; +}; +#endif + struct ufs_qcom_testbus { u8 select_major; u8 select_minor; @@ -212,12 +242,6 @@ struct ufs_qcom_host { * controller supports the QUniPro mode. */ #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) - - /* - * Set this capability if host controller can retain the secure - * configuration even after UFS controller core power collapse. - */ - #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1) u32 caps; struct phy *generic_phy; @@ -229,13 +253,15 @@ struct ufs_qcom_host { struct clk *rx_l1_sync_clk; struct clk *tx_l1_sync_clk; bool is_lane_clks_enabled; - + bool sec_cfg_updated; + struct ufs_qcom_ice_data ice; void __iomem *dev_ref_clk_ctrl_mmio; bool is_dev_ref_clk_enabled; struct ufs_hw_version hw_ver; - u32 dev_ref_clk_en_mask; - +#ifdef CONFIG_DEBUG_FS + struct qcom_debugfs_files debugfs_files; +#endif /* Bitmask for enabling debug prints */ u32 dbg_print_en; struct ufs_qcom_testbus testbus; @@ -246,6 +272,9 @@ struct ufs_qcom_host { #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) int ufs_qcom_testbus_config(struct ufs_qcom_host *host); +void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba, void *priv, + void (*print_fn)(struct ufs_hba *hba, int offset, int num_regs, + char *str, void *priv)); static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) { diff --git a/drivers/scsi/ufs/ufs-qcom.h~HEAD b/drivers/scsi/ufs/ufs-qcom.h~HEAD new file mode 100644 index 000000000000..36249b35f858 --- /dev/null +++ b/drivers/scsi/ufs/ufs-qcom.h~HEAD @@ -0,0 +1,258 @@ +/* Copyright (c) 2013-2015, 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. + * + */ + +#ifndef UFS_QCOM_H_ +#define UFS_QCOM_H_ + +#define MAX_UFS_QCOM_HOSTS 1 +#define MAX_U32 (~(u32)0) +#define MPHY_TX_FSM_STATE 0x41 +#define TX_FSM_HIBERN8 0x1 +#define HBRN8_POLL_TOUT_MS 100 +#define DEFAULT_CLK_RATE_HZ 1000000 +#define BUS_VECTOR_NAME_LEN 32 + +#define UFS_HW_VER_MAJOR_SHFT (28) +#define UFS_HW_VER_MAJOR_MASK (0x000F << UFS_HW_VER_MAJOR_SHFT) +#define UFS_HW_VER_MINOR_SHFT (16) +#define UFS_HW_VER_MINOR_MASK (0x0FFF << UFS_HW_VER_MINOR_SHFT) +#define UFS_HW_VER_STEP_SHFT (0) +#define UFS_HW_VER_STEP_MASK (0xFFFF << UFS_HW_VER_STEP_SHFT) + +/* vendor specific pre-defined parameters */ +#define SLOW 1 +#define FAST 2 + +#define UFS_QCOM_LIMIT_NUM_LANES_RX 2 +#define UFS_QCOM_LIMIT_NUM_LANES_TX 2 +#define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G3 +#define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G3 +#define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 +#define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 +#define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE +#define UFS_QCOM_LIMIT_TX_PWR_PWM SLOW_MODE +#define UFS_QCOM_LIMIT_RX_PWR_HS FAST_MODE +#define UFS_QCOM_LIMIT_TX_PWR_HS FAST_MODE +#define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B +#define UFS_QCOM_LIMIT_DESIRED_MODE FAST + +/* QCOM UFS host controller vendor specific registers */ +enum { + REG_UFS_SYS1CLK_1US = 0xC0, + REG_UFS_TX_SYMBOL_CLK_NS_US = 0xC4, + REG_UFS_LOCAL_PORT_ID_REG = 0xC8, + REG_UFS_PA_ERR_CODE = 0xCC, + REG_UFS_RETRY_TIMER_REG = 0xD0, + REG_UFS_PA_LINK_STARTUP_TIMER = 0xD8, + REG_UFS_CFG1 = 0xDC, + REG_UFS_CFG2 = 0xE0, + REG_UFS_HW_VERSION = 0xE4, + + UFS_TEST_BUS = 0xE8, + UFS_TEST_BUS_CTRL_0 = 0xEC, + UFS_TEST_BUS_CTRL_1 = 0xF0, + UFS_TEST_BUS_CTRL_2 = 0xF4, + UFS_UNIPRO_CFG = 0xF8, + + /* + * QCOM UFS host controller vendor specific registers + * added in HW Version 3.0.0 + */ + UFS_AH8_CFG = 0xFC, +}; + +/* QCOM UFS host controller vendor specific debug registers */ +enum { + UFS_DBG_RD_REG_UAWM = 0x100, + UFS_DBG_RD_REG_UARM = 0x200, + UFS_DBG_RD_REG_TXUC = 0x300, + UFS_DBG_RD_REG_RXUC = 0x400, + UFS_DBG_RD_REG_DFC = 0x500, + UFS_DBG_RD_REG_TRLUT = 0x600, + UFS_DBG_RD_REG_TMRLUT = 0x700, + UFS_UFS_DBG_RD_REG_OCSC = 0x800, + + UFS_UFS_DBG_RD_DESC_RAM = 0x1500, + UFS_UFS_DBG_RD_PRDT_RAM = 0x1700, + UFS_UFS_DBG_RD_RESP_RAM = 0x1800, + UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, +}; + +#define UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(x) (0x000 + x) +#define UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(x) (0x400 + x) + +/* bit definitions for REG_UFS_CFG1 register */ +#define QUNIPRO_SEL UFS_BIT(0) +#define TEST_BUS_EN BIT(18) +#define TEST_BUS_SEL GENMASK(22, 19) + +/* bit definitions for REG_UFS_CFG2 register */ +#define UAWM_HW_CGC_EN (1 << 0) +#define UARM_HW_CGC_EN (1 << 1) +#define TXUC_HW_CGC_EN (1 << 2) +#define RXUC_HW_CGC_EN (1 << 3) +#define DFC_HW_CGC_EN (1 << 4) +#define TRLUT_HW_CGC_EN (1 << 5) +#define TMRLUT_HW_CGC_EN (1 << 6) +#define OCSC_HW_CGC_EN (1 << 7) + +/* bit definition for UFS_UFS_TEST_BUS_CTRL_n */ +#define TEST_BUS_SUB_SEL_MASK 0x1F /* All XXX_SEL fields are 5 bits wide */ + +#define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ + TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ + DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\ + TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN) + +/* bit offset */ +enum { + OFFSET_UFS_PHY_SOFT_RESET = 1, + OFFSET_CLK_NS_REG = 10, +}; + +/* bit masks */ +enum { + MASK_UFS_PHY_SOFT_RESET = 0x2, + MASK_TX_SYMBOL_CLK_1US_REG = 0x3FF, + MASK_CLK_NS_REG = 0xFFFC00, +}; + +enum ufs_qcom_phy_init_type { + UFS_PHY_INIT_FULL, + UFS_PHY_INIT_CFG_RESTORE, +}; + +/* QCOM UFS debug print bit mask */ +#define UFS_QCOM_DBG_PRINT_REGS_EN BIT(0) +#define UFS_QCOM_DBG_PRINT_ICE_REGS_EN BIT(1) +#define UFS_QCOM_DBG_PRINT_TEST_BUS_EN BIT(2) + +#define UFS_QCOM_DBG_PRINT_ALL \ + (UFS_QCOM_DBG_PRINT_REGS_EN | UFS_QCOM_DBG_PRINT_ICE_REGS_EN | \ + UFS_QCOM_DBG_PRINT_TEST_BUS_EN) + +/* QUniPro Vendor specific attributes */ +#define DME_VS_CORE_CLK_CTRL 0xD002 +/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */ +#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8) +#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF + +static inline void +ufs_qcom_get_controller_revision(struct ufs_hba *hba, + u8 *major, u16 *minor, u16 *step) +{ + u32 ver = ufshcd_readl(hba, REG_UFS_HW_VERSION); + + *major = (ver & UFS_HW_VER_MAJOR_MASK) >> UFS_HW_VER_MAJOR_SHFT; + *minor = (ver & UFS_HW_VER_MINOR_MASK) >> UFS_HW_VER_MINOR_SHFT; + *step = (ver & UFS_HW_VER_STEP_MASK) >> UFS_HW_VER_STEP_SHFT; +}; + +static inline void ufs_qcom_assert_reset(struct ufs_hba *hba) +{ + ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, + 1 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); + + /* + * Make sure assertion of ufs phy reset is written to + * register before returning + */ + mb(); +} + +static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) +{ + ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, + 0 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); + + /* + * Make sure de-assertion of ufs phy reset is written to + * register before returning + */ + mb(); +} + +struct ufs_qcom_bus_vote { + uint32_t client_handle; + uint32_t curr_vote; + int min_bw_vote; + int max_bw_vote; + int saved_vote; + bool is_max_bw_needed; + struct device_attribute max_bus_bw; +}; + +/* Host controller hardware version: major.minor.step */ +struct ufs_hw_version { + u16 step; + u16 minor; + u8 major; +}; + +struct ufs_qcom_testbus { + u8 select_major; + u8 select_minor; +}; + +struct ufs_qcom_host { + /* + * Set this capability if host controller supports the QUniPro mode + * and if driver wants the Host controller to operate in QUniPro mode. + * Note: By default this capability will be kept enabled if host + * controller supports the QUniPro mode. + */ + #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) + + /* + * Set this capability if host controller can retain the secure + * configuration even after UFS controller core power collapse. + */ + #define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1) + u32 caps; + + struct phy *generic_phy; + struct ufs_hba *hba; + struct ufs_qcom_bus_vote bus_vote; + struct ufs_pa_layer_attr dev_req_params; + struct clk *rx_l0_sync_clk; + struct clk *tx_l0_sync_clk; + struct clk *rx_l1_sync_clk; + struct clk *tx_l1_sync_clk; + bool is_lane_clks_enabled; + + void __iomem *dev_ref_clk_ctrl_mmio; + bool is_dev_ref_clk_enabled; + struct ufs_hw_version hw_ver; + + u32 dev_ref_clk_en_mask; + + /* Bitmask for enabling debug prints */ + u32 dbg_print_en; + struct ufs_qcom_testbus testbus; +}; + +#define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) +#define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) +#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) + +int ufs_qcom_testbus_config(struct ufs_qcom_host *host); + +static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) +{ + if (host->caps & UFS_QCOM_CAP_QUNIPRO) + return true; + else + return false; +} + +#endif /* UFS_QCOM_H_ */ diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h new file mode 100644 index 000000000000..e4b2c95350ef --- /dev/null +++ b/drivers/scsi/ufs/ufs.h @@ -0,0 +1,493 @@ +/* + * Universal Flash Storage Host controller driver + * + * This code is based on drivers/scsi/ufs/ufs.h + * Copyright (C) 2011-2013 Samsung India Software Operations + * + * Authors: + * Santosh Yaraganavi <santosh.sy@samsung.com> + * Vinayak Holikatti <h.vinayak@samsung.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * <http://www.gnu.org/licenses/gpl-2.0.html> + * + * 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. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + */ + +#ifndef _UFS_H +#define _UFS_H + +#include <linux/mutex.h> +#include <linux/types.h> +#include <scsi/ufs/ufs.h> + +#define MAX_CDB_SIZE 16 +#define GENERAL_UPIU_REQUEST_SIZE 32 +#define QUERY_DESC_MAX_SIZE 255 +#define QUERY_DESC_MIN_SIZE 2 +#define QUERY_DESC_HDR_SIZE 2 +#define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ + (sizeof(struct utp_upiu_header))) +#define RESPONSE_UPIU_SENSE_DATA_LENGTH 18 + +#define UPIU_HEADER_DWORD(byte3, byte2, byte1, byte0)\ + cpu_to_be32((byte3 << 24) | (byte2 << 16) |\ + (byte1 << 8) | (byte0)) +/* + * UFS device may have standard LUs and LUN id could be from 0x00 to + * 0x7F. Standard LUs use "Peripheral Device Addressing Format". + * UFS device may also have the Well Known LUs (also referred as W-LU) + * which again could be from 0x00 to 0x7F. For W-LUs, device only use + * the "Extended Addressing Format" which means the W-LUNs would be + * from 0xc100 (SCSI_W_LUN_BASE) onwards. + * This means max. LUN number reported from UFS device could be 0xC17F. + */ +#define UFS_UPIU_MAX_UNIT_NUM_ID 0x7F +#define UFS_MAX_LUNS (SCSI_W_LUN_BASE + UFS_UPIU_MAX_UNIT_NUM_ID) +#define UFS_UPIU_WLUN_ID (1 << 7) +#define UFS_UPIU_MAX_GENERAL_LUN 8 + +/* Well known logical unit id in LUN field of UPIU */ +enum { + UFS_UPIU_REPORT_LUNS_WLUN = 0x81, + UFS_UPIU_UFS_DEVICE_WLUN = 0xD0, + UFS_UPIU_BOOT_WLUN = 0xB0, + UFS_UPIU_RPMB_WLUN = 0xC4, +}; + +/** + * ufs_is_valid_unit_desc_lun - checks if the given LUN has a unit descriptor + * @lun: LU number to check + * @return: true if the lun has a matching unit descriptor, false otherwise + */ +static inline bool ufs_is_valid_unit_desc_lun(u8 lun) +{ + return lun == UFS_UPIU_RPMB_WLUN || (lun < UFS_UPIU_MAX_GENERAL_LUN); +} + +/* + * UFS Protocol Information Unit related definitions + */ + +/* Task management functions */ +enum { + UFS_ABORT_TASK = 0x01, + UFS_ABORT_TASK_SET = 0x02, + UFS_CLEAR_TASK_SET = 0x04, + UFS_LOGICAL_RESET = 0x08, + UFS_QUERY_TASK = 0x80, + UFS_QUERY_TASK_SET = 0x81, +}; + +/* UTP UPIU Transaction Codes Initiator to Target */ +enum { + UPIU_TRANSACTION_NOP_OUT = 0x00, + UPIU_TRANSACTION_COMMAND = 0x01, + UPIU_TRANSACTION_DATA_OUT = 0x02, + UPIU_TRANSACTION_TASK_REQ = 0x04, + UPIU_TRANSACTION_QUERY_REQ = 0x16, +}; + +/* UTP UPIU Transaction Codes Target to Initiator */ +enum { + UPIU_TRANSACTION_NOP_IN = 0x20, + UPIU_TRANSACTION_RESPONSE = 0x21, + UPIU_TRANSACTION_DATA_IN = 0x22, + UPIU_TRANSACTION_TASK_RSP = 0x24, + UPIU_TRANSACTION_READY_XFER = 0x31, + UPIU_TRANSACTION_QUERY_RSP = 0x36, + UPIU_TRANSACTION_REJECT_UPIU = 0x3F, +}; + +/* UPIU Read/Write flags */ +enum { + UPIU_CMD_FLAGS_NONE = 0x00, + UPIU_CMD_FLAGS_WRITE = 0x20, + UPIU_CMD_FLAGS_READ = 0x40, +}; + +/* UPIU Task Attributes */ +enum { + UPIU_TASK_ATTR_SIMPLE = 0x00, + UPIU_TASK_ATTR_ORDERED = 0x01, + UPIU_TASK_ATTR_HEADQ = 0x02, + UPIU_TASK_ATTR_ACA = 0x03, +}; + +/* UPIU Query request function */ +enum { + UPIU_QUERY_FUNC_STANDARD_READ_REQUEST = 0x01, + UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST = 0x81, +}; + +enum desc_header_offset { + QUERY_DESC_LENGTH_OFFSET = 0x00, + QUERY_DESC_DESC_TYPE_OFFSET = 0x01, +}; + +enum ufs_desc_max_size { + QUERY_DESC_DEVICE_MAX_SIZE = 0x40, + QUERY_DESC_CONFIGURAION_MAX_SIZE = 0x90, + QUERY_DESC_UNIT_MAX_SIZE = 0x23, + QUERY_DESC_INTERCONNECT_MAX_SIZE = 0x06, + /* + * Max. 126 UNICODE characters (2 bytes per character) plus 2 bytes + * of descriptor header. + */ + QUERY_DESC_STRING_MAX_SIZE = 0xFE, + QUERY_DESC_GEOMETRY_MAZ_SIZE = 0x44, + QUERY_DESC_POWER_MAX_SIZE = 0x62, + QUERY_DESC_RFU_MAX_SIZE = 0x00, +}; + +/* Unit descriptor parameters offsets in bytes*/ +enum unit_desc_param { + UNIT_DESC_PARAM_LEN = 0x0, + UNIT_DESC_PARAM_TYPE = 0x1, + UNIT_DESC_PARAM_UNIT_INDEX = 0x2, + UNIT_DESC_PARAM_LU_ENABLE = 0x3, + UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4, + UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5, + UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6, + UNIT_DESC_PARAM_MEM_TYPE = 0x8, + UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9, + UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, + UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB, + UNIT_DESC_PARAM_ERASE_BLK_SIZE = 0x13, + UNIT_DESC_PARAM_PROVISIONING_TYPE = 0x17, + UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18, + UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20, + UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22, +}; + +/* Device descriptor parameters offsets in bytes*/ +enum device_desc_param { + DEVICE_DESC_PARAM_LEN = 0x0, + DEVICE_DESC_PARAM_TYPE = 0x1, + DEVICE_DESC_PARAM_DEVICE_TYPE = 0x2, + DEVICE_DESC_PARAM_DEVICE_CLASS = 0x3, + DEVICE_DESC_PARAM_DEVICE_SUB_CLASS = 0x4, + DEVICE_DESC_PARAM_PRTCL = 0x5, + DEVICE_DESC_PARAM_NUM_LU = 0x6, + DEVICE_DESC_PARAM_NUM_WLU = 0x7, + DEVICE_DESC_PARAM_BOOT_ENBL = 0x8, + DEVICE_DESC_PARAM_DESC_ACCSS_ENBL = 0x9, + DEVICE_DESC_PARAM_INIT_PWR_MODE = 0xA, + DEVICE_DESC_PARAM_HIGH_PR_LUN = 0xB, + DEVICE_DESC_PARAM_SEC_RMV_TYPE = 0xC, + DEVICE_DESC_PARAM_SEC_LU = 0xD, + DEVICE_DESC_PARAM_BKOP_TERM_LT = 0xE, + DEVICE_DESC_PARAM_ACTVE_ICC_LVL = 0xF, + DEVICE_DESC_PARAM_SPEC_VER = 0x10, + DEVICE_DESC_PARAM_MANF_DATE = 0x12, + DEVICE_DESC_PARAM_MANF_NAME = 0x14, + DEVICE_DESC_PARAM_PRDCT_NAME = 0x15, + DEVICE_DESC_PARAM_SN = 0x16, + DEVICE_DESC_PARAM_OEM_ID = 0x17, + DEVICE_DESC_PARAM_MANF_ID = 0x18, + DEVICE_DESC_PARAM_UD_OFFSET = 0x1A, + DEVICE_DESC_PARAM_UD_LEN = 0x1B, + DEVICE_DESC_PARAM_RTT_CAP = 0x1C, + DEVICE_DESC_PARAM_FRQ_RTC = 0x1D, +}; +/* + * Logical Unit Write Protect + * 00h: LU not write protected + * 01h: LU write protected when fPowerOnWPEn =1 + * 02h: LU permanently write protected when fPermanentWPEn =1 + */ +enum ufs_lu_wp_type { + UFS_LU_NO_WP = 0x00, + UFS_LU_POWER_ON_WP = 0x01, + UFS_LU_PERM_WP = 0x02, +}; + +/* bActiveICCLevel parameter current units */ +enum { + UFSHCD_NANO_AMP = 0, + UFSHCD_MICRO_AMP = 1, + UFSHCD_MILI_AMP = 2, + UFSHCD_AMP = 3, +}; + +#define POWER_DESC_MAX_SIZE 0x62 +#define POWER_DESC_MAX_ACTV_ICC_LVLS 16 + +/* Attribute bActiveICCLevel parameter bit masks definitions */ +#define ATTR_ICC_LVL_UNIT_OFFSET 14 +#define ATTR_ICC_LVL_UNIT_MASK (0x3 << ATTR_ICC_LVL_UNIT_OFFSET) +#define ATTR_ICC_LVL_VALUE_MASK 0x3FF + +/* Power descriptor parameters offsets in bytes */ +enum power_desc_param_offset { + PWR_DESC_LEN = 0x0, + PWR_DESC_TYPE = 0x1, + PWR_DESC_ACTIVE_LVLS_VCC_0 = 0x2, + PWR_DESC_ACTIVE_LVLS_VCCQ_0 = 0x22, + PWR_DESC_ACTIVE_LVLS_VCCQ2_0 = 0x42, +}; + +/* Exception event mask values */ +enum { + MASK_EE_STATUS = 0xFFFF, + MASK_EE_URGENT_BKOPS = (1 << 2), +}; + +/* Background operation status */ +enum bkops_status { + BKOPS_STATUS_NO_OP = 0x0, + BKOPS_STATUS_NON_CRITICAL = 0x1, + BKOPS_STATUS_PERF_IMPACT = 0x2, + BKOPS_STATUS_CRITICAL = 0x3, + BKOPS_STATUS_MAX = BKOPS_STATUS_CRITICAL, +}; + +/* Query response result code */ +enum { + QUERY_RESULT_SUCCESS = 0x00, + QUERY_RESULT_NOT_READABLE = 0xF6, + QUERY_RESULT_NOT_WRITEABLE = 0xF7, + QUERY_RESULT_ALREADY_WRITTEN = 0xF8, + QUERY_RESULT_INVALID_LENGTH = 0xF9, + QUERY_RESULT_INVALID_VALUE = 0xFA, + QUERY_RESULT_INVALID_SELECTOR = 0xFB, + QUERY_RESULT_INVALID_INDEX = 0xFC, + QUERY_RESULT_INVALID_IDN = 0xFD, + QUERY_RESULT_INVALID_OPCODE = 0xFE, + QUERY_RESULT_GENERAL_FAILURE = 0xFF, +}; + +/* UTP Transfer Request Command Type (CT) */ +enum { + UPIU_COMMAND_SET_TYPE_SCSI = 0x0, + UPIU_COMMAND_SET_TYPE_UFS = 0x1, + UPIU_COMMAND_SET_TYPE_QUERY = 0x2, +}; + +/* UTP Transfer Request Command Offset */ +#define UPIU_COMMAND_TYPE_OFFSET 28 + +/* Offset of the response code in the UPIU header */ +#define UPIU_RSP_CODE_OFFSET 8 + +enum { + MASK_SCSI_STATUS = 0xFF, + MASK_TASK_RESPONSE = 0xFF00, + MASK_RSP_UPIU_RESULT = 0xFFFF, + MASK_QUERY_DATA_SEG_LEN = 0xFFFF, + MASK_RSP_UPIU_DATA_SEG_LEN = 0xFFFF, + MASK_RSP_EXCEPTION_EVENT = 0x10000, +}; + +/* Task management service response */ +enum { + UPIU_TASK_MANAGEMENT_FUNC_COMPL = 0x00, + UPIU_TASK_MANAGEMENT_FUNC_NOT_SUPPORTED = 0x04, + UPIU_TASK_MANAGEMENT_FUNC_SUCCEEDED = 0x08, + UPIU_TASK_MANAGEMENT_FUNC_FAILED = 0x05, + UPIU_INCORRECT_LOGICAL_UNIT_NO = 0x09, +}; + +/* UFS device power modes */ +enum ufs_dev_pwr_mode { + UFS_ACTIVE_PWR_MODE = 1, + UFS_SLEEP_PWR_MODE = 2, + UFS_POWERDOWN_PWR_MODE = 3, +}; + +/** + * struct utp_upiu_header - UPIU header structure + * @dword_0: UPIU header DW-0 + * @dword_1: UPIU header DW-1 + * @dword_2: UPIU header DW-2 + */ +struct utp_upiu_header { + __be32 dword_0; + __be32 dword_1; + __be32 dword_2; +}; + +/** + * struct utp_upiu_cmd - Command UPIU structure + * @data_transfer_len: Data Transfer Length DW-3 + * @cdb: Command Descriptor Block CDB DW-4 to DW-7 + */ +struct utp_upiu_cmd { + __be32 exp_data_transfer_len; + u8 cdb[MAX_CDB_SIZE]; +}; + +/** + * struct utp_upiu_query - upiu request buffer structure for + * query request. + * @opcode: command to perform B-0 + * @idn: a value that indicates the particular type of data B-1 + * @index: Index to further identify data B-2 + * @selector: Index to further identify data B-3 + * @reserved_osf: spec reserved field B-4,5 + * @length: number of descriptor bytes to read/write B-6,7 + * @value: Attribute value to be written DW-5 + * @reserved: spec reserved DW-6,7 + */ +struct utp_upiu_query { + u8 opcode; + u8 idn; + u8 index; + u8 selector; + __be16 reserved_osf; + __be16 length; + __be32 value; + __be32 reserved[2]; +}; + +/** + * struct utp_upiu_req - general upiu request structure + * @header:UPIU header structure DW-0 to DW-2 + * @sc: fields structure for scsi command DW-3 to DW-7 + * @qr: fields structure for query request DW-3 to DW-7 + */ +struct utp_upiu_req { + struct utp_upiu_header header; + union { + struct utp_upiu_cmd sc; + struct utp_upiu_query qr; + }; +}; + +/** + * struct utp_cmd_rsp - Response UPIU structure + * @residual_transfer_count: Residual transfer count DW-3 + * @reserved: Reserved double words DW-4 to DW-7 + * @sense_data_len: Sense data length DW-8 U16 + * @sense_data: Sense data field DW-8 to DW-12 + */ +struct utp_cmd_rsp { + __be32 residual_transfer_count; + __be32 reserved[4]; + __be16 sense_data_len; + u8 sense_data[RESPONSE_UPIU_SENSE_DATA_LENGTH]; +}; + +/** + * struct utp_upiu_rsp - general upiu response structure + * @header: UPIU header structure DW-0 to DW-2 + * @sr: fields structure for scsi command DW-3 to DW-12 + * @qr: fields structure for query request DW-3 to DW-7 + */ +struct utp_upiu_rsp { + struct utp_upiu_header header; + union { + struct utp_cmd_rsp sr; + struct utp_upiu_query qr; + }; +}; + +/** + * struct utp_upiu_task_req - Task request UPIU structure + * @header - UPIU header structure DW0 to DW-2 + * @input_param1: Input parameter 1 DW-3 + * @input_param2: Input parameter 2 DW-4 + * @input_param3: Input parameter 3 DW-5 + * @reserved: Reserved double words DW-6 to DW-7 + */ +struct utp_upiu_task_req { + struct utp_upiu_header header; + __be32 input_param1; + __be32 input_param2; + __be32 input_param3; + __be32 reserved[2]; +}; + +/** + * struct utp_upiu_task_rsp - Task Management Response UPIU structure + * @header: UPIU header structure DW0-DW-2 + * @output_param1: Ouput parameter 1 DW3 + * @output_param2: Output parameter 2 DW4 + * @reserved: Reserved double words DW-5 to DW-7 + */ +struct utp_upiu_task_rsp { + struct utp_upiu_header header; + __be32 output_param1; + __be32 output_param2; + __be32 reserved[3]; +}; + +/** + * struct ufs_query_req - parameters for building a query request + * @query_func: UPIU header query function + * @upiu_req: the query request data + */ +struct ufs_query_req { + u8 query_func; + struct utp_upiu_query upiu_req; +}; + +/** + * struct ufs_query_resp - UPIU QUERY + * @response: device response code + * @upiu_res: query response data + */ +struct ufs_query_res { + u8 response; + struct utp_upiu_query upiu_res; +}; + +#define UFS_VREG_VCC_MIN_UV 2700000 /* uV */ +#define UFS_VREG_VCC_MAX_UV 3600000 /* uV */ +#define UFS_VREG_VCC_1P8_MIN_UV 1700000 /* uV */ +#define UFS_VREG_VCC_1P8_MAX_UV 1950000 /* uV */ +#define UFS_VREG_VCCQ_MIN_UV 1100000 /* uV */ +#define UFS_VREG_VCCQ_MAX_UV 1300000 /* uV */ +#define UFS_VREG_VCCQ2_MIN_UV 1650000 /* uV */ +#define UFS_VREG_VCCQ2_MAX_UV 1950000 /* uV */ + +/* + * VCCQ & VCCQ2 current requirement when UFS device is in sleep state + * and link is in Hibern8 state. + */ +#define UFS_VREG_LPM_LOAD_UA 1000 /* uA */ + +struct ufs_vreg { + struct regulator *reg; + const char *name; + bool enabled; + bool unused; + int min_uV; + int max_uV; + int min_uA; + int max_uA; +}; + +struct ufs_vreg_info { + struct ufs_vreg *vcc; + struct ufs_vreg *vccq; + struct ufs_vreg *vccq2; + struct ufs_vreg *vdd_hba; +}; + +struct ufs_dev_info { + bool f_power_on_wp_en; + /* Keeps information if any of the LU is power on write protected */ + bool is_lu_power_on_wp; +}; + +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/ufs_quirks.c b/drivers/scsi/ufs/ufs_quirks.c index 7212d31d6d99..a47dfba3243c 100644 --- a/drivers/scsi/ufs/ufs_quirks.c +++ b/drivers/scsi/ufs/ufs_quirks.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015, 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 @@ -11,7 +11,7 @@ * GNU General Public License for more details. */ -#include <linux/scsi/ufs/ufshcd.h> +#include "ufshcd.h" #include "ufs_quirks.h" diff --git a/drivers/scsi/ufs/ufs_test.c b/drivers/scsi/ufs/ufs_test.c index c23e09e7c225..09fd655d31b1 100644 --- a/drivers/scsi/ufs/ufs_test.c +++ b/drivers/scsi/ufs/ufs_test.c @@ -18,8 +18,8 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> -#include <linux/scsi/ufs/ufshcd.h> -#include <linux/scsi/ufs/ufs.h> +#include "ufshcd.h" +#include "ufs.h" #define MODULE_NAME "ufs_test" diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 650517925d51..52b546fb509b 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -33,7 +33,7 @@ * this program. */ -#include <linux/scsi/ufs/ufshcd.h> +#include "ufshcd.h" #include <linux/pci.h> #include <linux/pm_runtime.h> diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index d80e837bfb88..ca3e899fd1b6 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -39,7 +39,6 @@ #include "ufshcd.h" #include "ufshcd-pltfrm.h" -#include <linux/scsi/ufs/ufshcd.h> static int ufshcd_parse_clock_info(struct ufs_hba *hba) { diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 7b9ca922c892..be896d233038 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -42,7 +42,7 @@ #include <linux/devfreq.h> #include <linux/nls.h> #include <linux/of.h> -#include <linux/scsi/ufs/ufshcd.h> +#include "ufshcd.h" #include "ufshci.h" #include "ufs_quirks.h" #include "ufs-debugfs.h" diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h new file mode 100644 index 000000000000..ea90bdf9e715 --- /dev/null +++ b/drivers/scsi/ufs/ufshcd.h @@ -0,0 +1,1143 @@ +/* + * Universal Flash Storage Host controller driver + * + * This code is based on drivers/scsi/ufs/ufshcd.h + * Copyright (C) 2011-2013 Samsung India Software Operations + * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * + * Authors: + * Santosh Yaraganavi <santosh.sy@samsung.com> + * Vinayak Holikatti <h.vinayak@samsung.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * See the COPYING file in the top-level directory or visit + * <http://www.gnu.org/licenses/gpl-2.0.html> + * + * 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. + * + * This program is provided "AS IS" and "WITH ALL FAULTS" and + * without warranty of any kind. You are solely responsible for + * determining the appropriateness of using and distributing + * the program and assume all risks associated with your exercise + * of rights with respect to the program, including but not limited + * to infringement of third party rights, the risks and costs of + * program errors, damage to or loss of data, programs or equipment, + * and unavailability or interruption of operations. Under no + * circumstances will the contributor of this Program be liable for + * any damages of any kind arising from your use or distribution of + * this program. + */ + +#ifndef _UFSHCD_H +#define _UFSHCD_H + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/delay.h> +#include <linux/slab.h> +#include <linux/spinlock.h> +#include <linux/workqueue.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/wait.h> +#include <linux/bitops.h> +#include <linux/pm_runtime.h> +#include <linux/clk.h> +#include <linux/completion.h> +#include <linux/regulator/consumer.h> +#include <linux/pm_qos.h> +#include "unipro.h" + +#include <asm/irq.h> +#include <asm/byteorder.h> +#include <scsi/scsi.h> +#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_tcq.h> +#include <scsi/scsi_dbg.h> +#include <scsi/scsi_eh.h> + +#include <linux/fault-inject.h> +#include "ufs.h" + +#define UFSHCD "ufshcd" +#define UFSHCD_DRIVER_VERSION "0.2" + +#define UFS_BIT(x) BIT(x) + +struct ufs_hba; + +enum dev_cmd_type { + DEV_CMD_TYPE_NOP = 0x0, + DEV_CMD_TYPE_QUERY = 0x1, +}; + +/** + * struct uic_command - UIC command structure + * @command: UIC command + * @argument1: UIC command argument 1 + * @argument2: UIC command argument 2 + * @argument3: UIC command argument 3 + * @cmd_active: Indicate if UIC command is outstanding + * @result: UIC command result + * @done: UIC command completion + */ +struct uic_command { + u32 command; + u32 argument1; + u32 argument2; + u32 argument3; + int cmd_active; + int result; + struct completion done; +}; + +/* Used to differentiate the power management options */ +enum ufs_pm_op { + UFS_RUNTIME_PM, + UFS_SYSTEM_PM, + UFS_SHUTDOWN_PM, +}; + +#define ufshcd_is_runtime_pm(op) ((op) == UFS_RUNTIME_PM) +#define ufshcd_is_system_pm(op) ((op) == UFS_SYSTEM_PM) +#define ufshcd_is_shutdown_pm(op) ((op) == UFS_SHUTDOWN_PM) + +/* Host <-> Device UniPro Link state */ +enum uic_link_state { + UIC_LINK_OFF_STATE = 0, /* Link powered down or disabled */ + UIC_LINK_ACTIVE_STATE = 1, /* Link is in Fast/Slow/Sleep state */ + UIC_LINK_HIBERN8_STATE = 2, /* Link is in Hibernate state */ +}; + +#define ufshcd_is_link_off(hba) ((hba)->uic_link_state == UIC_LINK_OFF_STATE) +#define ufshcd_is_link_active(hba) ((hba)->uic_link_state == \ + UIC_LINK_ACTIVE_STATE) +#define ufshcd_is_link_hibern8(hba) ((hba)->uic_link_state == \ + UIC_LINK_HIBERN8_STATE) +#define ufshcd_set_link_off(hba) ((hba)->uic_link_state = UIC_LINK_OFF_STATE) +#define ufshcd_set_link_active(hba) ((hba)->uic_link_state = \ + UIC_LINK_ACTIVE_STATE) +#define ufshcd_set_link_hibern8(hba) ((hba)->uic_link_state = \ + UIC_LINK_HIBERN8_STATE) + +enum { + /* errors which require the host controller reset for recovery */ + UFS_ERR_HIBERN8_EXIT, + UFS_ERR_VOPS_SUSPEND, + UFS_ERR_EH, + UFS_ERR_CLEAR_PEND_XFER_TM, + UFS_ERR_INT_FATAL_ERRORS, + UFS_ERR_INT_UIC_ERROR, + + /* other errors */ + UFS_ERR_HIBERN8_ENTER, + UFS_ERR_RESUME, + UFS_ERR_SUSPEND, + UFS_ERR_LINKSTARTUP, + UFS_ERR_POWER_MODE_CHANGE, + UFS_ERR_TASK_ABORT, + UFS_ERR_MAX, +}; + +/* + * UFS Power management levels. + * Each level is in increasing order of power savings. + */ +enum ufs_pm_level { + UFS_PM_LVL_0, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_ACTIVE_STATE */ + UFS_PM_LVL_1, /* UFS_ACTIVE_PWR_MODE, UIC_LINK_HIBERN8_STATE */ + UFS_PM_LVL_2, /* UFS_SLEEP_PWR_MODE, UIC_LINK_ACTIVE_STATE */ + UFS_PM_LVL_3, /* UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE */ + UFS_PM_LVL_4, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_HIBERN8_STATE */ + UFS_PM_LVL_5, /* UFS_POWERDOWN_PWR_MODE, UIC_LINK_OFF_STATE */ + UFS_PM_LVL_MAX +}; + +struct ufs_pm_lvl_states { + enum ufs_dev_pwr_mode dev_state; + enum uic_link_state link_state; +}; + +/** + * struct ufshcd_lrb - local reference block + * @utr_descriptor_ptr: UTRD address of the command + * @ucd_req_ptr: UCD address of the command + * @ucd_rsp_ptr: Response UPIU address for this command + * @ucd_prdt_ptr: PRDT address of the command + * @utrd_dma_addr: UTRD dma address for debug + * @ucd_prdt_dma_addr: PRDT dma address for debug + * @ucd_rsp_dma_addr: UPIU response dma address for debug + * @ucd_req_dma_addr: UPIU request dma address for debug + * @cmd: pointer to SCSI command + * @sense_buffer: pointer to sense buffer address of the SCSI command + * @sense_bufflen: Length of the sense buffer + * @scsi_status: SCSI status of the command + * @command_type: SCSI, UFS, Query. + * @task_tag: Task tag of the command + * @lun: LUN of the command + * @intr_cmd: Interrupt command (doesn't participate in interrupt aggregation) + * @issue_time_stamp: time stamp for debug purposes + * @req_abort_skip: skip request abort task flag + */ +struct ufshcd_lrb { + struct utp_transfer_req_desc *utr_descriptor_ptr; + struct utp_upiu_req *ucd_req_ptr; + struct utp_upiu_rsp *ucd_rsp_ptr; + struct ufshcd_sg_entry *ucd_prdt_ptr; + + dma_addr_t utrd_dma_addr; + dma_addr_t ucd_req_dma_addr; + dma_addr_t ucd_rsp_dma_addr; + dma_addr_t ucd_prdt_dma_addr; + + struct scsi_cmnd *cmd; + u8 *sense_buffer; + unsigned int sense_bufflen; + int scsi_status; + + int command_type; + int task_tag; + u8 lun; /* UPIU LUN id field is only 8-bit wide */ + bool intr_cmd; + ktime_t issue_time_stamp; + + bool req_abort_skip; +}; + +/** + * struct ufs_query - holds relevent data structures for query request + * @request: request upiu and function + * @descriptor: buffer for sending/receiving descriptor + * @response: response upiu and response + */ +struct ufs_query { + struct ufs_query_req request; + u8 *descriptor; + struct ufs_query_res response; +}; + +/** + * struct ufs_dev_cmd - all assosiated fields with device management commands + * @type: device management command type - Query, NOP OUT + * @lock: lock to allow one command at a time + * @complete: internal commands completion + * @tag_wq: wait queue until free command slot is available + */ +struct ufs_dev_cmd { + enum dev_cmd_type type; + struct mutex lock; + struct completion *complete; + wait_queue_head_t tag_wq; + struct ufs_query query; +}; + +/** + * struct ufs_clk_info - UFS clock related info + * @list: list headed by hba->clk_list_head + * @clk: clock node + * @name: clock name + * @max_freq: maximum frequency supported by the clock + * @min_freq: min frequency that can be used for clock scaling + * @curr_freq: indicates the current frequency that it is set to + * @enabled: variable to check against multiple enable/disable + */ +struct ufs_clk_info { + struct list_head list; + struct clk *clk; + const char *name; + u32 max_freq; + u32 min_freq; + u32 curr_freq; + bool enabled; +}; + +enum ufs_notify_change_status { + PRE_CHANGE, + POST_CHANGE, +}; + +struct ufs_pa_layer_attr { + u32 gear_rx; + u32 gear_tx; + u32 lane_rx; + u32 lane_tx; + u32 pwr_rx; + u32 pwr_tx; + u32 hs_rate; +}; + +struct ufs_pwr_mode_info { + bool is_valid; + struct ufs_pa_layer_attr info; +}; + +/** + * struct ufs_hba_variant_ops - variant specific callbacks + * @name: variant name + * @init: called when the driver is initialized + * @exit: called to cleanup everything done in init + * @get_ufs_hci_version: called to get UFS HCI version + * @clk_scale_notify: notifies that clks are scaled up/down + * @setup_clocks: called before touching any of the controller registers + * @setup_regulators: called before accessing the host controller + * @hce_enable_notify: called before and after HCE enable bit is set to allow + * variant specific Uni-Pro initialization. + * @link_startup_notify: called before and after Link startup is carried out + * to allow variant specific Uni-Pro initialization. + * @pwr_change_notify: called before and after a power mode change + * is carried out to allow vendor spesific capabilities + * to be set. + * @suspend: called during host controller PM callback + * @resume: called during host controller PM callback + * @update_sec_cfg: called to restore host controller secure configuration + * @dbg_register_dump: used to dump controller debug information + * @crypto_engine_cfg: configure cryptographic engine according to tag parameter + * @crypto_engine_eh: cryptographic engine error handling. + * Return true is it detects an error, false on + * success + * @crypto_engine_get_err: returns the saved error status of the + * cryptographic engine.If a positive + * value is returned, host controller + * should be reset. + * @crypto_engine_reset_err: resets the saved error status of + * the cryptographic engine + * @dbg_register_dump: used to dump controller debug information + * @add_debugfs: used to add debugfs entries + * @remove_debugfs: used to remove debugfs entries + */ +struct ufs_hba_variant_ops { + const char *name; + int (*init)(struct ufs_hba *); + void (*exit)(struct ufs_hba *); + u32 (*get_ufs_hci_version)(struct ufs_hba *); + int (*clk_scale_notify)(struct ufs_hba *, bool, + enum ufs_notify_change_status); + int (*setup_clocks)(struct ufs_hba *, bool); + int (*setup_regulators)(struct ufs_hba *, bool); + int (*hce_enable_notify)(struct ufs_hba *, + enum ufs_notify_change_status); + int (*link_startup_notify)(struct ufs_hba *, + enum ufs_notify_change_status); + int (*pwr_change_notify)(struct ufs_hba *, + enum ufs_notify_change_status status, + struct ufs_pa_layer_attr *, + struct ufs_pa_layer_attr *); + int (*suspend)(struct ufs_hba *, enum ufs_pm_op); + int (*resume)(struct ufs_hba *, enum ufs_pm_op); + int (*update_sec_cfg)(struct ufs_hba *hba, bool restore_sec_cfg); + void (*dbg_register_dump)(struct ufs_hba *hba); + int (*crypto_engine_cfg)(struct ufs_hba *, unsigned int); + int (*crypto_engine_reset)(struct ufs_hba *); + int (*crypto_engine_eh)(struct ufs_hba *); + int (*crypto_engine_get_err)(struct ufs_hba *); + void (*crypto_engine_reset_err)(struct ufs_hba *); + void (*dbg_register_dump)(struct ufs_hba *hba); +#ifdef CONFIG_DEBUG_FS + void (*add_debugfs)(struct ufs_hba *hba, struct dentry *root); + void (*remove_debugfs)(struct ufs_hba *hba); +#endif +}; + +/* clock gating state */ +enum clk_gating_state { + CLKS_OFF, + CLKS_ON, + REQ_CLKS_OFF, + REQ_CLKS_ON, +}; + +/** + * struct ufs_clk_gating - UFS clock gating related info + * @gate_work: worker to turn off clocks after some delay as specified in + * delay_ms + * @ungate_work: worker to turn on clocks that will be used in case of + * interrupt context + * @state: the current clocks state + * @delay_ms: gating delay in ms + * @is_suspended: clk gating is suspended when set to 1 which can be used + * during suspend/resume + * @delay_attr: sysfs attribute to control delay_attr + * @enable_attr: sysfs attribute to enable/disable clock gating + * @is_enabled: Indicates the current status of clock gating + * @active_reqs: number of requests that are pending and should be waited for + * completion before gating clocks. + */ +struct ufs_clk_gating { + struct delayed_work gate_work; + struct work_struct ungate_work; + enum clk_gating_state state; + unsigned long delay_ms; + bool is_suspended; + struct device_attribute delay_attr; + struct device_attribute enable_attr; + bool is_enabled; + int active_reqs; +}; + +/* Hibern8 state */ +enum ufshcd_hibern8_on_idle_state { + HIBERN8_ENTERED, + HIBERN8_EXITED, + REQ_HIBERN8_ENTER, + REQ_HIBERN8_EXIT, +}; + +/** + * struct ufs_hibern8_on_idle - UFS Hibern8 on idle related data + * @enter_work: worker to put UFS link in hibern8 after some delay as + * specified in delay_ms + * @exit_work: worker to bring UFS link out of hibern8 + * @state: the current hibern8 state + * @delay_ms: hibern8 enter delay in ms + * @is_suspended: hibern8 enter is suspended when set to 1 which can be used + * during suspend/resume + * @active_reqs: number of requests that are pending and should be waited for + * completion before scheduling delayed "enter_work". + * @delay_attr: sysfs attribute to control delay_attr + * @enable_attr: sysfs attribute to enable/disable hibern8 on idle + * @is_enabled: Indicates the current status of hibern8 + */ +struct ufs_hibern8_on_idle { + struct delayed_work enter_work; + struct work_struct exit_work; + enum ufshcd_hibern8_on_idle_state state; + unsigned long delay_ms; + bool is_suspended; + int active_reqs; + struct device_attribute delay_attr; + struct device_attribute enable_attr; + bool is_enabled; +}; + +struct ufs_saved_pwr_info { + struct ufs_pa_layer_attr info; + bool is_valid; +}; + +struct ufs_clk_scaling { + ktime_t busy_start_t; + bool is_busy_started; + unsigned long tot_busy_t; + unsigned long window_start_t; + struct device_attribute enable_attr; + bool is_allowed; + struct ufs_saved_pwr_info saved_pwr_info; +}; + +/** + * struct ufs_init_prefetch - contains data that is pre-fetched once during + * initialization + * @icc_level: icc level which was read during initialization + */ +struct ufs_init_prefetch { + u32 icc_level; +}; + +#define UIC_ERR_REG_HIST_LENGTH 8 +/** + * struct ufs_uic_err_reg_hist - keeps history of uic errors + * @pos: index to indicate cyclic buffer position + * @reg: cyclic buffer for registers value + * @tstamp: cyclic buffer for time stamp + */ +struct ufs_uic_err_reg_hist { + int pos; + u32 reg[UIC_ERR_REG_HIST_LENGTH]; + ktime_t tstamp[UIC_ERR_REG_HIST_LENGTH]; +}; + +/** + * struct ufs_stats - keeps usage/err statistics + * @enabled: enable tagstats for debugfs + * @tag_stats: pointer to tag statistic counters + * @q_depth: current amount of busy slots + * @err_stats: counters to keep track of various errors + * @hibern8_exit_cnt: Counter to keep track of number of exits, + * reset this after link-startup. + * @last_hibern8_exit_tstamp: Set time after the hibern8 exit. + * Clear after the first successful command completion. + * @pa_err: tracks pa-uic errors + * @dl_err: tracks dl-uic errors + * @nl_err: tracks nl-uic errors + * @tl_err: tracks tl-uic errors + * @dme_err: tracks dme errors + */ +struct ufs_stats { +#ifdef CONFIG_DEBUG_FS + bool enabled; + u64 **tag_stats; + int q_depth; + int err_stats[UFS_ERR_MAX]; +#endif + u32 hibern8_exit_cnt; + ktime_t last_hibern8_exit_tstamp; + struct ufs_uic_err_reg_hist pa_err; + struct ufs_uic_err_reg_hist dl_err; + struct ufs_uic_err_reg_hist nl_err; + struct ufs_uic_err_reg_hist tl_err; + struct ufs_uic_err_reg_hist dme_err; +}; + +#ifdef CONFIG_DEBUG_FS +struct debugfs_files { + struct dentry *debugfs_root; + struct dentry *tag_stats; + struct dentry *err_stats; + struct dentry *show_hba; + struct dentry *host_regs; + struct dentry *dump_dev_desc; + struct dentry *power_mode; + struct dentry *dme_local_read; + struct dentry *dme_peer_read; + struct dentry *dbg_print_en; + u32 dme_local_attr_id; + u32 dme_peer_attr_id; +#ifdef CONFIG_UFS_FAULT_INJECTION + struct fault_attr fail_attr; +#endif + bool is_sys_suspended; +}; + +/* tag stats statistics types */ +enum ts_types { + TS_NOT_SUPPORTED = -1, + TS_TAG = 0, + TS_READ = 1, + TS_WRITE = 2, + TS_URGENT = 3, + TS_FLUSH = 4, + TS_NUM_STATS = 5, +}; +#endif + +/* PM QoS voting state */ +enum ufshcd_pm_qos_state { + PM_QOS_UNVOTED, + PM_QOS_VOTED, + PM_QOS_REQ_VOTE, + PM_QOS_REQ_UNVOTE, +}; + +/* Default latency for PM QOS */ +#define UFS_DEFAULT_CPU_DMA_LATENCY_US 200 /* microseconds */ + +/** + * struct ufshcd_pm_qos - data related to PM QoS voting logic + * @vote_work: work object for voting procedure + * @unvote_work: work object for un-voting procedure + * @req: request object for PM QoS + * @cpu_dma_latency_us: requested latency value used for voting in microseconds + * @state: voting state machine current state + * @active_reqs: number of active requests requiring PM QoS voting + * @is_suspended: flag specifying whether voting logic is suspended. + * When set, voting will not occur for pending requests. + */ +struct ufshcd_pm_qos { + struct work_struct vote_work; + struct work_struct unvote_work; + struct pm_qos_request req; + u32 cpu_dma_latency_us; + enum ufshcd_pm_qos_state state; + int active_reqs; + bool is_suspended; +}; + +/* UFS Host Controller debug print bitmask */ +#define UFSHCD_DBG_PRINT_CLK_FREQ_EN UFS_BIT(0) +#define UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN UFS_BIT(1) +#define UFSHCD_DBG_PRINT_HOST_REGS_EN UFS_BIT(2) +#define UFSHCD_DBG_PRINT_TRS_EN UFS_BIT(3) +#define UFSHCD_DBG_PRINT_TMRS_EN UFS_BIT(4) +#define UFSHCD_DBG_PRINT_PWR_EN UFS_BIT(5) + +#define UFSHCD_DBG_PRINT_ALL \ + (UFSHCD_DBG_PRINT_CLK_FREQ_EN | \ + UFSHCD_DBG_PRINT_UIC_ERR_HIST_EN | \ + UFSHCD_DBG_PRINT_HOST_REGS_EN | UFSHCD_DBG_PRINT_TRS_EN | \ + UFSHCD_DBG_PRINT_TMRS_EN | UFSHCD_DBG_PRINT_PWR_EN) + +/** + * struct ufs_hba - per adapter private structure + * @mmio_base: UFSHCI base register address + * @ucdl_base_addr: UFS Command Descriptor base address + * @utrdl_base_addr: UTP Transfer Request Descriptor base address + * @utmrdl_base_addr: UTP Task Management Descriptor base address + * @ucdl_dma_addr: UFS Command Descriptor DMA address + * @utrdl_dma_addr: UTRDL DMA address + * @utmrdl_dma_addr: UTMRDL DMA address + * @host: Scsi_Host instance of the driver + * @dev: device handle + * @lrb: local reference block + * @lrb_in_use: lrb in use + * @outstanding_tasks: Bits representing outstanding task requests + * @outstanding_reqs: Bits representing outstanding transfer requests + * @capabilities: UFS Controller Capabilities + * @nutrs: Transfer Request Queue depth supported by controller + * @nutmrs: Task Management Queue depth supported by controller + * @ufs_version: UFS Version to which controller complies + * @vops: pointer to variant specific operations + * @priv: pointer to variant specific private data + * @irq: Irq number of the controller + * @active_uic_cmd: handle of active UIC command + * @uic_cmd_mutex: mutex for uic command + * @tm_wq: wait queue for task management + * @tm_tag_wq: wait queue for free task management slots + * @tm_slots_in_use: bit map of task management request slots in use + * @pwr_done: completion for power mode change + * @tm_condition: condition variable for task management + * @ufshcd_state: UFSHCD states + * @eh_flags: Error handling flags + * @intr_mask: Interrupt Mask Bits + * @ee_ctrl_mask: Exception event control mask + * @is_powered: flag to check if HBA is powered + * @is_init_prefetch: flag to check if data was pre-fetched in initialization + * @init_prefetch_data: data pre-fetched during initialization + * @eh_work: Worker to handle UFS errors that require s/w attention + * @eeh_work: Worker to handle exception events + * @errors: HBA errors + * @uic_error: UFS interconnect layer error status + * @saved_err: sticky error mask + * @saved_uic_err: sticky UIC error mask + * @dev_cmd: ufs device management command information + * @last_dme_cmd_tstamp: time stamp of the last completed DME command + * @auto_bkops_enabled: to track whether bkops is enabled in device + * @ufs_stats: ufshcd statistics to be used via debugfs + * @debugfs_files: debugfs files associated with the ufs stats + * @ufshcd_dbg_print: Bitmask for enabling debug prints + * @vreg_info: UFS device voltage regulator information + * @clk_list_head: UFS host controller clocks list node head + * @pwr_info: holds current power mode + * @max_pwr_info: keeps the device max valid pwm + * @hibern8_on_idle: UFS Hibern8 on idle related data + */ +struct ufs_hba { + void __iomem *mmio_base; + + /* Virtual memory reference */ + struct utp_transfer_cmd_desc *ucdl_base_addr; + struct utp_transfer_req_desc *utrdl_base_addr; + struct utp_task_req_desc *utmrdl_base_addr; + + /* DMA memory reference */ + dma_addr_t ucdl_dma_addr; + dma_addr_t utrdl_dma_addr; + dma_addr_t utmrdl_dma_addr; + + struct Scsi_Host *host; + struct device *dev; + /* + * This field is to keep a reference to "scsi_device" corresponding to + * "UFS device" W-LU. + */ + struct scsi_device *sdev_ufs_device; + + enum ufs_dev_pwr_mode curr_dev_pwr_mode; + enum uic_link_state uic_link_state; + /* Desired UFS power management level during runtime PM */ + int rpm_lvl; + /* Desired UFS power management level during system PM */ + int spm_lvl; + struct device_attribute rpm_lvl_attr; + struct device_attribute spm_lvl_attr; + int pm_op_in_progress; + + struct ufshcd_lrb *lrb; + unsigned long lrb_in_use; + + unsigned long outstanding_tasks; + unsigned long outstanding_reqs; + + u32 capabilities; + int nutrs; + int nutmrs; + u32 ufs_version; + struct ufs_hba_variant_ops *vops; + void *priv; + unsigned int irq; + bool is_irq_enabled; + + /* Interrupt aggregation support is broken */ + #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) + + /* + * delay before each dme command is required as the unipro + * layer has shown instabilities + */ + #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(1) + + /* + * If UFS host controller is having issue in processing LCC (Line + * Control Command) coming from device then enable this quirk. + * When this quirk is enabled, host controller driver should disable + * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE + * attribute of device to 0). + */ + #define UFSHCD_QUIRK_BROKEN_LCC UFS_BIT(2) + + /* + * The attribute PA_RXHSUNTERMCAP specifies whether or not the + * inbound Link supports unterminated line in HS mode. Setting this + * attribute to 1 fixes moving to HS gear. + */ + #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP UFS_BIT(3) + + /* + * This quirk needs to be enabled if the host contoller only allows + * accessing the peer dme attributes in AUTO mode (FAST AUTO or + * SLOW AUTO). + */ + #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE UFS_BIT(4) + + /* + * This quirk needs to be enabled if the host contoller doesn't + * advertise the correct version in UFS_VER register. If this quirk + * is enabled, standard UFS host driver will call the vendor specific + * ops (get_ufs_hci_version) to get the correct version. + */ + #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION UFS_BIT(5) + + unsigned int quirks; /* Deviations from standard UFSHCI spec. */ + + /* Device deviations from standard UFS device spec. */ + unsigned int dev_quirks; + + wait_queue_head_t tm_wq; + wait_queue_head_t tm_tag_wq; + unsigned long tm_condition; + unsigned long tm_slots_in_use; + + struct uic_command *active_uic_cmd; + struct mutex uic_cmd_mutex; + struct completion *uic_async_done; + + u32 ufshcd_state; + u32 eh_flags; + u32 intr_mask; + u16 ee_ctrl_mask; + bool is_powered; + bool is_init_prefetch; + struct ufs_init_prefetch init_prefetch_data; + + /* Work Queues */ + struct work_struct eh_work; + struct work_struct eeh_work; + + /* HBA Errors */ + u32 errors; + u32 uic_error; + u32 saved_err; + u32 saved_uic_err; + bool silence_err_logs; + + /* Device management request data */ + struct ufs_dev_cmd dev_cmd; + ktime_t last_dme_cmd_tstamp; + + /* Keeps information of the UFS device connected to this host */ + struct ufs_dev_info dev_info; + bool auto_bkops_enabled; + + struct ufs_stats ufs_stats; +#ifdef CONFIG_DEBUG_FS + struct debugfs_files debugfs_files; +#endif + + struct ufs_vreg_info vreg_info; + struct list_head clk_list_head; + + bool wlun_dev_clr_ua; + + /* PM Quality-of-Service (QoS) data */ + struct ufshcd_pm_qos pm_qos; + + /* Number of requests aborts */ + int req_abort_count; + + /* Number of lanes available (1 or 2) for Rx/Tx */ + u32 lanes_per_direction; + + /* Bitmask for enabling debug prints */ + u32 ufshcd_dbg_print; + + struct ufs_pa_layer_attr pwr_info; + struct ufs_pwr_mode_info max_pwr_info; + + struct ufs_clk_gating clk_gating; + struct ufs_hibern8_on_idle hibern8_on_idle; + + /* Control to enable/disable host capabilities */ + u32 caps; + /* Allow dynamic clk gating */ +#define UFSHCD_CAP_CLK_GATING (1 << 0) + /* Allow hiberb8 with clk gating */ +#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1) + /* Allow dynamic clk scaling */ +#define UFSHCD_CAP_CLK_SCALING (1 << 2) + /* Allow auto bkops to enabled during runtime suspend */ +#define UFSHCD_CAP_AUTO_BKOPS_SUSPEND (1 << 3) + /* + * This capability allows host controller driver to use the UFS HCI's + * interrupt aggregation capability. + * CAUTION: Enabling this might reduce overall UFS throughput. + */ +#define UFSHCD_CAP_INTR_AGGR (1 << 4) + /* Allow standalone Hibern8 enter on idle */ +#define UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE (1 << 5) + /* + * This capability allows the device auto-bkops to be always enabled + * except during suspend (both runtime and suspend). + * Enabling this capability means that device will always be allowed + * to do background operation when it's active but it might degrade + * the performance of ongoing read/write operations. + */ +#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 6) + /* + * If host controller hardware can be power collapsed when UFS link is + * in hibern8 then enable this cap. + */ +#define UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8 (1 << 7) + + struct devfreq *devfreq; + struct ufs_clk_scaling clk_scaling; + bool is_sys_suspended; +}; + +/* Returns true if clocks can be gated. Otherwise false */ +static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_CLK_GATING; +} +static inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; +} +static inline int ufshcd_is_clkscaling_supported(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_CLK_SCALING; +} +static inline bool ufshcd_can_autobkops_during_suspend(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_AUTO_BKOPS_SUSPEND; +} +static inline bool ufshcd_is_hibern8_on_idle_allowed(struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_HIBERN8_ENTER_ON_IDLE; +} + +static inline bool ufshcd_is_power_collapse_during_hibern8_allowed( + struct ufs_hba *hba) +{ + return !!(hba->caps & UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8); +} + +static inline bool ufshcd_keep_autobkops_enabled_except_suspend( + struct ufs_hba *hba) +{ + return hba->caps & UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND; +} + +static inline bool ufshcd_is_intr_aggr_allowed(struct ufs_hba *hba) +{ + if ((hba->caps & UFSHCD_CAP_INTR_AGGR) && + !(hba->quirks & UFSHCD_QUIRK_BROKEN_INTR_AGGR)) + return true; + else + return false; +} + +#define ufshcd_writel(hba, val, reg) \ + writel_relaxed((val), (hba)->mmio_base + (reg)) +#define ufshcd_readl(hba, reg) \ + readl_relaxed((hba)->mmio_base + (reg)) + +/** + * ufshcd_rmwl - read modify write into a register + * @hba - per adapter instance + * @mask - mask to apply on read value + * @val - actual value to write + * @reg - register address + */ +static inline void ufshcd_rmwl(struct ufs_hba *hba, u32 mask, u32 val, u32 reg) +{ + u32 tmp; + + tmp = ufshcd_readl(hba, reg); + tmp &= ~mask; + tmp |= (val & mask); + ufshcd_writel(hba, tmp, reg); +} + +int ufshcd_alloc_host(struct device *, struct ufs_hba **); +void ufshcd_dealloc_host(struct ufs_hba *); +int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); +void ufshcd_remove(struct ufs_hba *); +int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, + u32 val, unsigned long interval_us, + unsigned long timeout_ms, bool can_sleep); + +/** + * ufshcd_set_variant - set variant specific data to the hba + * @hba - per adapter instance + * @variant - pointer to variant specific data + */ +static inline void ufshcd_set_variant(struct ufs_hba *hba, void *variant) +{ + BUG_ON(!hba); + hba->priv = variant; +} + +/** + * ufshcd_get_variant - get variant specific data from the hba + * @hba - per adapter instance + */ +static inline void *ufshcd_get_variant(struct ufs_hba *hba) +{ + BUG_ON(!hba); + return hba->priv; +} + +extern int ufshcd_runtime_suspend(struct ufs_hba *hba); +extern int ufshcd_runtime_resume(struct ufs_hba *hba); +extern int ufshcd_runtime_idle(struct ufs_hba *hba); +extern int ufshcd_system_suspend(struct ufs_hba *hba); +extern int ufshcd_system_resume(struct ufs_hba *hba); +extern int ufshcd_shutdown(struct ufs_hba *hba); +extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel, + u8 attr_set, u32 mib_val, u8 peer); +extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel, + u32 *mib_val, u8 peer); + +/* UIC command interfaces for DME primitives */ +#define DME_LOCAL 0 +#define DME_PEER 1 +#define ATTR_SET_NOR 0 /* NORMAL */ +#define ATTR_SET_ST 1 /* STATIC */ + +static inline int ufshcd_dme_set(struct ufs_hba *hba, u32 attr_sel, + u32 mib_val) +{ + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, + mib_val, DME_LOCAL); +} + +static inline int ufshcd_dme_st_set(struct ufs_hba *hba, u32 attr_sel, + u32 mib_val) +{ + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST, + mib_val, DME_LOCAL); +} + +static inline int ufshcd_dme_peer_set(struct ufs_hba *hba, u32 attr_sel, + u32 mib_val) +{ + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_NOR, + mib_val, DME_PEER); +} + +static inline int ufshcd_dme_peer_st_set(struct ufs_hba *hba, u32 attr_sel, + u32 mib_val) +{ + return ufshcd_dme_set_attr(hba, attr_sel, ATTR_SET_ST, + mib_val, DME_PEER); +} + +static inline int ufshcd_dme_get(struct ufs_hba *hba, + u32 attr_sel, u32 *mib_val) +{ + return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_LOCAL); +} + +static inline int ufshcd_dme_peer_get(struct ufs_hba *hba, + u32 attr_sel, u32 *mib_val) +{ + return ufshcd_dme_get_attr(hba, attr_sel, mib_val, DME_PEER); +} + +int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size); + +static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) +{ + return (pwr_info->pwr_rx == FAST_MODE || + pwr_info->pwr_rx == FASTAUTO_MODE) && + (pwr_info->pwr_tx == FAST_MODE || + pwr_info->pwr_tx == FASTAUTO_MODE); +} + +#define ASCII_STD true +#define UTF16_STD false +int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf, + u32 size, bool ascii); +/* variant specific ops structures */ +#ifdef CONFIG_SCSI_UFS_QCOM +extern const struct ufs_hba_variant_ops ufs_hba_qcom_vops; +#else +static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = { + .name = "qcom", +}; +#endif + +#ifndef CONFIG_SMP +static inline int ufshcd_pm_qos_init(struct ufs_hba *hba) +{ + return 0; +} + +static inline int ufshcd_pm_qos_hold(struct ufs_hba *hba, bool async) +{ + return 0; +} + +static inline int __ufshcd_pm_qos_hold(struct ufs_hba *hba, bool async) +{ + return 0; +} + +static inline int ufshcd_pm_qos_release(struct ufs_hba *hba) +{ + return 0; +} + +static inline int __ufshcd_pm_qos_release(struct ufs_hba *hba) +{ + return 0; +} + +static inline void ufshcd_pm_qos_remove(struct ufs_hba *hba) +{ +} + +static inline void ufshcd_parse_pm_qos(struct ufs_hba *hba) +{ +} +#endif /* CONFIG_SMP */ + +/* Expose Query-Request API */ +int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, + enum flag_idn idn, bool *flag_res); +int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, + enum attr_idn idn, u8 index, u8 selector, u32 *attr_val); +int ufshcd_query_descriptor(struct ufs_hba *hba, enum query_opcode opcode, + enum desc_idn idn, u8 index, u8 selector, u8 *desc_buf, int *buf_len); + +int ufshcd_hold(struct ufs_hba *hba, bool async); +void ufshcd_release(struct ufs_hba *hba, bool no_sched); +int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba, u64 wait_timeout_us); +int ufshcd_change_power_mode(struct ufs_hba *hba, + struct ufs_pa_layer_attr *pwr_mode); +void ufshcd_abort_outstanding_transfer_requests(struct ufs_hba *hba, + int result); + +/* Wrapper functions for safely calling variant operations */ +static inline const char *ufshcd_get_var_name(struct ufs_hba *hba) +{ + if (hba->vops) + return hba->vops->name; + return ""; +} + +static inline int ufshcd_vops_init(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->init) + return hba->vops->init(hba); + + return 0; +} + +static inline void ufshcd_vops_exit(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->exit) + return hba->vops->exit(hba); +} + +static inline u32 ufshcd_vops_get_ufs_hci_version(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->get_ufs_hci_version) + return hba->vops->get_ufs_hci_version(hba); + + return ufshcd_readl(hba, REG_UFS_VERSION); +} + +static inline int ufshcd_vops_clk_scale_notify(struct ufs_hba *hba, + bool up, enum ufs_notify_change_status status) +{ + if (hba->vops && hba->vops->clk_scale_notify) + return hba->vops->clk_scale_notify(hba, up, status); + return 0; +} + +static inline int ufshcd_vops_setup_clocks(struct ufs_hba *hba, bool on) +{ + if (hba->vops && hba->vops->setup_clocks) + return hba->vops->setup_clocks(hba, on); + return 0; +} + +static inline int ufshcd_vops_setup_regulators(struct ufs_hba *hba, bool status) +{ + if (hba->vops && hba->vops->setup_regulators) + return hba->vops->setup_regulators(hba, status); + + return 0; +} + +static inline int ufshcd_vops_hce_enable_notify(struct ufs_hba *hba, + bool status) +{ + if (hba->vops && hba->vops->hce_enable_notify) + return hba->vops->hce_enable_notify(hba, status); + + return 0; +} +static inline int ufshcd_vops_link_startup_notify(struct ufs_hba *hba, + bool status) +{ + if (hba->vops && hba->vops->link_startup_notify) + return hba->vops->link_startup_notify(hba, status); + + return 0; +} + +static inline int ufshcd_vops_pwr_change_notify(struct ufs_hba *hba, + bool status, + struct ufs_pa_layer_attr *dev_max_params, + struct ufs_pa_layer_attr *dev_req_params) +{ + if (hba->vops && hba->vops->pwr_change_notify) + return hba->vops->pwr_change_notify(hba, status, + dev_max_params, dev_req_params); + + return -ENOTSUPP; +} + +static inline int ufshcd_vops_suspend(struct ufs_hba *hba, enum ufs_pm_op op) +{ + if (hba->vops && hba->vops->suspend) + return hba->vops->suspend(hba, op); + + return 0; +} + +static inline int ufshcd_vops_resume(struct ufs_hba *hba, enum ufs_pm_op op) +{ + if (hba->vops && hba->vops->resume) + return hba->vops->resume(hba, op); + + return 0; +} + +static inline void ufshcd_vops_dbg_register_dump(struct ufs_hba *hba) +{ + if (hba->vops && hba->vops->dbg_register_dump) + hba->vops->dbg_register_dump(hba); +} +#endif /* End of Header */ diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h new file mode 100644 index 000000000000..3fdd775ee306 --- /dev/null +++ b/drivers/scsi/ufs/unipro.h @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef _UNIPRO_H_ +#define _UNIPRO_H_ + +/* + * M-TX Configuration Attributes + */ +#define TX_HIBERN8TIME_CAPABILITY 0x000F +#define TX_MODE 0x0021 +#define TX_HSRATE_SERIES 0x0022 +#define TX_HSGEAR 0x0023 +#define TX_PWMGEAR 0x0024 +#define TX_AMPLITUDE 0x0025 +#define TX_HS_SLEWRATE 0x0026 +#define TX_SYNC_SOURCE 0x0027 +#define TX_HS_SYNC_LENGTH 0x0028 +#define TX_HS_PREPARE_LENGTH 0x0029 +#define TX_LS_PREPARE_LENGTH 0x002A +#define TX_HIBERN8_CONTROL 0x002B +#define TX_LCC_ENABLE 0x002C +#define TX_PWM_BURST_CLOSURE_EXTENSION 0x002D +#define TX_BYPASS_8B10B_ENABLE 0x002E +#define TX_DRIVER_POLARITY 0x002F +#define TX_HS_UNTERMINATED_LINE_DRIVE_ENABLE 0x0030 +#define TX_LS_TERMINATED_LINE_DRIVE_ENABLE 0x0031 +#define TX_LCC_SEQUENCER 0x0032 +#define TX_MIN_ACTIVATETIME 0x0033 +#define TX_PWM_G6_G7_SYNC_LENGTH 0x0034 + +/* + * M-RX Configuration Attributes + */ +#define RX_MODE 0x00A1 +#define RX_HSRATE_SERIES 0x00A2 +#define RX_HSGEAR 0x00A3 +#define RX_PWMGEAR 0x00A4 +#define RX_LS_TERMINATED_ENABLE 0x00A5 +#define RX_HS_UNTERMINATED_ENABLE 0x00A6 +#define RX_ENTER_HIBERN8 0x00A7 +#define RX_BYPASS_8B10B_ENABLE 0x00A8 +#define RX_TERMINATION_FORCE_ENABLE 0x0089 +#define RX_MIN_ACTIVATETIME_CAPABILITY 0x008F +#define RX_HIBERN8TIME_CAPABILITY 0x0092 + +#define is_mphy_tx_attr(attr) (attr < RX_MODE) +#define RX_MIN_ACTIVATETIME_UNIT_US 100 +#define HIBERN8TIME_UNIT_US 100 + +/* + * PHY Adpater attributes + */ +#define PA_ACTIVETXDATALANES 0x1560 +#define PA_ACTIVERXDATALANES 0x1580 +#define PA_TXTRAILINGCLOCKS 0x1564 +#define PA_PHY_TYPE 0x1500 +#define PA_AVAILTXDATALANES 0x1520 +#define PA_AVAILRXDATALANES 0x1540 +#define PA_MINRXTRAILINGCLOCKS 0x1543 +#define PA_TXPWRSTATUS 0x1567 +#define PA_RXPWRSTATUS 0x1582 +#define PA_TXFORCECLOCK 0x1562 +#define PA_TXPWRMODE 0x1563 +#define PA_LEGACYDPHYESCDL 0x1570 +#define PA_MAXTXSPEEDFAST 0x1521 +#define PA_MAXTXSPEEDSLOW 0x1522 +#define PA_MAXRXSPEEDFAST 0x1541 +#define PA_MAXRXSPEEDSLOW 0x1542 +#define PA_TXLINKSTARTUPHS 0x1544 +#define PA_TXSPEEDFAST 0x1565 +#define PA_TXSPEEDSLOW 0x1566 +#define PA_REMOTEVERINFO 0x15A0 +#define PA_TXGEAR 0x1568 +#define PA_TXTERMINATION 0x1569 +#define PA_HSSERIES 0x156A +#define PA_PWRMODE 0x1571 +#define PA_RXGEAR 0x1583 +#define PA_RXTERMINATION 0x1584 +#define PA_MAXRXPWMGEAR 0x1586 +#define PA_MAXRXHSGEAR 0x1587 +#define PA_RXHSUNTERMCAP 0x15A5 +#define PA_RXLSTERMCAP 0x15A6 +#define PA_PACPREQTIMEOUT 0x1590 +#define PA_PACPREQEOBTIMEOUT 0x1591 +#define PA_HIBERN8TIME 0x15A7 +#define PA_LOCALVERINFO 0x15A9 +#define PA_TACTIVATE 0x15A8 +#define PA_PACPFRAMECOUNT 0x15C0 +#define PA_PACPERRORCOUNT 0x15C1 +#define PA_PHYTESTCONTROL 0x15C2 +#define PA_PWRMODEUSERDATA0 0x15B0 +#define PA_PWRMODEUSERDATA1 0x15B1 +#define PA_PWRMODEUSERDATA2 0x15B2 +#define PA_PWRMODEUSERDATA3 0x15B3 +#define PA_PWRMODEUSERDATA4 0x15B4 +#define PA_PWRMODEUSERDATA5 0x15B5 +#define PA_PWRMODEUSERDATA6 0x15B6 +#define PA_PWRMODEUSERDATA7 0x15B7 +#define PA_PWRMODEUSERDATA8 0x15B8 +#define PA_PWRMODEUSERDATA9 0x15B9 +#define PA_PWRMODEUSERDATA10 0x15BA +#define PA_PWRMODEUSERDATA11 0x15BB +#define PA_CONNECTEDTXDATALANES 0x1561 +#define PA_CONNECTEDRXDATALANES 0x1581 +#define PA_LOGICALLANEMAP 0x15A1 +#define PA_SLEEPNOCONFIGTIME 0x15A2 +#define PA_STALLNOCONFIGTIME 0x15A3 +#define PA_SAVECONFIGTIME 0x15A4 + +#define PA_TACTIVATE_TIME_UNIT_US 10 +#define PA_HIBERN8_TIME_UNIT_US 100 + +/* PHY Adapter Protocol Constants */ +#define PA_MAXDATALANES 4 + +/* PA power modes */ +enum { + FAST_MODE = 1, + SLOW_MODE = 2, + FASTAUTO_MODE = 4, + SLOWAUTO_MODE = 5, + UNCHANGED = 7, +}; + +/* PA TX/RX Frequency Series */ +enum { + PA_HS_MODE_A = 1, + PA_HS_MODE_B = 2, +}; + +enum ufs_pwm_gear_tag { + UFS_PWM_DONT_CHANGE, /* Don't change Gear */ + UFS_PWM_G1, /* PWM Gear 1 (default for reset) */ + UFS_PWM_G2, /* PWM Gear 2 */ + UFS_PWM_G3, /* PWM Gear 3 */ + UFS_PWM_G4, /* PWM Gear 4 */ + UFS_PWM_G5, /* PWM Gear 5 */ + UFS_PWM_G6, /* PWM Gear 6 */ + UFS_PWM_G7, /* PWM Gear 7 */ +}; + +enum ufs_hs_gear_tag { + UFS_HS_DONT_CHANGE, /* Don't change Gear */ + UFS_HS_G1, /* HS Gear 1 (default for reset) */ + UFS_HS_G2, /* HS Gear 2 */ + UFS_HS_G3, /* HS Gear 3 */ +}; + +enum ufs_unipro_ver { + UFS_UNIPRO_VER_RESERVED = 0, + UFS_UNIPRO_VER_1_40 = 1, /* UniPro version 1.40 */ + UFS_UNIPRO_VER_1_41 = 2, /* UniPro version 1.41 */ + UFS_UNIPRO_VER_1_6 = 3, /* UniPro version 1.6 */ + UFS_UNIPRO_VER_MAX = 4, /* UniPro unsupported version */ + /* UniPro version field mask in PA_LOCALVERINFO */ + UFS_UNIPRO_VER_MASK = 0xF, +}; + +/* + * Data Link Layer Attributes + */ +#define DL_TC0TXFCTHRESHOLD 0x2040 +#define DL_FC0PROTTIMEOUTVAL 0x2041 +#define DL_TC0REPLAYTIMEOUTVAL 0x2042 +#define DL_AFC0REQTIMEOUTVAL 0x2043 +#define DL_AFC0CREDITTHRESHOLD 0x2044 +#define DL_TC0OUTACKTHRESHOLD 0x2045 +#define DL_TC1TXFCTHRESHOLD 0x2060 +#define DL_FC1PROTTIMEOUTVAL 0x2061 +#define DL_TC1REPLAYTIMEOUTVAL 0x2062 +#define DL_AFC1REQTIMEOUTVAL 0x2063 +#define DL_AFC1CREDITTHRESHOLD 0x2064 +#define DL_TC1OUTACKTHRESHOLD 0x2065 +#define DL_TXPREEMPTIONCAP 0x2000 +#define DL_TC0TXMAXSDUSIZE 0x2001 +#define DL_TC0RXINITCREDITVAL 0x2002 +#define DL_TC0TXBUFFERSIZE 0x2005 +#define DL_PEERTC0PRESENT 0x2046 +#define DL_PEERTC0RXINITCREVAL 0x2047 +#define DL_TC1TXMAXSDUSIZE 0x2003 +#define DL_TC1RXINITCREDITVAL 0x2004 +#define DL_TC1TXBUFFERSIZE 0x2006 +#define DL_PEERTC1PRESENT 0x2066 +#define DL_PEERTC1RXINITCREVAL 0x2067 + +/* + * Network Layer Attributes + */ +#define N_DEVICEID 0x3000 +#define N_DEVICEID_VALID 0x3001 +#define N_TC0TXMAXSDUSIZE 0x3020 +#define N_TC1TXMAXSDUSIZE 0x3021 + +/* + * Transport Layer Attributes + */ +#define T_NUMCPORTS 0x4000 +#define T_NUMTESTFEATURES 0x4001 +#define T_CONNECTIONSTATE 0x4020 +#define T_PEERDEVICEID 0x4021 +#define T_PEERCPORTID 0x4022 +#define T_TRAFFICCLASS 0x4023 +#define T_PROTOCOLID 0x4024 +#define T_CPORTFLAGS 0x4025 +#define T_TXTOKENVALUE 0x4026 +#define T_RXTOKENVALUE 0x4027 +#define T_LOCALBUFFERSPACE 0x4028 +#define T_PEERBUFFERSPACE 0x4029 +#define T_CREDITSTOSEND 0x402A +#define T_CPORTMODE 0x402B +#define T_TC0TXMAXSDUSIZE 0x4060 +#define T_TC1TXMAXSDUSIZE 0x4061 + +#ifdef FALSE +#undef FALSE +#endif + +#ifdef TRUE +#undef TRUE +#endif + +/* Boolean attribute values */ +enum { + FALSE = 0, + TRUE, +}; + +#endif /* _UNIPRO_H_ */ |