1/* 2 * the ISA 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, wuzhangjin@gmail.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 <linux/pci.h> 17#include <cs5536/cs5536.h> 18#include <cs5536/cs5536_pci.h> 19 20/* common variables for PCI_ISA_READ/WRITE_BAR */ 21static const u32 divil_msr_reg[6] = { 22 DIVIL_MSR_REG(DIVIL_LBAR_SMB), DIVIL_MSR_REG(DIVIL_LBAR_GPIO), 23 DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), DIVIL_MSR_REG(DIVIL_LBAR_IRQ), 24 DIVIL_MSR_REG(DIVIL_LBAR_PMS), DIVIL_MSR_REG(DIVIL_LBAR_ACPI), 25}; 26 27static const u32 soft_bar_flag[6] = { 28 SOFT_BAR_SMB_FLAG, SOFT_BAR_GPIO_FLAG, SOFT_BAR_MFGPT_FLAG, 29 SOFT_BAR_IRQ_FLAG, SOFT_BAR_PMS_FLAG, SOFT_BAR_ACPI_FLAG, 30}; 31 32static const u32 sb_msr_reg[6] = { 33 SB_MSR_REG(SB_R0), SB_MSR_REG(SB_R1), SB_MSR_REG(SB_R2), 34 SB_MSR_REG(SB_R3), SB_MSR_REG(SB_R4), SB_MSR_REG(SB_R5), 35}; 36 37static const u32 bar_space_range[6] = { 38 CS5536_SMB_RANGE, CS5536_GPIO_RANGE, CS5536_MFGPT_RANGE, 39 CS5536_IRQ_RANGE, CS5536_PMS_RANGE, CS5536_ACPI_RANGE, 40}; 41 42static const int bar_space_len[6] = { 43 CS5536_SMB_LENGTH, CS5536_GPIO_LENGTH, CS5536_MFGPT_LENGTH, 44 CS5536_IRQ_LENGTH, CS5536_PMS_LENGTH, CS5536_ACPI_LENGTH, 45}; 46 47/* 48 * enable the divil module bar space. 49 * 50 * For all the DIVIL module LBAR, you should control the DIVIL LBAR reg 51 * and the RCONFx(0~5) reg to use the modules. 52 */ 53static void divil_lbar_enable(void) 54{ 55 u32 hi, lo; 56 int offset; 57 58 /* 59 * The DIVIL IRQ is not used yet. and make the RCONF0 reserved. 60 */ 61 62 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { 63 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); 64 hi |= 0x01; 65 _wrmsr(DIVIL_MSR_REG(offset), hi, lo); 66 } 67} 68 69/* 70 * disable the divil module bar space. 71 */ 72static void divil_lbar_disable(void) 73{ 74 u32 hi, lo; 75 int offset; 76 77 for (offset = DIVIL_LBAR_SMB; offset <= DIVIL_LBAR_PMS; offset++) { 78 _rdmsr(DIVIL_MSR_REG(offset), &hi, &lo); 79 hi &= ~0x01; 80 _wrmsr(DIVIL_MSR_REG(offset), hi, lo); 81 } 82} 83 84/* 85 * BAR write: write value to the n BAR 86 */ 87 88void pci_isa_write_bar(int n, u32 value) 89{ 90 u32 hi = 0, lo = value; 91 92 if (value == PCI_BAR_RANGE_MASK) { 93 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); 94 lo |= soft_bar_flag[n]; 95 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); 96 } else if (value & 0x01) { 97 /* NATIVE reg */ 98 hi = 0x0000f001; 99 lo &= bar_space_range[n]; 100 _wrmsr(divil_msr_reg[n], hi, lo); 101 102 /* RCONFx is 4bytes in units for I/O space */ 103 hi = ((value & 0x000ffffc) << 12) | 104 ((bar_space_len[n] - 4) << 12) | 0x01; 105 lo = ((value & 0x000ffffc) << 12) | 0x01; 106 _wrmsr(sb_msr_reg[n], hi, lo); 107 } 108} 109 110/* 111 * BAR read: read the n BAR 112 */ 113 114u32 pci_isa_read_bar(int n) 115{ 116 u32 conf_data = 0; 117 u32 hi, lo; 118 119 _rdmsr(GLCP_MSR_REG(GLCP_SOFT_COM), &hi, &lo); 120 if (lo & soft_bar_flag[n]) { 121 conf_data = bar_space_range[n] | PCI_BASE_ADDRESS_SPACE_IO; 122 lo &= ~soft_bar_flag[n]; 123 _wrmsr(GLCP_MSR_REG(GLCP_SOFT_COM), hi, lo); 124 } else { 125 _rdmsr(divil_msr_reg[n], &hi, &lo); 126 conf_data = lo & bar_space_range[n]; 127 conf_data |= 0x01; 128 conf_data &= ~0x02; 129 } 130 return conf_data; 131} 132 133/* 134 * isa_write: ISA write transfer 135 * 136 * We assume that this is not a bus master transfer. 137 */ 138void pci_isa_write_reg(int reg, u32 value) 139{ 140 u32 hi = 0, lo = value; 141 u32 temp; 142 143 switch (reg) { 144 case PCI_COMMAND: 145 if (value & PCI_COMMAND_IO) 146 divil_lbar_enable(); 147 else 148 divil_lbar_disable(); 149 break; 150 case PCI_STATUS: 151 _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); 152 temp = lo & 0x0000ffff; 153 if ((value & PCI_STATUS_SIG_TARGET_ABORT) && 154 (lo & SB_TAS_ERR_EN)) 155 temp |= SB_TAS_ERR_FLAG; 156 157 if ((value & PCI_STATUS_REC_TARGET_ABORT) && 158 (lo & SB_TAR_ERR_EN)) 159 temp |= SB_TAR_ERR_FLAG; 160 161 if ((value & PCI_STATUS_REC_MASTER_ABORT) 162 && (lo & SB_MAR_ERR_EN)) 163 temp |= SB_MAR_ERR_FLAG; 164 165 if ((value & PCI_STATUS_DETECTED_PARITY) 166 && (lo & SB_PARE_ERR_EN)) 167 temp |= SB_PARE_ERR_FLAG; 168 169 lo = temp; 170 _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); 171 break; 172 case PCI_CACHE_LINE_SIZE: 173 value &= 0x0000ff00; 174 _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); 175 hi &= 0xffffff00; 176 hi |= (value >> 8); 177 _wrmsr(SB_MSR_REG(SB_CTRL), hi, lo); 178 break; 179 case PCI_BAR0_REG: 180 pci_isa_write_bar(0, value); 181 break; 182 case PCI_BAR1_REG: 183 pci_isa_write_bar(1, value); 184 break; 185 case PCI_BAR2_REG: 186 pci_isa_write_bar(2, value); 187 break; 188 case PCI_BAR3_REG: 189 pci_isa_write_bar(3, value); 190 break; 191 case PCI_BAR4_REG: 192 pci_isa_write_bar(4, value); 193 break; 194 case PCI_BAR5_REG: 195 pci_isa_write_bar(5, value); 196 break; 197 case PCI_UART1_INT_REG: 198 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); 199 /* disable uart1 interrupt in PIC */ 200 lo &= ~(0xf << 24); 201 if (value) /* enable uart1 interrupt in PIC */ 202 lo |= (CS5536_UART1_INTR << 24); 203 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); 204 break; 205 case PCI_UART2_INT_REG: 206 _rdmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), &hi, &lo); 207 /* disable uart2 interrupt in PIC */ 208 lo &= ~(0xf << 28); 209 if (value) /* enable uart2 interrupt in PIC */ 210 lo |= (CS5536_UART2_INTR << 28); 211 _wrmsr(DIVIL_MSR_REG(PIC_YSEL_HIGH), hi, lo); 212 break; 213 case PCI_ISA_FIXUP_REG: 214 if (value) { 215 /* enable the TARGET ABORT/MASTER ABORT etc. */ 216 _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); 217 lo |= 0x00000063; 218 _wrmsr(SB_MSR_REG(SB_ERROR), hi, lo); 219 } 220 221 default: 222 /* ALL OTHER PCI CONFIG SPACE HEADER IS NOT IMPLEMENTED. */ 223 break; 224 } 225} 226 227/* 228 * isa_read: ISA read transfers 229 * 230 * We assume that this is not a bus master transfer. 231 */ 232u32 pci_isa_read_reg(int reg) 233{ 234 u32 conf_data = 0; 235 u32 hi, lo; 236 237 switch (reg) { 238 case PCI_VENDOR_ID: 239 conf_data = 240 CFG_PCI_VENDOR_ID(CS5536_ISA_DEVICE_ID, CS5536_VENDOR_ID); 241 break; 242 case PCI_COMMAND: 243 /* we just check the first LBAR for the IO enable bit, */ 244 /* maybe we should changed later. */ 245 _rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_SMB), &hi, &lo); 246 if (hi & 0x01) 247 conf_data |= PCI_COMMAND_IO; 248 break; 249 case PCI_STATUS: 250 conf_data |= PCI_STATUS_66MHZ; 251 conf_data |= PCI_STATUS_DEVSEL_MEDIUM; 252 conf_data |= PCI_STATUS_FAST_BACK; 253 254 _rdmsr(SB_MSR_REG(SB_ERROR), &hi, &lo); 255 if (lo & SB_TAS_ERR_FLAG) 256 conf_data |= PCI_STATUS_SIG_TARGET_ABORT; 257 if (lo & SB_TAR_ERR_FLAG) 258 conf_data |= PCI_STATUS_REC_TARGET_ABORT; 259 if (lo & SB_MAR_ERR_FLAG) 260 conf_data |= PCI_STATUS_REC_MASTER_ABORT; 261 if (lo & SB_PARE_ERR_FLAG) 262 conf_data |= PCI_STATUS_DETECTED_PARITY; 263 break; 264 case PCI_CLASS_REVISION: 265 _rdmsr(GLCP_MSR_REG(GLCP_CHIP_REV_ID), &hi, &lo); 266 conf_data = lo & 0x000000ff; 267 conf_data |= (CS5536_ISA_CLASS_CODE << 8); 268 break; 269 case PCI_CACHE_LINE_SIZE: 270 _rdmsr(SB_MSR_REG(SB_CTRL), &hi, &lo); 271 hi &= 0x000000f8; 272 conf_data = CFG_PCI_CACHE_LINE_SIZE(PCI_BRIDGE_HEADER_TYPE, hi); 273 break; 274 /* 275 * we only use the LBAR of DIVIL, no RCONF used. 276 * all of them are IO space. 277 */ 278 case PCI_BAR0_REG: 279 return pci_isa_read_bar(0); 280 break; 281 case PCI_BAR1_REG: 282 return pci_isa_read_bar(1); 283 break; 284 case PCI_BAR2_REG: 285 return pci_isa_read_bar(2); 286 break; 287 case PCI_BAR3_REG: 288 break; 289 case PCI_BAR4_REG: 290 return pci_isa_read_bar(4); 291 break; 292 case PCI_BAR5_REG: 293 return pci_isa_read_bar(5); 294 break; 295 case PCI_CARDBUS_CIS: 296 conf_data = PCI_CARDBUS_CIS_POINTER; 297 break; 298 case PCI_SUBSYSTEM_VENDOR_ID: 299 conf_data = 300 CFG_PCI_VENDOR_ID(CS5536_ISA_SUB_ID, CS5536_SUB_VENDOR_ID); 301 break; 302 case PCI_ROM_ADDRESS: 303 conf_data = PCI_EXPANSION_ROM_BAR; 304 break; 305 case PCI_CAPABILITY_LIST: 306 conf_data = PCI_CAPLIST_POINTER; 307 break; 308 case PCI_INTERRUPT_LINE: 309 /* no interrupt used here */ 310 conf_data = CFG_PCI_INTERRUPT_LINE(0x00, 0x00); 311 break; 312 default: 313 break; 314 } 315 316 return conf_data; 317} 318 319/* 320 * The mfgpt timer interrupt is running early, so we must keep the south bridge 321 * mmio always enabled. Otherwise we may race with the PCI configuration which 322 * may temporarily disable it. When that happens and the timer interrupt fires, 323 * we are not able to clear it and the system will hang. 324 */ 325static void cs5536_isa_mmio_always_on(struct pci_dev *dev) 326{ 327 dev->mmio_always_on = 1; 328} 329DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_ISA, 330 PCI_CLASS_BRIDGE_ISA, 8, cs5536_isa_mmio_always_on); 331