diff options
Diffstat (limited to 'drivers/usb/phy/phy-samsung-usb.c')
| -rw-r--r-- | drivers/usb/phy/phy-samsung-usb.c | 159 | 
1 files changed, 82 insertions, 77 deletions
| diff --git a/drivers/usb/phy/phy-samsung-usb.c b/drivers/usb/phy/phy-samsung-usb.c index 7b118ee5f5e4..ac025ca08425 100644 --- a/drivers/usb/phy/phy-samsung-usb.c +++ b/drivers/usb/phy/phy-samsung-usb.c @@ -73,7 +73,7 @@ EXPORT_SYMBOL_GPL(samsung_usbphy_parse_dt);   * Here 'on = true' would mean USB PHY block is isolated, hence   * de-activated and vice-versa.   */ -void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on) +void samsung_usbphy_set_isolation_4210(struct samsung_usbphy *sphy, bool on)  {  	void __iomem *reg = NULL;  	u32 reg_val; @@ -84,32 +84,12 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)  		return;  	} -	switch (sphy->drv_data->cpu_type) { -	case TYPE_S3C64XX: -		/* -		 * Do nothing: We will add here once S3C64xx goes for DT support -		 */ -		break; -	case TYPE_EXYNOS4210: -		/* -		 * Fall through since exynos4210 and exynos5250 have similar -		 * register architecture: two separate registers for host and -		 * device phy control with enable bit at position 0. -		 */ -	case TYPE_EXYNOS5250: -		if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { -			reg = sphy->pmuregs + -				sphy->drv_data->devphy_reg_offset; -			en_mask = sphy->drv_data->devphy_en_mask; -		} else if (sphy->phy_type == USB_PHY_TYPE_HOST) { -			reg = sphy->pmuregs + -				sphy->drv_data->hostphy_reg_offset; -			en_mask = sphy->drv_data->hostphy_en_mask; -		} -		break; -	default: -		dev_err(sphy->dev, "Invalid SoC type\n"); -		return; +	if (sphy->phy_type == USB_PHY_TYPE_DEVICE) { +		reg = sphy->pmuregs + sphy->drv_data->devphy_reg_offset; +		en_mask = sphy->drv_data->devphy_en_mask; +	} else if (sphy->phy_type == USB_PHY_TYPE_HOST) { +		reg = sphy->pmuregs + sphy->drv_data->hostphy_reg_offset; +		en_mask = sphy->drv_data->hostphy_en_mask;  	}  	reg_val = readl(reg); @@ -120,8 +100,13 @@ void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)  		reg_val |= en_mask;  	writel(reg_val, reg); + +	if (sphy->drv_data->cpu_type == TYPE_EXYNOS4X12) { +		writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL0); +		writel(reg_val, sphy->pmuregs + EXYNOS4X12_PHY_HSIC_CTRL1); +	}  } -EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation); +EXPORT_SYMBOL_GPL(samsung_usbphy_set_isolation_4210);  /*   * Configure the mode of working of usb-phy here: HOST/DEVICE. @@ -162,73 +147,93 @@ int samsung_usbphy_set_type(struct usb_phy *phy,  }  EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); +int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy, +							unsigned long rate) +{ +	unsigned int clksel; + +	switch (rate) { +	case 12 * MHZ: +		clksel = PHYCLK_CLKSEL_12M; +		break; +	case 24 * MHZ: +		clksel = PHYCLK_CLKSEL_24M; +		break; +	case 48 * MHZ: +		clksel = PHYCLK_CLKSEL_48M; +		break; +	default: +		dev_err(sphy->dev, +			"Invalid reference clock frequency: %lu\n", rate); +		return -EINVAL; +	} + +	return clksel; +} +EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_64xx); + +int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy, +							unsigned long rate) +{ +	unsigned int clksel; + +	switch (rate) { +	case 9600 * KHZ: +		clksel = FSEL_CLKSEL_9600K; +		break; +	case 10 * MHZ: +		clksel = FSEL_CLKSEL_10M; +		break; +	case 12 * MHZ: +		clksel = FSEL_CLKSEL_12M; +		break; +	case 19200 * KHZ: +		clksel = FSEL_CLKSEL_19200K; +		break; +	case 20 * MHZ: +		clksel = FSEL_CLKSEL_20M; +		break; +	case 24 * MHZ: +		clksel = FSEL_CLKSEL_24M; +		break; +	case 50 * MHZ: +		clksel = FSEL_CLKSEL_50M; +		break; +	default: +		dev_err(sphy->dev, +			"Invalid reference clock frequency: %lu\n", rate); +		return -EINVAL; +	} + +	return clksel; +} +EXPORT_SYMBOL_GPL(samsung_usbphy_rate_to_clksel_4x12); +  /*   * Returns reference clock frequency selection value   */  int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)  {  	struct clk *ref_clk; -	int refclk_freq = 0; +	unsigned long rate; +	int refclk_freq;  	/*  	 * In exynos5250 USB host and device PHY use  	 * external crystal clock XXTI  	 */  	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) -		ref_clk = devm_clk_get(sphy->dev, "ext_xtal"); +		ref_clk = clk_get(sphy->dev, "ext_xtal");  	else -		ref_clk = devm_clk_get(sphy->dev, "xusbxti"); +		ref_clk = clk_get(sphy->dev, "xusbxti");  	if (IS_ERR(ref_clk)) {  		dev_err(sphy->dev, "Failed to get reference clock\n");  		return PTR_ERR(ref_clk);  	} -	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { -		/* set clock frequency for PLL */ -		switch (clk_get_rate(ref_clk)) { -		case 9600 * KHZ: -			refclk_freq = FSEL_CLKSEL_9600K; -			break; -		case 10 * MHZ: -			refclk_freq = FSEL_CLKSEL_10M; -			break; -		case 12 * MHZ: -			refclk_freq = FSEL_CLKSEL_12M; -			break; -		case 19200 * KHZ: -			refclk_freq = FSEL_CLKSEL_19200K; -			break; -		case 20 * MHZ: -			refclk_freq = FSEL_CLKSEL_20M; -			break; -		case 50 * MHZ: -			refclk_freq = FSEL_CLKSEL_50M; -			break; -		case 24 * MHZ: -		default: -			/* default reference clock */ -			refclk_freq = FSEL_CLKSEL_24M; -			break; -		} -	} else { -		switch (clk_get_rate(ref_clk)) { -		case 12 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_12M; -			break; -		case 24 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_24M; -			break; -		case 48 * MHZ: -			refclk_freq = PHYCLK_CLKSEL_48M; -			break; -		default: -			if (sphy->drv_data->cpu_type == TYPE_S3C64XX) -				refclk_freq = PHYCLK_CLKSEL_48M; -			else -				refclk_freq = PHYCLK_CLKSEL_24M; -			break; -		} -	} +	rate = clk_get_rate(ref_clk); +	refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate); +  	clk_put(ref_clk);  	return refclk_freq; |