Version:  2.0.40 2.2.26 2.4.37 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9

Linux/drivers/usb/phy/phy-mxs-usb.c

  1 /*
  2  * Copyright 2012-2014 Freescale Semiconductor, Inc.
  3  * Copyright (C) 2012 Marek Vasut <marex@denx.de>
  4  * on behalf of DENX Software Engineering GmbH
  5  *
  6  * The code contained herein is licensed under the GNU General Public
  7  * License. You may obtain a copy of the GNU General Public License
  8  * Version 2 or later at the following locations:
  9  *
 10  * http://www.opensource.org/licenses/gpl-license.html
 11  * http://www.gnu.org/copyleft/gpl.html
 12  */
 13 
 14 #include <linux/module.h>
 15 #include <linux/kernel.h>
 16 #include <linux/platform_device.h>
 17 #include <linux/clk.h>
 18 #include <linux/usb/otg.h>
 19 #include <linux/stmp_device.h>
 20 #include <linux/delay.h>
 21 #include <linux/err.h>
 22 #include <linux/io.h>
 23 #include <linux/of_device.h>
 24 #include <linux/regmap.h>
 25 #include <linux/mfd/syscon.h>
 26 
 27 #define DRIVER_NAME "mxs_phy"
 28 
 29 #define HW_USBPHY_PWD                           0x00
 30 #define HW_USBPHY_TX                            0x10
 31 #define HW_USBPHY_CTRL                          0x30
 32 #define HW_USBPHY_CTRL_SET                      0x34
 33 #define HW_USBPHY_CTRL_CLR                      0x38
 34 
 35 #define HW_USBPHY_DEBUG_SET                     0x54
 36 #define HW_USBPHY_DEBUG_CLR                     0x58
 37 
 38 #define HW_USBPHY_IP                            0x90
 39 #define HW_USBPHY_IP_SET                        0x94
 40 #define HW_USBPHY_IP_CLR                        0x98
 41 
 42 #define GM_USBPHY_TX_TXCAL45DP(x)            (((x) & 0xf) << 16)
 43 #define GM_USBPHY_TX_TXCAL45DN(x)            (((x) & 0xf) << 8)
 44 #define GM_USBPHY_TX_D_CAL(x)                (((x) & 0xf) << 0)
 45 
 46 #define BM_USBPHY_CTRL_SFTRST                   BIT(31)
 47 #define BM_USBPHY_CTRL_CLKGATE                  BIT(30)
 48 #define BM_USBPHY_CTRL_OTG_ID_VALUE             BIT(27)
 49 #define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS        BIT(26)
 50 #define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE     BIT(25)
 51 #define BM_USBPHY_CTRL_ENVBUSCHG_WKUP           BIT(23)
 52 #define BM_USBPHY_CTRL_ENIDCHG_WKUP             BIT(22)
 53 #define BM_USBPHY_CTRL_ENDPDMCHG_WKUP           BIT(21)
 54 #define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD        BIT(20)
 55 #define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE        BIT(19)
 56 #define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL         BIT(18)
 57 #define BM_USBPHY_CTRL_ENUTMILEVEL3             BIT(15)
 58 #define BM_USBPHY_CTRL_ENUTMILEVEL2             BIT(14)
 59 #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT       BIT(1)
 60 
 61 #define BM_USBPHY_IP_FIX                       (BIT(17) | BIT(18))
 62 
 63 #define BM_USBPHY_DEBUG_CLKGATE                 BIT(30)
 64 
 65 /* Anatop Registers */
 66 #define ANADIG_ANA_MISC0                        0x150
 67 #define ANADIG_ANA_MISC0_SET                    0x154
 68 #define ANADIG_ANA_MISC0_CLR                    0x158
 69 
 70 #define ANADIG_USB1_VBUS_DET_STAT               0x1c0
 71 #define ANADIG_USB2_VBUS_DET_STAT               0x220
 72 
 73 #define ANADIG_USB1_LOOPBACK_SET                0x1e4
 74 #define ANADIG_USB1_LOOPBACK_CLR                0x1e8
 75 #define ANADIG_USB2_LOOPBACK_SET                0x244
 76 #define ANADIG_USB2_LOOPBACK_CLR                0x248
 77 
 78 #define ANADIG_USB1_MISC                        0x1f0
 79 #define ANADIG_USB2_MISC                        0x250
 80 
 81 #define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG    BIT(12)
 82 #define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL BIT(11)
 83 
 84 #define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3)
 85 #define BM_ANADIG_USB2_VBUS_DET_STAT_VBUS_VALID BIT(3)
 86 
 87 #define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1   BIT(2)
 88 #define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN      BIT(5)
 89 #define BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1   BIT(2)
 90 #define BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN      BIT(5)
 91 
 92 #define BM_ANADIG_USB1_MISC_RX_VPIN_FS          BIT(29)
 93 #define BM_ANADIG_USB1_MISC_RX_VMIN_FS          BIT(28)
 94 #define BM_ANADIG_USB2_MISC_RX_VPIN_FS          BIT(29)
 95 #define BM_ANADIG_USB2_MISC_RX_VMIN_FS          BIT(28)
 96 
 97 #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy)
 98 
 99 /* Do disconnection between PHY and controller without vbus */
100 #define MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS    BIT(0)
101 
102 /*
103  * The PHY will be in messy if there is a wakeup after putting
104  * bus to suspend (set portsc.suspendM) but before setting PHY to low
105  * power mode (set portsc.phcd).
106  */
107 #define MXS_PHY_ABNORMAL_IN_SUSPEND             BIT(1)
108 
109 /*
110  * The SOF sends too fast after resuming, it will cause disconnection
111  * between host and high speed device.
112  */
113 #define MXS_PHY_SENDING_SOF_TOO_FAST            BIT(2)
114 
115 /*
116  * IC has bug fixes logic, they include
117  * MXS_PHY_ABNORMAL_IN_SUSPEND and MXS_PHY_SENDING_SOF_TOO_FAST
118  * which are described at above flags, the RTL will handle it
119  * according to different versions.
120  */
121 #define MXS_PHY_NEED_IP_FIX                     BIT(3)
122 
123 /* Minimum and maximum values for device tree entries */
124 #define MXS_PHY_TX_CAL45_MIN                    30
125 #define MXS_PHY_TX_CAL45_MAX                    55
126 #define MXS_PHY_TX_D_CAL_MIN                    79
127 #define MXS_PHY_TX_D_CAL_MAX                    119
128 
129 struct mxs_phy_data {
130         unsigned int flags;
131 };
132 
133 static const struct mxs_phy_data imx23_phy_data = {
134         .flags = MXS_PHY_ABNORMAL_IN_SUSPEND | MXS_PHY_SENDING_SOF_TOO_FAST,
135 };
136 
137 static const struct mxs_phy_data imx6q_phy_data = {
138         .flags = MXS_PHY_SENDING_SOF_TOO_FAST |
139                 MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
140                 MXS_PHY_NEED_IP_FIX,
141 };
142 
143 static const struct mxs_phy_data imx6sl_phy_data = {
144         .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
145                 MXS_PHY_NEED_IP_FIX,
146 };
147 
148 static const struct mxs_phy_data vf610_phy_data = {
149         .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS |
150                 MXS_PHY_NEED_IP_FIX,
151 };
152 
153 static const struct mxs_phy_data imx6sx_phy_data = {
154         .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
155 };
156 
157 static const struct mxs_phy_data imx6ul_phy_data = {
158         .flags = MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS,
159 };
160 
161 static const struct of_device_id mxs_phy_dt_ids[] = {
162         { .compatible = "fsl,imx6sx-usbphy", .data = &imx6sx_phy_data, },
163         { .compatible = "fsl,imx6sl-usbphy", .data = &imx6sl_phy_data, },
164         { .compatible = "fsl,imx6q-usbphy", .data = &imx6q_phy_data, },
165         { .compatible = "fsl,imx23-usbphy", .data = &imx23_phy_data, },
166         { .compatible = "fsl,vf610-usbphy", .data = &vf610_phy_data, },
167         { .compatible = "fsl,imx6ul-usbphy", .data = &imx6ul_phy_data, },
168         { /* sentinel */ }
169 };
170 MODULE_DEVICE_TABLE(of, mxs_phy_dt_ids);
171 
172 struct mxs_phy {
173         struct usb_phy phy;
174         struct clk *clk;
175         const struct mxs_phy_data *data;
176         struct regmap *regmap_anatop;
177         int port_id;
178         u32 tx_reg_set;
179         u32 tx_reg_mask;
180 };
181 
182 static inline bool is_imx6q_phy(struct mxs_phy *mxs_phy)
183 {
184         return mxs_phy->data == &imx6q_phy_data;
185 }
186 
187 static inline bool is_imx6sl_phy(struct mxs_phy *mxs_phy)
188 {
189         return mxs_phy->data == &imx6sl_phy_data;
190 }
191 
192 /*
193  * PHY needs some 32K cycles to switch from 32K clock to
194  * bus (such as AHB/AXI, etc) clock.
195  */
196 static void mxs_phy_clock_switch_delay(void)
197 {
198         usleep_range(300, 400);
199 }
200 
201 static void mxs_phy_tx_init(struct mxs_phy *mxs_phy)
202 {
203         void __iomem *base = mxs_phy->phy.io_priv;
204         u32 phytx;
205 
206         /* Update TX register if there is anything to write */
207         if (mxs_phy->tx_reg_mask) {
208                 phytx = readl(base + HW_USBPHY_TX);
209                 phytx &= ~mxs_phy->tx_reg_mask;
210                 phytx |= mxs_phy->tx_reg_set;
211                 writel(phytx, base + HW_USBPHY_TX);
212         }
213 }
214 
215 static int mxs_phy_hw_init(struct mxs_phy *mxs_phy)
216 {
217         int ret;
218         void __iomem *base = mxs_phy->phy.io_priv;
219 
220         ret = stmp_reset_block(base + HW_USBPHY_CTRL);
221         if (ret)
222                 return ret;
223 
224         /* Power up the PHY */
225         writel(0, base + HW_USBPHY_PWD);
226 
227         /*
228          * USB PHY Ctrl Setting
229          * - Auto clock/power on
230          * - Enable full/low speed support
231          */
232         writel(BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
233                 BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
234                 BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
235                 BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
236                 BM_USBPHY_CTRL_ENAUTO_PWRON_PLL |
237                 BM_USBPHY_CTRL_ENUTMILEVEL2 |
238                 BM_USBPHY_CTRL_ENUTMILEVEL3,
239                base + HW_USBPHY_CTRL_SET);
240 
241         if (mxs_phy->data->flags & MXS_PHY_NEED_IP_FIX)
242                 writel(BM_USBPHY_IP_FIX, base + HW_USBPHY_IP_SET);
243 
244         mxs_phy_tx_init(mxs_phy);
245 
246         return 0;
247 }
248 
249 /* Return true if the vbus is there */
250 static bool mxs_phy_get_vbus_status(struct mxs_phy *mxs_phy)
251 {
252         unsigned int vbus_value = 0;
253 
254         if (!mxs_phy->regmap_anatop)
255                 return false;
256 
257         if (mxs_phy->port_id == 0)
258                 regmap_read(mxs_phy->regmap_anatop,
259                         ANADIG_USB1_VBUS_DET_STAT,
260                         &vbus_value);
261         else if (mxs_phy->port_id == 1)
262                 regmap_read(mxs_phy->regmap_anatop,
263                         ANADIG_USB2_VBUS_DET_STAT,
264                         &vbus_value);
265 
266         if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID)
267                 return true;
268         else
269                 return false;
270 }
271 
272 static void __mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool disconnect)
273 {
274         void __iomem *base = mxs_phy->phy.io_priv;
275         u32 reg;
276 
277         if (disconnect)
278                 writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
279                         base + HW_USBPHY_DEBUG_CLR);
280 
281         if (mxs_phy->port_id == 0) {
282                 reg = disconnect ? ANADIG_USB1_LOOPBACK_SET
283                         : ANADIG_USB1_LOOPBACK_CLR;
284                 regmap_write(mxs_phy->regmap_anatop, reg,
285                         BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 |
286                         BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN);
287         } else if (mxs_phy->port_id == 1) {
288                 reg = disconnect ? ANADIG_USB2_LOOPBACK_SET
289                         : ANADIG_USB2_LOOPBACK_CLR;
290                 regmap_write(mxs_phy->regmap_anatop, reg,
291                         BM_ANADIG_USB2_LOOPBACK_UTMI_DIG_TST1 |
292                         BM_ANADIG_USB2_LOOPBACK_TSTI_TX_EN);
293         }
294 
295         if (!disconnect)
296                 writel_relaxed(BM_USBPHY_DEBUG_CLKGATE,
297                         base + HW_USBPHY_DEBUG_SET);
298 
299         /* Delay some time, and let Linestate be SE0 for controller */
300         if (disconnect)
301                 usleep_range(500, 1000);
302 }
303 
304 static bool mxs_phy_is_otg_host(struct mxs_phy *mxs_phy)
305 {
306         void __iomem *base = mxs_phy->phy.io_priv;
307         u32 phyctrl = readl(base + HW_USBPHY_CTRL);
308 
309         if (IS_ENABLED(CONFIG_USB_OTG) &&
310                         !(phyctrl & BM_USBPHY_CTRL_OTG_ID_VALUE))
311                 return true;
312 
313         return false;
314 }
315 
316 static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on)
317 {
318         bool vbus_is_on = false;
319 
320         /* If the SoCs don't need to disconnect line without vbus, quit */
321         if (!(mxs_phy->data->flags & MXS_PHY_DISCONNECT_LINE_WITHOUT_VBUS))
322                 return;
323 
324         /* If the SoCs don't have anatop, quit */
325         if (!mxs_phy->regmap_anatop)
326                 return;
327 
328         vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
329 
330         if (on && !vbus_is_on && !mxs_phy_is_otg_host(mxs_phy))
331                 __mxs_phy_disconnect_line(mxs_phy, true);
332         else
333                 __mxs_phy_disconnect_line(mxs_phy, false);
334 
335 }
336 
337 static int mxs_phy_init(struct usb_phy *phy)
338 {
339         int ret;
340         struct mxs_phy *mxs_phy = to_mxs_phy(phy);
341 
342         mxs_phy_clock_switch_delay();
343         ret = clk_prepare_enable(mxs_phy->clk);
344         if (ret)
345                 return ret;
346 
347         return mxs_phy_hw_init(mxs_phy);
348 }
349 
350 static void mxs_phy_shutdown(struct usb_phy *phy)
351 {
352         struct mxs_phy *mxs_phy = to_mxs_phy(phy);
353         u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
354                         BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
355                         BM_USBPHY_CTRL_ENIDCHG_WKUP |
356                         BM_USBPHY_CTRL_ENAUTOSET_USBCLKS |
357                         BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE |
358                         BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD |
359                         BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE |
360                         BM_USBPHY_CTRL_ENAUTO_PWRON_PLL;
361 
362         writel(value, phy->io_priv + HW_USBPHY_CTRL_CLR);
363         writel(0xffffffff, phy->io_priv + HW_USBPHY_PWD);
364 
365         writel(BM_USBPHY_CTRL_CLKGATE,
366                phy->io_priv + HW_USBPHY_CTRL_SET);
367 
368         clk_disable_unprepare(mxs_phy->clk);
369 }
370 
371 static bool mxs_phy_is_low_speed_connection(struct mxs_phy *mxs_phy)
372 {
373         unsigned int line_state;
374         /* bit definition is the same for all controllers */
375         unsigned int dp_bit = BM_ANADIG_USB1_MISC_RX_VPIN_FS,
376                      dm_bit = BM_ANADIG_USB1_MISC_RX_VMIN_FS;
377         unsigned int reg = ANADIG_USB1_MISC;
378 
379         /* If the SoCs don't have anatop, quit */
380         if (!mxs_phy->regmap_anatop)
381                 return false;
382 
383         if (mxs_phy->port_id == 0)
384                 reg = ANADIG_USB1_MISC;
385         else if (mxs_phy->port_id == 1)
386                 reg = ANADIG_USB2_MISC;
387 
388         regmap_read(mxs_phy->regmap_anatop, reg, &line_state);
389 
390         if ((line_state & (dp_bit | dm_bit)) ==  dm_bit)
391                 return true;
392         else
393                 return false;
394 }
395 
396 static int mxs_phy_suspend(struct usb_phy *x, int suspend)
397 {
398         int ret;
399         struct mxs_phy *mxs_phy = to_mxs_phy(x);
400         bool low_speed_connection, vbus_is_on;
401 
402         low_speed_connection = mxs_phy_is_low_speed_connection(mxs_phy);
403         vbus_is_on = mxs_phy_get_vbus_status(mxs_phy);
404 
405         if (suspend) {
406                 /*
407                  * FIXME: Do not power down RXPWD1PT1 bit for low speed
408                  * connect. The low speed connection will have problem at
409                  * very rare cases during usb suspend and resume process.
410                  */
411                 if (low_speed_connection & vbus_is_on) {
412                         /*
413                          * If value to be set as pwd value is not 0xffffffff,
414                          * several 32Khz cycles are needed.
415                          */
416                         mxs_phy_clock_switch_delay();
417                         writel(0xffbfffff, x->io_priv + HW_USBPHY_PWD);
418                 } else {
419                         writel(0xffffffff, x->io_priv + HW_USBPHY_PWD);
420                 }
421                 writel(BM_USBPHY_CTRL_CLKGATE,
422                        x->io_priv + HW_USBPHY_CTRL_SET);
423                 clk_disable_unprepare(mxs_phy->clk);
424         } else {
425                 mxs_phy_clock_switch_delay();
426                 ret = clk_prepare_enable(mxs_phy->clk);
427                 if (ret)
428                         return ret;
429                 writel(BM_USBPHY_CTRL_CLKGATE,
430                        x->io_priv + HW_USBPHY_CTRL_CLR);
431                 writel(0, x->io_priv + HW_USBPHY_PWD);
432         }
433 
434         return 0;
435 }
436 
437 static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled)
438 {
439         struct mxs_phy *mxs_phy = to_mxs_phy(x);
440         u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP |
441                         BM_USBPHY_CTRL_ENDPDMCHG_WKUP |
442                                 BM_USBPHY_CTRL_ENIDCHG_WKUP;
443         if (enabled) {
444                 mxs_phy_disconnect_line(mxs_phy, true);
445                 writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET);
446         } else {
447                 writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR);
448                 mxs_phy_disconnect_line(mxs_phy, false);
449         }
450 
451         return 0;
452 }
453 
454 static int mxs_phy_on_connect(struct usb_phy *phy,
455                 enum usb_device_speed speed)
456 {
457         dev_dbg(phy->dev, "%s device has connected\n",
458                 (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
459 
460         if (speed == USB_SPEED_HIGH)
461                 writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
462                        phy->io_priv + HW_USBPHY_CTRL_SET);
463 
464         return 0;
465 }
466 
467 static int mxs_phy_on_disconnect(struct usb_phy *phy,
468                 enum usb_device_speed speed)
469 {
470         dev_dbg(phy->dev, "%s device has disconnected\n",
471                 (speed == USB_SPEED_HIGH) ? "HS" : "FS/LS");
472 
473         /* Sometimes, the speed is not high speed when the error occurs */
474         if (readl(phy->io_priv + HW_USBPHY_CTRL) &
475                         BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
476                 writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
477                        phy->io_priv + HW_USBPHY_CTRL_CLR);
478 
479         return 0;
480 }
481 
482 static int mxs_phy_probe(struct platform_device *pdev)
483 {
484         struct resource *res;
485         void __iomem *base;
486         struct clk *clk;
487         struct mxs_phy *mxs_phy;
488         int ret;
489         const struct of_device_id *of_id;
490         struct device_node *np = pdev->dev.of_node;
491         u32 val;
492 
493         of_id = of_match_device(mxs_phy_dt_ids, &pdev->dev);
494         if (!of_id)
495                 return -ENODEV;
496 
497         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
498         base = devm_ioremap_resource(&pdev->dev, res);
499         if (IS_ERR(base))
500                 return PTR_ERR(base);
501 
502         clk = devm_clk_get(&pdev->dev, NULL);
503         if (IS_ERR(clk)) {
504                 dev_err(&pdev->dev,
505                         "can't get the clock, err=%ld", PTR_ERR(clk));
506                 return PTR_ERR(clk);
507         }
508 
509         mxs_phy = devm_kzalloc(&pdev->dev, sizeof(*mxs_phy), GFP_KERNEL);
510         if (!mxs_phy)
511                 return -ENOMEM;
512 
513         /* Some SoCs don't have anatop registers */
514         if (of_get_property(np, "fsl,anatop", NULL)) {
515                 mxs_phy->regmap_anatop = syscon_regmap_lookup_by_phandle
516                         (np, "fsl,anatop");
517                 if (IS_ERR(mxs_phy->regmap_anatop)) {
518                         dev_dbg(&pdev->dev,
519                                 "failed to find regmap for anatop\n");
520                         return PTR_ERR(mxs_phy->regmap_anatop);
521                 }
522         }
523 
524         /* Precompute which bits of the TX register are to be updated, if any */
525         if (!of_property_read_u32(np, "fsl,tx-cal-45-dn-ohms", &val) &&
526             val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
527                 /* Scale to a 4-bit value */
528                 val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
529                         / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
530                 mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DN(~0);
531                 mxs_phy->tx_reg_set  |= GM_USBPHY_TX_TXCAL45DN(val);
532         }
533 
534         if (!of_property_read_u32(np, "fsl,tx-cal-45-dp-ohms", &val) &&
535             val >= MXS_PHY_TX_CAL45_MIN && val <= MXS_PHY_TX_CAL45_MAX) {
536                 /* Scale to a 4-bit value. */
537                 val = (MXS_PHY_TX_CAL45_MAX - val) * 0xF
538                         / (MXS_PHY_TX_CAL45_MAX - MXS_PHY_TX_CAL45_MIN);
539                 mxs_phy->tx_reg_mask |= GM_USBPHY_TX_TXCAL45DP(~0);
540                 mxs_phy->tx_reg_set  |= GM_USBPHY_TX_TXCAL45DP(val);
541         }
542 
543         if (!of_property_read_u32(np, "fsl,tx-d-cal", &val) &&
544             val >= MXS_PHY_TX_D_CAL_MIN && val <= MXS_PHY_TX_D_CAL_MAX) {
545                 /* Scale to a 4-bit value.  Round up the values and heavily
546                  * weight the rounding by adding 2/3 of the denominator.
547                  */
548                 val = ((MXS_PHY_TX_D_CAL_MAX - val) * 0xF
549                         + (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN) * 2/3)
550                         / (MXS_PHY_TX_D_CAL_MAX - MXS_PHY_TX_D_CAL_MIN);
551                 mxs_phy->tx_reg_mask |= GM_USBPHY_TX_D_CAL(~0);
552                 mxs_phy->tx_reg_set  |= GM_USBPHY_TX_D_CAL(val);
553         }
554 
555         ret = of_alias_get_id(np, "usbphy");
556         if (ret < 0)
557                 dev_dbg(&pdev->dev, "failed to get alias id, errno %d\n", ret);
558         mxs_phy->port_id = ret;
559 
560         mxs_phy->phy.io_priv            = base;
561         mxs_phy->phy.dev                = &pdev->dev;
562         mxs_phy->phy.label              = DRIVER_NAME;
563         mxs_phy->phy.init               = mxs_phy_init;
564         mxs_phy->phy.shutdown           = mxs_phy_shutdown;
565         mxs_phy->phy.set_suspend        = mxs_phy_suspend;
566         mxs_phy->phy.notify_connect     = mxs_phy_on_connect;
567         mxs_phy->phy.notify_disconnect  = mxs_phy_on_disconnect;
568         mxs_phy->phy.type               = USB_PHY_TYPE_USB2;
569         mxs_phy->phy.set_wakeup         = mxs_phy_set_wakeup;
570 
571         mxs_phy->clk = clk;
572         mxs_phy->data = of_id->data;
573 
574         platform_set_drvdata(pdev, mxs_phy);
575 
576         device_set_wakeup_capable(&pdev->dev, true);
577 
578         return usb_add_phy_dev(&mxs_phy->phy);
579 }
580 
581 static int mxs_phy_remove(struct platform_device *pdev)
582 {
583         struct mxs_phy *mxs_phy = platform_get_drvdata(pdev);
584 
585         usb_remove_phy(&mxs_phy->phy);
586 
587         return 0;
588 }
589 
590 #ifdef CONFIG_PM_SLEEP
591 static void mxs_phy_enable_ldo_in_suspend(struct mxs_phy *mxs_phy, bool on)
592 {
593         unsigned int reg = on ? ANADIG_ANA_MISC0_SET : ANADIG_ANA_MISC0_CLR;
594 
595         /* If the SoCs don't have anatop, quit */
596         if (!mxs_phy->regmap_anatop)
597                 return;
598 
599         if (is_imx6q_phy(mxs_phy))
600                 regmap_write(mxs_phy->regmap_anatop, reg,
601                         BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG);
602         else if (is_imx6sl_phy(mxs_phy))
603                 regmap_write(mxs_phy->regmap_anatop,
604                         reg, BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG_SL);
605 }
606 
607 static int mxs_phy_system_suspend(struct device *dev)
608 {
609         struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
610 
611         if (device_may_wakeup(dev))
612                 mxs_phy_enable_ldo_in_suspend(mxs_phy, true);
613 
614         return 0;
615 }
616 
617 static int mxs_phy_system_resume(struct device *dev)
618 {
619         struct mxs_phy *mxs_phy = dev_get_drvdata(dev);
620 
621         if (device_may_wakeup(dev))
622                 mxs_phy_enable_ldo_in_suspend(mxs_phy, false);
623 
624         return 0;
625 }
626 #endif /* CONFIG_PM_SLEEP */
627 
628 static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
629                 mxs_phy_system_resume);
630 
631 static struct platform_driver mxs_phy_driver = {
632         .probe = mxs_phy_probe,
633         .remove = mxs_phy_remove,
634         .driver = {
635                 .name = DRIVER_NAME,
636                 .of_match_table = mxs_phy_dt_ids,
637                 .pm = &mxs_phy_pm,
638          },
639 };
640 
641 static int __init mxs_phy_module_init(void)
642 {
643         return platform_driver_register(&mxs_phy_driver);
644 }
645 postcore_initcall(mxs_phy_module_init);
646 
647 static void __exit mxs_phy_module_exit(void)
648 {
649         platform_driver_unregister(&mxs_phy_driver);
650 }
651 module_exit(mxs_phy_module_exit);
652 
653 MODULE_ALIAS("platform:mxs-usb-phy");
654 MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
655 MODULE_AUTHOR("Richard Zhao <richard.zhao@freescale.com>");
656 MODULE_DESCRIPTION("Freescale MXS USB PHY driver");
657 MODULE_LICENSE("GPL");
658 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us