diff options
Diffstat (limited to 'drivers/usb/misc/usb3503.c')
| -rw-r--r-- | drivers/usb/misc/usb3503.c | 59 | 
1 files changed, 57 insertions, 2 deletions
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c index a31641e18d1..f43c61989ce 100644 --- a/drivers/usb/misc/usb3503.c +++ b/drivers/usb/misc/usb3503.c @@ -18,6 +18,7 @@   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */ +#include <linux/clk.h>  #include <linux/i2c.h>  #include <linux/gpio.h>  #include <linux/delay.h> @@ -57,10 +58,12 @@ struct usb3503 {  	enum usb3503_mode	mode;  	struct regmap		*regmap;  	struct device		*dev; +	struct clk		*clk;  	u8	port_off_mask;  	int	gpio_intn;  	int	gpio_reset;  	int	gpio_connect; +	bool	secondary_ref_clk;  };  static int usb3503_reset(struct usb3503 *hub, int state) @@ -184,8 +187,58 @@ static int usb3503_probe(struct usb3503 *hub)  		hub->gpio_reset		= pdata->gpio_reset;  		hub->mode		= pdata->initial_mode;  	} else if (np) { +		struct clk *clk;  		hub->port_off_mask = 0; +		clk = devm_clk_get(dev, "refclk"); +		if (IS_ERR(clk) && PTR_ERR(clk) != -ENOENT) { +			dev_err(dev, "unable to request refclk (%d)\n", err); +			return PTR_ERR(clk); +		} + +		if (!IS_ERR(clk)) { +			u32 rate = 0; +			hub->clk = clk; + +			if (!of_property_read_u32(np, "refclk-frequency", +						 &rate)) { + +				switch (rate) { +				case 38400000: +				case 26000000: +				case 19200000: +				case 12000000: +					hub->secondary_ref_clk = 0; +					break; +				case 24000000: +				case 27000000: +				case 25000000: +				case 50000000: +					hub->secondary_ref_clk = 1; +					break; +				default: +					dev_err(dev, +						"unsupported reference clock rate (%d)\n", +						(int) rate); +					return -EINVAL; +				} +				err = clk_set_rate(hub->clk, rate); +				if (err) { +					dev_err(dev, +						"unable to set reference clock rate to %d\n", +						(int) rate); +					return err; +				} +			} + +			err = clk_prepare_enable(hub->clk); +			if (err) { +				dev_err(dev, +					"unable to enable reference clock\n"); +				return err; +			} +		} +  		property = of_get_property(np, "disabled-ports", &len);  		if (property && (len / sizeof(u32)) > 0) {  			int i; @@ -213,8 +266,10 @@ static int usb3503_probe(struct usb3503 *hub)  		dev_err(dev, "Ports disabled with no control interface\n");  	if (gpio_is_valid(hub->gpio_intn)) { -		err = devm_gpio_request_one(dev, hub->gpio_intn, -				GPIOF_OUT_INIT_HIGH, "usb3503 intn"); +		int val = hub->secondary_ref_clk ? GPIOF_OUT_INIT_LOW : +						   GPIOF_OUT_INIT_HIGH; +		err = devm_gpio_request_one(dev, hub->gpio_intn, val, +					    "usb3503 intn");  		if (err) {  			dev_err(dev,  				"unable to request GPIO %d as connect pin (%d)\n",  | 
