Firmware for MNT ZZ9000 graphics and ARM coprocessor card for Amiga computers.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ehci-zynq.c 2.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2014, Xilinx, Inc
  4. *
  5. * USB Low level initialization(Specific to zynq)
  6. */
  7. #include "usb.h"
  8. #include "ehci-ci.h"
  9. #include "ulpi.h"
  10. #include "ehci.h"
  11. #include <stdio.h>
  12. #include <xusbps_hw.h>
  13. #include <sleep.h>
  14. #define EINVAL 1
  15. // see zynq TRM
  16. #define USB_BASE_ADDR 0xE0002000
  17. int ehci_hcd_init(int index, enum usb_init_type init,
  18. struct ehci_hccr **hccr, struct ehci_hcor **hcor)
  19. {
  20. if (index > 0) {
  21. printf("[ehci_hcd_init] index out of range: %d\n",index);
  22. return -EINVAL;
  23. }
  24. struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR);
  25. if (hccr && hcor) {
  26. *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
  27. *hcor = (struct ehci_hcor *)((uint32_t)*hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
  28. }
  29. return 0;
  30. }
  31. int ehci_zynq_probe(struct zynq_ehci_priv *priv)
  32. {
  33. struct ehci_hccr *hccr;
  34. struct ehci_hcor *hcor;
  35. struct ulpi_viewport ulpi_vp;
  36. /* Used for writing the ULPI data address */
  37. struct ulpi_regs *ulpi = (struct ulpi_regs *)0;
  38. int ret;
  39. struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR);
  40. priv->ehci = ehci;
  41. XUsbPs_ResetHw(USB_BASE_ADDR);
  42. hccr = (struct ehci_hccr *)((uint32_t)&priv->ehci->caplength);
  43. hcor = (struct ehci_hcor *)((uint32_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
  44. //printf("[ehci-zynq] hccr: %p hcor: %p\n", hccr, hcor);
  45. priv->ehcictrl.hccr = hccr;
  46. priv->ehcictrl.hcor = hcor;
  47. ulpi_vp.viewport_addr = (u32)&priv->ehci->ulpi_viewpoint;
  48. ulpi_vp.port_num = 0;
  49. //printf("[ehci-zynq] viewport_addr: %p\n", &priv->ehci->ulpi_viewpoint);
  50. // lifted from https://elixir.bootlin.com/u-boot/latest/source/drivers/usb/host/ehci-fsl.c#L275
  51. /* Set to Host mode */
  52. setbits_le32(&ehci->usbmode, CM_HOST);
  53. // FIXME: need to figure out which of these are necessary
  54. setbits_le32(&ehci->portsc, USB_EN);
  55. usleep(1000); /* delay required for PHY Clk to appear */
  56. out_le32(&(hcor)->or_portsc[0], PORT_PTS_ULPI);
  57. out_be32(&ehci->prictrl, 0x0000000c);
  58. out_be32(&ehci->age_cnt_limit, 0x00000040);
  59. out_be32(&ehci->sictrl, 0x00000001);
  60. in_le32(&ehci->usbmode);
  61. /* ULPI set flags */
  62. ret = ulpi_init(&ulpi_vp);
  63. if (ret) {
  64. puts("zynq ULPI viewport init failed\n");
  65. return -1;
  66. }
  67. // dp and dm pulldown = host mode (really?)
  68. // extvbusind = vbus indicator input
  69. ulpi_write(&ulpi_vp, &ulpi->otg_ctrl,
  70. ULPI_OTG_DP_PULLDOWN | ULPI_OTG_DM_PULLDOWN |
  71. ULPI_OTG_EXTVBUSIND);
  72. ulpi_write(&ulpi_vp, &ulpi->function_ctrl,
  73. ULPI_FC_FULL_SPEED | ULPI_FC_OPMODE_NORMAL |
  74. ULPI_FC_SUSPENDM);
  75. ulpi_write(&ulpi_vp, &ulpi->iface_ctrl, 0);
  76. /* drive external vbus switch */
  77. ulpi_write(&ulpi_vp, &ulpi->otg_ctrl_set,
  78. ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
  79. // FIXME removing this made it work! probably because there is another ehci_reset in there?
  80. //return ehci_register(&priv->ehcictrl, hccr, hcor, NULL, 0, USB_INIT_HOST);
  81. return 0;
  82. }