8442e0bfe8486864b9f4e767f1dfbb5d7b936c8b
[rpi-open-firmware.git] / drivers / BCM2708UsbPhy.cc
1 /*
2 * VideoCore4_Drivers
3 * Copyright (c) 2017 Authors of rpi-open-firmware
4 *
5 * USB PHY initialization driver.
6 */
7
8 #include <drivers/IODevice.hpp>
9 #include <drivers/BCM2708PowerManagement.hpp>
10 #define FLAG_BUSY (1 << 31)
11
12 struct BCM2708UsbPhy : IODevice {
13 IODriverConstructor(BCM2708UsbPhy);
14
15 void wait() {
16 while(USB_GMDIOCSR & FLAG_BUSY);
17 }
18
19 void write_bare(int reg, uint16_t value, int type) {
20 reg &= 0x1F;
21
22 /* precede MDIO access */
23 USB_GMDIOGEN = 0xFFFFFFFF;
24 wait();
25
26 /* write the actual value, with flags */
27 USB_GMDIOGEN = type | (reg << 18) | value;
28 wait();
29
30 /* dummy write due to errata; see BCM2835 peripheral manual */
31 USB_GMDIOGEN = 0;
32 wait();
33 }
34
35 uint16_t usb_read(int reg) {
36 write_bare(reg, 0, 0x60020000);
37 return USB_MDIO_CSR & 0xFFFFF;
38 }
39
40 virtual void usb_write(int reg, uint16_t value) {
41 IODriverLog("Writing 0x%X to reg 0x%X", value, reg);
42 write_bare(reg, value, 0x50020000);
43 }
44
45 virtual void start() override {
46 IODriverLog("starting ...");
47
48 /* pseudo code really.. */
49 A2W_XOSC_CTRL |= A2W_PASSWORD | A2W_XOSC_USBEN_SET;
50 while(!(A2W_XOSC_CTRL & A2W_XOSC_USBOK_SET));
51
52 /* the LAN_RUN pin is GPIO6 according to the schematic */
53 /* edit: it's different between models.
54 * see https://github.com/raspberrypi/firmware/blob/master/extra/dt-blob.dts#L711
55 * e.g. on the RPi 2B it's pin 31
56 */
57
58 unsigned int ra = GP_FSEL3;
59 ra &= ~(7 << 3);
60 ra |= 1 << 3;
61 GP_FSEL3 = ra;
62
63 udelay(300);
64 GP_CLR0 = (1 << 31);
65 udelay(300);
66 GP_SET0 = (1 << 31);
67 udelay(300);
68
69 IODriverLog("LAN reset");
70
71 USB_GMDIOCSR = (1 << 18);
72
73 usb_write(0x15, 272 /* devmode ? 4369 : 272*/);
74 usb_write(0x19, 0x4);
75 usb_write(0x18, 0x10);
76 usb_write(0x1D, 0x4);
77 usb_write(0x17, 5682);
78
79 while((usb_read(0x1B) & (1 << 7)) != 0);
80
81 USB_GVBUSDRV &= ~(1 << 7);
82
83 usb_write(0x1E, 0x8000);
84
85 usb_write(0x1D, 0x5000);
86 usb_write(0x19, 0xC004);
87 usb_write(0x20, 0x1C2F);
88 usb_write(0x22, 0x0100);
89 usb_write(0x24, 0x0010);
90 usb_write(0x19, 0x0004);
91
92 USB_GVBUSDRV = USB_GVBUSDRV & 0xFFF0FFFF | 0xD0000;
93 udelay(300);
94 mmio_write32(0x7E980400 + 3084, 0x20402700);
95 udelay(300);
96 mmio_write32(0x7E980400, 1);
97 udelay(300);
98 mmio_write32(0x7E980404, 0xBB80);
99 udelay(300);
100
101 IODriverLog("started");
102
103 IODevice::start();
104 }
105
106 virtual void init() override {
107 setName("BCM2708UsbPhy");
108 setTag('USBP');
109 }
110 };
111
112 IODriverCreateSingletonInstance(BCM2708UsbPhy);
113
This page took 0.107969 seconds and 3 git commands to generate.