| // SPDX-License-Identifier: GPL-2.0 | 
 | /* Copyright (C) 2019-2020 Linaro Limited */ | 
 |  | 
 | #include <linux/acpi.h> | 
 | #include <linux/firmware.h> | 
 | #include <linux/module.h> | 
 | #include <linux/pci.h> | 
 | #include <linux/slab.h> | 
 | #include <linux/unaligned.h> | 
 |  | 
 | #include "xhci.h" | 
 | #include "xhci-trace.h" | 
 | #include "xhci-pci.h" | 
 |  | 
 | #define RENESAS_FW_VERSION				0x6C | 
 | #define RENESAS_ROM_CONFIG				0xF0 | 
 | #define RENESAS_FW_STATUS				0xF4 | 
 | #define RENESAS_FW_STATUS_MSB				0xF5 | 
 | #define RENESAS_ROM_STATUS				0xF6 | 
 | #define RENESAS_ROM_STATUS_MSB				0xF7 | 
 | #define RENESAS_DATA0					0xF8 | 
 | #define RENESAS_DATA1					0xFC | 
 |  | 
 | #define RENESAS_FW_VERSION_FIELD			GENMASK(23, 7) | 
 | #define RENESAS_FW_VERSION_OFFSET			8 | 
 |  | 
 | #define RENESAS_FW_STATUS_DOWNLOAD_ENABLE		BIT(0) | 
 | #define RENESAS_FW_STATUS_LOCK				BIT(1) | 
 | #define RENESAS_FW_STATUS_RESULT			GENMASK(6, 4) | 
 |   #define RENESAS_FW_STATUS_INVALID			0 | 
 |   #define RENESAS_FW_STATUS_SUCCESS			BIT(4) | 
 |   #define RENESAS_FW_STATUS_ERROR			BIT(5) | 
 | #define RENESAS_FW_STATUS_SET_DATA0			BIT(8) | 
 | #define RENESAS_FW_STATUS_SET_DATA1			BIT(9) | 
 |  | 
 | #define RENESAS_ROM_STATUS_ACCESS			BIT(0) | 
 | #define RENESAS_ROM_STATUS_ERASE			BIT(1) | 
 | #define RENESAS_ROM_STATUS_RELOAD			BIT(2) | 
 | #define RENESAS_ROM_STATUS_RESULT			GENMASK(6, 4) | 
 |   #define RENESAS_ROM_STATUS_NO_RESULT			0 | 
 |   #define RENESAS_ROM_STATUS_SUCCESS			BIT(4) | 
 |   #define RENESAS_ROM_STATUS_ERROR			BIT(5) | 
 | #define RENESAS_ROM_STATUS_SET_DATA0			BIT(8) | 
 | #define RENESAS_ROM_STATUS_SET_DATA1			BIT(9) | 
 | #define RENESAS_ROM_STATUS_ROM_EXISTS			BIT(15) | 
 |  | 
 | #define RENESAS_ROM_ERASE_MAGIC				0x5A65726F | 
 | #define RENESAS_ROM_WRITE_MAGIC				0x53524F4D | 
 |  | 
 | #define RENESAS_RETRY			50000	/* 50000 * RENESAS_DELAY ~= 500ms */ | 
 | #define RENESAS_CHIP_ERASE_RETRY	500000	/* 500000 * RENESAS_DELAY ~= 5s */ | 
 | #define RENESAS_DELAY			10 | 
 |  | 
 | #define RENESAS_FW_NAME	"renesas_usb_fw.mem" | 
 |  | 
 | static int renesas_fw_download_image(struct pci_dev *dev, | 
 | 				     const u32 *fw, size_t step, bool rom) | 
 | { | 
 | 	size_t i; | 
 | 	int err; | 
 | 	u8 fw_status; | 
 | 	bool data0_or_data1; | 
 | 	u32 status_reg; | 
 |  | 
 | 	if (rom) | 
 | 		status_reg = RENESAS_ROM_STATUS_MSB; | 
 | 	else | 
 | 		status_reg = RENESAS_FW_STATUS_MSB; | 
 |  | 
 | 	/* | 
 | 	 * The hardware does alternate between two 32-bit pages. | 
 | 	 * (This is because each row of the firmware is 8 bytes). | 
 | 	 * | 
 | 	 * for even steps we use DATA0, for odd steps DATA1. | 
 | 	 */ | 
 | 	data0_or_data1 = (step & 1) == 1; | 
 |  | 
 | 	/* step+1. Read "Set DATAX" and confirm it is cleared. */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(dev, status_reg, &fw_status); | 
 | 		if (err) { | 
 | 			dev_err(&dev->dev, "Read Status failed: %d\n", | 
 | 				pcibios_err_to_errno(err)); | 
 | 			return pcibios_err_to_errno(err); | 
 | 		} | 
 | 		if (!(fw_status & BIT(data0_or_data1))) | 
 | 			break; | 
 |  | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) { | 
 | 		dev_err(&dev->dev, "Timeout for Set DATAX step: %zd\n", step); | 
 | 		return -ETIMEDOUT; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * step+2. Write FW data to "DATAX". | 
 | 	 * "LSB is left" => force little endian | 
 | 	 */ | 
 | 	err = pci_write_config_dword(dev, data0_or_data1 ? | 
 | 				     RENESAS_DATA1 : RENESAS_DATA0, | 
 | 				     (__force u32)cpu_to_le32(fw[step])); | 
 | 	if (err) { | 
 | 		dev_err(&dev->dev, "Write to DATAX failed: %d\n", | 
 | 			pcibios_err_to_errno(err)); | 
 | 		return pcibios_err_to_errno(err); | 
 | 	} | 
 |  | 
 | 	udelay(100); | 
 |  | 
 | 	/* step+3. Set "Set DATAX". */ | 
 | 	err = pci_write_config_byte(dev, status_reg, BIT(data0_or_data1)); | 
 | 	if (err) { | 
 | 		dev_err(&dev->dev, "Write config for DATAX failed: %d\n", | 
 | 			pcibios_err_to_errno(err)); | 
 | 		return pcibios_err_to_errno(err); | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int renesas_fw_verify(const void *fw_data, | 
 | 			     size_t length) | 
 | { | 
 | 	u16 fw_version_pointer; | 
 |  | 
 | 	/* | 
 | 	 * The Firmware's Data Format is describe in | 
 | 	 * "6.3 Data Format" R19UH0078EJ0500 Rev.5.00 page 124 | 
 | 	 */ | 
 |  | 
 | 	/* | 
 | 	 * The bootrom chips of the big brother have sizes up to 64k, let's | 
 | 	 * assume that's the biggest the firmware can get. | 
 | 	 */ | 
 | 	if (length < 0x1000 || length >= 0x10000) { | 
 | 		pr_err("firmware is size %zd is not (4k - 64k).", | 
 | 			length); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	/* The First 2 bytes are fixed value (55aa). "LSB on Left" */ | 
 | 	if (get_unaligned_le16(fw_data) != 0x55aa) { | 
 | 		pr_err("no valid firmware header found."); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	/* verify the firmware version position and print it. */ | 
 | 	fw_version_pointer = get_unaligned_le16(fw_data + 4); | 
 | 	if (fw_version_pointer + 2 >= length) { | 
 | 		pr_err("fw ver pointer is outside of the firmware image"); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static bool renesas_check_rom(struct pci_dev *pdev) | 
 | { | 
 | 	u16 rom_status; | 
 | 	int retval; | 
 |  | 
 | 	/* Check if external ROM exists */ | 
 | 	retval = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_status); | 
 | 	if (retval) | 
 | 		return false; | 
 |  | 
 | 	rom_status &= RENESAS_ROM_STATUS_ROM_EXISTS; | 
 | 	if (rom_status) { | 
 | 		dev_dbg(&pdev->dev, "External ROM exists\n"); | 
 | 		return true; /* External ROM exists */ | 
 | 	} | 
 |  | 
 | 	return false; | 
 | } | 
 |  | 
 | static int renesas_check_rom_state(struct pci_dev *pdev) | 
 | { | 
 | 	u16 rom_state; | 
 | 	u32 version; | 
 | 	int err; | 
 |  | 
 | 	/* check FW version */ | 
 | 	err = pci_read_config_dword(pdev, RENESAS_FW_VERSION, &version); | 
 | 	if (err) | 
 | 		return pcibios_err_to_errno(err); | 
 |  | 
 | 	version &= RENESAS_FW_VERSION_FIELD; | 
 | 	version = version >> RENESAS_FW_VERSION_OFFSET; | 
 | 	dev_dbg(&pdev->dev, "Found ROM version: %x\n", version); | 
 |  | 
 | 	/* | 
 | 	 * Test if ROM is present and loaded, if so we can skip everything | 
 | 	 */ | 
 | 	err = pci_read_config_word(pdev, RENESAS_ROM_STATUS, &rom_state); | 
 | 	if (err) | 
 | 		return pcibios_err_to_errno(err); | 
 |  | 
 | 	if (rom_state & RENESAS_ROM_STATUS_ROM_EXISTS) { | 
 | 		/* ROM exists */ | 
 | 		dev_dbg(&pdev->dev, "ROM exists\n"); | 
 |  | 
 | 		/* Check the "Result Code" Bits (6:4) and act accordingly */ | 
 | 		switch (rom_state & RENESAS_ROM_STATUS_RESULT) { | 
 | 		case RENESAS_ROM_STATUS_SUCCESS: | 
 | 			return 0; | 
 |  | 
 | 		case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */ | 
 | 			dev_dbg(&pdev->dev, "Unknown ROM status ...\n"); | 
 | 			return -ENOENT; | 
 |  | 
 | 		case RENESAS_ROM_STATUS_ERROR: /* Error State */ | 
 | 		default: /* All other states are marked as "Reserved states" */ | 
 | 			dev_err(&pdev->dev, "Invalid ROM.."); | 
 | 			break; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return -EIO; | 
 | } | 
 |  | 
 | static int renesas_fw_check_running(struct pci_dev *pdev) | 
 | { | 
 | 	u8 fw_state; | 
 | 	int err; | 
 |  | 
 | 	/* | 
 | 	 * Test if the device is actually needing the firmware. As most | 
 | 	 * BIOSes will initialize the device for us. If the device is | 
 | 	 * initialized. | 
 | 	 */ | 
 | 	err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_state); | 
 | 	if (err) | 
 | 		return pcibios_err_to_errno(err); | 
 |  | 
 | 	/* | 
 | 	 * Check if "FW Download Lock" is locked. If it is and the FW is | 
 | 	 * ready we can simply continue. If the FW is not ready, we have | 
 | 	 * to give up. | 
 | 	 */ | 
 | 	if (fw_state & RENESAS_FW_STATUS_LOCK) { | 
 | 		dev_dbg(&pdev->dev, "FW Download Lock is engaged."); | 
 |  | 
 | 		if (fw_state & RENESAS_FW_STATUS_SUCCESS) | 
 | 			return 0; | 
 |  | 
 | 		dev_err(&pdev->dev, | 
 | 			"FW Download Lock is set and FW is not ready. Giving Up."); | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * Check if "FW Download Enable" is set. If someone (us?) tampered | 
 | 	 * with it and it can't be reset, we have to give up too... and | 
 | 	 * ask for a forgiveness and a reboot. | 
 | 	 */ | 
 | 	if (fw_state & RENESAS_FW_STATUS_DOWNLOAD_ENABLE) { | 
 | 		dev_err(&pdev->dev, | 
 | 			"FW Download Enable is stale. Giving Up (poweroff/reboot needed)."); | 
 | 		return -EIO; | 
 | 	} | 
 |  | 
 | 	/* Otherwise, Check the "Result Code" Bits (6:4) and act accordingly */ | 
 | 	switch (fw_state & RENESAS_FW_STATUS_RESULT) { | 
 | 	case 0: /* No result yet */ | 
 | 		dev_dbg(&pdev->dev, "FW is not ready/loaded yet."); | 
 |  | 
 | 		/* tell the caller, that this device needs the firmware. */ | 
 | 		return 1; | 
 |  | 
 | 	case RENESAS_FW_STATUS_SUCCESS: /* Success, device should be working. */ | 
 | 		dev_dbg(&pdev->dev, "FW is ready."); | 
 | 		return 0; | 
 |  | 
 | 	case RENESAS_FW_STATUS_ERROR: /* Error State */ | 
 | 		dev_err(&pdev->dev, | 
 | 			"hardware is in an error state. Giving up (poweroff/reboot needed)."); | 
 | 		return -ENODEV; | 
 |  | 
 | 	default: /* All other states are marked as "Reserved states" */ | 
 | 		dev_err(&pdev->dev, | 
 | 			"hardware is in an invalid state %lx. Giving up (poweroff/reboot needed).", | 
 | 			(fw_state & RENESAS_FW_STATUS_RESULT) >> 4); | 
 | 		return -EINVAL; | 
 | 	} | 
 | } | 
 |  | 
 | static int renesas_fw_download(struct pci_dev *pdev, | 
 | 			       const struct firmware *fw) | 
 | { | 
 | 	const u32 *fw_data = (const u32 *)fw->data; | 
 | 	size_t i; | 
 | 	int err; | 
 | 	u8 fw_status; | 
 |  | 
 | 	/* | 
 | 	 * For more information and the big picture: please look at the | 
 | 	 * "Firmware Download Sequence" in "7.1 FW Download Interface" | 
 | 	 * of R19UH0078EJ0500 Rev.5.00 page 131 | 
 | 	 */ | 
 |  | 
 | 	/* | 
 | 	 * 0. Set "FW Download Enable" bit in the | 
 | 	 * "FW Download Control & Status Register" at 0xF4 | 
 | 	 */ | 
 | 	err = pci_write_config_byte(pdev, RENESAS_FW_STATUS, | 
 | 				    RENESAS_FW_STATUS_DOWNLOAD_ENABLE); | 
 | 	if (err) | 
 | 		return pcibios_err_to_errno(err); | 
 |  | 
 | 	/* 1 - 10 follow one step after the other. */ | 
 | 	for (i = 0; i < fw->size / 4; i++) { | 
 | 		err = renesas_fw_download_image(pdev, fw_data, i, false); | 
 | 		if (err) { | 
 | 			dev_err(&pdev->dev, | 
 | 				"Firmware Download Step %zd failed at position %zd bytes with (%d).", | 
 | 				i, i * 4, err); | 
 | 			return err; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * This sequence continues until the last data is written to | 
 | 	 * "DATA0" or "DATA1". Naturally, we wait until "SET DATA0/1" | 
 | 	 * is cleared by the hardware beforehand. | 
 | 	 */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS_MSB, | 
 | 					   &fw_status); | 
 | 		if (err) | 
 | 			return pcibios_err_to_errno(err); | 
 | 		if (!(fw_status & (BIT(0) | BIT(1)))) | 
 | 			break; | 
 |  | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) | 
 | 		dev_warn(&pdev->dev, "Final Firmware Download step timed out."); | 
 |  | 
 | 	/* | 
 | 	 * 11. After finishing writing the last data of FW, the | 
 | 	 * System Software must clear "FW Download Enable" | 
 | 	 */ | 
 | 	err = pci_write_config_byte(pdev, RENESAS_FW_STATUS, 0); | 
 | 	if (err) | 
 | 		return pcibios_err_to_errno(err); | 
 |  | 
 | 	/* 12. Read "Result Code" and confirm it is good. */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(pdev, RENESAS_FW_STATUS, &fw_status); | 
 | 		if (err) | 
 | 			return pcibios_err_to_errno(err); | 
 | 		if (fw_status & RENESAS_FW_STATUS_SUCCESS) | 
 | 			break; | 
 |  | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) { | 
 | 		/* Timed out / Error - let's see if we can fix this */ | 
 | 		err = renesas_fw_check_running(pdev); | 
 | 		switch (err) { | 
 | 		case 0: /* | 
 | 			 * we shouldn't end up here. | 
 | 			 * maybe it took a little bit longer. | 
 | 			 * But all should be well? | 
 | 			 */ | 
 | 			break; | 
 |  | 
 | 		case 1: /* (No result yet! */ | 
 | 			dev_err(&pdev->dev, "FW Load timedout"); | 
 | 			return -ETIMEDOUT; | 
 |  | 
 | 		default: | 
 | 			return err; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static void renesas_rom_erase(struct pci_dev *pdev) | 
 | { | 
 | 	int retval, i; | 
 | 	u8 status; | 
 |  | 
 | 	dev_dbg(&pdev->dev, "Performing ROM Erase...\n"); | 
 | 	retval = pci_write_config_dword(pdev, RENESAS_DATA0, | 
 | 					RENESAS_ROM_ERASE_MAGIC); | 
 | 	if (retval) { | 
 | 		dev_err(&pdev->dev, "ROM erase, magic word write failed: %d\n", | 
 | 			pcibios_err_to_errno(retval)); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status); | 
 | 	if (retval) { | 
 | 		dev_err(&pdev->dev, "ROM status read failed: %d\n", | 
 | 			pcibios_err_to_errno(retval)); | 
 | 		return; | 
 | 	} | 
 | 	status |= RENESAS_ROM_STATUS_ERASE; | 
 | 	retval = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, status); | 
 | 	if (retval) { | 
 | 		dev_err(&pdev->dev, "ROM erase set word write failed\n"); | 
 | 		return; | 
 | 	} | 
 |  | 
 | 	/* sleep a bit while ROM is erased */ | 
 | 	msleep(20); | 
 |  | 
 | 	for (i = 0; i < RENESAS_CHIP_ERASE_RETRY; i++) { | 
 | 		retval = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, | 
 | 					      &status); | 
 | 		status &= RENESAS_ROM_STATUS_ERASE; | 
 | 		if (!status) | 
 | 			break; | 
 |  | 
 | 		mdelay(RENESAS_DELAY); | 
 | 	} | 
 |  | 
 | 	if (i == RENESAS_RETRY) | 
 | 		dev_dbg(&pdev->dev, "Chip erase timedout: %x\n", status); | 
 |  | 
 | 	dev_dbg(&pdev->dev, "ROM Erase... Done success\n"); | 
 | } | 
 |  | 
 | static bool renesas_setup_rom(struct pci_dev *pdev, const struct firmware *fw) | 
 | { | 
 | 	const u32 *fw_data = (const u32 *)fw->data; | 
 | 	int err, i; | 
 | 	u8 status; | 
 |  | 
 | 	/* 2. Write magic word to Data0 */ | 
 | 	err = pci_write_config_dword(pdev, RENESAS_DATA0, | 
 | 				     RENESAS_ROM_WRITE_MAGIC); | 
 | 	if (err) | 
 | 		return false; | 
 |  | 
 | 	/* 3. Set External ROM access */ | 
 | 	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, | 
 | 				    RENESAS_ROM_STATUS_ACCESS); | 
 | 	if (err) | 
 | 		goto remove_bypass; | 
 |  | 
 | 	/* 4. Check the result */ | 
 | 	err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status); | 
 | 	if (err) | 
 | 		goto remove_bypass; | 
 | 	status &= GENMASK(6, 4); | 
 | 	if (status) { | 
 | 		dev_err(&pdev->dev, | 
 | 			"setting external rom failed: %x\n", status); | 
 | 		goto remove_bypass; | 
 | 	} | 
 |  | 
 | 	/* 5 to 16 Write FW to DATA0/1 while checking SetData0/1 */ | 
 | 	for (i = 0; i < fw->size / 4; i++) { | 
 | 		err = renesas_fw_download_image(pdev, fw_data, i, true); | 
 | 		if (err) { | 
 | 			dev_err(&pdev->dev, | 
 | 				"ROM Download Step %d failed at position %d bytes with (%d)\n", | 
 | 				 i, i * 4, err); | 
 | 			goto remove_bypass; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * wait till DATA0/1 is cleared | 
 | 	 */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB, | 
 | 					   &status); | 
 | 		if (err) | 
 | 			goto remove_bypass; | 
 | 		if (!(status & (BIT(0) | BIT(1)))) | 
 | 			break; | 
 |  | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) { | 
 | 		dev_err(&pdev->dev, "Final Firmware ROM Download step timed out\n"); | 
 | 		goto remove_bypass; | 
 | 	} | 
 |  | 
 | 	/* 17. Remove bypass */ | 
 | 	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0); | 
 | 	if (err) | 
 | 		return false; | 
 |  | 
 | 	udelay(10); | 
 |  | 
 | 	/* 18. check result */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status); | 
 | 		if (err) { | 
 | 			dev_err(&pdev->dev, "Read ROM status failed:%d\n", | 
 | 				pcibios_err_to_errno(err)); | 
 | 			return false; | 
 | 		} | 
 | 		status &= RENESAS_ROM_STATUS_RESULT; | 
 | 		if (status ==  RENESAS_ROM_STATUS_SUCCESS) { | 
 | 			dev_dbg(&pdev->dev, "Download ROM success\n"); | 
 | 			break; | 
 | 		} | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) { /* Timed out */ | 
 | 		dev_err(&pdev->dev, | 
 | 			"Download to external ROM TO: %x\n", status); | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	dev_dbg(&pdev->dev, "Download to external ROM succeeded\n"); | 
 |  | 
 | 	/* Last step set Reload */ | 
 | 	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS, | 
 | 				    RENESAS_ROM_STATUS_RELOAD); | 
 | 	if (err) { | 
 | 		dev_err(&pdev->dev, "Set ROM execute failed: %d\n", | 
 | 			pcibios_err_to_errno(err)); | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * wait till Reload is cleared | 
 | 	 */ | 
 | 	for (i = 0; i < RENESAS_RETRY; i++) { | 
 | 		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS, &status); | 
 | 		if (err) | 
 | 			return false; | 
 | 		if (!(status & RENESAS_ROM_STATUS_RELOAD)) | 
 | 			break; | 
 |  | 
 | 		udelay(RENESAS_DELAY); | 
 | 	} | 
 | 	if (i == RENESAS_RETRY) { | 
 | 		dev_err(&pdev->dev, "ROM Exec timed out: %x\n", status); | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	return true; | 
 |  | 
 | remove_bypass: | 
 | 	pci_write_config_byte(pdev, RENESAS_ROM_STATUS, 0); | 
 | 	return false; | 
 | } | 
 |  | 
 | static int renesas_load_fw(struct pci_dev *pdev, const struct firmware *fw) | 
 | { | 
 | 	int err = 0; | 
 | 	bool rom; | 
 |  | 
 | 	/* Check if the device has external ROM */ | 
 | 	rom = renesas_check_rom(pdev); | 
 | 	if (rom) { | 
 | 		/* perform chip erase first */ | 
 | 		renesas_rom_erase(pdev); | 
 |  | 
 | 		/* lets try loading fw on ROM first */ | 
 | 		rom = renesas_setup_rom(pdev, fw); | 
 | 		if (!rom) { | 
 | 			dev_dbg(&pdev->dev, | 
 | 				"ROM load failed, falling back on FW load\n"); | 
 | 		} else { | 
 | 			dev_dbg(&pdev->dev, | 
 | 				"ROM load success\n"); | 
 | 			goto exit; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	err = renesas_fw_download(pdev, fw); | 
 |  | 
 | exit: | 
 | 	if (err) | 
 | 		dev_err(&pdev->dev, "firmware failed to download (%d).", err); | 
 | 	return err; | 
 | } | 
 |  | 
 | static int renesas_xhci_check_request_fw(struct pci_dev *pdev, | 
 | 					 const struct pci_device_id *id) | 
 | { | 
 | 	const char fw_name[] = RENESAS_FW_NAME; | 
 | 	const struct firmware *fw; | 
 | 	bool has_rom; | 
 | 	int err; | 
 |  | 
 | 	/* Check if device has ROM and loaded, if so skip everything */ | 
 | 	has_rom = renesas_check_rom(pdev); | 
 | 	if (has_rom) { | 
 | 		err = renesas_check_rom_state(pdev); | 
 | 		if (!err) | 
 | 			return 0; | 
 | 		else if (err != -ENOENT) | 
 | 			has_rom = false; | 
 | 	} | 
 |  | 
 | 	err = renesas_fw_check_running(pdev); | 
 | 	/* Continue ahead, if the firmware is already running. */ | 
 | 	if (!err) | 
 | 		return 0; | 
 |  | 
 | 	/* no firmware interface available */ | 
 | 	if (err != 1) | 
 | 		return has_rom ? 0 : err; | 
 |  | 
 | 	pci_dev_get(pdev); | 
 | 	err = firmware_request_nowarn(&fw, fw_name, &pdev->dev); | 
 | 	pci_dev_put(pdev); | 
 | 	if (err) { | 
 | 		if (has_rom) { | 
 | 			dev_info(&pdev->dev, "failed to load firmware %s, fallback to ROM\n", | 
 | 				 fw_name); | 
 | 			return 0; | 
 | 		} | 
 | 		dev_err(&pdev->dev, "failed to load firmware %s: %d\n", | 
 | 			fw_name, err); | 
 | 		return err; | 
 | 	} | 
 |  | 
 | 	err = renesas_fw_verify(fw->data, fw->size); | 
 | 	if (err) | 
 | 		goto exit; | 
 |  | 
 | 	err = renesas_load_fw(pdev, fw); | 
 | exit: | 
 | 	release_firmware(fw); | 
 | 	return err; | 
 | } | 
 |  | 
 | static int | 
 | xhci_pci_renesas_probe(struct pci_dev *dev, const struct pci_device_id *id) | 
 | { | 
 | 	int retval; | 
 |  | 
 | 	retval = renesas_xhci_check_request_fw(dev, id); | 
 | 	if (retval) | 
 | 		return retval; | 
 |  | 
 | 	return xhci_pci_common_probe(dev, id); | 
 | } | 
 |  | 
 | static const struct pci_device_id pci_ids[] = { | 
 | 	{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0014) }, | 
 | 	{ PCI_DEVICE(PCI_VENDOR_ID_RENESAS, 0x0015) }, | 
 | 	{ /* end: all zeroes */ } | 
 | }; | 
 | MODULE_DEVICE_TABLE(pci, pci_ids); | 
 |  | 
 | static struct pci_driver xhci_renesas_pci_driver = { | 
 | 	.name =		"xhci-pci-renesas", | 
 | 	.id_table =	pci_ids, | 
 |  | 
 | 	.probe =	xhci_pci_renesas_probe, | 
 | 	.remove =	xhci_pci_remove, | 
 |  | 
 | 	.shutdown = 	usb_hcd_pci_shutdown, | 
 | 	.driver = { | 
 | 		.pm = pm_ptr(&usb_hcd_pci_pm_ops), | 
 | 	}, | 
 | }; | 
 | module_pci_driver(xhci_renesas_pci_driver); | 
 |  | 
 | MODULE_DESCRIPTION("Renesas xHCI PCI Host Controller Driver"); | 
 | MODULE_FIRMWARE(RENESAS_FW_NAME); | 
 | MODULE_IMPORT_NS("xhci"); | 
 | MODULE_LICENSE("GPL v2"); |