2 * the ISA Virtual Support Module of AMD CS5536
4 * Copyright (C) 2007 Lemote, Inc.
5 * Author : jlliu, liujl@lemote.com
7 * Copyright (C) 2009 Lemote, Inc.
8 * Author: Wu Zhangjin, wuzhangjin@gmail.com
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.
16 #include <cs5536/cs5536.h>
17 #include <cs5536/cs5536_pci.h>
19 /* common variables for PCI_ISA_READ/WRITE_BAR */
20 static const u32 divil_msr_reg
[6] = {
21 DIVIL_MSR_REG(DIVIL_LBAR_SMB
), DIVIL_MSR_REG(DIVIL_LBAR_GPIO
),
22 DIVIL_MSR_REG(DIVIL_LBAR_MFGPT
), DIVIL_MSR_REG(DIVIL_LBAR_IRQ
),
23 DIVIL_MSR_REG(DIVIL_LBAR_PMS
), DIVIL_MSR_REG(DIVIL_LBAR_ACPI
),
26 static const u32 soft_bar_flag
[6] = {
27 SOFT_BAR_SMB_FLAG
, SOFT_BAR_GPIO_FLAG
, SOFT_BAR_MFGPT_FLAG
,
28 SOFT_BAR_IRQ_FLAG
, SOFT_BAR_PMS_FLAG
, SOFT_BAR_ACPI_FLAG
,
31 static const u32 sb_msr_reg
[6] = {
32 SB_MSR_REG(SB_R0
), SB_MSR_REG(SB_R1
), SB_MSR_REG(SB_R2
),
33 SB_MSR_REG(SB_R3
), SB_MSR_REG(SB_R4
), SB_MSR_REG(SB_R5
),
36 static const u32 bar_space_range
[6] = {
37 CS5536_SMB_RANGE
, CS5536_GPIO_RANGE
, CS5536_MFGPT_RANGE
,
38 CS5536_IRQ_RANGE
, CS5536_PMS_RANGE
, CS5536_ACPI_RANGE
,
41 static const int bar_space_len
[6] = {
42 CS5536_SMB_LENGTH
, CS5536_GPIO_LENGTH
, CS5536_MFGPT_LENGTH
,
43 CS5536_IRQ_LENGTH
, CS5536_PMS_LENGTH
, CS5536_ACPI_LENGTH
,
47 * enable the divil module bar space.
49 * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg
50 * and the RCONFx(0~5) reg to use the modules.
52 static void divil_lbar_enable(void)
58 * The DIVIL IRQ is not used yet. and make the RCONF0 reserved.
61 for (offset
= DIVIL_LBAR_SMB
; offset
<= DIVIL_LBAR_PMS
; offset
++) {
62 _rdmsr(DIVIL_MSR_REG(offset
), &hi
, &lo
);
64 _wrmsr(DIVIL_MSR_REG(offset
), hi
, lo
);
69 * disable the divil module bar space.
71 static void divil_lbar_disable(void)
76 for (offset
= DIVIL_LBAR_SMB
; offset
<= DIVIL_LBAR_PMS
; offset
++) {
77 _rdmsr(DIVIL_MSR_REG(offset
), &hi
, &lo
);
79 _wrmsr(DIVIL_MSR_REG(offset
), hi
, lo
);
84 * BAR write: write value to the n BAR
87 void pci_isa_write_bar(int n
, u32 value
)
89 u32 hi
= 0, lo
= value
;
91 if (value
== PCI_BAR_RANGE_MASK
) {
92 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), &hi
, &lo
);
93 lo
|= soft_bar_flag
[n
];
94 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), hi
, lo
);
95 } else if (value
& 0x01) {
98 lo
&= bar_space_range
[n
];
99 _wrmsr(divil_msr_reg
[n
], hi
, lo
);
101 /* RCONFx is 4bytes in units for I/O space */
102 hi
= ((value
& 0x000ffffc) << 12) |
103 ((bar_space_len
[n
] - 4) << 12) | 0x01;
104 lo
= ((value
& 0x000ffffc) << 12) | 0x01;
105 _wrmsr(sb_msr_reg
[n
], hi
, lo
);
110 * BAR read: read the n BAR
113 u32
pci_isa_read_bar(int n
)
118 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), &hi
, &lo
);
119 if (lo
& soft_bar_flag
[n
]) {
120 conf_data
= bar_space_range
[n
] | PCI_BASE_ADDRESS_SPACE_IO
;
121 lo
&= ~soft_bar_flag
[n
];
122 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), hi
, lo
);
124 _rdmsr(divil_msr_reg
[n
], &hi
, &lo
);
125 conf_data
= lo
& bar_space_range
[n
];
133 * isa_write: ISA write transfer
135 * We assume that this is not a bus master transfer.
137 void pci_isa_write_reg(int reg
, u32 value
)
139 u32 hi
= 0, lo
= value
;
144 if (value
& PCI_COMMAND_IO
)
147 divil_lbar_disable();
150 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
151 temp
= lo
& 0x0000ffff;
152 if ((value
& PCI_STATUS_SIG_TARGET_ABORT
) &&
153 (lo
& SB_TAS_ERR_EN
))
154 temp
|= SB_TAS_ERR_FLAG
;
156 if ((value
& PCI_STATUS_REC_TARGET_ABORT
) &&
157 (lo
& SB_TAR_ERR_EN
))
158 temp
|= SB_TAR_ERR_FLAG
;
160 if ((value
& PCI_STATUS_REC_MASTER_ABORT
)
161 && (lo
& SB_MAR_ERR_EN
))
162 temp
|= SB_MAR_ERR_FLAG
;
164 if ((value
& PCI_STATUS_DETECTED_PARITY
)
165 && (lo
& SB_PARE_ERR_EN
))
166 temp
|= SB_PARE_ERR_FLAG
;
169 _wrmsr(SB_MSR_REG(SB_ERROR
), hi
, lo
);
171 case PCI_CACHE_LINE_SIZE
:
173 _rdmsr(SB_MSR_REG(SB_CTRL
), &hi
, &lo
);
176 _wrmsr(SB_MSR_REG(SB_CTRL
), hi
, lo
);
179 pci_isa_write_bar(0, value
);
182 pci_isa_write_bar(1, value
);
185 pci_isa_write_bar(2, value
);
188 pci_isa_write_bar(3, value
);
191 pci_isa_write_bar(4, value
);
194 pci_isa_write_bar(5, value
);
196 case PCI_UART1_INT_REG
:
197 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), &hi
, &lo
);
198 /* disable uart1 interrupt in PIC */
200 if (value
) /* enable uart1 interrupt in PIC */
201 lo
|= (CS5536_UART1_INTR
<< 24);
202 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), hi
, lo
);
204 case PCI_UART2_INT_REG
:
205 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), &hi
, &lo
);
206 /* disable uart2 interrupt in PIC */
208 if (value
) /* enable uart2 interrupt in PIC */
209 lo
|= (CS5536_UART2_INTR
<< 28);
210 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), hi
, lo
);
212 case PCI_ISA_FIXUP_REG
:
214 /* enable the TARGET ABORT/MASTER ABORT etc. */
215 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
217 _wrmsr(SB_MSR_REG(SB_ERROR
), hi
, lo
);
221 /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */
227 * isa_read: ISA read transfers
229 * We assume that this is not a bus master transfer.
231 u32
pci_isa_read_reg(int reg
)
239 CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID
, CS5536_VENDOR_ID
);
242 /* we just check the first LBAR for the IO enable bit, */
243 /* maybe we should changed later. */
244 _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB
), &hi
, &lo
);
246 conf_data
|= PCI_COMMAND_IO
;
249 conf_data
|= PCI_STATUS_66MHZ
;
250 conf_data
|= PCI_STATUS_DEVSEL_MEDIUM
;
251 conf_data
|= PCI_STATUS_FAST_BACK
;
253 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
254 if (lo
& SB_TAS_ERR_FLAG
)
255 conf_data
|= PCI_STATUS_SIG_TARGET_ABORT
;
256 if (lo
& SB_TAR_ERR_FLAG
)
257 conf_data
|= PCI_STATUS_REC_TARGET_ABORT
;
258 if (lo
& SB_MAR_ERR_FLAG
)
259 conf_data
|= PCI_STATUS_REC_MASTER_ABORT
;
260 if (lo
& SB_PARE_ERR_FLAG
)
261 conf_data
|= PCI_STATUS_DETECTED_PARITY
;
263 case PCI_CLASS_REVISION
:
264 _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID
), &hi
, &lo
);
265 conf_data
= lo
& 0x000000ff;
266 conf_data
|= (CS5536_ISA_CLASS_CODE
<< 8);
268 case PCI_CACHE_LINE_SIZE
:
269 _rdmsr(SB_MSR_REG(SB_CTRL
), &hi
, &lo
);
271 conf_data
= CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE
, hi
);
274 * we only use the LBAR of DIVIL, no RCONF used.
275 * all of them are IO space.
278 return pci_isa_read_bar(0);
281 return pci_isa_read_bar(1);
284 return pci_isa_read_bar(2);
289 return pci_isa_read_bar(4);
292 return pci_isa_read_bar(5);
294 case PCI_CARDBUS_CIS
:
295 conf_data
= PCI_CARDBUS_CIS_POINTER
;
297 case PCI_SUBSYSTEM_VENDOR_ID
:
299 CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID
, CS5536_SUB_VENDOR_ID
);
301 case PCI_ROM_ADDRESS
:
302 conf_data
= PCI_EXPANSION_ROM_BAR
;
304 case PCI_CAPABILITY_LIST
:
305 conf_data
= PCI_CAPLIST_POINTER
;
307 case PCI_INTERRUPT_LINE
:
308 /* no interrupt used here */
309 conf_data
= CFG_PCI_INTERRUPT_LINE(0x00, 0x00);