mirror of
https://github.com/torvalds/linux.git
synced 2024-12-06 11:01:43 +00:00
usb: host: xhci-tegra: Separate firmware request and load
Subsequent patches for system suspend/resume support will need to reload the firmware on resume. Since the firmware remains in system memory, the driver doesn't need to reload it from the filesystem. However, the XUSB controller will be reset across suspend/resume, so it needs to load the firmware into its microcontroller on resume. Split the firmware request and the firmware load code into two separate functions so that the driver can reuse the firmware in system memory to reload the microcontroller on resume. Based on work by JC Kuo <jckuo@nvidia.com>. Signed-off-by: Thierry Reding <treding@nvidia.com> Link: https://lore.kernel.org/r/20191206140653.2085561-3-thierry.reding@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c763771504
commit
741d6e5d84
@ -793,17 +793,10 @@ disable_clk:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
||||
static int tegra_xusb_request_firmware(struct tegra_xusb *tegra)
|
||||
{
|
||||
unsigned int code_tag_blocks, code_size_blocks, code_blocks;
|
||||
struct tegra_xusb_fw_header *header;
|
||||
struct device *dev = tegra->dev;
|
||||
const struct firmware *fw;
|
||||
unsigned long timeout;
|
||||
time64_t timestamp;
|
||||
struct tm time;
|
||||
u64 address;
|
||||
u32 value;
|
||||
int err;
|
||||
|
||||
err = request_firmware(&fw, tegra->soc->firmware, tegra->dev);
|
||||
@ -828,6 +821,24 @@ static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
||||
memcpy(tegra->fw.virt, fw->data, tegra->fw.size);
|
||||
release_firmware(fw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_xusb_load_firmware(struct tegra_xusb *tegra)
|
||||
{
|
||||
unsigned int code_tag_blocks, code_size_blocks, code_blocks;
|
||||
struct tegra_xusb_fw_header *header;
|
||||
struct xhci_cap_regs __iomem *cap;
|
||||
struct xhci_op_regs __iomem *op;
|
||||
struct device *dev = tegra->dev;
|
||||
unsigned long timeout;
|
||||
time64_t timestamp;
|
||||
struct tm time;
|
||||
u64 address;
|
||||
u32 value;
|
||||
|
||||
header = (struct tegra_xusb_fw_header *)tegra->fw.virt;
|
||||
|
||||
if (csb_readl(tegra, XUSB_CSB_MP_ILOAD_BASE_LO) != 0) {
|
||||
dev_info(dev, "Firmware already loaded, Falcon state %#x\n",
|
||||
csb_readl(tegra, XUSB_FALC_CPUCTL));
|
||||
@ -1208,10 +1219,16 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
||||
goto put_rpm;
|
||||
}
|
||||
|
||||
err = tegra_xusb_request_firmware(tegra);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to request firmware: %d\n", err);
|
||||
goto disable_phy;
|
||||
}
|
||||
|
||||
err = tegra_xusb_load_firmware(tegra);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to load firmware: %d\n", err);
|
||||
goto put_rpm;
|
||||
goto free_firmware;
|
||||
}
|
||||
|
||||
tegra->hcd->regs = tegra->regs;
|
||||
@ -1221,7 +1238,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)
|
||||
err = usb_add_hcd(tegra->hcd, tegra->xhci_irq, IRQF_SHARED);
|
||||
if (err < 0) {
|
||||
dev_err(&pdev->dev, "failed to add USB HCD: %d\n", err);
|
||||
goto put_rpm;
|
||||
goto free_firmware;
|
||||
}
|
||||
|
||||
device_wakeup_enable(tegra->hcd->self.controller);
|
||||
@ -1281,6 +1298,9 @@ put_rpm:
|
||||
tegra_xusb_runtime_suspend(&pdev->dev);
|
||||
put_hcd:
|
||||
usb_put_hcd(tegra->hcd);
|
||||
free_firmware:
|
||||
dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt,
|
||||
tegra->fw.phys);
|
||||
disable_phy:
|
||||
tegra_xusb_phy_disable(tegra);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
Loading…
Reference in New Issue
Block a user