1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * the ISA Virtual Support Module of AMD CS5536
5 * Copyright (C) 2007 Lemote, Inc.
6 * Author : jlliu, liujl@lemote.com
8 * Copyright (C) 2009 Lemote, Inc.
9 * Author: Wu Zhangjin, wuzhangjin@gmail.com
12 #include <linux/pci.h>
13 #include <cs5536/cs5536.h>
14 #include <cs5536/cs5536_pci.h>
16 /* common variables for PCI_ISA_READ/WRITE_BAR */
17 static const u32 divil_msr_reg
[6] = {
18 DIVIL_MSR_REG(DIVIL_LBAR_SMB
), DIVIL_MSR_REG(DIVIL_LBAR_GPIO
),
19 DIVIL_MSR_REG(DIVIL_LBAR_MFGPT
), DIVIL_MSR_REG(DIVIL_LBAR_IRQ
),
20 DIVIL_MSR_REG(DIVIL_LBAR_PMS
), DIVIL_MSR_REG(DIVIL_LBAR_ACPI
),
23 static const u32 soft_bar_flag
[6] = {
24 SOFT_BAR_SMB_FLAG
, SOFT_BAR_GPIO_FLAG
, SOFT_BAR_MFGPT_FLAG
,
25 SOFT_BAR_IRQ_FLAG
, SOFT_BAR_PMS_FLAG
, SOFT_BAR_ACPI_FLAG
,
28 static const u32 sb_msr_reg
[6] = {
29 SB_MSR_REG(SB_R0
), SB_MSR_REG(SB_R1
), SB_MSR_REG(SB_R2
),
30 SB_MSR_REG(SB_R3
), SB_MSR_REG(SB_R4
), SB_MSR_REG(SB_R5
),
33 static const u32 bar_space_range
[6] = {
34 CS5536_SMB_RANGE
, CS5536_GPIO_RANGE
, CS5536_MFGPT_RANGE
,
35 CS5536_IRQ_RANGE
, CS5536_PMS_RANGE
, CS5536_ACPI_RANGE
,
38 static const int bar_space_len
[6] = {
39 CS5536_SMB_LENGTH
, CS5536_GPIO_LENGTH
, CS5536_MFGPT_LENGTH
,
40 CS5536_IRQ_LENGTH
, CS5536_PMS_LENGTH
, CS5536_ACPI_LENGTH
,
44 * enable the divil module bar space.
46 * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg
47 * and the RCONFx(0~5) reg to use the modules.
49 static void divil_lbar_enable(void)
55 * The DIVIL IRQ is not used yet. and make the RCONF0 reserved.
58 for (offset
= DIVIL_LBAR_SMB
; offset
<= DIVIL_LBAR_PMS
; offset
++) {
59 _rdmsr(DIVIL_MSR_REG(offset
), &hi
, &lo
);
61 _wrmsr(DIVIL_MSR_REG(offset
), hi
, lo
);
66 * disable the divil module bar space.
68 static void divil_lbar_disable(void)
73 for (offset
= DIVIL_LBAR_SMB
; offset
<= DIVIL_LBAR_PMS
; offset
++) {
74 _rdmsr(DIVIL_MSR_REG(offset
), &hi
, &lo
);
76 _wrmsr(DIVIL_MSR_REG(offset
), hi
, lo
);
81 * BAR write: write value to the n BAR
84 void pci_isa_write_bar(int n
, u32 value
)
86 u32 hi
= 0, lo
= value
;
88 if (value
== PCI_BAR_RANGE_MASK
) {
89 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), &hi
, &lo
);
90 lo
|= soft_bar_flag
[n
];
91 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), hi
, lo
);
92 } else if (value
& 0x01) {
95 lo
&= bar_space_range
[n
];
96 _wrmsr(divil_msr_reg
[n
], hi
, lo
);
98 /* RCONFx is 4bytes in units for I/O space */
99 hi
= ((value
& 0x000ffffc) << 12) |
100 ((bar_space_len
[n
] - 4) << 12) | 0x01;
101 lo
= ((value
& 0x000ffffc) << 12) | 0x01;
102 _wrmsr(sb_msr_reg
[n
], hi
, lo
);
107 * BAR read: read the n BAR
110 u32
pci_isa_read_bar(int n
)
115 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), &hi
, &lo
);
116 if (lo
& soft_bar_flag
[n
]) {
117 conf_data
= bar_space_range
[n
] | PCI_BASE_ADDRESS_SPACE_IO
;
118 lo
&= ~soft_bar_flag
[n
];
119 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM
), hi
, lo
);
121 _rdmsr(divil_msr_reg
[n
], &hi
, &lo
);
122 conf_data
= lo
& bar_space_range
[n
];
130 * isa_write: ISA write transfer
132 * We assume that this is not a bus master transfer.
134 void pci_isa_write_reg(int reg
, u32 value
)
136 u32 hi
= 0, lo
= value
;
141 if (value
& PCI_COMMAND_IO
)
144 divil_lbar_disable();
147 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
148 temp
= lo
& 0x0000ffff;
149 if ((value
& PCI_STATUS_SIG_TARGET_ABORT
) &&
150 (lo
& SB_TAS_ERR_EN
))
151 temp
|= SB_TAS_ERR_FLAG
;
153 if ((value
& PCI_STATUS_REC_TARGET_ABORT
) &&
154 (lo
& SB_TAR_ERR_EN
))
155 temp
|= SB_TAR_ERR_FLAG
;
157 if ((value
& PCI_STATUS_REC_MASTER_ABORT
)
158 && (lo
& SB_MAR_ERR_EN
))
159 temp
|= SB_MAR_ERR_FLAG
;
161 if ((value
& PCI_STATUS_DETECTED_PARITY
)
162 && (lo
& SB_PARE_ERR_EN
))
163 temp
|= SB_PARE_ERR_FLAG
;
166 _wrmsr(SB_MSR_REG(SB_ERROR
), hi
, lo
);
168 case PCI_CACHE_LINE_SIZE
:
170 _rdmsr(SB_MSR_REG(SB_CTRL
), &hi
, &lo
);
173 _wrmsr(SB_MSR_REG(SB_CTRL
), hi
, lo
);
176 pci_isa_write_bar(0, value
);
179 pci_isa_write_bar(1, value
);
182 pci_isa_write_bar(2, value
);
185 pci_isa_write_bar(3, value
);
188 pci_isa_write_bar(4, value
);
191 pci_isa_write_bar(5, value
);
193 case PCI_UART1_INT_REG
:
194 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), &hi
, &lo
);
195 /* disable uart1 interrupt in PIC */
197 if (value
) /* enable uart1 interrupt in PIC */
198 lo
|= (CS5536_UART1_INTR
<< 24);
199 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), hi
, lo
);
201 case PCI_UART2_INT_REG
:
202 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), &hi
, &lo
);
203 /* disable uart2 interrupt in PIC */
205 if (value
) /* enable uart2 interrupt in PIC */
206 lo
|= (CS5536_UART2_INTR
<< 28);
207 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH
), hi
, lo
);
209 case PCI_ISA_FIXUP_REG
:
211 /* enable the TARGET ABORT/MASTER ABORT etc. */
212 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
214 _wrmsr(SB_MSR_REG(SB_ERROR
), hi
, lo
);
218 /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */
224 * isa_read: ISA read transfers
226 * We assume that this is not a bus master transfer.
228 u32
pci_isa_read_reg(int reg
)
236 CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID
, CS5536_VENDOR_ID
);
239 /* we just check the first LBAR for the IO enable bit, */
240 /* maybe we should changed later. */
241 _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB
), &hi
, &lo
);
243 conf_data
|= PCI_COMMAND_IO
;
246 conf_data
|= PCI_STATUS_66MHZ
;
247 conf_data
|= PCI_STATUS_DEVSEL_MEDIUM
;
248 conf_data
|= PCI_STATUS_FAST_BACK
;
250 _rdmsr(SB_MSR_REG(SB_ERROR
), &hi
, &lo
);
251 if (lo
& SB_TAS_ERR_FLAG
)
252 conf_data
|= PCI_STATUS_SIG_TARGET_ABORT
;
253 if (lo
& SB_TAR_ERR_FLAG
)
254 conf_data
|= PCI_STATUS_REC_TARGET_ABORT
;
255 if (lo
& SB_MAR_ERR_FLAG
)
256 conf_data
|= PCI_STATUS_REC_MASTER_ABORT
;
257 if (lo
& SB_PARE_ERR_FLAG
)
258 conf_data
|= PCI_STATUS_DETECTED_PARITY
;
260 case PCI_CLASS_REVISION
:
261 _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID
), &hi
, &lo
);
262 conf_data
= lo
& 0x000000ff;
263 conf_data
|= (CS5536_ISA_CLASS_CODE
<< 8);
265 case PCI_CACHE_LINE_SIZE
:
266 _rdmsr(SB_MSR_REG(SB_CTRL
), &hi
, &lo
);
268 conf_data
= CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE
, hi
);
271 * we only use the LBAR of DIVIL, no RCONF used.
272 * all of them are IO space.
275 return pci_isa_read_bar(0);
278 return pci_isa_read_bar(1);
281 return pci_isa_read_bar(2);
286 return pci_isa_read_bar(4);
289 return pci_isa_read_bar(5);
291 case PCI_CARDBUS_CIS
:
292 conf_data
= PCI_CARDBUS_CIS_POINTER
;
294 case PCI_SUBSYSTEM_VENDOR_ID
:
296 CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID
, CS5536_SUB_VENDOR_ID
);
298 case PCI_ROM_ADDRESS
:
299 conf_data
= PCI_EXPANSION_ROM_BAR
;
301 case PCI_CAPABILITY_LIST
:
302 conf_data
= PCI_CAPLIST_POINTER
;
304 case PCI_INTERRUPT_LINE
:
305 /* no interrupt used here */
306 conf_data
= CFG_PCI_INTERRUPT_LINE(0x00, 0x00);
316 * The mfgpt timer interrupt is running early, so we must keep the south bridge
317 * mmio always enabled. Otherwise we may race with the PCI configuration which
318 * may temporarily disable it. When that happens and the timer interrupt fires,
319 * we are not able to clear it and the system will hang.
321 static void cs5536_isa_mmio_always_on(struct pci_dev
*dev
)
323 dev
->mmio_always_on
= 1;
325 DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_AMD
, PCI_DEVICE_ID_AMD_CS5536_ISA
,
326 PCI_CLASS_BRIDGE_ISA
, 8, cs5536_isa_mmio_always_on
);