Loading drivers/scsi/ufs/ufs-qcom-debugfs.c +11 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015, Linux Foundation. All rights reserved. * Copyright (c) 2015,2017, 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 Loading Loading @@ -117,6 +117,9 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, int ret = 0; int major; int minor; unsigned long flags; struct ufs_hba *hba = host->hba; ret = simple_write_to_buffer(configuration, TESTBUS_CFG_BUFF_LINE_SIZE, &buff_pos, ubuf, cnt); Loading @@ -143,8 +146,15 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, goto out; } if (!ufs_qcom_testbus_cfg_is_ok(host, major, minor)) { ret = -EPERM; goto out; } spin_lock_irqsave(hba->host->host_lock, flags); host->testbus.select_major = (u8)major; host->testbus.select_minor = (u8)minor; spin_unlock_irqrestore(hba->host->host_lock, flags); /* * Sanity check of the {major, minor} tuple is done in the Loading drivers/scsi/ufs/ufs-qcom.c +24 −16 Original line number Diff line number Diff line Loading @@ -2466,12 +2466,13 @@ static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) host->testbus.select_minor = 37; } static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, u8 select_major, u8 select_minor) { if (host->testbus.select_major >= TSTBUS_MAX) { if (select_major >= TSTBUS_MAX) { dev_err(host->hba->dev, "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n", __func__, host->testbus.select_major); __func__, select_major); return false; } Loading @@ -2480,10 +2481,10 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) * mappings of select_minor, since there is no harm in * configuring a non-existent select_minor */ if (host->testbus.select_minor > 0xFF) { if (select_minor > 0xFF) { dev_err(host->hba->dev, "%s: 0x%05X is not a legal testbus option\n", __func__, host->testbus.select_minor); __func__, select_minor); return false; } Loading @@ -2497,16 +2498,16 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) */ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) { int reg; int offset; int reg = 0; int offset, ret = 0, testbus_sel_offset = 19; u32 mask = TEST_BUS_SUB_SEL_MASK; unsigned long flags; struct ufs_hba *hba; if (!host) return -EINVAL; if (!ufs_qcom_testbus_cfg_is_ok(host)) return -EPERM; hba = host->hba; spin_lock_irqsave(hba->host->host_lock, flags); switch (host->testbus.select_major) { case TSTBUS_UAWM: reg = UFS_TEST_BUS_CTRL_0; Loading Loading @@ -2565,20 +2566,27 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) } mask <<= offset; spin_unlock_irqrestore(hba->host->host_lock, flags); if (reg) { ufshcd_rmwl(host->hba, TEST_BUS_SEL, (u32)host->testbus.select_major << 19, (u32)host->testbus.select_major << testbus_sel_offset, REG_UFS_CFG1); ufshcd_rmwl(host->hba, mask, (u32)host->testbus.select_minor << offset, reg); } else { dev_err(hba->dev, "%s: Problem setting minor\n", __func__); ret = -EINVAL; goto out; } ufs_qcom_enable_test_bus(host); /* * Make sure the test bus configuration is * committed before returning. */ mb(); return 0; out: return ret; } static void ufs_qcom_testbus_read(struct ufs_hba *hba) Loading drivers/scsi/ufs/ufs-qcom.h +3 −1 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ enum { /* 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) #define TEST_BUS_SEL 0x780000 #define UFS_REG_TEST_BUS_EN BIT(30) /* bit definitions for REG_UFS_CFG2 register */ Loading Loading @@ -390,6 +390,8 @@ ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg) #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, u8 select_major, u8 select_minor); 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, Loading Loading
drivers/scsi/ufs/ufs-qcom-debugfs.c +11 −1 Original line number Diff line number Diff line /* * Copyright (c) 2015, Linux Foundation. All rights reserved. * Copyright (c) 2015,2017, 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 Loading Loading @@ -117,6 +117,9 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, int ret = 0; int major; int minor; unsigned long flags; struct ufs_hba *hba = host->hba; ret = simple_write_to_buffer(configuration, TESTBUS_CFG_BUFF_LINE_SIZE, &buff_pos, ubuf, cnt); Loading @@ -143,8 +146,15 @@ static ssize_t ufs_qcom_dbg_testbus_cfg_write(struct file *file, goto out; } if (!ufs_qcom_testbus_cfg_is_ok(host, major, minor)) { ret = -EPERM; goto out; } spin_lock_irqsave(hba->host->host_lock, flags); host->testbus.select_major = (u8)major; host->testbus.select_minor = (u8)minor; spin_unlock_irqrestore(hba->host->host_lock, flags); /* * Sanity check of the {major, minor} tuple is done in the Loading
drivers/scsi/ufs/ufs-qcom.c +24 −16 Original line number Diff line number Diff line Loading @@ -2466,12 +2466,13 @@ static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host) host->testbus.select_minor = 37; } static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, u8 select_major, u8 select_minor) { if (host->testbus.select_major >= TSTBUS_MAX) { if (select_major >= TSTBUS_MAX) { dev_err(host->hba->dev, "%s: UFS_CFG1[TEST_BUS_SEL} may not equal 0x%05X\n", __func__, host->testbus.select_major); __func__, select_major); return false; } Loading @@ -2480,10 +2481,10 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) * mappings of select_minor, since there is no harm in * configuring a non-existent select_minor */ if (host->testbus.select_minor > 0xFF) { if (select_minor > 0xFF) { dev_err(host->hba->dev, "%s: 0x%05X is not a legal testbus option\n", __func__, host->testbus.select_minor); __func__, select_minor); return false; } Loading @@ -2497,16 +2498,16 @@ static bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host) */ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) { int reg; int offset; int reg = 0; int offset, ret = 0, testbus_sel_offset = 19; u32 mask = TEST_BUS_SUB_SEL_MASK; unsigned long flags; struct ufs_hba *hba; if (!host) return -EINVAL; if (!ufs_qcom_testbus_cfg_is_ok(host)) return -EPERM; hba = host->hba; spin_lock_irqsave(hba->host->host_lock, flags); switch (host->testbus.select_major) { case TSTBUS_UAWM: reg = UFS_TEST_BUS_CTRL_0; Loading Loading @@ -2565,20 +2566,27 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host) } mask <<= offset; spin_unlock_irqrestore(hba->host->host_lock, flags); if (reg) { ufshcd_rmwl(host->hba, TEST_BUS_SEL, (u32)host->testbus.select_major << 19, (u32)host->testbus.select_major << testbus_sel_offset, REG_UFS_CFG1); ufshcd_rmwl(host->hba, mask, (u32)host->testbus.select_minor << offset, reg); } else { dev_err(hba->dev, "%s: Problem setting minor\n", __func__); ret = -EINVAL; goto out; } ufs_qcom_enable_test_bus(host); /* * Make sure the test bus configuration is * committed before returning. */ mb(); return 0; out: return ret; } static void ufs_qcom_testbus_read(struct ufs_hba *hba) Loading
drivers/scsi/ufs/ufs-qcom.h +3 −1 Original line number Diff line number Diff line Loading @@ -100,7 +100,7 @@ enum { /* 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) #define TEST_BUS_SEL 0x780000 #define UFS_REG_TEST_BUS_EN BIT(30) /* bit definitions for REG_UFS_CFG2 register */ Loading Loading @@ -390,6 +390,8 @@ ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg) #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, u8 select_major, u8 select_minor); 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, Loading