blob: 8fdb02b6e90f79a52699a10e85e9ca55c8d3fd15 [file] [log] [blame]
Wu Zhangjin22c21002009-11-10 00:06:12 +08001/*
2 * the OHCI Virtual Support Module of AMD CS5536
3 *
4 * Copyright (C) 2007 Lemote, Inc.
5 * Author : jlliu, liujl@lemote.com
6 *
7 * Copyright (C) 2009 Lemote, Inc.
8 * Author: Wu Zhangjin, wuzj@lemote.com
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <cs5536/cs5536.h>
17#include <cs5536/cs5536_pci.h>
18
19void pci_ohci_write_reg(int reg, u32 value)
20{
21 u32 hi = 0, lo = value;
22
23 switch (reg) {
24 case PCI_COMMAND:
25 _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
26 if (value & PCI_COMMAND_MASTER)
27 hi |= PCI_COMMAND_MASTER;
28 else
29 hi &= ~PCI_COMMAND_MASTER;
30
31 if (value & PCI_COMMAND_MEMORY)
32 hi |= PCI_COMMAND_MEMORY;
33 else
34 hi &= ~PCI_COMMAND_MEMORY;
35 _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
36 break;
37 case PCI_STATUS:
38 if (value & PCI_STATUS_PARITY) {
39 _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
40 if (lo & SB_PARE_ERR_FLAG) {
41 lo = (lo & 0x0000ffff) | SB_PARE_ERR_FLAG;
42 _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo);
43 }
44 }
45 break;
46 case PCI_BAR0_REG:
47 if (value == PCI_BAR_RANGE_MASK) {
48 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
49 lo |= SOFT_BAR_OHCI_FLAG;
50 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
51 } else if ((value & 0x01) == 0x00) {
52 _wrmsr(USB_MSR_REG(USB_OHCI), hi, lo);
53
54 value &= 0xfffffff0;
55 hi = 0x40000000 | ((value & 0xff000000) >> 24);
56 lo = 0x000fffff | ((value & 0x00fff000) << 8);
57 _wrmsr(GLIU_MSR_REG(GLIU_P2D_BM3), hi, lo);
58 }
59 break;
60 case PCI_OHCI_INT_REG:
61 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
62 lo &= ~(0xf << PIC_YSEL_LOW_USB_SHIFT);
63 if (value) /* enable all the usb interrupt in PIC */
64 lo |= (CS5536_USB_INTR << PIC_YSEL_LOW_USB_SHIFT);
65 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), hi, lo);
66 break;
67 default:
68 break;
69 }
70}
71
72u32 pci_ohci_read_reg(int reg)
73{
74 u32 conf_data = 0;
75 u32 hi, lo;
76
77 switch (reg) {
78 case PCI_VENDOR_ID:
79 conf_data =
80 CFG_PCI_VENDOR_ID(CS5536_OHCI_DEVICE_ID, CS5536_VENDOR_ID);
81 break;
82 case PCI_COMMAND:
83 _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
84 if (hi & PCI_COMMAND_MASTER)
85 conf_data |= PCI_COMMAND_MASTER;
86 if (hi & PCI_COMMAND_MEMORY)
87 conf_data |= PCI_COMMAND_MEMORY;
88 break;
89 case PCI_STATUS:
90 conf_data |= PCI_STATUS_66MHZ;
91 conf_data |= PCI_STATUS_FAST_BACK;
92 _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo);
93 if (lo & SB_PARE_ERR_FLAG)
94 conf_data |= PCI_STATUS_PARITY;
95 conf_data |= PCI_STATUS_DEVSEL_MEDIUM;
96 break;
97 case PCI_CLASS_REVISION:
98 _rdmsr(USB_MSR_REG(USB_CAP), &hi, &lo);
99 conf_data = lo & 0x000000ff;
100 conf_data |= (CS5536_OHCI_CLASS_CODE << 8);
101 break;
102 case PCI_CACHE_LINE_SIZE:
103 conf_data =
104 CFG_PCI_CACHE_LINE_SIZE(PCI_NORMAL_HEADER_TYPE,
105 PCI_NORMAL_LATENCY_TIMER);
106 break;
107 case PCI_BAR0_REG:
108 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo);
109 if (lo & SOFT_BAR_OHCI_FLAG) {
110 conf_data = CS5536_OHCI_RANGE |
111 PCI_BASE_ADDRESS_SPACE_MEMORY;
112 lo &= ~SOFT_BAR_OHCI_FLAG;
113 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo);
114 } else {
115 _rdmsr(USB_MSR_REG(USB_OHCI), &hi, &lo);
116 conf_data = lo & 0xffffff00;
117 conf_data &= ~0x0000000f; /* 32bit mem */
118 }
119 break;
120 case PCI_CARDBUS_CIS:
121 conf_data = PCI_CARDBUS_CIS_POINTER;
122 break;
123 case PCI_SUBSYSTEM_VENDOR_ID:
124 conf_data =
125 CFG_PCI_VENDOR_ID(CS5536_OHCI_SUB_ID, CS5536_SUB_VENDOR_ID);
126 break;
127 case PCI_ROM_ADDRESS:
128 conf_data = PCI_EXPANSION_ROM_BAR;
129 break;
130 case PCI_CAPABILITY_LIST:
131 conf_data = PCI_CAPLIST_USB_POINTER;
132 break;
133 case PCI_INTERRUPT_LINE:
134 conf_data =
135 CFG_PCI_INTERRUPT_LINE(PCI_DEFAULT_PIN, CS5536_USB_INTR);
136 break;
137 case PCI_OHCI_INT_REG:
138 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
139 if ((lo & 0x00000f00) == CS5536_USB_INTR)
140 conf_data = 1;
141 break;
142 default:
143 break;
144 }
145
146 return conf_data;
147}