Commit 0aa823a2 authored by Tomasz Figa's avatar Tomasz Figa Committed by Felipe Balbi

usb: phy: samsung: Consolidate reference clock rate handling

This patch cleans up handling of reference clock rate in Samsung USB PHY
drivers. It is mostly a cosmetic change but improves error handling in
case of failing to get reference clock or invalid clock rate.
Signed-off-by: default avatarTomasz Figa <t.figa@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 87331b06
...@@ -162,73 +162,93 @@ int samsung_usbphy_set_type(struct usb_phy *phy, ...@@ -162,73 +162,93 @@ int samsung_usbphy_set_type(struct usb_phy *phy,
} }
EXPORT_SYMBOL_GPL(samsung_usbphy_set_type); EXPORT_SYMBOL_GPL(samsung_usbphy_set_type);
/* int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy,
* Returns reference clock frequency selection value unsigned long rate)
*/
int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
{ {
struct clk *ref_clk; unsigned int clksel;
int refclk_freq = 0;
/* switch (rate) {
* In exynos5250 USB host and device PHY use case 12 * MHZ:
* external crystal clock XXTI clksel = PHYCLK_CLKSEL_12M;
*/ break;
if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) case 24 * MHZ:
ref_clk = clk_get(sphy->dev, "ext_xtal"); clksel = PHYCLK_CLKSEL_24M;
else break;
ref_clk = clk_get(sphy->dev, "xusbxti"); case 48 * MHZ:
if (IS_ERR(ref_clk)) { clksel = PHYCLK_CLKSEL_48M;
dev_err(sphy->dev, "Failed to get reference clock\n"); break;
return PTR_ERR(ref_clk); default:
dev_err(sphy->dev,
"Invalid reference clock frequency: %lu\n", rate);
return -EINVAL;
} }
if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250) { return clksel;
/* set clock frequency for PLL */ }
switch (clk_get_rate(ref_clk)) { 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: case 9600 * KHZ:
refclk_freq = FSEL_CLKSEL_9600K; clksel = FSEL_CLKSEL_9600K;
break; break;
case 10 * MHZ: case 10 * MHZ:
refclk_freq = FSEL_CLKSEL_10M; clksel = FSEL_CLKSEL_10M;
break; break;
case 12 * MHZ: case 12 * MHZ:
refclk_freq = FSEL_CLKSEL_12M; clksel = FSEL_CLKSEL_12M;
break; break;
case 19200 * KHZ: case 19200 * KHZ:
refclk_freq = FSEL_CLKSEL_19200K; clksel = FSEL_CLKSEL_19200K;
break; break;
case 20 * MHZ: case 20 * MHZ:
refclk_freq = FSEL_CLKSEL_20M; clksel = 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; break;
case 24 * MHZ: case 24 * MHZ:
refclk_freq = PHYCLK_CLKSEL_24M; clksel = FSEL_CLKSEL_24M;
break; break;
case 48 * MHZ: case 50 * MHZ:
refclk_freq = PHYCLK_CLKSEL_48M; clksel = FSEL_CLKSEL_50M;
break; break;
default: default:
if (sphy->drv_data->cpu_type == TYPE_S3C64XX) dev_err(sphy->dev,
refclk_freq = PHYCLK_CLKSEL_48M; "Invalid reference clock frequency: %lu\n", rate);
else return -EINVAL;
refclk_freq = PHYCLK_CLKSEL_24M;
break;
} }
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;
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 = clk_get(sphy->dev, "ext_xtal");
else
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);
} }
rate = clk_get_rate(ref_clk);
refclk_freq = sphy->drv_data->rate_to_clksel(sphy, rate);
clk_put(ref_clk); clk_put(ref_clk);
return refclk_freq; return refclk_freq;
......
...@@ -244,6 +244,8 @@ enum samsung_cpu_type { ...@@ -244,6 +244,8 @@ enum samsung_cpu_type {
TYPE_EXYNOS5250, TYPE_EXYNOS5250,
}; };
struct samsung_usbphy;
/* /*
* struct samsung_usbphy_drvdata - driver data for various SoC variants * struct samsung_usbphy_drvdata - driver data for various SoC variants
* @cpu_type: machine identifier * @cpu_type: machine identifier
...@@ -268,6 +270,7 @@ struct samsung_usbphy_drvdata { ...@@ -268,6 +270,7 @@ struct samsung_usbphy_drvdata {
int hostphy_en_mask; int hostphy_en_mask;
u32 devphy_reg_offset; u32 devphy_reg_offset;
u32 hostphy_reg_offset; u32 hostphy_reg_offset;
int (*rate_to_clksel)(struct samsung_usbphy *, unsigned long);
}; };
/* /*
...@@ -325,3 +328,7 @@ extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy); ...@@ -325,3 +328,7 @@ extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
extern int samsung_usbphy_set_type(struct usb_phy *phy, extern int samsung_usbphy_set_type(struct usb_phy *phy,
enum samsung_usb_phy_type phy_type); enum samsung_usb_phy_type phy_type);
extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy); extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
extern int samsung_usbphy_rate_to_clksel_64xx(struct samsung_usbphy *sphy,
unsigned long rate);
extern int samsung_usbphy_rate_to_clksel_4x12(struct samsung_usbphy *sphy,
unsigned long rate);
...@@ -408,7 +408,10 @@ static int samsung_usb2phy_probe(struct platform_device *pdev) ...@@ -408,7 +408,10 @@ static int samsung_usb2phy_probe(struct platform_device *pdev)
sphy->phy.label = "samsung-usb2phy"; sphy->phy.label = "samsung-usb2phy";
sphy->phy.init = samsung_usb2phy_init; sphy->phy.init = samsung_usb2phy_init;
sphy->phy.shutdown = samsung_usb2phy_shutdown; sphy->phy.shutdown = samsung_usb2phy_shutdown;
sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
if (sphy->ref_clk_freq < 0)
return -EINVAL;
sphy->phy.otg = otg; sphy->phy.otg = otg;
sphy->phy.otg->phy = &sphy->phy; sphy->phy.otg->phy = &sphy->phy;
...@@ -438,18 +441,21 @@ static int samsung_usb2phy_remove(struct platform_device *pdev) ...@@ -438,18 +441,21 @@ static int samsung_usb2phy_remove(struct platform_device *pdev)
static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = { static const struct samsung_usbphy_drvdata usb2phy_s3c64xx = {
.cpu_type = TYPE_S3C64XX, .cpu_type = TYPE_S3C64XX,
.devphy_en_mask = S3C64XX_USBPHY_ENABLE, .devphy_en_mask = S3C64XX_USBPHY_ENABLE,
.rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx,
}; };
static const struct samsung_usbphy_drvdata usb2phy_exynos4 = { static const struct samsung_usbphy_drvdata usb2phy_exynos4 = {
.cpu_type = TYPE_EXYNOS4210, .cpu_type = TYPE_EXYNOS4210,
.devphy_en_mask = EXYNOS_USBPHY_ENABLE, .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
.hostphy_en_mask = EXYNOS_USBPHY_ENABLE, .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
.rate_to_clksel = samsung_usbphy_rate_to_clksel_64xx,
}; };
static struct samsung_usbphy_drvdata usb2phy_exynos5 = { static struct samsung_usbphy_drvdata usb2phy_exynos5 = {
.cpu_type = TYPE_EXYNOS5250, .cpu_type = TYPE_EXYNOS5250,
.hostphy_en_mask = EXYNOS_USBPHY_ENABLE, .hostphy_en_mask = EXYNOS_USBPHY_ENABLE,
.hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET, .hostphy_reg_offset = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
.rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
...@@ -274,7 +274,10 @@ static int samsung_usb3phy_probe(struct platform_device *pdev) ...@@ -274,7 +274,10 @@ static int samsung_usb3phy_probe(struct platform_device *pdev)
sphy->phy.init = samsung_usb3phy_init; sphy->phy.init = samsung_usb3phy_init;
sphy->phy.shutdown = samsung_usb3phy_shutdown; sphy->phy.shutdown = samsung_usb3phy_shutdown;
sphy->drv_data = samsung_usbphy_get_driver_data(pdev); sphy->drv_data = samsung_usbphy_get_driver_data(pdev);
sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy); sphy->ref_clk_freq = samsung_usbphy_get_refclk_freq(sphy);
if (sphy->ref_clk_freq < 0)
return -EINVAL;
spin_lock_init(&sphy->lock); spin_lock_init(&sphy->lock);
...@@ -300,6 +303,7 @@ static int samsung_usb3phy_remove(struct platform_device *pdev) ...@@ -300,6 +303,7 @@ static int samsung_usb3phy_remove(struct platform_device *pdev)
static struct samsung_usbphy_drvdata usb3phy_exynos5 = { static struct samsung_usbphy_drvdata usb3phy_exynos5 = {
.cpu_type = TYPE_EXYNOS5250, .cpu_type = TYPE_EXYNOS5250,
.devphy_en_mask = EXYNOS_USBPHY_ENABLE, .devphy_en_mask = EXYNOS_USBPHY_ENABLE,
.rate_to_clksel = samsung_usbphy_rate_to_clksel_4x12,
}; };
#ifdef CONFIG_OF #ifdef CONFIG_OF
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment