811 lines
25 KiB
C
811 lines
25 KiB
C
/*
|
|
* Samsung EXYNOS SoC series USB DRD PHY DebugFS file
|
|
*
|
|
* Phy provider for USB 3.0 DRD controller on Exynos SoC series
|
|
*
|
|
* Copyright (C) 2016 Samsung Electronics Co., Ltd.
|
|
* Author: Kyounghye Yun <k-hye.yun@samsung.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/io.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/ptrace.h>
|
|
#include <linux/types.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/device.h>
|
|
#include <linux/regmap.h>
|
|
|
|
#include <linux/usb/ch9.h>
|
|
#include "phy-exynos-usbdrd.h"
|
|
#include "phy-samsung-usb3-cal.h"
|
|
#include "phy-samsung-usb3-cal-combo.h"
|
|
#include "phy-exynos-debug.h"
|
|
|
|
struct exynos_debugfs_prvdata *prvdata;
|
|
static const struct debugfs_reg32 exynos_usb3drd_phycon_regs[] = {
|
|
dump_register(CTRLVER),
|
|
dump_register(LINKCTRL),
|
|
dump_register(PHYCON_LINKPORT),
|
|
dump_register(LINK_DEBUG_L),
|
|
dump_register(LINK_DEBUG_H),
|
|
dump_register(LTSTATE_HIS),
|
|
dump_register(CLKRSTCTRL),
|
|
dump_register(PWRCTL),
|
|
dump_register(SSPPLLCTL),
|
|
dump_register(SECPMACTL),
|
|
dump_register(UTMICTRL),
|
|
dump_register(HSPCTRL),
|
|
dump_register(HSPPARACON),
|
|
dump_register(HSPTEST),
|
|
dump_register(HSPPLLTUNE),
|
|
dump_register(REWA_CTRL),
|
|
dump_register(HSREWA_INTR),
|
|
dump_register(HSREWA_CTRL),
|
|
dump_register(HSREWA_REFTO),
|
|
dump_register(HSREWA_HSTK),
|
|
dump_register(HSREWA_CNT),
|
|
dump_register(HSREWA_INT1_EVNT),
|
|
dump_register(HSREWA_INT1_EVNT_MSK),
|
|
};
|
|
|
|
static const struct debugfs_reg32 exynos_usb3drd_regs[] = {
|
|
dump_register(LINKSYSTEM),
|
|
dump_register(PHYUTMI),
|
|
dump_register(PHYCLKRST),
|
|
dump_register(PHYREG0),
|
|
dump_register(PHYPARAM0),
|
|
dump_register(PHYPARAM1),
|
|
dump_register(PHYTEST),
|
|
dump_register(PHYRESUME),
|
|
dump_register(PHYPCSVAL),
|
|
dump_register(LINKPORT),
|
|
dump_register(PHYPARAM2),
|
|
};
|
|
|
|
static const struct debugfs_reg32 exynos_usb2drd_regs[] = {
|
|
dump_register(LINKSYSTEM),
|
|
dump_register(PHYUTMI),
|
|
dump_register(PHYCLKRST),
|
|
dump_register(PHYPARAM0),
|
|
dump_register(PHYPOWERDOWN),
|
|
dump_register(PHYRESUME),
|
|
dump_register(LINKPORT),
|
|
dump_register(HSPHYCTRL),
|
|
dump_register(HSPHYPLLTUNE),
|
|
};
|
|
|
|
/* PHY Control register set of SOC which combo phy is applied in */
|
|
static const struct debugfs_regmap32 exynos_usb3drd_phycon_regmap[] = {
|
|
dump_regmap_mask(CTRLVER, CTRL_VER, 0),
|
|
dump_regmap(LINKCTRL, FORCE_RXELECIDLE, 18),
|
|
dump_regmap(LINKCTRL, FORCE_PHYSTATUS, 17),
|
|
dump_regmap(LINKCTRL, FORCE_PIPE_EN, 16),
|
|
dump_regmap(LINKCTRL, DIS_BUSPEND_QACT, 13),
|
|
dump_regmap(LINKCTRL, DIS_LINKGATE_QACT, 12),
|
|
dump_regmap(LINKCTRL, DIS_ID0_QACT, 11),
|
|
dump_regmap(LINKCTRL, DIS_VBUSVALID_QACT, 10),
|
|
dump_regmap(LINKCTRL, DIS_BVALID_QACT, 9),
|
|
dump_regmap(LINKCTRL, FORCE_QACT, 8),
|
|
dump_regmap_mask(LINKCTRL, BUS_FILTER_BYPASS, 4),
|
|
dump_regmap(LINKCTRL, HOST_SYSTEM_ERR, 2),
|
|
dump_regmap(LINKCTRL, LINK_PME, 1),
|
|
dump_regmap(LINKCTRL, PME_GENERATION, 0),
|
|
dump_regmap_mask(PHYCON_LINKPORT, HOST_NUM_U3, 16),
|
|
dump_regmap_mask(PHYCON_LINKPORT, HOST_NUM_U2, 12),
|
|
dump_regmap(PHYCON_LINKPORT, HOST_U3_PORT_DISABLE, 9),
|
|
dump_regmap(PHYCON_LINKPORT, HOST_U2_PORT_DISABLE, 8),
|
|
dump_regmap(PHYCON_LINKPORT, HOST_PORT_POWER_CON_PRESENT, 6),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PORT_OVERCURRENT_U3, 5),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PORT_OVERCURRENT_U2, 4),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PORT_OVERCURRENT_SET_U3, 3),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PORT_OVERCURRENT_SET_U2, 2),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PERM_ATTACH_U3, 1),
|
|
dump_regmap(PHYCON_LINKPORT, HUB_PERM_ATTACH_U2, 0),
|
|
dump_regmap_mask(LINK_DEBUG_L, DEBUG_L, 0),
|
|
dump_regmap_mask(LINK_DEBUG_H, DEBUG_H, 0),
|
|
dump_regmap(LTSTATE_HIS, LINKTRN_DONE, 31),
|
|
dump_regmap_mask(LTSTATE_HIS, LTSTATE_HIS4, 16),
|
|
dump_regmap_mask(LTSTATE_HIS, LTSTATE_HIS3, 12),
|
|
dump_regmap_mask(LTSTATE_HIS, LTSTATE_HIS2, 8),
|
|
dump_regmap_mask(LTSTATE_HIS, LTSTATE_HIS1, 4),
|
|
dump_regmap_mask(LTSTATE_HIS, LTSTATE_HIS0, 0),
|
|
dump_regmap(CLKRSTCTRL, USBAUDIO_CLK_GATE_EN, 9),
|
|
dump_regmap(CLKRSTCTRL, USBAUDIO_CLK_SEL, 8),
|
|
dump_regmap(CLKRSTCTRL, LINK_PCLK_SEL, 7),
|
|
dump_regmap(CLKRSTCTRL, REFCLKSEL, 4),
|
|
dump_regmap(CLKRSTCTRL, PHY_SW_RST, 3),
|
|
dump_regmap(CLKRSTCTRL, PHY_RESET_SEL, 2),
|
|
dump_regmap(CLKRSTCTRL, PORTRESET, 1),
|
|
dump_regmap(CLKRSTCTRL, LINK_SW_RST, 0),
|
|
dump_regmap(PWRCTL, FORCE_POWERDOWN, 2),
|
|
dump_regmap_mask(SSPPLLCTL, FSEL, 0),
|
|
dump_regmap_mask(SECPMACTL, PMA_PLL_REF_CLK_SEL, 10),
|
|
dump_regmap_mask(SECPMACTL, PMA_REF_FREQ_SEL, 8),
|
|
dump_regmap(SECPMACTL, PMA_LOW_PWR, 4),
|
|
dump_regmap(SECPMACTL, PMA_TRSV_SW_RST, 3),
|
|
dump_regmap(SECPMACTL, PMA_CMN_SW_RST, 2),
|
|
dump_regmap(SECPMACTL, PMA_INIT_SW_RST, 1),
|
|
dump_regmap(SECPMACTL, PMA_APB_SW_RST, 0),
|
|
dump_regmap(UTMICTRL, OPMODE_EN, 8),
|
|
dump_regmap_mask(UTMICTRL, FORCE_OPMODE, 6),
|
|
dump_regmap(UTMICTRL, FORCE_VBUSVALID, 5),
|
|
dump_regmap(UTMICTRL, FORCE_BVALID, 4),
|
|
dump_regmap(UTMICTRL, FORCE_DPPULLDOWN, 3),
|
|
dump_regmap(UTMICTRL, FORCE_DMPULLDOWN, 2),
|
|
dump_regmap(UTMICTRL, FORCE_SUSPEND, 1),
|
|
dump_regmap(UTMICTRL, FORCE_SLEEP, 0),
|
|
dump_regmap(HSPCTRL, AUTORSM_ENB, 29),
|
|
dump_regmap(HSPCTRL, RETENABLE_EN, 28),
|
|
dump_regmap(HSPCTRL, FSLS_SPEED_SEL, 25),
|
|
dump_regmap(HSPCTRL, FSV_OUT_EN, 24),
|
|
dump_regmap(HSPCTRL, HS_XCVR_EXT_CTL, 22),
|
|
dump_regmap(HSPCTRL, HS_RXDAT, 21),
|
|
dump_regmap(HSPCTRL, HS_SQUELCH, 20),
|
|
dump_regmap(HSPCTRL, FSVMINUS, 17),
|
|
dump_regmap(HSPCTRL, FSVPLUS, 16),
|
|
dump_regmap(HSPCTRL, VBUSVLDEXTSEL, 13),
|
|
dump_regmap(HSPCTRL, VBUSVLDEXT, 12),
|
|
dump_regmap(HSPCTRL, EN_UTMISUSPEND, 9),
|
|
dump_regmap(HSPCTRL, COMMONONN, 8),
|
|
dump_regmap(HSPCTRL, VATESTENB, 6),
|
|
dump_regmap(HSPCTRL, CHGDET, 5),
|
|
dump_regmap(HSPCTRL, VDATSRCENB, 4),
|
|
dump_regmap(HSPCTRL, VDATDETENB, 3),
|
|
dump_regmap(HSPCTRL, CHRGSEL, 2),
|
|
dump_regmap(HSPCTRL, ACAENB, 1),
|
|
dump_regmap(HSPCTRL, DEDENB, 0),
|
|
dump_regmap_mask(HSPPARACON, TXVREFTUNE, 28),
|
|
dump_regmap_mask(HSPPARACON, TXRISETUNE, 24),
|
|
dump_regmap_mask(HSPPARACON, TXRESTUNE, 21),
|
|
dump_regmap(HSPPARACON, TXPREEMPPULSETUNE, 20),
|
|
dump_regmap_mask(HSPPARACON, TXPREEMPAMPTUNE, 18),
|
|
dump_regmap_mask(HSPPARACON, TXHSXVTUNE, 16),
|
|
dump_regmap_mask(HSPPARACON, TXFSLSTUNE, 12),
|
|
dump_regmap_mask(HSPPARACON, SQRXTUNE, 8),
|
|
dump_regmap_mask(HSPPARACON, OTGTUNE, 4),
|
|
dump_regmap_mask(HSPPARACON, COMPDISTUNE, 0),
|
|
dump_regmap(HSPTEST, SIDDQ_PORT0, 24),
|
|
dump_regmap_mask(HSPTEST, LINESTATE_PORT0, 20),
|
|
dump_regmap_mask(HSPTEST, TESTDATAOUT_PORT0, 16),
|
|
dump_regmap(HSPTEST, TESTCLK_PORT0, 13),
|
|
dump_regmap(HSPTEST, TESTDATAOUTSEL_PORT0, 12),
|
|
dump_regmap_mask(HSPTEST, TESTADDR_PORT0, 8),
|
|
dump_regmap_mask(HSPTEST, TESTDATAIN_PORT0, 0),
|
|
dump_regmap(HSPPLLTUNE, PLLBTUNE, 8),
|
|
dump_regmap_mask(HSPPLLTUNE, PLLITUNE, 4),
|
|
dump_regmap_mask(HSPPLLTUNE, PLLPTUNE, 0),
|
|
dump_regmap(REWA_CTRL, HSREWA_EN, 0),
|
|
dump_regmap_mask(HSREWA_INTR, WAKEUP_MASK, 12),
|
|
dump_regmap_mask(HSREWA_INTR, TIMEOUT_INTR_MASK, 8),
|
|
dump_regmap_mask(HSREWA_INTR, EVENT_INT_MASK, 4),
|
|
dump_regmap_mask(HSREWA_INTR, WAKEUP_INTR_MASK, 0),
|
|
dump_regmap(HSREWA_CTRL, DIG_BYPASS_CON_EN, 28),
|
|
dump_regmap(HSREWA_CTRL, DPDM_MONITOR_SEL, 24),
|
|
dump_regmap(HSREWA_CTRL, HS_LINK_READY, 20),
|
|
dump_regmap(HSREWA_CTRL, HS_SYS_VALID, 16),
|
|
dump_regmap(HSREWA_CTRL, HS_REWA_ERROR, 4),
|
|
dump_regmap(HSREWA_CTRL, HS_REWA_DONE, 0),
|
|
dump_regmap_mask(HSREWA_REFTO, HOST_K_TIMEOUT, 0),
|
|
dump_regmap_mask(HSREWA_HSTK, HOST_K_DELAY, 0),
|
|
dump_regmap_mask(HSREWA_CNT, WAKEUP_CNT, 0),
|
|
dump_regmap(HSREWA_INT1_EVNT, ERR_SUS, 18),
|
|
dump_regmap(HSREWA_INT1_EVNT, ERR_DEV_K, 17),
|
|
dump_regmap(HSREWA_INT1_EVNT, DISCON, 16),
|
|
dump_regmap(HSREWA_INT1_EVNT, BYPASS_DIS, 2),
|
|
dump_regmap(HSREWA_INT1_EVNT, RET_DIS, 1),
|
|
dump_regmap(HSREWA_INT1_EVNT, RET_EN, 0),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, ERR_SUS_MASK, 18),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, ERR_DEV_K_MASK, 17),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, DISCON_MASK, 16),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, BYPASS_DIS_MASK, 2),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, RET_DIS_MASK, 1),
|
|
dump_regmap(HSREWA_INT1_EVNT_MSK, RET_EN_MASK, 0),
|
|
};
|
|
|
|
static const struct debugfs_regmap32 exynos_usb2drd_regmap[] = {
|
|
dump_regmap(LINKSYSTEM, HOST_SYSTEM_ERR, 31),
|
|
dump_regmap(LINKSYSTEM, PHY_POWER_DOWN, 30),
|
|
dump_regmap(LINKSYSTEM, PHY_SW_RESET, 29),
|
|
dump_regmap(LINKSYSTEM, LINK_SW_RESET, 28),
|
|
dump_regmap(LINKSYSTEM, XHCI_VERSION_CONTROL, 27),
|
|
dump_regmap(LINKSYSTEM, FORCE_VBUSVALID, 8),
|
|
dump_regmap(LINKSYSTEM, FORCE_BVALID, 7),
|
|
dump_regmap_mask(LINKSYSTEM, FLADJ, 1),
|
|
dump_regmap(PHYUTMI, UTMI_SUSPEND_COM_N, 12),
|
|
dump_regmap(PHYUTMI, UTMI_L1_SUSPEND_COM_N, 11),
|
|
dump_regmap(PHYUTMI, VBUSVLDEXTSEL, 10),
|
|
dump_regmap(PHYUTMI, VBUSVLDEXT, 9),
|
|
dump_regmap(PHYUTMI, TXBITSTUFFENH, 8),
|
|
dump_regmap(PHYUTMI, TXBITSTUFFEN, 7),
|
|
dump_regmap(PHYUTMI, OTGDISABLE, 6),
|
|
dump_regmap(PHYUTMI, IDPULLUP, 5),
|
|
dump_regmap(PHYUTMI, DRVVBUS, 4),
|
|
dump_regmap(PHYUTMI, DPPULLDOWN, 3),
|
|
dump_regmap(PHYUTMI, DMPULLDOWN, 2),
|
|
dump_regmap(PHYUTMI, FORCESUSPEND, 1),
|
|
dump_regmap(PHYUTMI, FORCESLEEP, 0),
|
|
dump_regmap(PHYCLKRST, EN_UTMISUSPEND, 31),
|
|
dump_regmap_mask(PHYCLKRST, SSC_REFCLKSEL, 23),
|
|
dump_regmap_mask(PHYCLKRST, SSC_RANGE, 21),
|
|
dump_regmap(PHYCLKRST, SSC_EN, 20),
|
|
dump_regmap(PHYCLKRST, REF_SSP_EN, 19),
|
|
dump_regmap(PHYCLKRST, REF_CLKDIV2, 18),
|
|
dump_regmap_mask(PHYCLKRST, MPLL_MULTIPLIER, 11),
|
|
dump_regmap_mask(PHYCLKRST, FSEL, 5),
|
|
dump_regmap(PHYCLKRST, RETENABLEN, 4),
|
|
dump_regmap_mask(PHYCLKRST, REFCLKSEL, 2),
|
|
dump_regmap(PHYCLKRST, PORTRESET, 1),
|
|
dump_regmap(PHYCLKRST, COMMONONN, 0),
|
|
dump_regmap_mask(PHYPARAM0, TXVREFTUNE, 22),
|
|
dump_regmap_mask(PHYPARAM0, TXRISETUNE, 20),
|
|
dump_regmap_mask(PHYPARAM0, TXRESTUNE, 18),
|
|
dump_regmap(PHYPARAM0, TXPREEMPPULSETUNE, 17),
|
|
dump_regmap_mask(PHYPARAM0, TXPREEMPAMPTUNE, 15),
|
|
dump_regmap_mask(PHYPARAM0, TXHSXVTUNE, 13),
|
|
dump_regmap_mask(PHYPARAM0, TXFSLSTUNE, 9),
|
|
dump_regmap_mask(PHYPARAM0, SQRXTUNE, 6),
|
|
dump_regmap_mask(PHYPARAM0, OTGTUNE, 3),
|
|
dump_regmap_mask(PHYPARAM0, COMPDISTUNE, 0),
|
|
dump_regmap(PHYPOWERDOWN, VATESTENB, 6),
|
|
dump_regmap_mask(PHYPOWERDOWN, TEST_BURNIN, 4),
|
|
dump_regmap(PHYRESUME, BYPASS_SEL, 4),
|
|
dump_regmap(PHYRESUME, BYPASS_DM_EN, 3),
|
|
dump_regmap(PHYRESUME, BYPASS_DP_EN, 2),
|
|
dump_regmap(PHYRESUME, BYPASS_DM_DATA, 1),
|
|
dump_regmap(PHYRESUME, BYPASS_DP_DATA, 0),
|
|
dump_regmap_mask(LINKPORT, HOST_NUM_U2_PORT, 9),
|
|
dump_regmap(LINKPORT, HOST_U2_PORT_DISABLE, 7),
|
|
dump_regmap(LINKPORT, PORT_POWER_CONTROL, 6),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U2, 4),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U2_SEL, 2),
|
|
dump_regmap(LINKPORT, PERM_ATTACH_U2, 0),
|
|
dump_regmap(HSPHYCTRL, PHYSWRSTALL, 31),
|
|
dump_regmap(HSPHYCTRL, SIDDQ, 6),
|
|
dump_regmap(HSPHYCTRL, PHYSWRST, 0),
|
|
dump_regmap(HSPHYPLLTUNE, PLL_B_TUNE, 6),
|
|
dump_regmap_mask(HSPHYPLLTUNE, PLL_I_TUNE, 4),
|
|
dump_regmap_mask(HSPHYPLLTUNE, PLL_P_TUNE, 0),
|
|
};
|
|
|
|
static const struct debugfs_regmap32 exynos_usb3drd_regmap[] = {
|
|
dump_regmap(LINKSYSTEM, HOST_SYSTEM_ERR, 31),
|
|
dump_regmap(LINKSYSTEM, PHY_POWER_DOWN, 30),
|
|
dump_regmap(LINKSYSTEM, XHCI_VERSION_CONTROL, 27),
|
|
dump_regmap(LINKSYSTEM, FORCE_VBUSVALID, 8),
|
|
dump_regmap(LINKSYSTEM, FORCE_BVALID, 7),
|
|
dump_regmap_mask(LINKSYSTEM, FLADJ, 1),
|
|
dump_regmap(PHYUTMI, VBUSVLDEXTSEL, 10),
|
|
dump_regmap(PHYUTMI, VBUSVLDEXT, 9),
|
|
dump_regmap(PHYUTMI, TXBITSTUFFENH, 8),
|
|
dump_regmap(PHYUTMI, TXBITSTUFFEN, 7),
|
|
dump_regmap(PHYUTMI, OTGDISABLE, 6),
|
|
dump_regmap(PHYUTMI, IDPULLUP, 5),
|
|
dump_regmap(PHYUTMI, DRVVBUS, 4),
|
|
dump_regmap(PHYUTMI, DPPULLDOWN, 3),
|
|
dump_regmap(PHYUTMI, DMPULLDOWN, 2),
|
|
dump_regmap(PHYUTMI, FORCESUSPEND, 1),
|
|
dump_regmap(PHYUTMI, FORCESLEEP, 0),
|
|
dump_regmap(PHYPIPE, PHY_CLOCK_SEL, 4),
|
|
dump_regmap(PHYCLKRST, EN_UTMISUSPEND, 31),
|
|
dump_regmap(PHYCLKRST, SSC_EN, 20),
|
|
dump_regmap(PHYCLKRST, REF_SSP_EN, 19),
|
|
dump_regmap(PHYCLKRST, REF_CLKDIV2, 18),
|
|
dump_regmap_mask(PHYCLKRST, MPLL_MULTIPLIER, 11),
|
|
dump_regmap_mask(PHYCLKRST, FSEL, 5),
|
|
dump_regmap(PHYCLKRST, RETENABLEN, 4),
|
|
dump_regmap_mask(PHYCLKRST, REFCLKSEL, 2),
|
|
dump_regmap(PHYCLKRST, PORTRESET, 1),
|
|
dump_regmap(PHYCLKRST, COMMONONN, 0),
|
|
dump_regmap_mask(PHYREG0, SSC_REFCLKSEL, 23),
|
|
dump_regmap_mask(PHYREG0, SSC_RANGE, 20),
|
|
dump_regmap(PHYPARAM0, REF_USE_PAD, 31),
|
|
dump_regmap_mask(PHYPARAM0, REF_LOSLEVEL, 26),
|
|
dump_regmap_mask(PHYPARAM0, TXVREFTUNE, 22),
|
|
dump_regmap_mask(PHYPARAM0, TXRISETUNE, 20),
|
|
dump_regmap_mask(PHYPARAM0, TXRESTUNE, 18),
|
|
dump_regmap(PHYPARAM0, TXPREEMPPULSETUNE, 17),
|
|
dump_regmap_mask(PHYPARAM0, TXPREEMPAMPTUNE, 15),
|
|
dump_regmap_mask(PHYPARAM0, TXHSXVTUNE, 13),
|
|
dump_regmap_mask(PHYPARAM0, TXFSLSTUNE, 9),
|
|
dump_regmap_mask(PHYPARAM0, SQRXTUNE, 6),
|
|
dump_regmap_mask(PHYPARAM0, OTGTUNE, 3),
|
|
dump_regmap_mask(PHYPARAM0, COMPDISTUNE, 0),
|
|
dump_regmap_mask(PHYPARAM1, TX0_TERM_OFFSET, 26),
|
|
dump_regmap_mask(PHYPARAM1, PCS_TXSWING_FULL, 12),
|
|
dump_regmap_mask(PHYPARAM1, PCS_TXDEEMPH_3P5DB, 0),
|
|
dump_regmap(PHYTEST, POWERDOWN_SSP, 3),
|
|
dump_regmap(PHYTEST, POWERDOWN_HSP, 2),
|
|
dump_regmap(PHYRESUME, BYPASS_SEL, 4),
|
|
dump_regmap(PHYRESUME, BYPASS_DM_EN, 3),
|
|
dump_regmap(PHYRESUME, BYPASS_DP_EN, 2),
|
|
dump_regmap(PHYRESUME, BYPASS_DM_DATA, 1),
|
|
dump_regmap(PHYRESUME, BYPASS_DP_DATA, 0),
|
|
dump_regmap_mask(PHYPCSVAL, PCS_RX_LOS_MASK_VAL, 0),
|
|
dump_regmap_mask(LINKPORT, HOST_NUM_U3_PORT, 13),
|
|
dump_regmap_mask(LINKPORT, HOST_NUM_U2_PORT, 9),
|
|
dump_regmap(LINKPORT, HOST_U3_PORT_DISABLE, 8),
|
|
dump_regmap(LINKPORT, HOST_U2_PORT_DISABLE, 7),
|
|
dump_regmap(LINKPORT, PORT_POWER_CONTROL, 6),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U3, 5),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U2, 4),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U3_SEL, 3),
|
|
dump_regmap(LINKPORT, HOST_PORT_OVCR_U2_SEL, 2),
|
|
dump_regmap(LINKPORT, PERM_ATTACH_U2, 0),
|
|
dump_regmap_mask(PHYPARAM2, TX_VBOOST_LVL, 3),
|
|
dump_regmap_mask(PHYPARAM2, LOS_BIAS, 0),
|
|
};
|
|
|
|
int debugfs_phy_power_state(struct exynos_usbdrd_phy *phy_drd, int phy_index)
|
|
{
|
|
struct regmap *reg_pmu;
|
|
u32 pmu_offset;
|
|
int phy_on;
|
|
int ret;
|
|
|
|
reg_pmu = phy_drd->phys[phy_index].reg_pmu;
|
|
pmu_offset = phy_drd->phys[phy_index].pmu_offset;
|
|
ret = regmap_read(reg_pmu, pmu_offset, &phy_on);
|
|
if (ret) {
|
|
dev_err(phy_drd->dev, "Can't read 0x%x\n", pmu_offset);
|
|
return ret;
|
|
}
|
|
phy_on &= phy_drd->phys[phy_index].pmu_mask;
|
|
|
|
return phy_on;
|
|
}
|
|
|
|
int debugfs_print_regmap(struct seq_file *s, const struct debugfs_regmap32 *regs,
|
|
int nregs, void __iomem *base,
|
|
const struct debugfs_reg32 *parent)
|
|
{
|
|
int i, j= 0;
|
|
int bit = 0;
|
|
unsigned int bitmask;
|
|
int max_string = 24;
|
|
int calc_tab;
|
|
u32 bit_value, reg_value;
|
|
|
|
reg_value = readl(base + parent->offset);
|
|
seq_printf(s, "%s (0x%04lx) : 0x%08x\n", parent->name,
|
|
parent->offset, reg_value);
|
|
for (i = 0; i < nregs; i++, regs++) {
|
|
if (!strcmp(regs->name, parent->name)) {
|
|
bit_value = (reg_value & regs->bitmask) >> regs->bitoffset;
|
|
|
|
seq_printf(s, "\t%s", regs->bitname);
|
|
calc_tab = max_string/8 - strlen(regs->bitname)/8;
|
|
for (j = 0 ; j < calc_tab; j++)
|
|
seq_printf(s, "\t");
|
|
|
|
if (regs->mask) {
|
|
bitmask = regs->bitmask;
|
|
bitmask = bitmask >> regs->bitoffset;
|
|
while (bitmask) {
|
|
bitmask = bitmask >> 1;
|
|
bit++;
|
|
}
|
|
seq_printf(s, "[%d:%d]\t: 0x%x\n", (int)regs->bitoffset,
|
|
((int)regs->bitoffset + bit - 1), bit_value);
|
|
bit = 0;
|
|
} else {
|
|
seq_printf(s, "[%d]\t: 0x%x\n", (int)regs->bitoffset,
|
|
bit_value);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int debugfs_show_regmap(struct seq_file *s, void *data)
|
|
{
|
|
struct exynos_debugfs_prvdata *prvdata = s->private;
|
|
struct debugfs_regset_map *regmap = prvdata->regmap;
|
|
struct debugfs_regset32 *regset = prvdata->regset;
|
|
const struct debugfs_reg32 *regs = regset->regs;
|
|
int phy_on, i = 0;
|
|
|
|
phy_on = debugfs_phy_power_state(prvdata->phy_drd, 0);
|
|
if (phy_on < 0) {
|
|
seq_printf(s, "can't read PHY register, error : %d\n", phy_on);
|
|
return -ENODEV;
|
|
}
|
|
if (!phy_on) {
|
|
seq_printf(s, "can't get PHY register, PHY:%d : Power OFF\n", i);
|
|
return -ENODEV;
|
|
}
|
|
for (i = 0; i < regset->nregs; i++, regs++) {
|
|
debugfs_print_regmap(s, regmap->regs, regmap->nregs,
|
|
regset->base, regs);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int debugfs_open_regmap(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, debugfs_show_regmap, inode->i_private);
|
|
}
|
|
|
|
static const struct file_operations fops_regmap = {
|
|
.open = debugfs_open_regmap,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
int debugfs_print_regdump(struct seq_file *s, struct exynos_usbdrd_phy *phy_drd,
|
|
const struct debugfs_reg32 *regs, int nregs,
|
|
void __iomem *base)
|
|
{
|
|
int phy_on;
|
|
int i;
|
|
|
|
for (i = 0; i < EXYNOS_DRDPHYS_NUM; i++) {
|
|
phy_on = debugfs_phy_power_state(phy_drd, i);
|
|
if (phy_on < 0) {
|
|
seq_printf(s, "can't read PHY register, error : %d \n", phy_on);
|
|
return phy_on;
|
|
}
|
|
if (!phy_on) {
|
|
seq_printf(s, "can't get PHY register, PHY%d : Power OFF\n", i);
|
|
continue;
|
|
}
|
|
|
|
for (i = 0; i < nregs; i++, regs++) {
|
|
seq_printf(s, "%s", regs->name);
|
|
if (strlen(regs->name) < 8)
|
|
seq_printf(s, "\t\t");
|
|
else
|
|
seq_printf(s, "\t");
|
|
|
|
seq_printf(s, "= 0x%08x\n", readl(base + regs->offset));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
static int debugfs_show_regdump(struct seq_file *s, void *data)
|
|
{
|
|
struct exynos_debugfs_prvdata *prvdata = s->private;
|
|
struct debugfs_regset32 *regset = prvdata->regset;
|
|
int ret;
|
|
|
|
ret = debugfs_print_regdump(s, prvdata->phy_drd, regset->regs,
|
|
regset->nregs, regset->base);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int debugfs_open_regdump(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, debugfs_show_regdump, inode->i_private);
|
|
}
|
|
|
|
static const struct file_operations fops_regdump = {
|
|
.open = debugfs_open_regdump,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
static int debugfs_show_bitset(struct seq_file *s, void *data)
|
|
{
|
|
char *b_name = s->private;
|
|
struct debugfs_regset_map *regmap = prvdata->regmap;
|
|
const struct debugfs_regmap32 *cmp = regmap->regs;
|
|
const struct debugfs_regmap32 *regs = NULL;
|
|
unsigned int bitmask;
|
|
int i, bit = 0;
|
|
u32 reg_value, bit_value;
|
|
|
|
for (i = 0; i < regmap->nregs; i++, cmp++) {
|
|
if (!strcmp(cmp->bitname, b_name)) {
|
|
regs = cmp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!regs) {
|
|
seq_printf(s, "%s, regs is NULL\n", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
reg_value = readl(prvdata->regset->base + regs->offset);
|
|
bit_value = (reg_value & regs->bitmask) >> regs->bitoffset;
|
|
if (regs->mask) {
|
|
bitmask = regs->bitmask;
|
|
bitmask = bitmask >> regs->bitoffset;
|
|
while (bitmask) {
|
|
bitmask = bitmask >> 1;
|
|
bit++;
|
|
}
|
|
seq_printf(s, "%s [%d:%d] = 0x%x\n", regs->name,
|
|
(int)regs->bitoffset,
|
|
((int)regs->bitoffset + bit - 1), bit_value);
|
|
} else {
|
|
seq_printf(s, "%s [%d] = 0x%x\n", regs->name,
|
|
(int)regs->bitoffset, bit_value);
|
|
}
|
|
return 0;
|
|
}
|
|
static ssize_t debugfs_write_regset(struct file *file,
|
|
const char __user *ubuf, size_t count, loff_t *ppos)
|
|
{
|
|
struct seq_file *s = file->private_data;
|
|
char *reg_name = s->private;
|
|
struct debugfs_regset32 *regset = prvdata->regset;
|
|
const struct debugfs_reg32 *regs = regset->regs;
|
|
unsigned long value;
|
|
char buf[8];
|
|
int i;
|
|
|
|
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
|
return -EFAULT;
|
|
|
|
value = simple_strtol(buf, NULL, 16);
|
|
|
|
for (i = 0; i < regset->nregs; i++, regs++) {
|
|
if (!strcmp(regs->name, reg_name))
|
|
break;
|
|
}
|
|
|
|
writel(value, regset->base + regs->offset);
|
|
|
|
return count;
|
|
}
|
|
static ssize_t debugfs_write_bitset(struct file *file,
|
|
const char __user *ubuf, size_t count, loff_t *ppos)
|
|
{
|
|
struct seq_file *s = file->private_data;
|
|
char *b_name = s->private;
|
|
struct debugfs_regset_map *regmap = prvdata->regmap;
|
|
const struct debugfs_regmap32 *regs = regmap->regs;
|
|
unsigned long value;
|
|
char buf[32];
|
|
int i;
|
|
u32 reg_value;
|
|
|
|
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) {
|
|
seq_printf(s, "%s, write error \n", __func__);
|
|
return -EFAULT;
|
|
}
|
|
value = simple_strtol(buf, NULL, 2);
|
|
|
|
for (i = 0; i < regmap->nregs; i++, regs++) {
|
|
if (!strcmp(regs->bitname, b_name))
|
|
break;
|
|
}
|
|
|
|
value = value << regs->bitoffset;
|
|
reg_value = readl(prvdata->regset->base + regs->offset);
|
|
reg_value &= ~(regs->bitmask);
|
|
reg_value |= value;
|
|
writel(reg_value, prvdata->regset->base + regs->offset);
|
|
|
|
return count;
|
|
}
|
|
|
|
static int debugfs_open_bitset(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, debugfs_show_bitset, inode->i_private);
|
|
}
|
|
|
|
static int debugfs_show_regset(struct seq_file *s, void *data)
|
|
{
|
|
char *p_name = s->private;
|
|
struct debugfs_regset32 *regset = prvdata->regset;
|
|
struct debugfs_regset_map *regmap = prvdata->regmap;
|
|
const struct debugfs_reg32 *regs = regset->regs;
|
|
const struct debugfs_reg32 *parents = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < regset->nregs; i++, regs++) {
|
|
if (!strcmp(regs->name, p_name)) {
|
|
parents = regs;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!parents) {
|
|
seq_printf(s, "%s, parent is NULL\n", __func__);
|
|
return -EFAULT;
|
|
}
|
|
|
|
debugfs_print_regmap(s, prvdata->regmap->regs, regmap->nregs,
|
|
regset->base, parents);
|
|
return 0;
|
|
}
|
|
|
|
static int debugfs_open_regset(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, debugfs_show_regset, inode->i_private);
|
|
}
|
|
|
|
static const struct file_operations fops_regset = {
|
|
.open = debugfs_open_regset,
|
|
.write = debugfs_write_regset,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
static const struct file_operations fops_bitset = {
|
|
.open = debugfs_open_bitset,
|
|
.write = debugfs_write_bitset,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
static int debugfs_create_regfile(struct exynos_debugfs_prvdata *prvdata,
|
|
const struct debugfs_reg32 *parents,
|
|
struct dentry *root)
|
|
{
|
|
struct debugfs_regset_map *regmap = prvdata->regmap;
|
|
const struct debugfs_regmap32 *regs = regmap->regs;
|
|
struct dentry *file;
|
|
int i, ret;
|
|
|
|
file = debugfs_create_file(parents->name, S_IRUGO | S_IWUGO, root,
|
|
parents->name, &fops_regset);
|
|
if (!file) {
|
|
ret = -ENOMEM;
|
|
return ret;
|
|
}
|
|
for (i = 0; i < regmap->nregs; i++, regs++) {
|
|
if (!strcmp(regs->name, parents->name)) {
|
|
file = debugfs_create_file(regs->bitname, S_IRUGO | S_IWUGO,
|
|
root, regs->bitname, &fops_bitset);
|
|
if (!file) {
|
|
ret = -ENOMEM;
|
|
return ret;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int debugfs_create_regdir(struct exynos_debugfs_prvdata *prvdata,
|
|
struct dentry *root)
|
|
{
|
|
struct exynos_usbdrd_phy *phy_drd = prvdata->phy_drd;
|
|
struct debugfs_regset32 *regset = prvdata->regset;
|
|
const struct debugfs_reg32 *regs = regset->regs;
|
|
struct dentry *dir;
|
|
int ret, i;
|
|
|
|
for (i = 0; i < regset->nregs; i++, regs++) {
|
|
dir = debugfs_create_dir(regs->name, root);
|
|
if (!dir) {
|
|
dev_err(phy_drd->dev, "failed to create '%s' reg dir",
|
|
regs->name);
|
|
return -ENOMEM;
|
|
}
|
|
ret = debugfs_create_regfile(prvdata, regs, dir);
|
|
if (ret < 0) {
|
|
dev_err(phy_drd->dev, "failed to create bitfile for %s, error : %d\n",
|
|
regs->name, ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
int exynos_usbdrd_debugfs_init(struct exynos_usbdrd_phy *phy_drd)
|
|
{
|
|
struct device *dev = phy_drd->dev;
|
|
struct dentry *root;
|
|
struct dentry *dir;
|
|
struct dentry *file;
|
|
u32 version = phy_drd->usbphy_info.version;
|
|
int ret;
|
|
|
|
|
|
root = debugfs_create_dir(dev_name(dev), NULL);
|
|
if (!root) {
|
|
dev_err(dev, "failed to create root directory for USBPHY debugfs");
|
|
ret = -ENOMEM;
|
|
goto err0;
|
|
}
|
|
|
|
prvdata = devm_kmalloc(dev, sizeof(struct exynos_debugfs_prvdata), GFP_KERNEL);
|
|
if (!prvdata) {
|
|
dev_err(dev, "failed to alloc private data for debugfs");
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
prvdata->root = root;
|
|
prvdata->phy_drd = phy_drd;
|
|
|
|
prvdata->regset = devm_kmalloc(dev, sizeof(*prvdata->regset), GFP_KERNEL);
|
|
if (!prvdata->regset) {
|
|
dev_err(dev, "failed to alloc regmap");
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
|
|
if ((version >= EXYNOS_USBCON_VER_02_0_0) &&
|
|
(version <= EXYNOS_USBCON_VER_02_MAX)) {
|
|
/* for USB2PHY */
|
|
prvdata->regset->regs = exynos_usb2drd_regs;
|
|
prvdata->regset->nregs = ARRAY_SIZE(exynos_usb2drd_regs);
|
|
} else if ((version >= EXYNOS_USBCON_VER_03_0_0) &&
|
|
(version <= EXYNOS_USBCON_VER_03_MAX)) {
|
|
prvdata->regset->regs = exynos_usb3drd_phycon_regs;
|
|
prvdata->regset->nregs = ARRAY_SIZE(exynos_usb3drd_phycon_regs);
|
|
} else {
|
|
/* for USB3PHY */
|
|
prvdata->regset->regs = exynos_usb3drd_regs;
|
|
prvdata->regset->nregs = ARRAY_SIZE(exynos_usb3drd_regs);
|
|
}
|
|
prvdata->regset->base = phy_drd->reg_phy;
|
|
|
|
prvdata->regmap = devm_kmalloc(dev, sizeof(*prvdata->regmap), GFP_KERNEL);
|
|
if (!prvdata->regmap) {
|
|
dev_err(dev, "failed to alloc regmap");
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
|
|
if ((version >= EXYNOS_USBCON_VER_02_0_0) &&
|
|
/* for USB2PHY */
|
|
(version <= EXYNOS_USBCON_VER_02_MAX)) {
|
|
prvdata->regmap->regs = exynos_usb2drd_regmap;
|
|
prvdata->regmap->nregs = ARRAY_SIZE(exynos_usb2drd_regmap);
|
|
} else if ((version >= EXYNOS_USBCON_VER_03_0_0) &&
|
|
(version <= EXYNOS_USBCON_VER_03_MAX)) {
|
|
prvdata->regmap->regs = exynos_usb3drd_phycon_regmap;
|
|
prvdata->regmap->nregs = ARRAY_SIZE(exynos_usb3drd_phycon_regmap);
|
|
} else {
|
|
/* for USB3PHY */
|
|
prvdata->regmap->regs = exynos_usb3drd_regmap;
|
|
prvdata->regmap->nregs = ARRAY_SIZE(exynos_usb3drd_regmap);
|
|
}
|
|
|
|
file = debugfs_create_file("regdump", S_IRUGO, root, prvdata, &fops_regdump);
|
|
if (!file) {
|
|
dev_err(dev, "failed to create file for register dump");
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
|
|
file = debugfs_create_file("regmap", S_IRUGO, root, prvdata, &fops_regmap);
|
|
if (!file) {
|
|
dev_err(dev, "failed to create file for register dump");
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
|
|
dir = debugfs_create_dir("regset", root);
|
|
if (!dir) {
|
|
ret = -ENOMEM;
|
|
goto err1;
|
|
}
|
|
|
|
ret = debugfs_create_regdir(prvdata, dir);
|
|
if (ret < 0) {
|
|
dev_err(dev, "failed to create regfile, error = %d\n", ret);
|
|
goto err1;
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
|
err1:
|
|
debugfs_remove_recursive(root);
|
|
err0:
|
|
return ret;
|
|
}
|