diff options
Diffstat (limited to 'drivers/usb/phy/phy-omap-usb3.c')
-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; |