2019-05-29 07:17:56 -07:00
// SPDX-License-Identifier: GPL-2.0-only
2017-09-22 15:34:01 -04:00
/*
* phy - brcm - usb - init . c - Broadcom USB Phy chip specific init functions
*
* Copyright ( C ) 2014 - 2017 Broadcom
*/
/*
* This module contains USB PHY initialization for power up and S3 resume
*/
# include <linux/delay.h>
# include <linux/io.h>
# include <linux/soc/brcmstb/brcmstb.h>
# include "phy-brcm-usb-init.h"
# define PHY_PORTS 2
# define PHY_PORT_SELECT_0 0
# define PHY_PORT_SELECT_1 0x1000
/* Register definitions for the USB CTRL block */
# define USB_CTRL_SETUP 0x00
# define USB_CTRL_SETUP_IOC_MASK 0x00000010
# define USB_CTRL_SETUP_IPP_MASK 0x00000020
# define USB_CTRL_SETUP_BABO_MASK 0x00000001
# define USB_CTRL_SETUP_FNHW_MASK 0x00000002
# define USB_CTRL_SETUP_FNBO_MASK 0x00000004
# define USB_CTRL_SETUP_WABO_MASK 0x00000008
# define USB_CTRL_SETUP_SCB_CLIENT_SWAP_MASK 0x00002000 /* option */
# define USB_CTRL_SETUP_SCB1_EN_MASK 0x00004000 /* option */
# define USB_CTRL_SETUP_SCB2_EN_MASK 0x00008000 /* option */
# define USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK 0X00020000 /* option */
# define USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK 0x00010000 /* option */
# define USB_CTRL_SETUP_STRAP_IPP_SEL_MASK 0x02000000 /* option */
# define USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK 0x04000000 /* option */
# define USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK 0x08000000 /* opt */
# define USB_CTRL_SETUP_OC3_DISABLE_MASK 0xc0000000 /* option */
# define USB_CTRL_PLL_CTL 0x04
# define USB_CTRL_PLL_CTL_PLL_SUSPEND_EN_MASK 0x08000000
# define USB_CTRL_PLL_CTL_PLL_RESETB_MASK 0x40000000
# define USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK 0x80000000 /* option */
# define USB_CTRL_EBRIDGE 0x0c
# define USB_CTRL_EBRIDGE_ESTOP_SCB_REQ_MASK 0x00020000 /* option */
2017-12-27 14:28:49 -05:00
# define USB_CTRL_OBRIDGE 0x10
# define USB_CTRL_OBRIDGE_LS_KEEP_ALIVE_MASK 0x08000000
2017-09-22 15:34:01 -04:00
# define USB_CTRL_MDIO 0x14
# define USB_CTRL_MDIO2 0x18
# define USB_CTRL_UTMI_CTL_1 0x2c
# define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_MASK 0x00000800
# define USB_CTRL_UTMI_CTL_1_POWER_UP_FSM_EN_P1_MASK 0x08000000
# define USB_CTRL_USB_PM 0x34
# define USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK 0x00800000 /* option */
# define USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK 0x00400000 /* option */
# define USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK 0x40000000 /* option */
# define USB_CTRL_USB_PM_USB_PWRDN_MASK 0x80000000 /* option */
# define USB_CTRL_USB_PM_SOFT_RESET_MASK 0x40000000 /* option */
# define USB_CTRL_USB_PM_USB20_HC_RESETB_MASK 0x30000000 /* option */
# define USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK 0x00300000 /* option */
# define USB_CTRL_USB30_CTL1 0x60
# define USB_CTRL_USB30_CTL1_PHY3_PLL_SEQ_START_MASK 0x00000010
# define USB_CTRL_USB30_CTL1_PHY3_RESETB_MASK 0x00010000
# define USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK 0x00020000 /* option */
# define USB_CTRL_USB30_CTL1_USB3_IOC_MASK 0x10000000 /* option */
# define USB_CTRL_USB30_CTL1_USB3_IPP_MASK 0x20000000 /* option */
# define USB_CTRL_USB30_PCTL 0x70
# define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_MASK 0x00000002
2017-12-27 14:28:50 -05:00
# define USB_CTRL_USB30_PCTL_PHY3_IDDQ_OVERRIDE_MASK 0x00008000
2017-09-22 15:34:01 -04:00
# define USB_CTRL_USB30_PCTL_PHY3_SOFT_RESETB_P1_MASK 0x00020000
# define USB_CTRL_USB_DEVICE_CTL1 0x90
# define USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK 0x00000003 /* option */
/* Register definitions for the XHCI EC block */
# define USB_XHCI_EC_IRAADR 0x658
# define USB_XHCI_EC_IRADAT 0x65c
enum brcm_family_type {
BRCM_FAMILY_3390A0 ,
BRCM_FAMILY_7250B0 ,
BRCM_FAMILY_7271A0 ,
BRCM_FAMILY_7364A0 ,
BRCM_FAMILY_7366C0 ,
BRCM_FAMILY_74371A0 ,
BRCM_FAMILY_7439B0 ,
BRCM_FAMILY_7445D0 ,
BRCM_FAMILY_7260A0 ,
BRCM_FAMILY_7278A0 ,
BRCM_FAMILY_COUNT ,
} ;
# define USB_BRCM_FAMILY(chip) \
[ BRCM_FAMILY_ # # chip ] = __stringify ( chip )
static const char * family_names [ BRCM_FAMILY_COUNT ] = {
USB_BRCM_FAMILY ( 3390 A0 ) ,
USB_BRCM_FAMILY ( 7250 B0 ) ,
USB_BRCM_FAMILY ( 7271 A0 ) ,
USB_BRCM_FAMILY ( 7364 A0 ) ,
USB_BRCM_FAMILY ( 7366 C0 ) ,
USB_BRCM_FAMILY ( 74371 A0 ) ,
USB_BRCM_FAMILY ( 7439 B0 ) ,
USB_BRCM_FAMILY ( 7445 D0 ) ,
USB_BRCM_FAMILY ( 7260 A0 ) ,
USB_BRCM_FAMILY ( 7278 A0 ) ,
} ;
enum {
USB_CTRL_SETUP_SCB1_EN_SELECTOR ,
USB_CTRL_SETUP_SCB2_EN_SELECTOR ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_SELECTOR ,
USB_CTRL_SETUP_STRAP_IPP_SEL_SELECTOR ,
USB_CTRL_SETUP_OC3_DISABLE_SELECTOR ,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_SELECTOR ,
USB_CTRL_USB_PM_BDC_SOFT_RESETB_SELECTOR ,
USB_CTRL_USB_PM_XHC_SOFT_RESETB_SELECTOR ,
USB_CTRL_USB_PM_USB_PWRDN_SELECTOR ,
USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_SELECTOR ,
USB_CTRL_USB30_CTL1_USB3_IOC_SELECTOR ,
USB_CTRL_USB30_CTL1_USB3_IPP_SELECTOR ,
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_SELECTOR ,
USB_CTRL_USB_PM_SOFT_RESET_SELECTOR ,
USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_SELECTOR ,
USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_SELECTOR ,
USB_CTRL_USB_PM_USB20_HC_RESETB_SELECTOR ,
USB_CTRL_SETUP_ENDIAN_SELECTOR ,
USB_CTRL_SELECTOR_COUNT ,
} ;
2019-10-15 17:03:31 +01:00
# define USB_CTRL_REG(base, reg) ((void __iomem *)base + USB_CTRL_##reg)
# define USB_XHCI_EC_REG(base, reg) ((void __iomem *)base + USB_XHCI_EC_##reg)
2017-09-22 15:34:01 -04:00
# define USB_CTRL_MASK(reg, field) \
USB_CTRL_ # # reg # # _ # # field # # _MASK
# define USB_CTRL_MASK_FAMILY(params, reg, field) \
( params - > usb_reg_bits_map [ USB_CTRL_ # # reg # # _ # # field # # _SELECTOR ] )
# define USB_CTRL_SET_FAMILY(params, reg, field) \
usb_ctrl_set_family ( params , USB_CTRL_ # # reg , \
USB_CTRL_ # # reg # # _ # # field # # _SELECTOR )
# define USB_CTRL_UNSET_FAMILY(params, reg, field) \
usb_ctrl_unset_family ( params , USB_CTRL_ # # reg , \
USB_CTRL_ # # reg # # _ # # field # # _SELECTOR )
# define USB_CTRL_SET(base, reg, field) \
usb_ctrl_set ( USB_CTRL_REG ( base , reg ) , \
USB_CTRL_ # # reg # # _ # # field # # _MASK )
# define USB_CTRL_UNSET(base, reg, field) \
usb_ctrl_unset ( USB_CTRL_REG ( base , reg ) , \
USB_CTRL_ # # reg # # _ # # field # # _MASK )
# define MDIO_USB2 0
# define MDIO_USB3 BIT(31)
# define USB_CTRL_SETUP_ENDIAN_BITS ( \
USB_CTRL_MASK ( SETUP , BABO ) | \
USB_CTRL_MASK ( SETUP , FNHW ) | \
USB_CTRL_MASK ( SETUP , FNBO ) | \
USB_CTRL_MASK ( SETUP , WABO ) )
# ifdef __LITTLE_ENDIAN
# define ENDIAN_SETTINGS ( \
USB_CTRL_MASK ( SETUP , BABO ) | \
USB_CTRL_MASK ( SETUP , FNHW ) )
# else
# define ENDIAN_SETTINGS ( \
USB_CTRL_MASK ( SETUP , FNHW ) | \
USB_CTRL_MASK ( SETUP , FNBO ) | \
USB_CTRL_MASK ( SETUP , WABO ) )
# endif
struct id_to_type {
u32 id ;
int type ;
} ;
static const struct id_to_type id_to_type_table [ ] = {
{ 0x33900000 , BRCM_FAMILY_3390A0 } ,
{ 0x72500010 , BRCM_FAMILY_7250B0 } ,
{ 0x72600000 , BRCM_FAMILY_7260A0 } ,
{ 0x72680000 , BRCM_FAMILY_7271A0 } ,
{ 0x72710000 , BRCM_FAMILY_7271A0 } ,
{ 0x73640000 , BRCM_FAMILY_7364A0 } ,
{ 0x73660020 , BRCM_FAMILY_7366C0 } ,
{ 0x07437100 , BRCM_FAMILY_74371A0 } ,
{ 0x74390010 , BRCM_FAMILY_7439B0 } ,
{ 0x74450030 , BRCM_FAMILY_7445D0 } ,
{ 0x72780000 , BRCM_FAMILY_7278A0 } ,
{ 0 , BRCM_FAMILY_7271A0 } , /* default */
} ;
static const u32
usb_reg_bits_map_table [ BRCM_FAMILY_COUNT ] [ USB_CTRL_SELECTOR_COUNT ] = {
/* 3390B0 */
[ BRCM_FAMILY_3390A0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK ,
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK ,
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7250b0 */
[ BRCM_FAMILY_7250B0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
0 , /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK ,
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK ,
0 , /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
0 , /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7271a0 */
[ BRCM_FAMILY_7271A0 ] = {
0 , /* USB_CTRL_SETUP_SCB1_EN_MASK */
0 , /* USB_CTRL_SETUP_SCB2_EN_MASK */
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK ,
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK ,
USB_CTRL_USB_PM_SOFT_RESET_MASK ,
USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK ,
USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK ,
USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7364a0 */
[ BRCM_FAMILY_7364A0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
0 , /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK ,
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK ,
0 , /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
0 , /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7366c0 */
[ BRCM_FAMILY_7366C0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
0 , /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
USB_CTRL_USB_PM_XHC_SOFT_RESETB_VAR_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
0 , /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 74371A0 */
[ BRCM_FAMILY_74371A0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK ,
0 , /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
0 , /* USB_CTRL_SETUP_OC3_DISABLE_MASK */
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK ,
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB30_CTL1_USB3_IOC_MASK ,
USB_CTRL_USB30_CTL1_USB3_IPP_MASK ,
0 , /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
0 , /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7439B0 */
[ BRCM_FAMILY_7439B0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK ,
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK ,
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7445d0 */
[ BRCM_FAMILY_7445D0 ] = {
USB_CTRL_SETUP_SCB1_EN_MASK ,
USB_CTRL_SETUP_SCB2_EN_MASK ,
USB_CTRL_SETUP_SS_EHCI64BIT_EN_VAR_MASK ,
0 , /* USB_CTRL_SETUP_STRAP_IPP_SEL_MASK */
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK ,
0 , /* USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB_PM_USB_PWRDN_MASK */
USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK ,
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
0 , /* USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK */
0 , /* USB_CTRL_USB_PM_SOFT_RESET_MASK */
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7260a0 */
[ BRCM_FAMILY_7260A0 ] = {
0 , /* USB_CTRL_SETUP_SCB1_EN_MASK */
0 , /* USB_CTRL_SETUP_SCB2_EN_MASK */
USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK ,
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK ,
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK ,
USB_CTRL_USB_PM_SOFT_RESET_MASK ,
USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK ,
USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK ,
USB_CTRL_USB_PM_USB20_HC_RESETB_VAR_MASK ,
ENDIAN_SETTINGS , /* USB_CTRL_SETUP ENDIAN bits */
} ,
/* 7278a0 */
[ BRCM_FAMILY_7278A0 ] = {
0 , /* USB_CTRL_SETUP_SCB1_EN_MASK */
0 , /* USB_CTRL_SETUP_SCB2_EN_MASK */
0 , /*USB_CTRL_SETUP_SS_EHCI64BIT_EN_MASK */
USB_CTRL_SETUP_STRAP_IPP_SEL_MASK ,
USB_CTRL_SETUP_OC3_DISABLE_MASK ,
0 , /* USB_CTRL_PLL_CTL_PLL_IDDQ_PWRDN_MASK */
USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK ,
USB_CTRL_USB_PM_USB_PWRDN_MASK ,
0 , /* USB_CTRL_USB30_CTL1_XHC_SOFT_RESETB_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IOC_MASK */
0 , /* USB_CTRL_USB30_CTL1_USB3_IPP_MASK */
USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK ,
USB_CTRL_USB_PM_SOFT_RESET_MASK ,
0 , /* USB_CTRL_SETUP_CC_DRD_MODE_ENABLE_MASK */
0 , /* USB_CTRL_SETUP_STRAP_CC_DRD_MODE_ENABLE_SEL_MASK */
0 , /* USB_CTRL_USB_PM_USB20_HC_RESETB_MASK */
0 , /* USB_CTRL_SETUP ENDIAN bits */
} ,
} ;
static inline u32 brcmusb_readl ( void __iomem * addr )
{
return readl ( addr ) ;
}
static inline void brcmusb_writel ( u32 val , void __iomem * addr )
{
writel ( val , addr ) ;
}
static inline
void usb_ctrl_unset_family ( struct brcm_usb_init_params * params ,
u32 reg_offset , u32 field )
{
u32 mask ;
2019-10-15 17:03:31 +01:00
void __iomem * reg ;
2017-09-22 15:34:01 -04:00
mask = params - > usb_reg_bits_map [ field ] ;
reg = params - > ctrl_regs + reg_offset ;
brcmusb_writel ( brcmusb_readl ( reg ) & ~ mask , reg ) ;
} ;
static inline
void usb_ctrl_set_family ( struct brcm_usb_init_params * params ,
u32 reg_offset , u32 field )
{
u32 mask ;
2019-10-15 17:03:31 +01:00
void __iomem * reg ;
2017-09-22 15:34:01 -04:00
mask = params - > usb_reg_bits_map [ field ] ;
reg = params - > ctrl_regs + reg_offset ;
brcmusb_writel ( brcmusb_readl ( reg ) | mask , reg ) ;
} ;
static inline void usb_ctrl_set ( void __iomem * reg , u32 field )
{
u32 value ;
value = brcmusb_readl ( reg ) ;
brcmusb_writel ( value | field , reg ) ;
}
static inline void usb_ctrl_unset ( void __iomem * reg , u32 field )
{
u32 value ;
value = brcmusb_readl ( reg ) ;
brcmusb_writel ( value & ~ field , reg ) ;
}
static u32 brcmusb_usb_mdio_read ( void __iomem * ctrl_base , u32 reg , int mode )
{
u32 data ;
data = ( reg < < 16 ) | mode ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
data | = ( 1 < < 24 ) ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
data & = ~ ( 1 < < 24 ) ;
/* wait for the 60MHz parallel to serial shifter */
usleep_range ( 10 , 20 ) ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
/* wait for the 60MHz parallel to serial shifter */
usleep_range ( 10 , 20 ) ;
return brcmusb_readl ( USB_CTRL_REG ( ctrl_base , MDIO2 ) ) & 0xffff ;
}
static void brcmusb_usb_mdio_write ( void __iomem * ctrl_base , u32 reg ,
u32 val , int mode )
{
u32 data ;
data = ( reg < < 16 ) | val | mode ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
data | = ( 1 < < 25 ) ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
data & = ~ ( 1 < < 25 ) ;
/* wait for the 60MHz parallel to serial shifter */
usleep_range ( 10 , 20 ) ;
brcmusb_writel ( data , USB_CTRL_REG ( ctrl_base , MDIO ) ) ;
/* wait for the 60MHz parallel to serial shifter */
usleep_range ( 10 , 20 ) ;
}
static void brcmusb_usb_phy_ldo_fix ( void __iomem * ctrl_base )
{
/* first disable FSM but also leave it that way */
/* to allow normal suspend/resume */
USB_CTRL_UNSET ( ctrl_base , UTMI_CTL_1 , POWER_UP_FSM_EN ) ;
USB_CTRL_UNSET ( ctrl_base , UTMI_CTL_1 , POWER_UP_FSM_EN_P1 ) ;
/* reset USB 2.0 PLL */
USB_CTRL_UNSET ( ctrl_base , PLL_CTL , PLL_RESETB ) ;
/* PLL reset period */
udelay ( 1 ) ;
USB_CTRL_SET ( ctrl_base , PLL_CTL , PLL_RESETB ) ;
/* Give PLL enough time to lock */
usleep_range ( 1000 , 2000 ) ;
}
static void brcmusb_usb2_eye_fix ( void __iomem * ctrl_base )
{
/* Increase USB 2.0 TX level to meet spec requirement */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x80a0 , MDIO_USB2 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x0a , 0xc6a0 , MDIO_USB2 ) ;
}
static void brcmusb_usb3_pll_fix ( void __iomem * ctrl_base )
{
/* Set correct window for PLL lock detect */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x8000 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x07 , 0x1503 , MDIO_USB3 ) ;
}
static void brcmusb_usb3_enable_pipe_reset ( void __iomem * ctrl_base )
{
u32 val ;
/* Re-enable USB 3.0 pipe reset */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x8000 , MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x0f , MDIO_USB3 ) | 0x200 ;
brcmusb_usb_mdio_write ( ctrl_base , 0x0f , val , MDIO_USB3 ) ;
}
static void brcmusb_usb3_enable_sigdet ( void __iomem * ctrl_base )
{
u32 val , ofs ;
int ii ;
ofs = 0 ;
for ( ii = 0 ; ii < PHY_PORTS ; + + ii ) {
/* Set correct default for sigdet */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , ( 0x8080 + ofs ) ,
MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x05 , MDIO_USB3 ) ;
val = ( val & ~ 0x800f ) | 0x800d ;
brcmusb_usb_mdio_write ( ctrl_base , 0x05 , val , MDIO_USB3 ) ;
ofs = PHY_PORT_SELECT_1 ;
}
}
static void brcmusb_usb3_enable_skip_align ( void __iomem * ctrl_base )
{
u32 val , ofs ;
int ii ;
ofs = 0 ;
for ( ii = 0 ; ii < PHY_PORTS ; + + ii ) {
/* Set correct default for SKIP align */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , ( 0x8060 + ofs ) ,
MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x01 , MDIO_USB3 ) | 0x200 ;
brcmusb_usb_mdio_write ( ctrl_base , 0x01 , val , MDIO_USB3 ) ;
ofs = PHY_PORT_SELECT_1 ;
}
}
static void brcmusb_usb3_unfreeze_aeq ( void __iomem * ctrl_base )
{
u32 val , ofs ;
int ii ;
ofs = 0 ;
for ( ii = 0 ; ii < PHY_PORTS ; + + ii ) {
/* Let EQ freeze after TSEQ */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , ( 0x80e0 + ofs ) ,
MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x01 , MDIO_USB3 ) ;
val & = ~ 0x0008 ;
brcmusb_usb_mdio_write ( ctrl_base , 0x01 , val , MDIO_USB3 ) ;
ofs = PHY_PORT_SELECT_1 ;
}
}
static void brcmusb_usb3_pll_54mhz ( struct brcm_usb_init_params * params )
{
u32 ofs ;
int ii ;
void __iomem * ctrl_base = params - > ctrl_regs ;
/*
* On newer B53 based SoC ' s , the reference clock for the
* 3.0 PLL has been changed from 50 MHz to 54 MHz so the
* PLL needs to be reprogrammed .
* See SWLINUX - 4006.
*
* On the 7364 C0 , the reference clock for the
* 3.0 PLL has been changed from 50 MHz to 54 MHz to
* work around a MOCA issue .
* See SWLINUX - 4169.
*/
switch ( params - > selected_family ) {
case BRCM_FAMILY_3390A0 :
case BRCM_FAMILY_7250B0 :
case BRCM_FAMILY_7366C0 :
case BRCM_FAMILY_74371A0 :
case BRCM_FAMILY_7439B0 :
case BRCM_FAMILY_7445D0 :
case BRCM_FAMILY_7260A0 :
return ;
case BRCM_FAMILY_7364A0 :
if ( BRCM_REV ( params - > family_id ) < 0x20 )
return ;
break ;
}
/* set USB 3.0 PLL to accept 54Mhz reference clock */
USB_CTRL_UNSET ( ctrl_base , USB30_CTL1 , PHY3_PLL_SEQ_START ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x8000 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x10 , 0x5784 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x11 , 0x01d0 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x12 , 0x1DE8 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x13 , 0xAA80 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x14 , 0x8826 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x15 , 0x0044 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x16 , 0x8000 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x17 , 0x0851 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x18 , 0x0000 , MDIO_USB3 ) ;
/* both ports */
ofs = 0 ;
for ( ii = 0 ; ii < PHY_PORTS ; + + ii ) {
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , ( 0x8040 + ofs ) ,
MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x03 , 0x0090 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x04 , 0x0134 , MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , ( 0x8020 + ofs ) ,
MDIO_USB3 ) ;
brcmusb_usb_mdio_write ( ctrl_base , 0x01 , 0x00e2 , MDIO_USB3 ) ;
ofs = PHY_PORT_SELECT_1 ;
}
/* restart PLL sequence */
USB_CTRL_SET ( ctrl_base , USB30_CTL1 , PHY3_PLL_SEQ_START ) ;
/* Give PLL enough time to lock */
usleep_range ( 1000 , 2000 ) ;
}
static void brcmusb_usb3_ssc_enable ( void __iomem * ctrl_base )
{
u32 val ;
/* Enable USB 3.0 TX spread spectrum */
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x8040 , MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x01 , MDIO_USB3 ) | 0xf ;
brcmusb_usb_mdio_write ( ctrl_base , 0x01 , val , MDIO_USB3 ) ;
/* Currently, USB 3.0 SSC is enabled via port 0 MDIO registers,
* which should have been adequate . However , due to a bug in the
* USB 3.0 PHY , it must be enabled via both ports ( HWUSB3DVT - 26 ) .
*/
brcmusb_usb_mdio_write ( ctrl_base , 0x1f , 0x9040 , MDIO_USB3 ) ;
val = brcmusb_usb_mdio_read ( ctrl_base , 0x01 , MDIO_USB3 ) | 0xf ;
brcmusb_usb_mdio_write ( ctrl_base , 0x01 , val , MDIO_USB3 ) ;
}
static void brcmusb_usb3_phy_workarounds ( struct brcm_usb_init_params * params )
{
void __iomem * ctrl_base = params - > ctrl_regs ;
brcmusb_usb3_pll_fix ( ctrl_base ) ;
brcmusb_usb3_pll_54mhz ( params ) ;
brcmusb_usb3_ssc_enable ( ctrl_base ) ;
brcmusb_usb3_enable_pipe_reset ( ctrl_base ) ;
brcmusb_usb3_enable_sigdet ( ctrl_base ) ;
brcmusb_usb3_enable_skip_align ( ctrl_base ) ;
brcmusb_usb3_unfreeze_aeq ( ctrl_base ) ;
}
static void brcmusb_memc_fix ( struct brcm_usb_init_params * params )
{
u32 prid ;
if ( params - > selected_family ! = BRCM_FAMILY_7445D0 )
return ;
/*
* This is a workaround for HW7445 - 1869 where a DMA write ends up
* doing a read pre - fetch after the end of the DMA buffer . This
* causes a problem when the DMA buffer is at the end of physical
* memory , causing the pre - fetch read to access non - existent memory ,
* and the chip bondout has MEMC2 disabled . When the pre - fetch read
* tries to use the disabled MEMC2 , it hangs the bus . The workaround
* is to disable MEMC2 access in the usb controller which avoids
* the hang .
*/
prid = params - > product_id & 0xfffff000 ;
switch ( prid ) {
case 0x72520000 :
case 0x74480000 :
case 0x74490000 :
case 0x07252000 :
case 0x07448000 :
case 0x07449000 :
USB_CTRL_UNSET_FAMILY ( params , SETUP , SCB2_EN ) ;
}
}
static void brcmusb_usb3_otp_fix ( struct brcm_usb_init_params * params )
{
void __iomem * xhci_ec_base = params - > xhci_ec_regs ;
u32 val ;
2019-10-15 17:03:32 +01:00
if ( params - > family_id ! = 0x74371000 | | ! xhci_ec_base )
2017-09-22 15:34:01 -04:00
return ;
brcmusb_writel ( 0xa20c , USB_XHCI_EC_REG ( xhci_ec_base , IRAADR ) ) ;
val = brcmusb_readl ( USB_XHCI_EC_REG ( xhci_ec_base , IRADAT ) ) ;
/* set cfg_pick_ss_lock */
val | = ( 1 < < 27 ) ;
brcmusb_writel ( val , USB_XHCI_EC_REG ( xhci_ec_base , IRADAT ) ) ;
/* Reset USB 3.0 PHY for workaround to take effect */
USB_CTRL_UNSET ( params - > ctrl_regs , USB30_CTL1 , PHY3_RESETB ) ;
USB_CTRL_SET ( params - > ctrl_regs , USB30_CTL1 , PHY3_RESETB ) ;
}
static void brcmusb_xhci_soft_reset ( struct brcm_usb_init_params * params ,
int on_off )
{
/* Assert reset */
if ( on_off ) {
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , XHC_SOFT_RESETB ) )
USB_CTRL_UNSET_FAMILY ( params , USB_PM , XHC_SOFT_RESETB ) ;
else
USB_CTRL_UNSET_FAMILY ( params ,
USB30_CTL1 , XHC_SOFT_RESETB ) ;
} else { /* De-assert reset */
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , XHC_SOFT_RESETB ) )
USB_CTRL_SET_FAMILY ( params , USB_PM , XHC_SOFT_RESETB ) ;
else
USB_CTRL_SET_FAMILY ( params , USB30_CTL1 ,
XHC_SOFT_RESETB ) ;
}
}
/*
* Return the best map table family . The order is :
* - exact match of chip and major rev
* - exact match of chip and closest older major rev
* - default chip / rev .
* NOTE : The minor rev is always ignored .
*/
static enum brcm_family_type brcmusb_get_family_type (
struct brcm_usb_init_params * params )
{
int last_type = - 1 ;
u32 last_family = 0 ;
u32 family_no_major ;
unsigned int x ;
u32 family ;
family = params - > family_id & 0xfffffff0 ;
family_no_major = params - > family_id & 0xffffff00 ;
for ( x = 0 ; id_to_type_table [ x ] . id ; x + + ) {
if ( family = = id_to_type_table [ x ] . id )
return id_to_type_table [ x ] . type ;
if ( family_no_major = = ( id_to_type_table [ x ] . id & 0xffffff00 ) )
if ( family > id_to_type_table [ x ] . id & &
last_family < id_to_type_table [ x ] . id ) {
last_family = id_to_type_table [ x ] . id ;
last_type = id_to_type_table [ x ] . type ;
}
}
/* If no match, return the default family */
if ( last_type = = - 1 )
return id_to_type_table [ x ] . type ;
return last_type ;
}
void brcm_usb_init_ipp ( struct brcm_usb_init_params * params )
{
void __iomem * ctrl = params - > ctrl_regs ;
u32 reg ;
u32 orig_reg ;
/* Starting with the 7445d0, there are no longer separate 3.0
* versions of IOC and IPP .
*/
if ( USB_CTRL_MASK_FAMILY ( params , USB30_CTL1 , USB3_IOC ) ) {
if ( params - > ioc )
USB_CTRL_SET_FAMILY ( params , USB30_CTL1 , USB3_IOC ) ;
if ( params - > ipp = = 1 )
USB_CTRL_SET_FAMILY ( params , USB30_CTL1 , USB3_IPP ) ;
}
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , SETUP ) ) ;
orig_reg = reg ;
if ( USB_CTRL_MASK_FAMILY ( params , SETUP , STRAP_CC_DRD_MODE_ENABLE_SEL ) )
/* Never use the strap, it's going away. */
reg & = ~ ( USB_CTRL_MASK_FAMILY ( params ,
SETUP ,
STRAP_CC_DRD_MODE_ENABLE_SEL ) ) ;
if ( USB_CTRL_MASK_FAMILY ( params , SETUP , STRAP_IPP_SEL ) )
if ( params - > ipp ! = 2 )
/* override ipp strap pin (if it exits) */
reg & = ~ ( USB_CTRL_MASK_FAMILY ( params , SETUP ,
STRAP_IPP_SEL ) ) ;
/* Override the default OC and PP polarity */
reg & = ~ ( USB_CTRL_MASK ( SETUP , IPP ) | USB_CTRL_MASK ( SETUP , IOC ) ) ;
if ( params - > ioc )
reg | = USB_CTRL_MASK ( SETUP , IOC ) ;
if ( params - > ipp = = 1 & & ( ( reg & USB_CTRL_MASK ( SETUP , IPP ) ) = = 0 ) )
reg | = USB_CTRL_MASK ( SETUP , IPP ) ;
brcmusb_writel ( reg , USB_CTRL_REG ( ctrl , SETUP ) ) ;
/*
* If we ' re changing IPP , make sure power is off long enough
* to turn off any connected devices .
*/
if ( reg ! = orig_reg )
msleep ( 50 ) ;
}
int brcm_usb_init_get_dual_select ( struct brcm_usb_init_params * params )
{
void __iomem * ctrl = params - > ctrl_regs ;
u32 reg = 0 ;
if ( USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 , PORT_MODE ) ) {
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , USB_DEVICE_CTL1 ) ) ;
reg & = USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 ,
PORT_MODE ) ;
}
return reg ;
}
void brcm_usb_init_set_dual_select ( struct brcm_usb_init_params * params ,
int mode )
{
void __iomem * ctrl = params - > ctrl_regs ;
u32 reg ;
if ( USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 , PORT_MODE ) ) {
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , USB_DEVICE_CTL1 ) ) ;
reg & = ~ USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 ,
PORT_MODE ) ;
reg | = mode ;
brcmusb_writel ( reg , USB_CTRL_REG ( ctrl , USB_DEVICE_CTL1 ) ) ;
}
}
void brcm_usb_init_common ( struct brcm_usb_init_params * params )
{
u32 reg ;
void __iomem * ctrl = params - > ctrl_regs ;
/* Take USB out of power down */
if ( USB_CTRL_MASK_FAMILY ( params , PLL_CTL , PLL_IDDQ_PWRDN ) ) {
USB_CTRL_UNSET_FAMILY ( params , PLL_CTL , PLL_IDDQ_PWRDN ) ;
/* 1 millisecond - for USB clocks to settle down */
usleep_range ( 1000 , 2000 ) ;
}
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , USB_PWRDN ) ) {
USB_CTRL_UNSET_FAMILY ( params , USB_PM , USB_PWRDN ) ;
/* 1 millisecond - for USB clocks to settle down */
usleep_range ( 1000 , 2000 ) ;
}
if ( params - > selected_family ! = BRCM_FAMILY_74371A0 & &
( BRCM_ID ( params - > family_id ) ! = 0x7364 ) )
/*
* HW7439 - 637 : 7439 a0 and its derivatives do not have large
* enough descriptor storage for this .
*/
USB_CTRL_SET_FAMILY ( params , SETUP , SS_EHCI64BIT_EN ) ;
/* Block auto PLL suspend by USB2 PHY (Sasi) */
USB_CTRL_SET ( ctrl , PLL_CTL , PLL_SUSPEND_EN ) ;
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , SETUP ) ) ;
if ( params - > selected_family = = BRCM_FAMILY_7364A0 )
/* Suppress overcurrent indication from USB30 ports for A0 */
reg | = USB_CTRL_MASK_FAMILY ( params , SETUP , OC3_DISABLE ) ;
brcmusb_usb_phy_ldo_fix ( ctrl ) ;
brcmusb_usb2_eye_fix ( ctrl ) ;
/*
* Make sure the the second and third memory controller
* interfaces are enabled if they exist .
*/
if ( USB_CTRL_MASK_FAMILY ( params , SETUP , SCB1_EN ) )
reg | = USB_CTRL_MASK_FAMILY ( params , SETUP , SCB1_EN ) ;
if ( USB_CTRL_MASK_FAMILY ( params , SETUP , SCB2_EN ) )
reg | = USB_CTRL_MASK_FAMILY ( params , SETUP , SCB2_EN ) ;
brcmusb_writel ( reg , USB_CTRL_REG ( ctrl , SETUP ) ) ;
brcmusb_memc_fix ( params ) ;
if ( USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 , PORT_MODE ) ) {
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , USB_DEVICE_CTL1 ) ) ;
reg & = ~ USB_CTRL_MASK_FAMILY ( params , USB_DEVICE_CTL1 ,
PORT_MODE ) ;
reg | = params - > mode ;
brcmusb_writel ( reg , USB_CTRL_REG ( ctrl , USB_DEVICE_CTL1 ) ) ;
}
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , BDC_SOFT_RESETB ) ) {
switch ( params - > mode ) {
case USB_CTLR_MODE_HOST :
USB_CTRL_UNSET_FAMILY ( params , USB_PM , BDC_SOFT_RESETB ) ;
break ;
default :
2017-12-27 14:28:51 -05:00
USB_CTRL_UNSET_FAMILY ( params , USB_PM , BDC_SOFT_RESETB ) ;
2017-09-22 15:34:01 -04:00
USB_CTRL_SET_FAMILY ( params , USB_PM , BDC_SOFT_RESETB ) ;
break ;
}
}
if ( USB_CTRL_MASK_FAMILY ( params , SETUP , CC_DRD_MODE_ENABLE ) ) {
if ( params - > mode = = USB_CTLR_MODE_TYPEC_PD )
USB_CTRL_SET_FAMILY ( params , SETUP , CC_DRD_MODE_ENABLE ) ;
else
USB_CTRL_UNSET_FAMILY ( params , SETUP ,
CC_DRD_MODE_ENABLE ) ;
}
}
void brcm_usb_init_eohci ( struct brcm_usb_init_params * params )
{
u32 reg ;
void __iomem * ctrl = params - > ctrl_regs ;
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , USB20_HC_RESETB ) )
USB_CTRL_SET_FAMILY ( params , USB_PM , USB20_HC_RESETB ) ;
if ( params - > selected_family = = BRCM_FAMILY_7366C0 )
/*
* Don ' t enable this so the memory controller doesn ' t read
* into memory holes . NOTE : This bit is low true on 7366 C0 .
*/
2017-12-27 14:28:49 -05:00
USB_CTRL_SET ( ctrl , EBRIDGE , ESTOP_SCB_REQ ) ;
2017-09-22 15:34:01 -04:00
/* Setup the endian bits */
reg = brcmusb_readl ( USB_CTRL_REG ( ctrl , SETUP ) ) ;
reg & = ~ USB_CTRL_SETUP_ENDIAN_BITS ;
reg | = USB_CTRL_MASK_FAMILY ( params , SETUP , ENDIAN ) ;
brcmusb_writel ( reg , USB_CTRL_REG ( ctrl , SETUP ) ) ;
2017-12-27 14:28:49 -05:00
if ( params - > selected_family = = BRCM_FAMILY_7271A0 )
/* Enable LS keep alive fix for certain keyboards */
USB_CTRL_SET ( ctrl , OBRIDGE , LS_KEEP_ALIVE ) ;
2017-09-22 15:34:01 -04:00
}
void brcm_usb_init_xhci ( struct brcm_usb_init_params * params )
{
void __iomem * ctrl = params - > ctrl_regs ;
2018-06-08 15:10:15 +09:00
USB_CTRL_UNSET ( ctrl , USB30_PCTL , PHY3_IDDQ_OVERRIDE ) ;
/* 1 millisecond - for USB clocks to settle down */
usleep_range ( 1000 , 2000 ) ;
2017-09-22 15:34:01 -04:00
if ( BRCM_ID ( params - > family_id ) = = 0x7366 ) {
/*
* The PHY3_SOFT_RESETB bits default to the wrong state .
*/
USB_CTRL_SET ( ctrl , USB30_PCTL , PHY3_SOFT_RESETB ) ;
USB_CTRL_SET ( ctrl , USB30_PCTL , PHY3_SOFT_RESETB_P1 ) ;
}
/*
* Kick start USB3 PHY
* Make sure it ' s low to insure a rising edge .
*/
USB_CTRL_UNSET ( ctrl , USB30_CTL1 , PHY3_PLL_SEQ_START ) ;
USB_CTRL_SET ( ctrl , USB30_CTL1 , PHY3_PLL_SEQ_START ) ;
brcmusb_usb3_phy_workarounds ( params ) ;
brcmusb_xhci_soft_reset ( params , 0 ) ;
brcmusb_usb3_otp_fix ( params ) ;
}
void brcm_usb_uninit_common ( struct brcm_usb_init_params * params )
{
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , USB_PWRDN ) )
USB_CTRL_SET_FAMILY ( params , USB_PM , USB_PWRDN ) ;
if ( USB_CTRL_MASK_FAMILY ( params , PLL_CTL , PLL_IDDQ_PWRDN ) )
USB_CTRL_SET_FAMILY ( params , PLL_CTL , PLL_IDDQ_PWRDN ) ;
}
void brcm_usb_uninit_eohci ( struct brcm_usb_init_params * params )
{
if ( USB_CTRL_MASK_FAMILY ( params , USB_PM , USB20_HC_RESETB ) )
USB_CTRL_UNSET_FAMILY ( params , USB_PM , USB20_HC_RESETB ) ;
}
void brcm_usb_uninit_xhci ( struct brcm_usb_init_params * params )
{
brcmusb_xhci_soft_reset ( params , 1 ) ;
2017-12-27 14:28:50 -05:00
USB_CTRL_SET ( params - > ctrl_regs , USB30_PCTL , PHY3_IDDQ_OVERRIDE ) ;
2017-09-22 15:34:01 -04:00
}
void brcm_usb_set_family_map ( struct brcm_usb_init_params * params )
{
int fam ;
fam = brcmusb_get_family_type ( params ) ;
params - > selected_family = fam ;
params - > usb_reg_bits_map =
& usb_reg_bits_map_table [ fam ] [ 0 ] ;
params - > family_name = family_names [ fam ] ;
}