rockchip_usb2_phy.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2016 Rockchip Electronics Co., Ltd
  4. */
  5. #include <common.h>
  6. #include <asm/io.h>
  7. #include <linux/libfdt.h>
  8. #include "../gadget/dwc2_udc_otg_priv.h"
  9. DECLARE_GLOBAL_DATA_PTR;
  10. #define BIT_WRITEABLE_SHIFT 16
  11. struct usb2phy_reg {
  12. unsigned int offset;
  13. unsigned int bitend;
  14. unsigned int bitstart;
  15. unsigned int disable;
  16. unsigned int enable;
  17. };
  18. /**
  19. * struct rockchip_usb2_phy_cfg: usb-phy port configuration
  20. * @port_reset: usb otg per-port reset register
  21. * @soft_con: software control usb otg register
  22. * @suspend: phy suspend register
  23. */
  24. struct rockchip_usb2_phy_cfg {
  25. struct usb2phy_reg port_reset;
  26. struct usb2phy_reg soft_con;
  27. struct usb2phy_reg suspend;
  28. };
  29. struct rockchip_usb2_phy_dt_id {
  30. char compatible[128];
  31. const void *data;
  32. };
  33. static const struct rockchip_usb2_phy_cfg rk3288_pdata = {
  34. .port_reset = {0x00, 12, 12, 0, 1},
  35. .soft_con = {0x08, 2, 2, 0, 1},
  36. .suspend = {0x0c, 5, 0, 0x01, 0x2A},
  37. };
  38. static struct rockchip_usb2_phy_dt_id rockchip_usb2_phy_dt_ids[] = {
  39. { .compatible = "rockchip,rk3288-usb-phy", .data = &rk3288_pdata },
  40. {}
  41. };
  42. static void property_enable(struct dwc2_plat_otg_data *pdata,
  43. const struct usb2phy_reg *reg, bool en)
  44. {
  45. unsigned int val, mask, tmp;
  46. tmp = en ? reg->enable : reg->disable;
  47. mask = GENMASK(reg->bitend, reg->bitstart);
  48. val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
  49. writel(val, pdata->regs_phy + reg->offset);
  50. }
  51. void otg_phy_init(struct dwc2_udc *dev)
  52. {
  53. struct dwc2_plat_otg_data *pdata = dev->pdata;
  54. struct rockchip_usb2_phy_cfg *phy_cfg = NULL;
  55. struct rockchip_usb2_phy_dt_id *of_id;
  56. int i;
  57. for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) {
  58. of_id = &rockchip_usb2_phy_dt_ids[i];
  59. if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node,
  60. of_id->compatible) == 0) {
  61. phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data;
  62. break;
  63. }
  64. }
  65. if (!phy_cfg) {
  66. debug("Can't find device platform data\n");
  67. hang();
  68. return;
  69. }
  70. pdata->priv = phy_cfg;
  71. /* disable software control */
  72. property_enable(pdata, &phy_cfg->soft_con, false);
  73. /* reset otg port */
  74. property_enable(pdata, &phy_cfg->port_reset, true);
  75. mdelay(1);
  76. property_enable(pdata, &phy_cfg->port_reset, false);
  77. udelay(1);
  78. }
  79. void otg_phy_off(struct dwc2_udc *dev)
  80. {
  81. struct dwc2_plat_otg_data *pdata = dev->pdata;
  82. struct rockchip_usb2_phy_cfg *phy_cfg = pdata->priv;
  83. /* enable software control */
  84. property_enable(pdata, &phy_cfg->soft_con, true);
  85. /* enter suspend */
  86. property_enable(pdata, &phy_cfg->suspend, true);
  87. }