diff options
| author | Roger Quadros <rogerq@ti.com> | 2013-07-09 07:38:31 -0400 |
|---|---|---|
| committer | Felipe Balbi <balbi@ti.com> | 2013-07-29 06:58:09 -0400 |
| commit | 519c6013d356fef95c9e45cfb533b3e68b47dbf4 (patch) | |
| tree | 04597d1061d4f76b121c31ef19a7ddda70eecb64 | |
| parent | 88650d62a12de7fb9437b5508cc7f6b28da58cbf (diff) | |
usb: phy: omap-usb3: Improve DPLL parameter lookup code
Use a mapping table (dpll_map) to match the possible system clock rates
to the appropriate DPLL parameters.
Introduce a function "omap_usb3_get_dpll_params()" that will
return the matching DPLL parameters for the given clock rate.
Also, bail out on phy init if DPLL locking fails.
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
| -rw-r--r-- | drivers/usb/phy/phy-omap-usb3.c | 87 |
1 files changed, 38 insertions, 49 deletions
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c index a2fb30bbb971..fc15694d3031 100644 --- a/drivers/usb/phy/phy-omap-usb3.c +++ b/drivers/usb/phy/phy-omap-usb3.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
| 28 | #include <linux/usb/omap_control_usb.h> | 28 | #include <linux/usb/omap_control_usb.h> |
| 29 | 29 | ||
| 30 | #define NUM_SYS_CLKS 6 | ||
| 31 | #define PLL_STATUS 0x00000004 | 30 | #define PLL_STATUS 0x00000004 |
| 32 | #define PLL_GO 0x00000008 | 31 | #define PLL_GO 0x00000008 |
| 33 | #define PLL_CONFIGURATION1 0x0000000C | 32 | #define PLL_CONFIGURATION1 0x0000000C |
| @@ -57,26 +56,32 @@ | |||
| 57 | */ | 56 | */ |
| 58 | # define PLL_IDLE_TIME 100; | 57 | # define PLL_IDLE_TIME 100; |
| 59 | 58 | ||
| 60 | enum sys_clk_rate { | 59 | struct usb_dpll_map { |
| 61 | CLK_RATE_UNDEFINED = -1, | 60 | unsigned long rate; |
| 62 | CLK_RATE_12MHZ, | 61 | struct usb_dpll_params params; |
| 63 | CLK_RATE_16MHZ, | ||
| 64 | CLK_RATE_19MHZ, | ||
| 65 | CLK_RATE_20MHZ, | ||
| 66 | CLK_RATE_26MHZ, | ||
| 67 | CLK_RATE_38MHZ | ||
| 68 | }; | 62 | }; |
| 69 | 63 | ||
| 70 | static struct usb_dpll_params omap_usb3_dpll_params[NUM_SYS_CLKS] = { | 64 | static struct usb_dpll_map dpll_map[] = { |
| 71 | {1250, 5, 4, 20, 0}, /* 12 MHz */ | 65 | {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */ |
| 72 | {3125, 20, 4, 20, 0}, /* 16.8 MHz */ | 66 | {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */ |
| 73 | {1172, 8, 4, 20, 65537}, /* 19.2 MHz */ | 67 | {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */ |
| 74 | {1000, 7, 4, 10, 0}, /* 20 MHz */ | 68 | {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */ |
| 75 | {1250, 12, 4, 20, 0}, /* 26 MHz */ | 69 | {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */ |
| 76 | {3125, 47, 4, 20, 92843}, /* 38.4 MHz */ | 70 | {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */ |
| 77 | |||
| 78 | }; | 71 | }; |
| 79 | 72 | ||
| 73 | static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate) | ||
| 74 | { | ||
| 75 | int i; | ||
| 76 | |||
| 77 | for (i = 0; i < ARRAY_SIZE(dpll_map); i++) { | ||
| 78 | if (rate == dpll_map[i].rate) | ||
| 79 | return &dpll_map[i].params; | ||
| 80 | } | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 80 | static int omap_usb3_suspend(struct usb_phy *x, int suspend) | 85 | static int omap_usb3_suspend(struct usb_phy *x, int suspend) |
| 81 | { | 86 | { |
| 82 | struct omap_usb *phy = phy_to_omapusb(x); | 87 | struct omap_usb *phy = phy_to_omapusb(x); |
| @@ -116,26 +121,6 @@ static int omap_usb3_suspend(struct usb_phy *x, int suspend) | |||
| 116 | return 0; | 121 | return 0; |
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | static inline enum sys_clk_rate __get_sys_clk_index(unsigned long rate) | ||
| 120 | { | ||
| 121 | switch (rate) { | ||
| 122 | case 12000000: | ||
| 123 | return CLK_RATE_12MHZ; | ||
| 124 | case 16800000: | ||
| 125 | return CLK_RATE_16MHZ; | ||
| 126 | case 19200000: | ||
| 127 | return CLK_RATE_19MHZ; | ||
| 128 | case 20000000: | ||
| 129 | return CLK_RATE_20MHZ; | ||
| 130 | case 26000000: | ||
| 131 | return CLK_RATE_26MHZ; | ||
| 132 | case 38400000: | ||
| 133 | return CLK_RATE_38MHZ; | ||
| 134 | default: | ||
| 135 | return CLK_RATE_UNDEFINED; | ||
| 136 | } | ||
| 137 | } | ||
| 138 | |||
| 139 | static void omap_usb_dpll_relock(struct omap_usb *phy) | 124 | static void omap_usb_dpll_relock(struct omap_usb *phy) |
| 140 | { | 125 | { |
| 141 | u32 val; | 126 | u32 val; |
| @@ -155,39 +140,39 @@ static int omap_usb_dpll_lock(struct omap_usb *phy) | |||
| 155 | { | 140 | { |
| 156 | u32 val; | 141 | u32 val; |
| 157 | unsigned long rate; | 142 | unsigned long rate; |
| 158 | enum sys_clk_rate clk_index; | 143 | struct usb_dpll_params *dpll_params; |
| 159 | |||
| 160 | rate = clk_get_rate(phy->sys_clk); | ||
| 161 | clk_index = __get_sys_clk_index(rate); | ||
| 162 | 144 | ||
| 163 | if (clk_index == CLK_RATE_UNDEFINED) { | 145 | rate = clk_get_rate(phy->sys_clk); |
| 164 | pr_err("dpll cannot be locked for sys clk freq:%luHz\n", rate); | 146 | dpll_params = omap_usb3_get_dpll_params(rate); |
| 147 | if (!dpll_params) { | ||
| 148 | dev_err(phy->dev, | ||
| 149 | "No DPLL configuration for %lu Hz SYS CLK\n", rate); | ||
| 165 | return -EINVAL; | 150 | return -EINVAL; |
| 166 | } | 151 | } |
| 167 | 152 | ||
| 168 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | 153 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); |
| 169 | val &= ~PLL_REGN_MASK; | 154 | val &= ~PLL_REGN_MASK; |
| 170 | val |= omap_usb3_dpll_params[clk_index].n << PLL_REGN_SHIFT; | 155 | val |= dpll_params->n << PLL_REGN_SHIFT; |
| 171 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | 156 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); |
| 172 | 157 | ||
| 173 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); | 158 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2); |
| 174 | val &= ~PLL_SELFREQDCO_MASK; | 159 | val &= ~PLL_SELFREQDCO_MASK; |
| 175 | val |= omap_usb3_dpll_params[clk_index].freq << PLL_SELFREQDCO_SHIFT; | 160 | val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT; |
| 176 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); | 161 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val); |
| 177 | 162 | ||
| 178 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); | 163 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1); |
| 179 | val &= ~PLL_REGM_MASK; | 164 | val &= ~PLL_REGM_MASK; |
| 180 | val |= omap_usb3_dpll_params[clk_index].m << PLL_REGM_SHIFT; | 165 | val |= dpll_params->m << PLL_REGM_SHIFT; |
| 181 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); | 166 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val); |
| 182 | 167 | ||
| 183 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); | 168 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4); |
| 184 | val &= ~PLL_REGM_F_MASK; | 169 | val &= ~PLL_REGM_F_MASK; |
| 185 | val |= omap_usb3_dpll_params[clk_index].mf << PLL_REGM_F_SHIFT; | 170 | val |= dpll_params->mf << PLL_REGM_F_SHIFT; |
| 186 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); | 171 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val); |
| 187 | 172 | ||
| 188 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); | 173 | val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3); |
| 189 | val &= ~PLL_SD_MASK; | 174 | val &= ~PLL_SD_MASK; |
| 190 | val |= omap_usb3_dpll_params[clk_index].sd << PLL_SD_SHIFT; | 175 | val |= dpll_params->sd << PLL_SD_SHIFT; |
| 191 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); | 176 | omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); |
| 192 | 177 | ||
| 193 | omap_usb_dpll_relock(phy); | 178 | omap_usb_dpll_relock(phy); |
| @@ -198,8 +183,12 @@ static int omap_usb_dpll_lock(struct omap_usb *phy) | |||
| 198 | static int omap_usb3_init(struct usb_phy *x) | 183 | static int omap_usb3_init(struct usb_phy *x) |
| 199 | { | 184 | { |
| 200 | struct omap_usb *phy = phy_to_omapusb(x); | 185 | struct omap_usb *phy = phy_to_omapusb(x); |
| 186 | int ret; | ||
| 187 | |||
| 188 | ret = omap_usb_dpll_lock(phy); | ||
| 189 | if (ret) | ||
| 190 | return ret; | ||
| 201 | 191 | ||
| 202 | omap_usb_dpll_lock(phy); | ||
| 203 | omap_control_usb3_phy_power(phy->control_dev, 1); | 192 | omap_control_usb3_phy_power(phy->control_dev, 1); |
| 204 | 193 | ||
| 205 | return 0; | 194 | return 0; |
