usb: dwc3: Set DMA and coherent masks early

dwc3 allocates scratch and event buffers in the top-level driver. Hack the
probe function to set the DMA mask before trying to allocate these.

I think the event buffers are only used in device mode, but the scratch
buffers may be used if core hibernation is enabled.

usb: dwc3: add support for new DT quirks

Apply the optional axi-pipe-limit and dis-in-autoretry-quirk properties
during driver probe.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>

phy: phy-brcm-usb: Add 2712 support

usb: dwc3: if the host controller instance number is present in DT, use it

If two instances of a dwc3 host controller are specified in devicetree,
then the probe order may be arbitrary which results in the device names
swapping on a per-boot basis.

If a "usb" alias with the instance number is specified, then use
that to construct the device name instead of autogenerating one.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>

rp1 dwc3 changes

drivers: usb: dwc3: allow setting GTXTHRCFG on dwc_usb3.0 hardware

Equivalent register fields exist in the SuperSpeed Host version of the
hardware, so allow the use of TX thresholds if specified in devicetree.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>

drivers: usb: dwc3: remove downstream quirk dis-in-autoretry

Upstream have unilaterally disabled the feature.

Partially reverts 6e9142a26ee0fdc3a5adc49ed6cedc0b16ec2ed1 (downstream)

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
This commit is contained in:
Jonathan Bell
2021-09-13 11:14:32 +01:00
committed by Dom Cobley
parent b4dd62d20a
commit 676ac97c6b
7 changed files with 144 additions and 3 deletions

View File

@@ -93,7 +93,7 @@ config PHY_BRCM_SATA
config PHY_BRCM_USB config PHY_BRCM_USB
tristate "Broadcom STB USB PHY driver" tristate "Broadcom STB USB PHY driver"
depends on ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST depends on ARCH_BCMBCA || ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST
depends on OF depends on OF
select GENERIC_PHY select GENERIC_PHY
select SOC_BRCMSTB if ARCH_BRCMSTB select SOC_BRCMSTB if ARCH_BRCMSTB

View File

@@ -356,6 +356,36 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params)
usb_init_common(params); usb_init_common(params);
} }
static void usb_init_common_2712(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
void __iomem *bdc_ec = params->regs[BRCM_REGS_BDC_EC];
u32 reg;
if (params->syscon_piarbctl)
syscon_piarbctl_init(params->syscon_piarbctl);
USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
usb_wake_enable_7211b0(params, false);
usb_init_common(params);
/*
* The BDC controller will get occasional failures with
* the default "Read Transaction Size" of 6 (1024 bytes).
* Set it to 4 (256 bytes).
*/
if ((params->supported_port_modes != USB_CTLR_MODE_HOST) && bdc_ec) {
reg = brcm_usb_readl(bdc_ec + BDC_EC_AXIRDA);
reg &= ~BDC_EC_AXIRDA_RTS_MASK;
reg |= (0x4 << BDC_EC_AXIRDA_RTS_SHIFT);
brcm_usb_writel(reg, bdc_ec + BDC_EC_AXIRDA);
}
usb2_eye_fix_7211b0(params);
}
static void usb_init_xhci(struct brcm_usb_init_params *params) static void usb_init_xhci(struct brcm_usb_init_params *params)
{ {
pr_debug("%s\n", __func__); pr_debug("%s\n", __func__);
@@ -437,6 +467,18 @@ static void usb_uninit_common_7211b0(struct brcm_usb_init_params *params)
} }
static void usb_uninit_common_2712(struct brcm_usb_init_params *params)
{
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
if (params->wake_enabled) {
USB_CTRL_SET(ctrl, TEST_PORT_CTL, TPOUT_SEL_PME_GEN);
usb_wake_enable_7211b0(params, true);
} else {
USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
}
}
static void usb_uninit_xhci(struct brcm_usb_init_params *params) static void usb_uninit_xhci(struct brcm_usb_init_params *params)
{ {
@@ -501,6 +543,16 @@ static const struct brcm_usb_init_ops bcm7211b0_ops = {
.set_dual_select = usb_set_dual_select, .set_dual_select = usb_set_dual_select,
}; };
static const struct brcm_usb_init_ops bcm2712_ops = {
.init_ipp = usb_init_ipp,
.init_common = usb_init_common_2712,
.init_xhci = usb_init_xhci,
.uninit_common = usb_uninit_common_2712,
.uninit_xhci = usb_uninit_xhci,
.get_dual_select = usb_get_dual_select,
.set_dual_select = usb_set_dual_select,
};
void brcm_usb_dvr_init_74110(struct brcm_usb_init_params *params) void brcm_usb_dvr_init_74110(struct brcm_usb_init_params *params)
{ {
params->family_name = "74110"; params->family_name = "74110";
@@ -524,3 +576,10 @@ void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params)
params->family_name = "7211"; params->family_name = "7211";
params->ops = &bcm7211b0_ops; params->ops = &bcm7211b0_ops;
} }
void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params)
{
params->family_name = "2712";
params->ops = &bcm2712_ops;
params->suspend_with_clocks = true;
}

View File

@@ -70,6 +70,7 @@ struct brcm_usb_init_params {
const struct brcm_usb_init_ops *ops; const struct brcm_usb_init_ops *ops;
struct regmap *syscon_piarbctl; struct regmap *syscon_piarbctl;
bool wake_enabled; bool wake_enabled;
bool suspend_with_clocks;
}; };
void brcm_usb_dvr_init_74110(struct brcm_usb_init_params *params); void brcm_usb_dvr_init_74110(struct brcm_usb_init_params *params);
@@ -77,6 +78,7 @@ void brcm_usb_dvr_init_4908(struct brcm_usb_init_params *params);
void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params); void brcm_usb_dvr_init_7445(struct brcm_usb_init_params *params);
void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params); void brcm_usb_dvr_init_7216(struct brcm_usb_init_params *params);
void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params); void brcm_usb_dvr_init_7211b0(struct brcm_usb_init_params *params);
void brcm_usb_dvr_init_2712(struct brcm_usb_init_params *params);
static inline u32 brcm_usb_readl(void __iomem *addr) static inline u32 brcm_usb_readl(void __iomem *addr)
{ {

View File

@@ -75,7 +75,7 @@ struct brcm_usb_phy_data {
}; };
static s8 *node_reg_names[BRCM_REGS_MAX] = { static s8 *node_reg_names[BRCM_REGS_MAX] = {
"crtl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec" "ctrl", "xhci_ec", "xhci_gbl", "usb_phy", "usb_mdio", "bdc_ec"
}; };
static int brcm_pm_notifier(struct notifier_block *notifier, static int brcm_pm_notifier(struct notifier_block *notifier,
@@ -325,6 +325,18 @@ static const struct match_chip_info chip_info_7211b0 = {
.optional_reg = BRCM_REGS_BDC_EC, .optional_reg = BRCM_REGS_BDC_EC,
}; };
static const struct match_chip_info chip_info_2712 = {
.init_func = &brcm_usb_dvr_init_2712,
.required_regs = {
BRCM_REGS_CTRL,
BRCM_REGS_XHCI_EC,
BRCM_REGS_XHCI_GBL,
BRCM_REGS_USB_MDIO,
-1,
},
.optional_reg = BRCM_REGS_BDC_EC,
};
static const struct match_chip_info chip_info_7445 = { static const struct match_chip_info chip_info_7445 = {
.init_func = &brcm_usb_dvr_init_7445, .init_func = &brcm_usb_dvr_init_7445,
.required_regs = { .required_regs = {
@@ -351,6 +363,10 @@ static const struct of_device_id brcm_usb_dt_ids[] = {
.compatible = "brcm,bcm7211-usb-phy", .compatible = "brcm,bcm7211-usb-phy",
.data = &chip_info_7211b0, .data = &chip_info_7211b0,
}, },
{
.compatible = "brcm,bcm2712-usb-phy",
.data = &chip_info_2712,
},
{ {
.compatible = "brcm,brcmstb-usb-phy", .compatible = "brcm,brcmstb-usb-phy",
.data = &chip_info_7445, .data = &chip_info_7445,

View File

@@ -1321,6 +1321,24 @@ static void dwc3_config_threshold(struct dwc3 *dwc)
} }
} }
static void dwc3_set_axi_pipe_limit(struct dwc3 *dwc)
{
struct device *dev = dwc->dev;
u32 cfg;
if (!dwc->axi_pipe_limit)
return;
if (dwc->axi_pipe_limit > 16) {
dev_err(dev, "Invalid axi_pipe_limit property\n");
return;
}
cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG1);
cfg &= ~DWC3_GSBUSCFG1_PIPETRANSLIMIT(15);
cfg |= DWC3_GSBUSCFG1_PIPETRANSLIMIT(dwc->axi_pipe_limit - 1);
dwc3_writel(dwc->regs, DWC3_GSBUSCFG1, cfg);
}
/** /**
* dwc3_core_init - Low-level initialization of DWC3 Core * dwc3_core_init - Low-level initialization of DWC3 Core
* @dwc: Pointer to our controller context structure * @dwc: Pointer to our controller context structure
@@ -1388,6 +1406,8 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_config_soc_bus(dwc); dwc3_config_soc_bus(dwc);
dwc3_set_axi_pipe_limit(dwc);
ret = dwc3_phy_power_on(dwc); ret = dwc3_phy_power_on(dwc);
if (ret) if (ret)
goto err_exit_phy; goto err_exit_phy;
@@ -1516,6 +1536,24 @@ static int dwc3_core_init(struct dwc3 *dwc)
dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
} }
if (DWC3_IP_IS(DWC3) && dwc->dr_mode == USB_DR_MODE_HOST) {
u8 tx_thr_num = dwc->tx_thr_num_pkt_prd;
u8 tx_maxburst = dwc->tx_max_burst_prd;
if (tx_thr_num && tx_maxburst) {
reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
reg |= DWC3_GTXTHRCFG_PKTCNTSEL;
reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0);
reg |= DWC3_GTXTHRCFG_TXPKTCNT(tx_thr_num);
reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0);
reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
}
}
return 0; return 0;
err_power_off_phy: err_power_off_phy:
@@ -1702,6 +1740,7 @@ static void dwc3_get_properties(struct dwc3 *dwc)
u8 tx_max_burst_prd = 0; u8 tx_max_burst_prd = 0;
u8 tx_fifo_resize_max_num; u8 tx_fifo_resize_max_num;
u16 num_hc_interrupters; u16 num_hc_interrupters;
u8 axi_pipe_limit;
/* default to highest possible threshold */ /* default to highest possible threshold */
lpm_nyet_threshold = 0xf; lpm_nyet_threshold = 0xf;
@@ -1724,6 +1763,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
/* default to a single XHCI interrupter */ /* default to a single XHCI interrupter */
num_hc_interrupters = 1; num_hc_interrupters = 1;
/* Default to 0 (don't override hardware defaults) */
axi_pipe_limit = 0;
dwc->maximum_speed = usb_get_maximum_speed(dev); dwc->maximum_speed = usb_get_maximum_speed(dev);
dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev); dwc->max_ssp_rate = usb_get_maximum_ssp_rate(dev);
@@ -1845,6 +1886,9 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->dis_split_quirk = device_property_read_bool(dev, dwc->dis_split_quirk = device_property_read_bool(dev,
"snps,dis-split-quirk"); "snps,dis-split-quirk");
device_property_read_u8(dev, "snps,axi-pipe-limit",
&axi_pipe_limit);
dwc->lpm_nyet_threshold = lpm_nyet_threshold; dwc->lpm_nyet_threshold = lpm_nyet_threshold;
dwc->tx_de_emphasis = tx_de_emphasis; dwc->tx_de_emphasis = tx_de_emphasis;
@@ -1862,6 +1906,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd; dwc->tx_thr_num_pkt_prd = tx_thr_num_pkt_prd;
dwc->tx_max_burst_prd = tx_max_burst_prd; dwc->tx_max_burst_prd = tx_max_burst_prd;
dwc->axi_pipe_limit = axi_pipe_limit;
dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num; dwc->tx_fifo_resize_max_num = tx_fifo_resize_max_num;
dwc->num_hc_interrupters = num_hc_interrupters; dwc->num_hc_interrupters = num_hc_interrupters;
@@ -2211,6 +2257,12 @@ int dwc3_core_probe(const struct dwc3_probe_data *data)
if (IS_ERR(dwc->usb_psy)) if (IS_ERR(dwc->usb_psy))
return dev_err_probe(dev, PTR_ERR(dwc->usb_psy), "couldn't get usb power supply\n"); return dev_err_probe(dev, PTR_ERR(dwc->usb_psy), "couldn't get usb power supply\n");
if (!dwc->sysdev_is_parent) {
ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
if (ret)
return ret;
}
if (!data->ignore_clocks_and_resets) { if (!data->ignore_clocks_and_resets) {
dwc->reset = devm_reset_control_array_get_optional_shared(dev); dwc->reset = devm_reset_control_array_get_optional_shared(dev);
if (IS_ERR(dwc->reset)) { if (IS_ERR(dwc->reset)) {

View File

@@ -198,6 +198,9 @@
#define DWC3_GSBUSCFG0_REQINFO(n) (((n) & 0xffff) << 16) #define DWC3_GSBUSCFG0_REQINFO(n) (((n) & 0xffff) << 16)
#define DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED 0xffffffff #define DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED 0xffffffff
/* Global SoC Bus Configuration Register 1 */
#define DWC3_GSBUSCFG1_PIPETRANSLIMIT(n) (((n) & 0xf) << 8)
/* Global Debug LSP MUX Select */ /* Global Debug LSP MUX Select */
#define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */ #define DWC3_GDBGLSPMUX_ENDBC BIT(15) /* Host only */
#define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff) #define DWC3_GDBGLSPMUX_HOSTSELECT(n) ((n) & 0x3fff)
@@ -1084,6 +1087,7 @@ struct dwc3_scratchpad_array {
* @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize * @tx_fifo_resize_max_num: max number of fifos allocated during txfifo resize
* @clear_stall_protocol: endpoint number that requires a delayed status phase * @clear_stall_protocol: endpoint number that requires a delayed status phase
* @num_hc_interrupters: number of host controller interrupters * @num_hc_interrupters: number of host controller interrupters
* @axi_max_pipe: set to override the maximum number of pipelined AXI transfers
* @hsphy_interface: "utmi" or "ulpi" * @hsphy_interface: "utmi" or "ulpi"
* @connected: true when we're connected to a host, false otherwise * @connected: true when we're connected to a host, false otherwise
* @softconnect: true when gadget connect is called, false when disconnect runs * @softconnect: true when gadget connect is called, false when disconnect runs
@@ -1335,6 +1339,7 @@ struct dwc3 {
u8 tx_fifo_resize_max_num; u8 tx_fifo_resize_max_num;
u8 clear_stall_protocol; u8 clear_stall_protocol;
u16 num_hc_interrupters; u16 num_hc_interrupters;
u8 axi_pipe_limit;
const char *hsphy_interface; const char *hsphy_interface;

View File

@@ -126,10 +126,12 @@ out:
int dwc3_host_init(struct dwc3 *dwc) int dwc3_host_init(struct dwc3 *dwc)
{ {
struct platform_device *pdev = to_platform_device(dwc->dev);
struct property_entry props[6]; struct property_entry props[6];
struct platform_device *xhci; struct platform_device *xhci;
int ret, irq; int ret, irq;
int prop_idx = 0; int prop_idx = 0;
int id;
/* /*
* Some platforms need to power off all Root hub ports immediately after DWC3 set to host * Some platforms need to power off all Root hub ports immediately after DWC3 set to host
@@ -141,7 +143,12 @@ int dwc3_host_init(struct dwc3 *dwc)
if (irq < 0) if (irq < 0)
return irq; return irq;
id = of_alias_get_id(pdev->dev.of_node, "usb");
if (id >= 0)
xhci = platform_device_alloc("xhci-hcd", id);
else
xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO); xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
if (!xhci) { if (!xhci) {
dev_err(dwc->dev, "couldn't allocate xHCI device\n"); dev_err(dwc->dev, "couldn't allocate xHCI device\n");
return -ENOMEM; return -ENOMEM;