Commit 40758e49 authored by Alexander Stein's avatar Alexander Stein Committed by Greg Kroah-Hartman
Browse files

usb: misc: onboard_usb_hub: Add reset-gpio support



Despite default reset upon probe, release reset line after powering up
the hub and assert reset again before powering down.

Signed-off-by: default avatarAlexander Stein <alexander.stein@ew.tq-group.com>
Link: https://lore.kernel.org/r/20220727141117.909361-1-alexander.stein@ew.tq-group.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e0c6b1f3
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@

#include <linux/device.h>
#include <linux/export.h>
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -38,6 +39,8 @@ struct usbdev_node {
struct onboard_hub {
	struct regulator *vdd;
	struct device *dev;
	const struct onboard_hub_pdata *pdata;
	struct gpio_desc *reset_gpio;
	bool always_powered_in_suspend;
	bool is_powered_on;
	bool going_away;
@@ -56,6 +59,9 @@ static int onboard_hub_power_on(struct onboard_hub *hub)
		return err;
	}

	fsleep(hub->pdata->reset_us);
	gpiod_set_value_cansleep(hub->reset_gpio, 0);

	hub->is_powered_on = true;

	return 0;
@@ -65,6 +71,11 @@ static int onboard_hub_power_off(struct onboard_hub *hub)
{
	int err;

	if (hub->reset_gpio) {
		gpiod_set_value_cansleep(hub->reset_gpio, 1);
		fsleep(hub->pdata->reset_us);
	}

	err = regulator_disable(hub->vdd);
	if (err) {
		dev_err(hub->dev, "failed to disable regulator: %d\n", err);
@@ -219,6 +230,7 @@ static void onboard_hub_attach_usb_driver(struct work_struct *work)

static int onboard_hub_probe(struct platform_device *pdev)
{
	const struct of_device_id *of_id;
	struct device *dev = &pdev->dev;
	struct onboard_hub *hub;
	int err;
@@ -227,10 +239,26 @@ static int onboard_hub_probe(struct platform_device *pdev)
	if (!hub)
		return -ENOMEM;

	of_id = of_match_device(onboard_hub_match, &pdev->dev);
	if (!of_id)
		return -ENODEV;

	hub->pdata = of_id->data;
	if (!hub->pdata)
		return -EINVAL;

	hub->vdd = devm_regulator_get(dev, "vdd");
	if (IS_ERR(hub->vdd))
		return PTR_ERR(hub->vdd);

	hub->reset_gpio = devm_gpiod_get_optional(dev, "reset",
						  GPIOD_OUT_HIGH);
	if (IS_ERR(hub->reset_gpio))
		return dev_err_probe(dev, PTR_ERR(hub->reset_gpio), "failed to get reset GPIO\n");

	if (hub->reset_gpio)
		fsleep(hub->pdata->reset_us);

	hub->dev = dev;
	mutex_init(&hub->lock);
	INIT_LIST_HEAD(&hub->udev_list);
+17 −5
Original line number Diff line number Diff line
@@ -6,12 +6,24 @@
#ifndef _USB_MISC_ONBOARD_USB_HUB_H
#define _USB_MISC_ONBOARD_USB_HUB_H

struct onboard_hub_pdata {
	unsigned long reset_us;		/* reset pulse width in us */
};

static const struct onboard_hub_pdata microchip_usb424_data = {
	.reset_us = 1,
};

static const struct onboard_hub_pdata realtek_rts5411_data = {
	.reset_us = 0,
};

static const struct of_device_id onboard_hub_match[] = {
	{ .compatible = "usb424,2514" },
	{ .compatible = "usbbda,411" },
	{ .compatible = "usbbda,5411" },
	{ .compatible = "usbbda,414" },
	{ .compatible = "usbbda,5414" },
	{ .compatible = "usb424,2514", .data = &microchip_usb424_data, },
	{ .compatible = "usbbda,411", .data = &realtek_rts5411_data, },
	{ .compatible = "usbbda,5411", .data = &realtek_rts5411_data, },
	{ .compatible = "usbbda,414", .data = &realtek_rts5411_data, },
	{ .compatible = "usbbda,5414", .data = &realtek_rts5411_data, },
	{}
};