brintos

brintos / linux-shallow public Read only

0
0
Text · 13.7 KiB · 950b7ae Raw
460 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (c) 2018, Broadcom */3 4/*5 * This module contains USB PHY initialization for power up and S3 resume6 * for newer Synopsys based USB hardware first used on the bcm7216.7 */8 9#include <linux/delay.h>10#include <linux/io.h>11 12#include <linux/soc/brcmstb/brcmstb.h>13#include "phy-brcm-usb-init.h"14 15#define PHY_LOCK_TIMEOUT_MS 20016 17/* Register definitions for syscon piarbctl registers */18#define PIARBCTL_CAM			0x0019#define PIARBCTL_SPLITTER		0x0420#define PIARBCTL_MISC			0x0821#define   PIARBCTL_MISC_SATA_PRIORITY_MASK		GENMASK(3, 0)22#define   PIARBCTL_MISC_CAM0_MEM_PAGE_MASK		GENMASK(7, 4)23#define   PIARBCTL_MISC_CAM1_MEM_PAGE_MASK		GENMASK(11, 8)24#define   PIARBCTL_MISC_USB_MEM_PAGE_MASK		GENMASK(15, 12)25#define   PIARBCTL_MISC_USB_PRIORITY_MASK		GENMASK(19, 16)26#define   PIARBCTL_MISC_USB_4G_SDRAM_MASK		BIT(29)27#define   PIARBCTL_MISC_USB_SELECT_MASK			BIT(30)28#define   PIARBCTL_MISC_SECURE_MASK			BIT(31)29 30#define PIARBCTL_MISC_USB_ONLY_MASK		\31	(PIARBCTL_MISC_USB_SELECT_MASK |	\32	 PIARBCTL_MISC_USB_4G_SDRAM_MASK |	\33	 PIARBCTL_MISC_USB_PRIORITY_MASK |	\34	 PIARBCTL_MISC_USB_MEM_PAGE_MASK)35 36/* Register definitions for the USB CTRL block */37#define USB_CTRL_SETUP			0x0038#define   USB_CTRL_SETUP_IOC_MASK			BIT(4)39#define   USB_CTRL_SETUP_IPP_MASK			BIT(5)40#define   USB_CTRL_SETUP_SOFT_SHUTDOWN_MASK		BIT(9)41#define   USB_CTRL_SETUP_SCB1_EN_MASK			BIT(14)42#define   USB_CTRL_SETUP_SCB2_EN_MASK			BIT(15)43#define   USB_CTRL_SETUP_tca_drv_sel_MASK		BIT(24)44#define   USB_CTRL_SETUP_STRAP_IPP_SEL_MASK		BIT(25)45#define USB_CTRL_USB_PM			0x0446#define   USB_CTRL_USB_PM_XHC_S2_CLK_SWITCH_EN_MASK	BIT(3)47#define   USB_CTRL_USB_PM_XHC_PME_EN_MASK		BIT(4)48#define   USB_CTRL_USB_PM_XHC_SOFT_RESETB_MASK		BIT(22)49#define   USB_CTRL_USB_PM_BDC_SOFT_RESETB_MASK		BIT(23)50#define   USB_CTRL_USB_PM_SOFT_RESET_MASK		BIT(30)51#define   USB_CTRL_USB_PM_USB_PWRDN_MASK		BIT(31)52#define USB_CTRL_USB_PM_STATUS		0x0853#define USB_CTRL_USB_DEVICE_CTL1	0x1054#define   USB_CTRL_USB_DEVICE_CTL1_PORT_MODE_MASK	GENMASK(1, 0)55#define USB_CTRL_TEST_PORT_CTL		0x3056#define   USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_MASK		GENMASK(7, 0)57#define   USB_CTRL_TEST_PORT_CTL_TPOUT_SEL_PME_GEN_MASK	0x0000002e58#define USB_CTRL_TP_DIAG1		0x3459#define   USB_CTLR_TP_DIAG1_wake_MASK			BIT(1)60#define USB_CTRL_CTLR_CSHCR		0x5061#define   USB_CTRL_CTLR_CSHCR_ctl_pme_en_MASK		BIT(18)62#define USB_CTRL_P0_U2PHY_CFG1		0x6863#define   USB_CTRL_P0_U2PHY_CFG1_COMMONONN_MASK		BIT(10)64 65/* Register definitions for the USB_PHY block in 7211b0 */66#define USB_PHY_PLL_CTL			0x0067#define   USB_PHY_PLL_CTL_PLL_SUSPEND_MASK		BIT(27)68#define   USB_PHY_PLL_CTL_PLL_RESETB_MASK		BIT(30)69#define USB_PHY_PLL_LDO_CTL		0x0870#define   USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK	BIT(0)71#define   USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK	BIT(1)72#define   USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK		BIT(2)73#define USB_PHY_UTMI_CTL_1		0x0474#define   USB_PHY_UTMI_CTL_1_PHY_MODE_MASK		GENMASK(3, 2)75#define   USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT		276#define   USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK	BIT(11)77#define USB_PHY_IDDQ			0x1c78#define   USB_PHY_IDDQ_phy_iddq_MASK			BIT(0)79#define USB_PHY_STATUS			0x2080#define   USB_PHY_STATUS_pll_lock_MASK			BIT(0)81 82/* Register definitions for the MDIO registers in the DWC2 block of83 * the 7211b0.84 * NOTE: The PHY's MDIO registers are only accessible through the85 * legacy DesignWare USB controller even though it's not being used.86 */87#define USB_GMDIOCSR	088#define USB_GMDIOGEN	489 90/* Register definitions for the BDC EC block in 7211b0 */91#define BDC_EC_AXIRDA			0x0c92#define   BDC_EC_AXIRDA_RTS_MASK			GENMASK(31, 28)93#define   BDC_EC_AXIRDA_RTS_SHIFT			2894 95#define USB_XHCI_GBL_GUSB2PHYCFG	0x10096#define   USB_XHCI_GBL_GUSB2PHYCFG_U2_FREECLK_EXISTS_MASK	BIT(30)97 98static void usb_mdio_write_7211b0(struct brcm_usb_init_params *params,99				  uint8_t addr, uint16_t data)100{101	void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];102 103	addr &= 0x1f; /* 5-bit address */104	brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);105	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))106		;107	brcm_usb_writel(0x59020000 | (addr << 18) | data,108			usb_mdio + USB_GMDIOGEN);109	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))110		;111	brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);112	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))113		;114}115 116static uint16_t __maybe_unused usb_mdio_read_7211b0(117	struct brcm_usb_init_params *params, uint8_t addr)118{119	void __iomem *usb_mdio = params->regs[BRCM_REGS_USB_MDIO];120 121	addr &= 0x1f; /* 5-bit address */122	brcm_usb_writel(0xffffffff, usb_mdio + USB_GMDIOGEN);123	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))124		;125	brcm_usb_writel(0x69020000 | (addr << 18), usb_mdio + USB_GMDIOGEN);126	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))127		;128	brcm_usb_writel(0x00000000, usb_mdio + USB_GMDIOGEN);129	while (brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & (1<<31))130		;131	return brcm_usb_readl(usb_mdio + USB_GMDIOCSR) & 0xffff;132}133 134static void usb2_eye_fix_7211b0(struct brcm_usb_init_params *params)135{136	/* select bank */137	usb_mdio_write_7211b0(params, 0x1f, 0x80a0);138 139	/* Set the eye */140	usb_mdio_write_7211b0(params, 0x0a, 0xc6a0);141}142 143static void xhci_soft_reset(struct brcm_usb_init_params *params,144			int on_off)145{146	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];147	void __iomem *xhci_gbl = params->regs[BRCM_REGS_XHCI_GBL];148 149	/* Assert reset */150	if (on_off) {151		USB_CTRL_UNSET(ctrl, USB_PM, XHC_SOFT_RESETB);152	/* De-assert reset */153	} else {154		USB_CTRL_SET(ctrl, USB_PM, XHC_SOFT_RESETB);155		/* Required for COMMONONN to be set */156		if (params->supported_port_modes != USB_CTLR_MODE_DRD)157			USB_XHCI_GBL_UNSET(xhci_gbl, GUSB2PHYCFG,158					   U2_FREECLK_EXISTS);159	}160}161 162static void usb_init_ipp(struct brcm_usb_init_params *params)163{164	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];165	u32 reg;166	u32 orig_reg;167 168	pr_debug("%s\n", __func__);169 170	orig_reg = reg = brcm_usb_readl(USB_CTRL_REG(ctrl, SETUP));171	if (params->ipp != 2)172		/* override ipp strap pin (if it exits) */173		reg &= ~(USB_CTRL_MASK(SETUP, STRAP_IPP_SEL));174 175	/* Override the default OC and PP polarity */176	reg &= ~(USB_CTRL_MASK(SETUP, IPP) | USB_CTRL_MASK(SETUP, IOC));177	if (params->ioc)178		reg |= USB_CTRL_MASK(SETUP, IOC);179	if (params->ipp == 1)180		reg |= USB_CTRL_MASK(SETUP, IPP);181	brcm_usb_writel(reg, USB_CTRL_REG(ctrl, SETUP));182 183	/*184	 * If we're changing IPP, make sure power is off long enough185	 * to turn off any connected devices.186	 */187	if ((reg ^ orig_reg) & USB_CTRL_MASK(SETUP, IPP))188		msleep(50);189}190 191static void syscon_piarbctl_init(struct regmap *rmap)192{193	/* Switch from legacy USB OTG controller to new STB USB controller */194	regmap_update_bits(rmap, PIARBCTL_MISC, PIARBCTL_MISC_USB_ONLY_MASK,195			   PIARBCTL_MISC_USB_SELECT_MASK |196			   PIARBCTL_MISC_USB_4G_SDRAM_MASK);197}198 199static void usb_init_common(struct brcm_usb_init_params *params)200{201	u32 reg;202	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];203 204	pr_debug("%s\n", __func__);205 206	if (USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE)) {207		reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));208		reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);209		reg |= params->port_mode;210		brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));211	}212	switch (params->supported_port_modes) {213	case USB_CTLR_MODE_HOST:214		USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);215		break;216	default:217		USB_CTRL_UNSET(ctrl, USB_PM, BDC_SOFT_RESETB);218		USB_CTRL_SET(ctrl, USB_PM, BDC_SOFT_RESETB);219		break;220	}221}222 223static void usb_wake_enable_7211b0(struct brcm_usb_init_params *params,224				   bool enable)225{226	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];227 228	if (enable)229		USB_CTRL_SET(ctrl, CTLR_CSHCR, ctl_pme_en);230	else231		USB_CTRL_UNSET(ctrl, CTLR_CSHCR, ctl_pme_en);232}233 234static void usb_wake_enable_7216(struct brcm_usb_init_params *params,235				 bool enable)236{237	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];238 239	if (enable)240		USB_CTRL_SET(ctrl, USB_PM, XHC_PME_EN);241	else242		USB_CTRL_UNSET(ctrl, USB_PM, XHC_PME_EN);243}244 245static void usb_init_common_7211b0(struct brcm_usb_init_params *params)246{247	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];248	void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];249	void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];250	int timeout_ms = PHY_LOCK_TIMEOUT_MS;251	u32 reg;252 253	if (params->syscon_piarbctl)254		syscon_piarbctl_init(params->syscon_piarbctl);255 256	USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);257 258	usb_wake_enable_7211b0(params, false);259	if (!params->wake_enabled) {260 261		/* undo possible suspend settings */262		brcm_usb_writel(0, usb_phy + USB_PHY_IDDQ);263		reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);264		reg |= USB_PHY_PLL_CTL_PLL_RESETB_MASK;265		brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);266 267		/* temporarily enable FSM so PHY comes up properly */268		reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);269		reg |= USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;270		brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);271	}272 273	/* Disable PLL auto suspend */274	reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);275	reg |= USB_PHY_PLL_CTL_PLL_SUSPEND_MASK;276	brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);277 278	/* Init the PHY */279	reg = USB_PHY_PLL_LDO_CTL_AFE_CORERDY_MASK |280		USB_PHY_PLL_LDO_CTL_AFE_LDO_PWRDWNB_MASK |281		USB_PHY_PLL_LDO_CTL_AFE_BG_PWRDWNB_MASK;282	brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_LDO_CTL);283 284	/* wait for lock */285	while (timeout_ms-- > 0) {286		reg = brcm_usb_readl(usb_phy + USB_PHY_STATUS);287		if (reg & USB_PHY_STATUS_pll_lock_MASK)288			break;289		usleep_range(1000, 2000);290	}291 292	/* Set the PHY_MODE */293	reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);294	reg &= ~USB_PHY_UTMI_CTL_1_PHY_MODE_MASK;295	reg |= params->supported_port_modes << USB_PHY_UTMI_CTL_1_PHY_MODE_SHIFT;296	brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);297 298	usb_init_common(params);299 300	/*301	 * The BDC controller will get occasional failures with302	 * the default "Read Transaction Size" of 6 (1024 bytes).303	 * Set it to 4 (256 bytes).304	 */305	if ((params->supported_port_modes != USB_CTLR_MODE_HOST) && bdc_ec) {306		reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);307		reg &= ~BDC_EC_AXIRDA_RTS_MASK;308		reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);309		brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);310	}311 312	/*313	 * Disable FSM, otherwise the PHY will auto suspend when no314	 * device is connected and will be reset on resume.315	 */316	reg = brcm_usb_readl(usb_phy + USB_PHY_UTMI_CTL_1);317	reg &= ~USB_PHY_UTMI_CTL_1_POWER_UP_FSM_EN_MASK;318	brcm_usb_writel(reg, usb_phy + USB_PHY_UTMI_CTL_1);319 320	usb2_eye_fix_7211b0(params);321}322 323static void usb_init_common_7216(struct brcm_usb_init_params *params)324{325	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];326 327	USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);328	USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);329 330	/* 1 millisecond - for USB clocks to settle down */331	usleep_range(1000, 2000);332 333	/*334	 * Disable PHY when port is suspended335	 * Does not work in DRD mode336	 */337	if (params->supported_port_modes != USB_CTLR_MODE_DRD)338		USB_CTRL_SET(ctrl, P0_U2PHY_CFG1, COMMONONN);339 340	usb_wake_enable_7216(params, false);341	usb_init_common(params);342}343 344static void usb_init_xhci(struct brcm_usb_init_params *params)345{346	pr_debug("%s\n", __func__);347 348	xhci_soft_reset(params, 0);349}350 351static void usb_uninit_common_7216(struct brcm_usb_init_params *params)352{353	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];354 355	pr_debug("%s\n", __func__);356 357	if (params->wake_enabled) {358		/* Switch to using slower clock during suspend to save power */359		USB_CTRL_SET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);360		usb_wake_enable_7216(params, true);361	} else {362		USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);363	}364}365 366static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)367{368	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];369	void __iomem *usb_phy = params->regs[BRCM_REGS_USB_PHY];370	u32 reg;371 372	pr_debug("%s\n", __func__);373 374	if (params->wake_enabled) {375		USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);376		usb_wake_enable_7211b0(params, true);377	} else {378		USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);379		brcm_usb_writel(0, usb_phy + USB_PHY_PLL_LDO_CTL);380		reg = brcm_usb_readl(usb_phy + USB_PHY_PLL_CTL);381		reg &= ~USB_PHY_PLL_CTL_PLL_RESETB_MASK;382		brcm_usb_writel(reg, usb_phy + USB_PHY_PLL_CTL);383		brcm_usb_writel(USB_PHY_IDDQ_phy_iddq_MASK,384				usb_phy + USB_PHY_IDDQ);385	}386 387}388 389static void usb_uninit_xhci(struct brcm_usb_init_params *params)390{391 392	pr_debug("%s\n", __func__);393 394	if (!params->wake_enabled)395		xhci_soft_reset(params, 1);396}397 398static int usb_get_dual_select(struct brcm_usb_init_params *params)399{400	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];401	u32 reg = 0;402 403	pr_debug("%s\n", __func__);404 405	reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));406	reg &= USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);407	return reg;408}409 410static void usb_set_dual_select(struct brcm_usb_init_params *params)411{412	void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];413	u32 reg;414 415	pr_debug("%s\n", __func__);416 417	reg = brcm_usb_readl(USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));418	reg &= ~USB_CTRL_MASK(USB_DEVICE_CTL1, PORT_MODE);419	reg |= params->port_mode;420	brcm_usb_writel(reg, USB_CTRL_REG(ctrl, USB_DEVICE_CTL1));421}422 423static const struct brcm_usb_init_ops bcm7216_ops = {424	.init_ipp = usb_init_ipp,425	.init_common = usb_init_common_7216,426	.init_xhci = usb_init_xhci,427	.uninit_common = usb_uninit_common_7216,428	.uninit_xhci = usb_uninit_xhci,429	.get_dual_select = usb_get_dual_select,430	.set_dual_select = usb_set_dual_select,431};432 433static const struct brcm_usb_init_ops bcm7211b0_ops = {434	.init_ipp = usb_init_ipp,435	.init_common = usb_init_common_7211b0,436	.init_xhci = usb_init_xhci,437	.uninit_common = usb_uninit_common_7211b0,438	.uninit_xhci = usb_uninit_xhci,439	.get_dual_select = usb_get_dual_select,440	.set_dual_select = usb_set_dual_select,441};442 443void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params)444{445 446	pr_debug("%s\n", __func__);447 448	params->family_name = "7216";449	params->ops = &bcm7216_ops;450}451 452void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)453{454 455	pr_debug("%s\n", __func__);456 457	params->family_name = "7211";458	params->ops = &bcm7211b0_ops;459}460