Skip to content
Snippets Groups Projects
Commit e1cc60c0 authored by Marek Vasut's avatar Marek Vasut Committed by Marek Vasut
Browse files

usb: xhci: Add Renesas R-Car xHCI driver


Add firmware V3, firmware loader and XHCI glue for the Renesas R-Car
Gen3 SoCs XHCI controller. Thus far only the R-Car Gen3 R8A7795 ES2.0+
and R8A7796 are supported.

Signed-off-by: default avatarMarek Vasut <marek.vasut+renesas@gmail.com>
Cc: Nobuhiro Iwamatsu <iwamatsu@nigauri.org>
Cc: Bin Meng <bmeng.cn@gmail.com>
parent 9829ce2f
No related branches found
No related tags found
No related merge requests found
Copyright (c) 2014, Renesas Electronics Corporation
All rights reserved.
Redistribution and use in binary form, without modification, are permitted
provided that the following conditions are met:
1. Redistribution in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
2. The name of Renesas Electronics Corporation may not be used to endorse or
promote products derived from this software without specific prior written
permission.
3. Reverse engineering, decompilation, or disassembly of this software is
not permitted.
THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS ELECTRONICS CORPORATION DISCLAIMS
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND
NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL RENESAS ELECTRONICS
CORPORATION BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
...@@ -47,6 +47,14 @@ config USB_XHCI_ROCKCHIP ...@@ -47,6 +47,14 @@ config USB_XHCI_ROCKCHIP
help help
Enables support for the on-chip xHCI controller on Rockchip SoCs. Enables support for the on-chip xHCI controller on Rockchip SoCs.
config USB_XHCI_RCAR
bool "Renesas RCar USB 3.0 support"
default y
depends on ARCH_RMOBILE
help
Choose this option to add support for USB 3.0 driver on Renesas
RCar Gen3 SoCs.
config USB_XHCI_STI config USB_XHCI_STI
bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller" bool "Support for STMicroelectronics STiH407 family on-chip xHCI USB controller"
depends on ARCH_STI depends on ARCH_STI
......
...@@ -59,6 +59,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o ...@@ -59,6 +59,7 @@ obj-$(CONFIG_USB_XHCI_FSL) += xhci-fsl.o
obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o obj-$(CONFIG_USB_XHCI_MVEBU) += xhci-mvebu.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o
obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o
obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o
# designware # designware
......
This diff is collapsed.
/*
* Copyright (C) 2017 Marek Vasut <marek.vasut@gmail.com>
*
* Renesas RCar USB HOST xHCI Controller
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <clk.h>
#include <dm.h>
#include <fdtdec.h>
#include <usb.h>
#include <wait_bit.h>
#include "xhci.h"
#include "xhci-rcar-r8a779x_usb3_v3.h"
/* Register Offset */
#define RCAR_USB3_DL_CTRL 0x250 /* FW Download Control & Status */
#define RCAR_USB3_FW_DATA0 0x258 /* FW Data0 */
/* Register Settings */
/* FW Download Control & Status */
#define RCAR_USB3_DL_CTRL_ENABLE BIT(0)
#define RCAR_USB3_DL_CTRL_FW_SUCCESS BIT(4)
#define RCAR_USB3_DL_CTRL_FW_SET_DATA0 BIT(8)
struct rcar_xhci_platdata {
fdt_addr_t hcd_base;
struct clk clk;
};
/**
* Contains pointers to register base addresses
* for the usb controller.
*/
struct rcar_xhci {
struct xhci_ctrl ctrl; /* Needs to come first in this struct! */
struct usb_platdata usb_plat;
struct xhci_hccr *hcd;
};
static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data,
const size_t fw_array_size)
{
void __iomem *regs = (void __iomem *)ctx->hcd;
int i, ret;
/* Download R-Car USB3.0 firmware */
setbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
for (i = 0; i < fw_array_size; i++) {
writel(fw_data[i], regs + RCAR_USB3_FW_DATA0);
setbits_le32(regs + RCAR_USB3_DL_CTRL,
RCAR_USB3_DL_CTRL_FW_SET_DATA0);
ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
RCAR_USB3_DL_CTRL_FW_SET_DATA0, false,
10, false);
if (ret)
break;
}
clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE);
ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL,
RCAR_USB3_DL_CTRL_FW_SUCCESS, true,
10, false);
return ret;
}
static int xhci_rcar_probe(struct udevice *dev)
{
struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
struct rcar_xhci *ctx = dev_get_priv(dev);
struct xhci_hcor *hcor;
int len, ret;
ret = clk_get_by_index(dev, 0, &plat->clk);
if (ret < 0) {
dev_err(dev, "Failed to get USB3 clock\n");
return ret;
}
ret = clk_enable(&plat->clk);
if (ret) {
dev_err(dev, "Failed to enable USB3 clock\n");
goto err_clk;
}
ctx->hcd = (struct xhci_hccr *)plat->hcd_base;
len = HC_LENGTH(xhci_readl(&ctx->hcd->cr_capbase));
hcor = (struct xhci_hcor *)((uintptr_t)ctx->hcd + len);
ret = xhci_rcar_download_fw(ctx, firmware_r8a779x_usb3_v3,
ARRAY_SIZE(firmware_r8a779x_usb3_v3));
if (ret) {
dev_err(dev, "Failed to download firmware\n");
goto err_fw;
}
ret = xhci_register(dev, ctx->hcd, hcor);
if (ret) {
dev_err(dev, "Failed to register xHCI\n");
goto err_fw;
}
return 0;
err_fw:
clk_disable(&plat->clk);
err_clk:
clk_free(&plat->clk);
return ret;
}
static int xhci_rcar_deregister(struct udevice *dev)
{
struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
clk_disable(&plat->clk);
clk_free(&plat->clk);
return xhci_deregister(dev);
}
static int xhci_rcar_ofdata_to_platdata(struct udevice *dev)
{
struct rcar_xhci_platdata *plat = dev_get_platdata(dev);
plat->hcd_base = devfdt_get_addr(dev);
if (plat->hcd_base == FDT_ADDR_T_NONE) {
debug("Can't get the XHCI register base address\n");
return -ENXIO;
}
return 0;
}
static const struct udevice_id xhci_rcar_ids[] = {
{ .compatible = "renesas,xhci-r8a7795" },
{ .compatible = "renesas,xhci-r8a7796" },
{ }
};
U_BOOT_DRIVER(usb_xhci) = {
.name = "xhci_rcar",
.id = UCLASS_USB,
.probe = xhci_rcar_probe,
.remove = xhci_rcar_deregister,
.ops = &xhci_usb_ops,
.of_match = xhci_rcar_ids,
.ofdata_to_platdata = xhci_rcar_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct rcar_xhci_platdata),
.priv_auto_alloc_size = sizeof(struct rcar_xhci),
.flags = DM_FLAG_ALLOC_PRIV_DMA,
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment