aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2014-03-06 09:38:43 -0500
committerKishon Vijay Abraham I <kishon@ti.com>2014-03-09 03:15:11 -0400
commit629138dbaec33cecbb61fda1f5c1f047a1374993 (patch)
tree7554c011ff72e491d5d060f26c52a719f3170bbf /drivers/phy
parent9c7f04436088b00727fa389e2b97b182d8488123 (diff)
phy: ti-pipe3: streamline PHY operations
Limit .power_on() and .power_off() to just control the PHY power and not the DPLL. The DPLL will be enabled in .init() and idled in .exit(). Don't reprogram the DPLL if it has been already locked by the bootloader. This fixes a problem with SATA, where it fails if SATA was used by the bootloader. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/phy-ti-pipe3.c114
1 files changed, 63 insertions, 51 deletions
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index baa3f78d62bc..12cc900491a4 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -47,7 +47,8 @@
47#define PLL_SD_MASK 0x0003FC00 47#define PLL_SD_MASK 0x0003FC00
48#define PLL_SD_SHIFT 10 48#define PLL_SD_SHIFT 10
49#define SET_PLL_GO 0x1 49#define SET_PLL_GO 0x1
50#define PLL_TICOPWDN 0x10000 50#define PLL_LDOPWDN BIT(15)
51#define PLL_TICOPWDN BIT(16)
51#define PLL_LOCK 0x2 52#define PLL_LOCK 0x2
52#define PLL_IDLE 0x1 53#define PLL_IDLE 0x1
53 54
@@ -56,7 +57,8 @@
56 * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status 57 * value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
57 * to be correctly reflected in the PIPE3PHY_PLL_STATUS register. 58 * to be correctly reflected in the PIPE3PHY_PLL_STATUS register.
58 */ 59 */
59# define PLL_IDLE_TIME 100; 60#define PLL_IDLE_TIME 100 /* in milliseconds */
61#define PLL_LOCK_TIME 100 /* in milliseconds */
60 62
61struct pipe3_dpll_params { 63struct pipe3_dpll_params {
62 u16 m; 64 u16 m;
@@ -132,24 +134,6 @@ static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
132static int ti_pipe3_power_off(struct phy *x) 134static int ti_pipe3_power_off(struct phy *x)
133{ 135{
134 struct ti_pipe3 *phy = phy_get_drvdata(x); 136 struct ti_pipe3 *phy = phy_get_drvdata(x);
135 int val;
136 int timeout = PLL_IDLE_TIME;
137
138 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
139 val |= PLL_IDLE;
140 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
141
142 do {
143 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
144 if (val & PLL_TICOPWDN)
145 break;
146 udelay(5);
147 } while (--timeout);
148
149 if (!timeout) {
150 dev_err(phy->dev, "power off failed\n");
151 return -EBUSY;
152 }
153 137
154 omap_control_phy_power(phy->control_dev, 0); 138 omap_control_phy_power(phy->control_dev, 0);
155 139
@@ -159,44 +143,34 @@ static int ti_pipe3_power_off(struct phy *x)
159static int ti_pipe3_power_on(struct phy *x) 143static int ti_pipe3_power_on(struct phy *x)
160{ 144{
161 struct ti_pipe3 *phy = phy_get_drvdata(x); 145 struct ti_pipe3 *phy = phy_get_drvdata(x);
162 int val;
163 int timeout = PLL_IDLE_TIME;
164
165 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
166 val &= ~PLL_IDLE;
167 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
168 146
169 do { 147 omap_control_phy_power(phy->control_dev, 1);
170 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
171 if (!(val & PLL_TICOPWDN))
172 break;
173 udelay(5);
174 } while (--timeout);
175
176 if (!timeout) {
177 dev_err(phy->dev, "power on failed\n");
178 return -EBUSY;
179 }
180 148
181 return 0; 149 return 0;
182} 150}
183 151
184static void ti_pipe3_dpll_relock(struct ti_pipe3 *phy) 152static int ti_pipe3_dpll_wait_lock(struct ti_pipe3 *phy)
185{ 153{
186 u32 val; 154 u32 val;
187 unsigned long timeout; 155 unsigned long timeout;
188 156
189 ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO); 157 timeout = jiffies + msecs_to_jiffies(PLL_LOCK_TIME);
190
191 timeout = jiffies + msecs_to_jiffies(20);
192 do { 158 do {
159 cpu_relax();
193 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS); 160 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
194 if (val & PLL_LOCK) 161 if (val & PLL_LOCK)
195 break; 162 break;
196 } while (!WARN_ON(time_after(jiffies, timeout))); 163 } while (!time_after(jiffies, timeout));
164
165 if (!(val & PLL_LOCK)) {
166 dev_err(phy->dev, "DPLL failed to lock\n");
167 return -EBUSY;
168 }
169
170 return 0;
197} 171}
198 172
199static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy) 173static int ti_pipe3_dpll_program(struct ti_pipe3 *phy)
200{ 174{
201 u32 val; 175 u32 val;
202 struct pipe3_dpll_params *dpll_params; 176 struct pipe3_dpll_params *dpll_params;
@@ -230,27 +204,65 @@ static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy)
230 val |= dpll_params->sd << PLL_SD_SHIFT; 204 val |= dpll_params->sd << PLL_SD_SHIFT;
231 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val); 205 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
232 206
233 ti_pipe3_dpll_relock(phy); 207 ti_pipe3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
234 208
235 return 0; 209 return ti_pipe3_dpll_wait_lock(phy);
236} 210}
237 211
238static int ti_pipe3_init(struct phy *x) 212static int ti_pipe3_init(struct phy *x)
239{ 213{
240 struct ti_pipe3 *phy = phy_get_drvdata(x); 214 struct ti_pipe3 *phy = phy_get_drvdata(x);
241 int ret; 215 u32 val;
216 int ret = 0;
242 217
243 ret = ti_pipe3_dpll_lock(phy); 218 /* Bring it out of IDLE if it is IDLE */
244 if (ret) 219 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
245 return ret; 220 if (val & PLL_IDLE) {
221 val &= ~PLL_IDLE;
222 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
223 ret = ti_pipe3_dpll_wait_lock(phy);
224 }
246 225
247 omap_control_phy_power(phy->control_dev, 1); 226 /* Program the DPLL only if not locked */
227 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
228 if (!(val & PLL_LOCK))
229 if (ti_pipe3_dpll_program(phy))
230 return -EINVAL;
248 231
249 return 0; 232 return ret;
250} 233}
251 234
235static int ti_pipe3_exit(struct phy *x)
236{
237 struct ti_pipe3 *phy = phy_get_drvdata(x);
238 u32 val;
239 unsigned long timeout;
240
241 /* Put DPLL in IDLE mode */
242 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
243 val |= PLL_IDLE;
244 ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
245
246 /* wait for LDO and Oscillator to power down */
247 timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
248 do {
249 cpu_relax();
250 val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
251 if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
252 break;
253 } while (!time_after(jiffies, timeout));
254
255 if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
256 dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
257 val);
258 return -EBUSY;
259 }
260
261 return 0;
262}
252static struct phy_ops ops = { 263static struct phy_ops ops = {
253 .init = ti_pipe3_init, 264 .init = ti_pipe3_init,
265 .exit = ti_pipe3_exit,
254 .power_on = ti_pipe3_power_on, 266 .power_on = ti_pipe3_power_on,
255 .power_off = ti_pipe3_power_off, 267 .power_off = ti_pipe3_power_off,
256 .owner = THIS_MODULE, 268 .owner = THIS_MODULE,