implement usb2 termination and dpll delay setting for vt8237r
[coreboot.git] / src / southbridge / via / vt8237r / usb.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007, 2008 Rudolf Marek <r.marek@assembler.cz>
5  * Copyright (C) 2009 Jon Harrison <bothlyn@blueyonder.co.uk>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <console/console.h>
22 #include <device/device.h>
23 #include <device/pci.h>
24 #include <device/pci_ids.h>
25 #include "chip.h"
26 #include "vt8237r.h"
27
28 #if CONFIG_EPIA_VT8237R_INIT
29 u32 usb_io_addr[4] = {0xcc00, 0xd000, 0xd400, 0xd800};
30 #endif
31
32 static void usb_i_init(struct device *dev)
33 {
34 #if CONFIG_EPIA_VT8237R_INIT
35         u8 reg8;
36
37         printk(BIOS_DEBUG, "Entering %s\n", __func__);
38
39         reg8 = pci_read_config8(dev, 0x04);
40
41         printk(BIOS_SPEW, "%s Read %02X from PCI Command Reg\n", dev_path(dev), reg8);
42
43         reg8 = reg8 | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
44         pci_write_config8(dev, 0x04, reg8);
45
46         printk(BIOS_SPEW, "%s Wrote %02X to PCI Command Reg\n", dev_path(dev), reg8);
47
48         /* Set Cache Line Size and Latency Timer */
49         pci_write_config8(dev, 0x0c, 0x08);
50         pci_write_config8(dev, 0x0d, 0x20);
51
52         /* Enable Sub Device ID Back Door and set Generic */
53         reg8 = pci_read_config8(dev, 0x42);
54         reg8 |= 0x10;
55         pci_write_config8(dev, 0x42, reg8);
56         pci_write_config16(dev, 0x2e, 0xAA07);
57         reg8 &= ~0x10;
58         pci_write_config8(dev, 0x42, reg8);
59
60
61         pci_write_config8(dev, 0x41, 0x12);
62
63         pci_write_config8(dev, 0x49, 0x0B);
64
65         /* Clear PCI Status */
66         pci_write_config16(dev, 0x06, 0x7A10);
67 #endif
68         return;
69 }
70
71 static void vt8237_usb_i_read_resources(struct device *dev)
72 {
73 #if CONFIG_EPIA_VT8237R_INIT
74         struct resource *res;
75         u8 function = (u8) dev->path.pci.devfn & 0x7;
76
77         printk(BIOS_SPEW, "VT8237R Fixing USB 1.1 fn %d I/O resource = 0x%04X\n", function, usb_io_addr[function]);
78
79         /* Fix the I/O Resources of the USB1.1 Interfaces */
80         /* Auto PCI probe seems to size the resources     */
81         /* Incorrectly                                    */
82         res = new_resource(dev, PCI_BASE_ADDRESS_4);
83         res->base = usb_io_addr[function];
84         res->size = 256;
85         res->limit = 0xffffUL;
86         res->align = 10;
87         res->gran = 8;
88         res->flags = IORESOURCE_IO | IORESOURCE_FIXED |
89                                 IORESOURCE_ASSIGNED;
90 #else
91         pci_dev_read_resources(dev);
92 #endif
93         return;
94 }
95
96 static void usb_ii_init(struct device *dev)
97 {
98         struct southbridge_via_vt8237r_config *cfg;
99 #if CONFIG_EPIA_VT8237R_INIT
100         u8 reg8;
101
102         printk(BIOS_DEBUG, "Entering %s\n", __func__);
103
104         /* Set memory Write and Invalidate */
105         reg8 = pci_read_config8(dev, 0x04);
106         reg8 |= 0x10;
107         pci_write_config8(dev, 0x04, reg8);
108
109         /* Set Cache line Size and Latency Timer */
110         pci_write_config8(dev, 0x0c, 0x08);
111         pci_write_config8(dev, 0x0d, 0x20);
112
113         /* Clear PCI Status */
114         pci_write_config16(dev, 0x06, 0x7A10);
115 #endif
116
117         cfg = dev->chip_info;
118
119         if (cfg) {
120                 if (cfg->usb2_termination_set) {
121                         /* High Speed Port Pad Termination Resistor Fine Tune */
122                         pci_write_config8(dev, 0x5a, cfg->usb2_termination_c |
123                                 (cfg->usb2_termination_d << 4));
124                         pci_write_config8(dev, 0x5b, cfg->usb2_termination_a |
125                                 (cfg->usb2_termination_b << 4));
126                         pci_write_config8(dev, 0x5d, cfg->usb2_termination_e |
127                                 (cfg->usb2_termination_f << 4));
128                         pci_write_config8(dev, 0x5e, cfg->usb2_termination_g |
129                                 (cfg->usb2_termination_h << 4));
130                 }
131
132                 if (cfg->usb2_dpll_set) {
133                         /* Delay DPLL Input Data Control */
134                         pci_write_config8(dev, 0x5c,
135                                 (pci_read_config8(dev, 0x5c) & ~0x70) |
136                                 (cfg->usb2_dpll_delay << 4));
137                 }
138         }
139 }
140
141 static void vt8237_usb_ii_read_resources(struct device *dev)
142 {
143 #if CONFIG_EPIA_VT8237R_INIT
144         struct resource *res;
145
146         /* Fix the I/O Resources of the USB2.0 Interface */
147         res = new_resource(dev, PCI_BASE_ADDRESS_0);
148         res->base = 0xF6000000ULL;
149         res->size = 256;
150         res->align = 12;
151         res->gran = 8;
152         res->limit = res->base + res->size - 1;
153         res->flags = IORESOURCE_MEM | IORESOURCE_FIXED |
154                                 IORESOURCE_ASSIGNED;
155 #else
156         pci_dev_read_resources(dev);
157 #endif
158         return;
159 }
160
161 static const struct device_operations usb_i_ops = {
162         .read_resources         = vt8237_usb_i_read_resources,
163         .set_resources          = pci_dev_set_resources,
164         .enable_resources       = pci_dev_enable_resources,
165         .init                           = usb_i_init,
166         .enable                         = 0,
167         .ops_pci                        = 0,
168 };
169
170 static const struct device_operations usb_ii_ops = {
171         .read_resources         = vt8237_usb_ii_read_resources,
172         .set_resources          = pci_dev_set_resources,
173         .enable_resources       = pci_dev_enable_resources,
174         .init                           = usb_ii_init,
175         .enable                         = 0,
176         .ops_pci                        = 0,
177 };
178
179 static const struct pci_driver vt8237r_driver_usbii __pci_driver = {
180         .ops    = &usb_ii_ops,
181         .vendor = PCI_VENDOR_ID_VIA,
182         .device = PCI_DEVICE_ID_VIA_VT8237R_EHCI,
183 };
184
185 static const struct pci_driver vt8237r_driver_usbi __pci_driver = {
186         .ops    = &usb_i_ops,
187         .vendor = PCI_VENDOR_ID_VIA,
188         .device = PCI_DEVICE_ID_VIA_VT8237R_UHCI,
189 };