ecddd5244f3d5124c99bf29eda99e960830ee2c3
[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 /* the LAN_RUN pin is GPIO6 according to the schematic */
49 /* edit: it's different between models.
50 * see https://github.com/raspberrypi/firmware/blob/master/extra/dt-blob.dts#L711
51 * e.g. on the RPi 2B it's pin 31
52 */
53
54 unsigned int ra = GP_FSEL3;
55 ra &= ~(7 << 3);
56 ra |= 1 << 3;
57 GP_FSEL3 = ra;
58
59 udelay(300);
60 GP_CLR0 = (1 << 31);
61 udelay(300);
62 GP_SET0 = (1 << 31);
63 udelay(300);
64
65 IODriverLog("LAN reset");
66
67 USB_GMDIOCSR = (1 << 18);
68
69 usb_write(0x15, 272 /* devmode ? 4369 : 272*/);
70 usb_write(0x19, 0x4);
71 usb_write(0x18, 0x10);
72 usb_write(0x1D, 0x4);
73 usb_write(0x17, 5682);
74
75 while((usb_read(0x1B) & (1 << 7)) != 0);
76
77 USB_GVBUSDRV &= ~(1 << 7);
78
79 usb_write(0x1E, 0x8000);
80
81 usb_write(0x1D, 0x5000);
82 usb_write(0x19, 0xC004);
83 usb_write(0x20, 0x1C2F);
84 usb_write(0x22, 0x0100);
85 usb_write(0x24, 0x0010);
86 usb_write(0x19, 0x0004);
87
88 USB_GVBUSDRV = USB_GVBUSDRV & 0xFFF0FFFF | 0xD0000;
89 udelay(300);
90 mmio_write32(0x7E980400 + 3084, 0x20402700);
91 udelay(300);
92 mmio_write32(0x7E980400, 1);
93 udelay(300);
94 mmio_write32(0x7E980404, 0xBB80);
95 udelay(300);
96
97 IODriverLog("started");
98
99 IODevice::start();
100 }
101
102 virtual void init() override {
103 setName("BCM2708UsbPhy");
104 setTag('USBP');
105 }
106 };
107
108 IODriverCreateSingletonInstance(BCM2708UsbPhy);
109
This page took 0.083623 seconds and 3 git commands to generate.