setup-usb-phy-s3c64xx.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0+
  2. //
  3. // Copyright (C) 2011 Samsung Electronics Co.Ltd
  4. // Author: Joonyoung Shim <[email protected]>
  5. #include <linux/clk.h>
  6. #include <linux/delay.h>
  7. #include <linux/err.h>
  8. #include <linux/io.h>
  9. #include <linux/platform_device.h>
  10. #include "map.h"
  11. #include "cpu.h"
  12. #include "usb-phy.h"
  13. #include "regs-sys-s3c64xx.h"
  14. #include "regs-usb-hsotg-phy-s3c64xx.h"
  15. enum samsung_usb_phy_type {
  16. USB_PHY_TYPE_DEVICE,
  17. USB_PHY_TYPE_HOST,
  18. };
  19. static int s3c_usb_otgphy_init(struct platform_device *pdev)
  20. {
  21. struct clk *xusbxti;
  22. u32 phyclk;
  23. writel(readl(S3C64XX_OTHERS) | S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
  24. /* set clock frequency for PLL */
  25. phyclk = readl(S3C_PHYCLK) & ~S3C_PHYCLK_CLKSEL_MASK;
  26. xusbxti = clk_get(&pdev->dev, "xusbxti");
  27. if (!IS_ERR(xusbxti)) {
  28. switch (clk_get_rate(xusbxti)) {
  29. case 12 * MHZ:
  30. phyclk |= S3C_PHYCLK_CLKSEL_12M;
  31. break;
  32. case 24 * MHZ:
  33. phyclk |= S3C_PHYCLK_CLKSEL_24M;
  34. break;
  35. default:
  36. case 48 * MHZ:
  37. /* default reference clock */
  38. break;
  39. }
  40. clk_put(xusbxti);
  41. }
  42. /* TODO: select external clock/oscillator */
  43. writel(phyclk | S3C_PHYCLK_CLK_FORCE, S3C_PHYCLK);
  44. /* set to normal OTG PHY */
  45. writel((readl(S3C_PHYPWR) & ~S3C_PHYPWR_NORMAL_MASK), S3C_PHYPWR);
  46. mdelay(1);
  47. /* reset OTG PHY and Link */
  48. writel(S3C_RSTCON_PHY | S3C_RSTCON_HCLK | S3C_RSTCON_PHYCLK,
  49. S3C_RSTCON);
  50. udelay(20); /* at-least 10uS */
  51. writel(0, S3C_RSTCON);
  52. return 0;
  53. }
  54. static int s3c_usb_otgphy_exit(struct platform_device *pdev)
  55. {
  56. writel((readl(S3C_PHYPWR) | S3C_PHYPWR_ANALOG_POWERDOWN |
  57. S3C_PHYPWR_OTG_DISABLE), S3C_PHYPWR);
  58. writel(readl(S3C64XX_OTHERS) & ~S3C64XX_OTHERS_USBMASK, S3C64XX_OTHERS);
  59. return 0;
  60. }
  61. int s3c_usb_phy_init(struct platform_device *pdev, int type)
  62. {
  63. if (type == USB_PHY_TYPE_DEVICE)
  64. return s3c_usb_otgphy_init(pdev);
  65. return -EINVAL;
  66. }
  67. int s3c_usb_phy_exit(struct platform_device *pdev, int type)
  68. {
  69. if (type == USB_PHY_TYPE_DEVICE)
  70. return s3c_usb_otgphy_exit(pdev);
  71. return -EINVAL;
  72. }