All of lore.kernel.org
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
To: Andrew Bresticker <abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Cc: Stephen Warren <swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org>,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
	Pawel Moll <pawel.moll-5wv7dgnIgG8@public.gmane.org>,
	Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>,
	Ian Campbell
	<ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org>,
	Kumar Gala <galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>,
	Russell King <linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>,
	Jassi Brar
	<jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Linus Walleij
	<linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	Greg Kroah-Hartman
	<gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org>,
	Mathias Nyman
	<mathias.nyman-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	Grant Likely
	<grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
	Alan Stern
	<stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org>,
	Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>,
	Kishon Vijay Abraham I <kishon-l0cyMroinI0@public.gmane.org>,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
	linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH RESEND V4 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
Date: Wed, 29 Oct 2014 11:49:29 +0100	[thread overview]
Message-ID: <20141029104927.GC28356@ulmo.nvidia.com> (raw)
In-Reply-To: <1414535277-15645-7-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 7556 bytes --]

On Tue, Oct 28, 2014 at 03:27:53PM -0700, Andrew Bresticker wrote:
[...]
> diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
[...]
> +#define TEGRA_XHCI_NUM_SUPPLIES 8
> +static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
> +	"avddio-pex",
> +	"dvddio-pex",
> +	"avdd-usb",
> +	"avdd-pll-utmip",
> +	"avdd-pll-erefe",
> +	"avdd-pex-pll",
> +	"hvdd-pex",
> +	"hvdd-pex-plle",
> +};

This could be in a per-SoC structure since it's likely to change in a
future SoC. That could be done later on when it really becomes relevant,
though.

> +
> +static const struct {
> +	const char *name;
> +	int num;

unsigned?

> +} tegra_xhci_phy_types[] = {
> +	{
> +		.name = "usb3",
> +		.num = TEGRA_XUSB_USB3_PHYS,
> +	}, {
> +		.name = "utmi",
> +		.num = TEGRA_XUSB_UTMI_PHYS,
> +	}, {
> +		.name = "hsic",
> +		.num = TEGRA_XUSB_HSIC_PHYS,
> +	},
> +};

Should these constants perhaps be in a per-SoC structure like
tegra_xhci_soc_config rather than defined in a global header?

> +static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
> +{
[...]
> +	/* Start Falcon CPU. */
> +	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
> +	usleep_range(1000, 2000);
> +
> +	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
> +	time_to_tm(fw_time, 0, &fw_tm);
> +	dev_info(dev,
> +		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
> +		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
> +		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
> +		 fw_tm.tm_min, fw_tm.tm_sec,
> +		 csb_readl(tegra, XUSB_FALC_CPUCTL));
> +
> +	/* Make sure Falcon CPU is now running. */
> +	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
> +		return -EIO;

It seems somewhat strange to output the dev_info() message when in fact
it could be that the Falcon wasn't successfully booted. Also is it
guaranteed that the Falcon will always be up after 1 ms? Perhaps better
would be to use a timed loop?

> +static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
> +				 unsigned long rate)
> +{
> +	unsigned long new_parent_rate, old_parent_rate;
> +	int ret, div;
> +	struct clk *clk = tegra->ss_src_clk;
> +
> +	if (clk_get_rate(clk) == rate)
> +		return 0;
> +
> +	switch (rate) {
> +	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
> +		/*
> +		 * Reparent to PLLU_480M. Set divider first to avoid
> +		 * overclocking.
> +		 */
> +		old_parent_rate = clk_get_rate(clk_get_parent(clk));
> +		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
> +		div = new_parent_rate / rate;
> +		ret = clk_set_rate(clk, old_parent_rate / div);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_parent(clk, tegra->pll_u_480m);
> +		if (ret)
> +			return ret;
> +		/*
> +		 * The rate should already be correct, but set it again just
> +		 * to be sure.
> +		 */
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
> +		/* Reparent to CLK_M */
> +		ret = clk_set_parent(clk, tegra->clk_m);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	default:
> +		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
> +		return -EINVAL;
> +	}
> +
> +	if (clk_get_rate(clk) != rate) {
> +		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}

So this is why you need pllu_480m and clk_m clocks. I would've thought
it nice to use something like the assigned-clocks properties to take
care of this, but it seems like this may actually be required to be
updated dynamically at runtime, so a fixed property is not going to be
an option.

> +static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	clk_prepare_enable(tegra->pll_e);
> +	clk_prepare_enable(tegra->host_clk);
> +	clk_prepare_enable(tegra->ss_clk);
> +	clk_prepare_enable(tegra->falc_clk);
> +	clk_prepare_enable(tegra->fs_src_clk);
> +	clk_prepare_enable(tegra->hs_src_clk);

You should error-check these.

> +static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	int ret;
> +	int i;

I prefer unsigned when the value can't be negative as in this case.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		ret = phy_init(tegra->phys[i]);
> +		if (ret)
> +			goto disable_phy;
> +		ret = phy_power_on(tegra->phys[i]);
> +		if (ret) {
> +			phy_exit(tegra->phys[i]);
> +			goto disable_phy;
> +		}
> +	}

Perhaps a phy_init_and_power_on() helper would be useful. Nothing that
needs to be done as part of this patch, though.

> +
> +	return 0;
> +disable_phy:
> +	for (i = i - 1; i >= 0; i--) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);

You could write this as:

	for (i = i; i > 0; i--) {
		phy_power_off(tegra->phys[i - 1]);
		...
	}

for the unsigned case. But I guess this would be a reasonable exception
to let i be signed.

> +static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
> +{
> +	int i;

There's no reason for it to be signed here, though.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);
> +	}
> +}
> +
> +static bool is_host_mbox_message(u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static void tegra_xhci_mbox_work(struct work_struct *work)
> +{
> +	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
> +						    mbox_req_work);

There's only a single instance of this, but it might still be useful to
wrap it in a static inline for readability.

> +	/*
> +	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)

I don't think this driver calls xhci_plat_setup() (anymore?).

> +	 * is called by usb_add_hcd().
> +	 */
> +	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;

This makes me a little uneasy. Perhaps this should be an XHCI wrapper to
make it look less like you're doing something you shouldn't.

> +static int tegra_xhci_probe(struct platform_device *pdev)
> +{
> +	struct tegra_xhci_hcd *tegra;
> +	struct usb_hcd *hcd;
> +	struct resource	*res;

There's a tab between resource and *res which should be a space.

> +	struct phy *phy;
> +	const struct of_device_id *match;
> +	int ret, i, j, k;
> +
> +	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
> +
> +	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
> +	if (!tegra)
> +		return -ENOMEM;
> +	tegra->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, tegra);
> +
> +	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
> +	if (!match) {
> +		dev_err(&pdev->dev, "No device match found\n");
> +		return -ENODEV;
> +	}

I don't think this can happen. If there's no match in the table then
this function shouldn't have been called in the first place.

> +	tegra->soc_config = match->data;
> +
> +	/*
> +	 * Right now device-tree probed devices don't get dma_mask set.
> +	 * Since shared usb code relies on it, set it here for now.
> +	 * Once we have dma capability bindings this can go away.
> +	 */
> +	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +	if (ret)
> +		return ret;

I think that's no longer necessary. of_dma_configure() should take care
of this now.

> +	k = 0;
> +	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {

I think a more idiomatic way to write this would be:

	for (i = 0, k = 0; ...)

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

WARNING: multiple messages have this Message-ID (diff)
From: thierry.reding@gmail.com (Thierry Reding)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH RESEND V4 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
Date: Wed, 29 Oct 2014 11:49:29 +0100	[thread overview]
Message-ID: <20141029104927.GC28356@ulmo.nvidia.com> (raw)
In-Reply-To: <1414535277-15645-7-git-send-email-abrestic@chromium.org>

On Tue, Oct 28, 2014 at 03:27:53PM -0700, Andrew Bresticker wrote:
[...]
> diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
[...]
> +#define TEGRA_XHCI_NUM_SUPPLIES 8
> +static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
> +	"avddio-pex",
> +	"dvddio-pex",
> +	"avdd-usb",
> +	"avdd-pll-utmip",
> +	"avdd-pll-erefe",
> +	"avdd-pex-pll",
> +	"hvdd-pex",
> +	"hvdd-pex-plle",
> +};

This could be in a per-SoC structure since it's likely to change in a
future SoC. That could be done later on when it really becomes relevant,
though.

> +
> +static const struct {
> +	const char *name;
> +	int num;

unsigned?

> +} tegra_xhci_phy_types[] = {
> +	{
> +		.name = "usb3",
> +		.num = TEGRA_XUSB_USB3_PHYS,
> +	}, {
> +		.name = "utmi",
> +		.num = TEGRA_XUSB_UTMI_PHYS,
> +	}, {
> +		.name = "hsic",
> +		.num = TEGRA_XUSB_HSIC_PHYS,
> +	},
> +};

Should these constants perhaps be in a per-SoC structure like
tegra_xhci_soc_config rather than defined in a global header?

> +static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
> +{
[...]
> +	/* Start Falcon CPU. */
> +	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
> +	usleep_range(1000, 2000);
> +
> +	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
> +	time_to_tm(fw_time, 0, &fw_tm);
> +	dev_info(dev,
> +		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
> +		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
> +		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
> +		 fw_tm.tm_min, fw_tm.tm_sec,
> +		 csb_readl(tegra, XUSB_FALC_CPUCTL));
> +
> +	/* Make sure Falcon CPU is now running. */
> +	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
> +		return -EIO;

It seems somewhat strange to output the dev_info() message when in fact
it could be that the Falcon wasn't successfully booted. Also is it
guaranteed that the Falcon will always be up after 1 ms? Perhaps better
would be to use a timed loop?

> +static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
> +				 unsigned long rate)
> +{
> +	unsigned long new_parent_rate, old_parent_rate;
> +	int ret, div;
> +	struct clk *clk = tegra->ss_src_clk;
> +
> +	if (clk_get_rate(clk) == rate)
> +		return 0;
> +
> +	switch (rate) {
> +	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
> +		/*
> +		 * Reparent to PLLU_480M. Set divider first to avoid
> +		 * overclocking.
> +		 */
> +		old_parent_rate = clk_get_rate(clk_get_parent(clk));
> +		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
> +		div = new_parent_rate / rate;
> +		ret = clk_set_rate(clk, old_parent_rate / div);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_parent(clk, tegra->pll_u_480m);
> +		if (ret)
> +			return ret;
> +		/*
> +		 * The rate should already be correct, but set it again just
> +		 * to be sure.
> +		 */
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
> +		/* Reparent to CLK_M */
> +		ret = clk_set_parent(clk, tegra->clk_m);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	default:
> +		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
> +		return -EINVAL;
> +	}
> +
> +	if (clk_get_rate(clk) != rate) {
> +		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}

So this is why you need pllu_480m and clk_m clocks. I would've thought
it nice to use something like the assigned-clocks properties to take
care of this, but it seems like this may actually be required to be
updated dynamically at runtime, so a fixed property is not going to be
an option.

> +static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	clk_prepare_enable(tegra->pll_e);
> +	clk_prepare_enable(tegra->host_clk);
> +	clk_prepare_enable(tegra->ss_clk);
> +	clk_prepare_enable(tegra->falc_clk);
> +	clk_prepare_enable(tegra->fs_src_clk);
> +	clk_prepare_enable(tegra->hs_src_clk);

You should error-check these.

> +static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	int ret;
> +	int i;

I prefer unsigned when the value can't be negative as in this case.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		ret = phy_init(tegra->phys[i]);
> +		if (ret)
> +			goto disable_phy;
> +		ret = phy_power_on(tegra->phys[i]);
> +		if (ret) {
> +			phy_exit(tegra->phys[i]);
> +			goto disable_phy;
> +		}
> +	}

Perhaps a phy_init_and_power_on() helper would be useful. Nothing that
needs to be done as part of this patch, though.

> +
> +	return 0;
> +disable_phy:
> +	for (i = i - 1; i >= 0; i--) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);

You could write this as:

	for (i = i; i > 0; i--) {
		phy_power_off(tegra->phys[i - 1]);
		...
	}

for the unsigned case. But I guess this would be a reasonable exception
to let i be signed.

> +static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
> +{
> +	int i;

There's no reason for it to be signed here, though.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);
> +	}
> +}
> +
> +static bool is_host_mbox_message(u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static void tegra_xhci_mbox_work(struct work_struct *work)
> +{
> +	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
> +						    mbox_req_work);

There's only a single instance of this, but it might still be useful to
wrap it in a static inline for readability.

> +	/*
> +	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)

I don't think this driver calls xhci_plat_setup() (anymore?).

> +	 * is called by usb_add_hcd().
> +	 */
> +	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;

This makes me a little uneasy. Perhaps this should be an XHCI wrapper to
make it look less like you're doing something you shouldn't.

> +static int tegra_xhci_probe(struct platform_device *pdev)
> +{
> +	struct tegra_xhci_hcd *tegra;
> +	struct usb_hcd *hcd;
> +	struct resource	*res;

There's a tab between resource and *res which should be a space.

> +	struct phy *phy;
> +	const struct of_device_id *match;
> +	int ret, i, j, k;
> +
> +	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
> +
> +	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
> +	if (!tegra)
> +		return -ENOMEM;
> +	tegra->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, tegra);
> +
> +	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
> +	if (!match) {
> +		dev_err(&pdev->dev, "No device match found\n");
> +		return -ENODEV;
> +	}

I don't think this can happen. If there's no match in the table then
this function shouldn't have been called in the first place.

> +	tegra->soc_config = match->data;
> +
> +	/*
> +	 * Right now device-tree probed devices don't get dma_mask set.
> +	 * Since shared usb code relies on it, set it here for now.
> +	 * Once we have dma capability bindings this can go away.
> +	 */
> +	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +	if (ret)
> +		return ret;

I think that's no longer necessary. of_dma_configure() should take care
of this now.

> +	k = 0;
> +	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {

I think a more idiomatic way to write this would be:

	for (i = 0, k = 0; ...)

Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20141029/abba4609/attachment.sig>

WARNING: multiple messages have this Message-ID (diff)
From: Thierry Reding <thierry.reding@gmail.com>
To: Andrew Bresticker <abrestic@chromium.org>
Cc: Stephen Warren <swarren@wwwdotorg.org>,
	linux-tegra@vger.kernel.org, Rob Herring <robh+dt@kernel.org>,
	Pawel Moll <pawel.moll@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	Kumar Gala <galak@codeaurora.org>,
	Russell King <linux@arm.linux.org.uk>,
	Jassi Brar <jassisinghbrar@gmail.com>,
	Linus Walleij <linus.walleij@linaro.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Mathias Nyman <mathias.nyman@intel.com>,
	Grant Likely <grant.likely@linaro.org>,
	Alan Stern <stern@rowland.harvard.edu>,
	Arnd Bergmann <arnd@arndb.de>,
	Kishon Vijay Abraham I <kishon@ti.com>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-usb@vger.kernel.org
Subject: Re: [PATCH RESEND V4 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver
Date: Wed, 29 Oct 2014 11:49:29 +0100	[thread overview]
Message-ID: <20141029104927.GC28356@ulmo.nvidia.com> (raw)
In-Reply-To: <1414535277-15645-7-git-send-email-abrestic@chromium.org>

[-- Attachment #1: Type: text/plain, Size: 7556 bytes --]

On Tue, Oct 28, 2014 at 03:27:53PM -0700, Andrew Bresticker wrote:
[...]
> diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
[...]
> +#define TEGRA_XHCI_NUM_SUPPLIES 8
> +static const char *tegra_xhci_supply_names[TEGRA_XHCI_NUM_SUPPLIES] = {
> +	"avddio-pex",
> +	"dvddio-pex",
> +	"avdd-usb",
> +	"avdd-pll-utmip",
> +	"avdd-pll-erefe",
> +	"avdd-pex-pll",
> +	"hvdd-pex",
> +	"hvdd-pex-plle",
> +};

This could be in a per-SoC structure since it's likely to change in a
future SoC. That could be done later on when it really becomes relevant,
though.

> +
> +static const struct {
> +	const char *name;
> +	int num;

unsigned?

> +} tegra_xhci_phy_types[] = {
> +	{
> +		.name = "usb3",
> +		.num = TEGRA_XUSB_USB3_PHYS,
> +	}, {
> +		.name = "utmi",
> +		.num = TEGRA_XUSB_UTMI_PHYS,
> +	}, {
> +		.name = "hsic",
> +		.num = TEGRA_XUSB_HSIC_PHYS,
> +	},
> +};

Should these constants perhaps be in a per-SoC structure like
tegra_xhci_soc_config rather than defined in a global header?

> +static int tegra_xhci_load_firmware(struct tegra_xhci_hcd *tegra)
> +{
[...]
> +	/* Start Falcon CPU. */
> +	csb_writel(tegra, CPUCTL_STARTCPU, XUSB_FALC_CPUCTL);
> +	usleep_range(1000, 2000);
> +
> +	fw_time = le32_to_cpu(cfg_tbl->fwimg_created_time);
> +	time_to_tm(fw_time, 0, &fw_tm);
> +	dev_info(dev,
> +		 "Firmware timestamp: %ld-%02d-%02d %02d:%02d:%02d UTC, "
> +		 "Falcon state 0x%x\n", fw_tm.tm_year + 1900,
> +		 fw_tm.tm_mon + 1, fw_tm.tm_mday, fw_tm.tm_hour,
> +		 fw_tm.tm_min, fw_tm.tm_sec,
> +		 csb_readl(tegra, XUSB_FALC_CPUCTL));
> +
> +	/* Make sure Falcon CPU is now running. */
> +	if (csb_readl(tegra, XUSB_FALC_CPUCTL) == CPUCTL_STATE_HALTED)
> +		return -EIO;

It seems somewhat strange to output the dev_info() message when in fact
it could be that the Falcon wasn't successfully booted. Also is it
guaranteed that the Falcon will always be up after 1 ms? Perhaps better
would be to use a timed loop?

> +static int tegra_xhci_set_ss_clk(struct tegra_xhci_hcd *tegra,
> +				 unsigned long rate)
> +{
> +	unsigned long new_parent_rate, old_parent_rate;
> +	int ret, div;
> +	struct clk *clk = tegra->ss_src_clk;
> +
> +	if (clk_get_rate(clk) == rate)
> +		return 0;
> +
> +	switch (rate) {
> +	case TEGRA_XHCI_SS_CLK_HIGH_SPEED:
> +		/*
> +		 * Reparent to PLLU_480M. Set divider first to avoid
> +		 * overclocking.
> +		 */
> +		old_parent_rate = clk_get_rate(clk_get_parent(clk));
> +		new_parent_rate = clk_get_rate(tegra->pll_u_480m);
> +		div = new_parent_rate / rate;
> +		ret = clk_set_rate(clk, old_parent_rate / div);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_parent(clk, tegra->pll_u_480m);
> +		if (ret)
> +			return ret;
> +		/*
> +		 * The rate should already be correct, but set it again just
> +		 * to be sure.
> +		 */
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	case TEGRA_XHCI_SS_CLK_LOW_SPEED:
> +		/* Reparent to CLK_M */
> +		ret = clk_set_parent(clk, tegra->clk_m);
> +		if (ret)
> +			return ret;
> +		ret = clk_set_rate(clk, rate);
> +		if (ret)
> +			return ret;
> +		break;
> +	default:
> +		dev_err(tegra->dev, "Invalid SS rate: %lu\n", rate);
> +		return -EINVAL;
> +	}
> +
> +	if (clk_get_rate(clk) != rate) {
> +		dev_err(tegra->dev, "SS clock doesn't match requested rate\n");
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}

So this is why you need pllu_480m and clk_m clocks. I would've thought
it nice to use something like the assigned-clocks properties to take
care of this, but it seems like this may actually be required to be
updated dynamically at runtime, so a fixed property is not going to be
an option.

> +static int tegra_xhci_clk_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	clk_prepare_enable(tegra->pll_e);
> +	clk_prepare_enable(tegra->host_clk);
> +	clk_prepare_enable(tegra->ss_clk);
> +	clk_prepare_enable(tegra->falc_clk);
> +	clk_prepare_enable(tegra->fs_src_clk);
> +	clk_prepare_enable(tegra->hs_src_clk);

You should error-check these.

> +static int tegra_xhci_phy_enable(struct tegra_xhci_hcd *tegra)
> +{
> +	int ret;
> +	int i;

I prefer unsigned when the value can't be negative as in this case.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		ret = phy_init(tegra->phys[i]);
> +		if (ret)
> +			goto disable_phy;
> +		ret = phy_power_on(tegra->phys[i]);
> +		if (ret) {
> +			phy_exit(tegra->phys[i]);
> +			goto disable_phy;
> +		}
> +	}

Perhaps a phy_init_and_power_on() helper would be useful. Nothing that
needs to be done as part of this patch, though.

> +
> +	return 0;
> +disable_phy:
> +	for (i = i - 1; i >= 0; i--) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);

You could write this as:

	for (i = i; i > 0; i--) {
		phy_power_off(tegra->phys[i - 1]);
		...
	}

for the unsigned case. But I guess this would be a reasonable exception
to let i be signed.

> +static void tegra_xhci_phy_disable(struct tegra_xhci_hcd *tegra)
> +{
> +	int i;

There's no reason for it to be signed here, though.

> +
> +	for (i = 0; i < ARRAY_SIZE(tegra->phys); i++) {
> +		phy_power_off(tegra->phys[i]);
> +		phy_exit(tegra->phys[i]);
> +	}
> +}
> +
> +static bool is_host_mbox_message(u32 cmd)
> +{
> +	switch (cmd) {
> +	case MBOX_CMD_INC_SSPI_CLOCK:
> +	case MBOX_CMD_DEC_SSPI_CLOCK:
> +	case MBOX_CMD_INC_FALC_CLOCK:
> +	case MBOX_CMD_DEC_FALC_CLOCK:
> +	case MBOX_CMD_SET_BW:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static void tegra_xhci_mbox_work(struct work_struct *work)
> +{
> +	struct tegra_xhci_hcd *tegra = container_of(work, struct tegra_xhci_hcd,
> +						    mbox_req_work);

There's only a single instance of this, but it might still be useful to
wrap it in a static inline for readability.

> +	/*
> +	 * Set the xHCI pointer before xhci_plat_setup() (aka hcd_driver.reset)

I don't think this driver calls xhci_plat_setup() (anymore?).

> +	 * is called by usb_add_hcd().
> +	 */
> +	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;

This makes me a little uneasy. Perhaps this should be an XHCI wrapper to
make it look less like you're doing something you shouldn't.

> +static int tegra_xhci_probe(struct platform_device *pdev)
> +{
> +	struct tegra_xhci_hcd *tegra;
> +	struct usb_hcd *hcd;
> +	struct resource	*res;

There's a tab between resource and *res which should be a space.

> +	struct phy *phy;
> +	const struct of_device_id *match;
> +	int ret, i, j, k;
> +
> +	BUILD_BUG_ON(sizeof(struct tegra_xhci_fw_cfgtbl) != 256);
> +
> +	tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
> +	if (!tegra)
> +		return -ENOMEM;
> +	tegra->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, tegra);
> +
> +	match = of_match_device(tegra_xhci_of_match, &pdev->dev);
> +	if (!match) {
> +		dev_err(&pdev->dev, "No device match found\n");
> +		return -ENODEV;
> +	}

I don't think this can happen. If there's no match in the table then
this function shouldn't have been called in the first place.

> +	tegra->soc_config = match->data;
> +
> +	/*
> +	 * Right now device-tree probed devices don't get dma_mask set.
> +	 * Since shared usb code relies on it, set it here for now.
> +	 * Once we have dma capability bindings this can go away.
> +	 */
> +	ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
> +	if (ret)
> +		return ret;

I think that's no longer necessary. of_dma_configure() should take care
of this now.

> +	k = 0;
> +	for (i = 0; i < ARRAY_SIZE(tegra_xhci_phy_types); i++) {

I think a more idiomatic way to write this would be:

	for (i = 0, k = 0; ...)

Thierry

[-- Attachment #2: Type: application/pgp-signature, Size: 819 bytes --]

  parent reply	other threads:[~2014-10-29 10:49 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-28 22:27 [PATCH RESEND V4 0/9] Tegra xHCI support Andrew Bresticker
2014-10-28 22:27 ` Andrew Bresticker
2014-10-28 22:27 ` Andrew Bresticker
     [not found] ` <1414535277-15645-1-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-10-28 22:27   ` [PATCH RESEND V4 1/9] of: Add NVIDIA Tegra XUSB mailbox binding Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-28 22:27   ` [PATCH RESEND V4 3/9] of: Update Tegra XUSB pad controller binding for USB Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-31  9:44     ` Linus Walleij
2014-10-31  9:44       ` Linus Walleij
2014-10-31  9:44       ` Linus Walleij
2014-10-31 16:42       ` Andrew Bresticker
2014-10-31 16:42         ` Andrew Bresticker
2014-10-31 16:42         ` Andrew Bresticker
2014-10-28 22:27   ` [PATCH RESEND V4 4/9] pinctrl: tegra-xusb: Add USB PHY support Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
     [not found]     ` <1414535277-15645-5-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-10-29 12:27       ` Thierry Reding
2014-10-29 12:27         ` Thierry Reding
2014-10-29 12:27         ` Thierry Reding
2014-10-29 19:43         ` Andrew Bresticker
2014-10-29 19:43           ` Andrew Bresticker
2014-10-29 19:43           ` Andrew Bresticker
2014-10-30 13:45           ` Thierry Reding
2014-10-30 13:45             ` Thierry Reding
2014-10-30 13:45             ` Thierry Reding
     [not found]             ` <20141030134517.GB19802-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2014-10-30 17:10               ` Andrew Bresticker
2014-10-30 17:10                 ` Andrew Bresticker
2014-10-30 17:10                 ` Andrew Bresticker
2014-10-31 11:22                 ` Thierry Reding
2014-10-31 11:22                   ` Thierry Reding
2014-10-31 11:22                   ` Thierry Reding
2014-10-28 22:27   ` [PATCH RESEND V4 8/9] ARM: tegra: jetson-tk1: Add xHCI support Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-28 22:27     ` Andrew Bresticker
2014-10-29  5:52   ` [PATCH RESEND V4 0/9] Tegra " Alexandre Courbot
2014-10-29  5:52     ` Alexandre Courbot
2014-10-29  5:52     ` Alexandre Courbot
2014-10-28 22:27 ` [PATCH RESEND V4 2/9] mailbox: Add NVIDIA Tegra XUSB mailbox driver Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker
     [not found]   ` <1414535277-15645-3-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-10-29 11:34     ` Thierry Reding
2014-10-29 11:34       ` Thierry Reding
2014-10-29 11:34       ` Thierry Reding
     [not found]       ` <20141029113415.GD28356-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2014-10-29 18:02         ` Andrew Bresticker
2014-10-29 18:02           ` Andrew Bresticker
2014-10-29 18:02           ` Andrew Bresticker
2014-10-30 13:22           ` Thierry Reding
2014-10-30 13:22             ` Thierry Reding
2014-10-30 13:22             ` Thierry Reding
2014-10-30 16:57             ` Andrew Bresticker
2014-10-30 16:57               ` Andrew Bresticker
2014-10-30 16:57               ` Andrew Bresticker
2014-10-28 22:27 ` [PATCH RESEND V4 5/9] of: Add NVIDIA Tegra xHCI controller binding Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker
     [not found]   ` <1414535277-15645-6-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-10-29  9:43     ` Thierry Reding
2014-10-29  9:43       ` Thierry Reding
2014-10-29  9:43       ` Thierry Reding
2014-10-29 16:37       ` Andrew Bresticker
2014-10-29 16:37         ` Andrew Bresticker
2014-10-29 16:37         ` Andrew Bresticker
2014-10-30 13:55         ` Thierry Reding
2014-10-30 13:55           ` Thierry Reding
2014-10-30 13:55           ` Thierry Reding
     [not found]           ` <20141030135500.GC19802-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2014-10-30 17:19             ` Andrew Bresticker
2014-10-30 17:19               ` Andrew Bresticker
2014-10-30 17:19               ` Andrew Bresticker
     [not found]               ` <CAL1qeaG701hKtcUL5a67b=X38hbcYunUOUBziZMpxemvhhAayA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-10-30 17:24                 ` Thierry Reding
2014-10-30 17:24                   ` Thierry Reding
2014-10-30 17:24                   ` Thierry Reding
2014-10-30 17:26                   ` Andrew Bresticker
2014-10-30 17:26                     ` Andrew Bresticker
2014-10-30 17:26                     ` Andrew Bresticker
     [not found]                     ` <CAL1qeaEbRkOQApyjkpwxBd3mGkQ3JuXNiar1MbBd844NWe5h9g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-10-31 11:32                       ` Thierry Reding
2014-10-31 11:32                         ` Thierry Reding
2014-10-31 11:32                         ` Thierry Reding
2014-10-31 16:41                         ` Andrew Bresticker
2014-10-31 16:41                           ` Andrew Bresticker
2014-10-31 16:41                           ` Andrew Bresticker
     [not found]                           ` <CAL1qeaFcyoSUbVdgUdWZ6RtRiuj0X1H-ohXCsckwF8=VPw8jRA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-04 20:44                             ` Andrew Bresticker
2014-11-04 20:44                               ` Andrew Bresticker
2014-11-04 20:44                               ` Andrew Bresticker
2014-10-29  9:58   ` Thierry Reding
2014-10-29  9:58     ` Thierry Reding
2014-10-28 22:27 ` [PATCH RESEND V4 6/9] usb: xhci: Add NVIDIA Tegra xHCI host-controller driver Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker
     [not found]   ` <1414535277-15645-7-git-send-email-abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
2014-10-29 10:49     ` Thierry Reding [this message]
2014-10-29 10:49       ` Thierry Reding
2014-10-29 10:49       ` Thierry Reding
2014-10-28 22:27 ` [PATCH RESEND V4 7/9] ARM: tegra: Add Tegra124 XUSB mailbox and xHCI controller Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker
2014-10-28 22:27 ` [PATCH RESEND V4 9/9] ARM: tegra: venice2: Add xHCI support Andrew Bresticker
2014-10-28 22:27   ` Andrew Bresticker

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=20141029104927.GC28356@ulmo.nvidia.com \
    --to=thierry.reding-re5jqeeqqe8avxtiumwx3w@public.gmane.org \
    --cc=abrestic-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org \
    --cc=arnd-r2nGTMty4D4@public.gmane.org \
    --cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=galak-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org \
    --cc=grant.likely-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
    --cc=ijc+devicetree-KcIKpvwj1kUDXYZnReoRVg@public.gmane.org \
    --cc=jassisinghbrar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=kishon-l0cyMroinI0@public.gmane.org \
    --cc=linus.walleij-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
    --cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org \
    --cc=linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
    --cc=mathias.nyman-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=pawel.moll-5wv7dgnIgG8@public.gmane.org \
    --cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
    --cc=stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org \
    --cc=swarren-3lzwWm7+Weoh9ZMKESR00Q@public.gmane.org \
    /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.