All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mathias Nyman <mathias.nyman@linux.intel.com>
To: Vinod Koul <vkoul@kernel.org>,
	Mathias Nyman <mathias.nyman@intel.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-arm-msm@vger.kernel.org,
	"Bjorn Andersson" <bjorn.andersson@linaro.org>,
	"Yoshihiro Shimoda" <yoshihiro.shimoda.uh@renesas.com>,
	"Christian Lamparter" <chunkeey@googlemail.com>,
	"John Stultz" <john.stultz@linaro.org>,
	"Alan Stern" <stern@rowland.harvard.edu>,
	"Andreas Böhler" <dev@aboehler.at>,
	linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v10 4/5] usb: renesas-xhci: Add ROM loader for uPD720201
Date: Wed, 29 Apr 2020 17:39:26 +0300	[thread overview]
Message-ID: <94266bc2-ae44-d7a2-61e9-4e09c29bd18d@linux.intel.com> (raw)
In-Reply-To: <20200424101410.2364219-5-vkoul@kernel.org>

On 24.4.2020 13.14, Vinod Koul wrote:
> uPD720201 supports ROM and allows software to program the ROM and boot
> from it. Add support for detecting if ROM is present, if so load the ROM
> if not programmed earlier.
> 
> Signed-off-by: Vinod Koul <vkoul@kernel.org>
> Cc: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
> Cc: Christian Lamparter <chunkeey@googlemail.com>
> ---
>  drivers/usb/host/xhci-pci-renesas.c | 342 +++++++++++++++++++++++++++-
>  1 file changed, 341 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
> index 402e86912c9f..6bb537999754 100644
> --- a/drivers/usb/host/xhci-pci-renesas.c
> +++ b/drivers/usb/host/xhci-pci-renesas.c
> @@ -50,6 +50,22 @@
>  #define RENESAS_RETRY	10000
>  #define RENESAS_DELAY	10
>  
> +#define ROM_VALID_01 0x2013
> +#define ROM_VALID_02 0x2026
> +
> +static int renesas_verify_fw_version(struct pci_dev *pdev, u32 version)
> +{
> +	switch (version) {
> +	case ROM_VALID_01:
> +	case ROM_VALID_02:
> +		return 0;
> +	default:
> +		dev_err(&pdev->dev, "FW has invalid version :%d\n", version);
> +		return 1;
> +	}
> +	return -EINVAL;

This never returns -EINVAL
Maybe just get rid of the default case and print
the error message before returning

> +}
> +
>  static int renesas_fw_download_image(struct pci_dev *dev,
>  				     const u32 *fw,
>  				     size_t step)
> @@ -144,10 +160,84 @@ static int renesas_fw_verify(const void *fw_data,
>  	return 0;
>  }
>  
> -static int renesas_fw_check_running(struct pci_dev *pdev)
> +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;
> +
> +	err = renesas_verify_fw_version(pdev, version);
> +	if (err)
> +		return err;
> +
> +	/*
> +	 * 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 & BIT(15)) {
> +		/* 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 */
> +			return 0;
> +
> +		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;
> +
> +	/* Check if device has ROM and loaded, if so skip everything */
> +	err = renesas_check_rom(pdev);
> +	if (err) { /* we have rom */
> +		err = renesas_check_rom_state(pdev);
> +		if (!err)
> +			return err;
> +	}
>  
>  	/*
>  	 * Test if the device is actually needing the firmware. As most
> @@ -303,11 +393,261 @@ static int renesas_fw_download(struct pci_dev *pdev,
>  	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_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_download_rom(struct pci_dev *pdev,
> +				 const u32 *fw, size_t step)
> +{
> +	bool data0_or_data1;
> +	u8 fw_status;
> +	size_t i;
> +	int err;
> +
> +	/*
> +	 * 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;
> +
> +	/* Read "Set DATAX" and confirm it is cleared. */
> +	for (i = 0; i < RENESAS_RETRY; i++) {
> +		err = pci_read_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
> +					   &fw_status);
> +		if (err) {
> +			dev_err(&pdev->dev, "Read ROM Status failed: %d\n",
> +				pcibios_err_to_errno(err));
> +			return false;
> +		}
> +		if (!(fw_status & BIT(data0_or_data1)))
> +			break;
> +
> +		udelay(RENESAS_DELAY);
> +	}
> +	if (i == RENESAS_RETRY) {
> +		dev_err(&pdev->dev, "Timeout for Set DATAX step: %zd\n", step);
> +		return false;
> +	}
> +
> +	/*
> +	 * Write FW data to "DATAX".
> +	 * "LSB is left" => force little endian
> +	 */
> +	err = pci_write_config_dword(pdev, data0_or_data1 ?
> +				     RENESAS_DATA1 : RENESAS_DATA0,
> +				     (__force u32)cpu_to_le32(fw[step]));
> +	if (err) {
> +		dev_err(&pdev->dev, "Write to DATAX failed: %d\n",
> +			pcibios_err_to_errno(err));
> +		return false;
> +	}
> +
> +	udelay(100);
> +
> +	/* Set "Set DATAX". */
> +	err = pci_write_config_byte(pdev, RENESAS_ROM_STATUS_MSB,
> +				    BIT(data0_or_data1));
> +	if (err) {
> +		dev_err(&pdev->dev, "Write config for DATAX failed: %d\n",
> +			pcibios_err_to_errno(err));
> +		return false;
> +	}
> +
> +	return true;
> +}

The above function is almost identical to renesas_fw_download_image() added in a 
previous patch.
To avoid code duplication I'm sure one function that handles both cases would be possible. 

-Mathias

  reply	other threads:[~2020-04-29 14:36 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-24 10:14 [PATCH v10 0/5] usb: xhci: Add support for Renesas USB controllers Vinod Koul
2020-04-24 10:14 ` [PATCH v10 1/5] usb: hci: add hc_driver as argument for usb_hcd_pci_probe Vinod Koul
2020-04-24 10:14 ` [PATCH v10 2/5] usb: renesas-xhci: Add the renesas xhci driver Vinod Koul
2020-04-24 10:14 ` [PATCH v10 3/5] usb: xhci: Add support for Renesas controller with memory Vinod Koul
2020-04-29 13:53   ` Mathias Nyman
2020-04-29 14:28     ` Vinod Koul
2020-04-30  6:20       ` Vinod Koul
2020-04-30  8:16         ` Mathias Nyman
2020-04-30  9:16           ` Vinod Koul
2020-04-24 10:14 ` [PATCH v10 4/5] usb: renesas-xhci: Add ROM loader for uPD720201 Vinod Koul
2020-04-29 14:39   ` Mathias Nyman [this message]
2020-04-30  9:17     ` Vinod Koul
2020-04-24 10:14 ` [PATCH v10 5/5] usb: xhci: provide a debugfs hook for erasing rom Vinod Koul

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=94266bc2-ae44-d7a2-61e9-4e09c29bd18d@linux.intel.com \
    --to=mathias.nyman@linux.intel.com \
    --cc=bjorn.andersson@linaro.org \
    --cc=chunkeey@googlemail.com \
    --cc=dev@aboehler.at \
    --cc=gregkh@linuxfoundation.org \
    --cc=john.stultz@linaro.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    --cc=stern@rowland.harvard.edu \
    --cc=vkoul@kernel.org \
    --cc=yoshihiro.shimoda.uh@renesas.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.