1/* 2 * pci-vr41xx.c, PCI Control Unit routines for the NEC VR4100 series. 3 * 4 * Copyright (C) 2001-2003 MontaVista Software Inc. 5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> 6 * Copyright (C) 2004-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 7 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org) 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 */ 23/* 24 * Changes: 25 * MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com> 26 * - New creation, NEC VR4122 and VR4131 are supported. 27 */ 28#include <linux/init.h> 29#include <linux/pci.h> 30#include <linux/types.h> 31 32#include <asm/cpu.h> 33#include <asm/io.h> 34#include <asm/vr41xx/pci.h> 35#include <asm/vr41xx/vr41xx.h> 36 37#include "pci-vr41xx.h" 38 39extern struct pci_ops vr41xx_pci_ops; 40 41static void __iomem *pciu_base; 42 43#define pciu_read(offset) readl(pciu_base + (offset)) 44#define pciu_write(offset, value) writel((value), pciu_base + (offset)) 45 46static struct pci_master_address_conversion pci_master_memory1 = { 47 .bus_base_address = PCI_MASTER_MEM1_BUS_BASE_ADDRESS, 48 .address_mask = PCI_MASTER_MEM1_ADDRESS_MASK, 49 .pci_base_address = PCI_MASTER_MEM1_PCI_BASE_ADDRESS, 50}; 51 52static struct pci_target_address_conversion pci_target_memory1 = { 53 .address_mask = PCI_TARGET_MEM1_ADDRESS_MASK, 54 .bus_base_address = PCI_TARGET_MEM1_BUS_BASE_ADDRESS, 55}; 56 57static struct pci_master_address_conversion pci_master_io = { 58 .bus_base_address = PCI_MASTER_IO_BUS_BASE_ADDRESS, 59 .address_mask = PCI_MASTER_IO_ADDRESS_MASK, 60 .pci_base_address = PCI_MASTER_IO_PCI_BASE_ADDRESS, 61}; 62 63static struct pci_mailbox_address pci_mailbox = { 64 .base_address = PCI_MAILBOX_BASE_ADDRESS, 65}; 66 67static struct pci_target_address_window pci_target_window1 = { 68 .base_address = PCI_TARGET_WINDOW1_BASE_ADDRESS, 69}; 70 71static struct resource pci_mem_resource = { 72 .name = "PCI Memory resources", 73 .start = PCI_MEM_RESOURCE_START, 74 .end = PCI_MEM_RESOURCE_END, 75 .flags = IORESOURCE_MEM, 76}; 77 78static struct resource pci_io_resource = { 79 .name = "PCI I/O resources", 80 .start = PCI_IO_RESOURCE_START, 81 .end = PCI_IO_RESOURCE_END, 82 .flags = IORESOURCE_IO, 83}; 84 85static struct pci_controller_unit_setup vr41xx_pci_controller_unit_setup = { 86 .master_memory1 = &pci_master_memory1, 87 .target_memory1 = &pci_target_memory1, 88 .master_io = &pci_master_io, 89 .exclusive_access = CANNOT_LOCK_FROM_DEVICE, 90 .wait_time_limit_from_irdy_to_trdy = 0, 91 .mailbox = &pci_mailbox, 92 .target_window1 = &pci_target_window1, 93 .master_latency_timer = 0x80, 94 .retry_limit = 0, 95 .arbiter_priority_control = PCI_ARBITRATION_MODE_FAIR, 96 .take_away_gnt_mode = PCI_TAKE_AWAY_GNT_DISABLE, 97}; 98 99static struct pci_controller vr41xx_pci_controller = { 100 .pci_ops = &vr41xx_pci_ops, 101 .mem_resource = &pci_mem_resource, 102 .io_resource = &pci_io_resource, 103}; 104 105void __init vr41xx_pciu_setup(struct pci_controller_unit_setup *setup) 106{ 107 vr41xx_pci_controller_unit_setup = *setup; 108} 109 110static int __init vr41xx_pciu_init(void) 111{ 112 struct pci_controller_unit_setup *setup; 113 struct pci_master_address_conversion *master; 114 struct pci_target_address_conversion *target; 115 struct pci_mailbox_address *mailbox; 116 struct pci_target_address_window *window; 117 unsigned long vtclock, pci_clock_max; 118 uint32_t val; 119 120 setup = &vr41xx_pci_controller_unit_setup; 121 122 if (request_mem_region(PCIU_BASE, PCIU_SIZE, "PCIU") == NULL) 123 return -EBUSY; 124 125 pciu_base = ioremap(PCIU_BASE, PCIU_SIZE); 126 if (pciu_base == NULL) { 127 release_mem_region(PCIU_BASE, PCIU_SIZE); 128 return -EBUSY; 129 } 130 131 /* Disable PCI interrupt */ 132 vr41xx_disable_pciint(); 133 134 /* Supply VTClock to PCIU */ 135 vr41xx_supply_clock(PCIU_CLOCK); 136 137 /* Dummy write, waiting for supply of VTClock. */ 138 vr41xx_disable_pciint(); 139 140 /* Select PCI clock */ 141 if (setup->pci_clock_max != 0) 142 pci_clock_max = setup->pci_clock_max; 143 else 144 pci_clock_max = PCI_CLOCK_MAX; 145 vtclock = vr41xx_get_vtclock_frequency(); 146 if (vtclock < pci_clock_max) 147 pciu_write(PCICLKSELREG, EQUAL_VTCLOCK); 148 else if ((vtclock / 2) < pci_clock_max) 149 pciu_write(PCICLKSELREG, HALF_VTCLOCK); 150 else if (current_cpu_data.processor_id >= PRID_VR4131_REV2_1 && 151 (vtclock / 3) < pci_clock_max) 152 pciu_write(PCICLKSELREG, ONE_THIRD_VTCLOCK); 153 else if ((vtclock / 4) < pci_clock_max) 154 pciu_write(PCICLKSELREG, QUARTER_VTCLOCK); 155 else { 156 printk(KERN_ERR "PCI Clock is over 33MHz.\n"); 157 return -EINVAL; 158 } 159 160 /* Supply PCI clock by PCI bus */ 161 vr41xx_supply_clock(PCI_CLOCK); 162 163 if (setup->master_memory1 != NULL) { 164 master = setup->master_memory1; 165 val = IBA(master->bus_base_address) | 166 MASTER_MSK(master->address_mask) | 167 WINEN | 168 PCIA(master->pci_base_address); 169 pciu_write(PCIMMAW1REG, val); 170 } else { 171 val = pciu_read(PCIMMAW1REG); 172 val &= ~WINEN; 173 pciu_write(PCIMMAW1REG, val); 174 } 175 176 if (setup->master_memory2 != NULL) { 177 master = setup->master_memory2; 178 val = IBA(master->bus_base_address) | 179 MASTER_MSK(master->address_mask) | 180 WINEN | 181 PCIA(master->pci_base_address); 182 pciu_write(PCIMMAW2REG, val); 183 } else { 184 val = pciu_read(PCIMMAW2REG); 185 val &= ~WINEN; 186 pciu_write(PCIMMAW2REG, val); 187 } 188 189 if (setup->target_memory1 != NULL) { 190 target = setup->target_memory1; 191 val = TARGET_MSK(target->address_mask) | 192 WINEN | 193 ITA(target->bus_base_address); 194 pciu_write(PCITAW1REG, val); 195 } else { 196 val = pciu_read(PCITAW1REG); 197 val &= ~WINEN; 198 pciu_write(PCITAW1REG, val); 199 } 200 201 if (setup->target_memory2 != NULL) { 202 target = setup->target_memory2; 203 val = TARGET_MSK(target->address_mask) | 204 WINEN | 205 ITA(target->bus_base_address); 206 pciu_write(PCITAW2REG, val); 207 } else { 208 val = pciu_read(PCITAW2REG); 209 val &= ~WINEN; 210 pciu_write(PCITAW2REG, val); 211 } 212 213 if (setup->master_io != NULL) { 214 master = setup->master_io; 215 val = IBA(master->bus_base_address) | 216 MASTER_MSK(master->address_mask) | 217 WINEN | 218 PCIIA(master->pci_base_address); 219 pciu_write(PCIMIOAWREG, val); 220 } else { 221 val = pciu_read(PCIMIOAWREG); 222 val &= ~WINEN; 223 pciu_write(PCIMIOAWREG, val); 224 } 225 226 if (setup->exclusive_access == CANNOT_LOCK_FROM_DEVICE) 227 pciu_write(PCIEXACCREG, UNLOCK); 228 else 229 pciu_write(PCIEXACCREG, 0); 230 231 if (current_cpu_data.cputype == CPU_VR4122) 232 pciu_write(PCITRDYVREG, TRDYV(setup->wait_time_limit_from_irdy_to_trdy)); 233 234 pciu_write(LATTIMEREG, MLTIM(setup->master_latency_timer)); 235 236 if (setup->mailbox != NULL) { 237 mailbox = setup->mailbox; 238 val = MBADD(mailbox->base_address) | TYPE_32BITSPACE | 239 MSI_MEMORY | PREF_APPROVAL; 240 pciu_write(MAILBAREG, val); 241 } 242 243 if (setup->target_window1) { 244 window = setup->target_window1; 245 val = PMBA(window->base_address) | TYPE_32BITSPACE | 246 MSI_MEMORY | PREF_APPROVAL; 247 pciu_write(PCIMBA1REG, val); 248 } 249 250 if (setup->target_window2) { 251 window = setup->target_window2; 252 val = PMBA(window->base_address) | TYPE_32BITSPACE | 253 MSI_MEMORY | PREF_APPROVAL; 254 pciu_write(PCIMBA2REG, val); 255 } 256 257 val = pciu_read(RETVALREG); 258 val &= ~RTYVAL_MASK; 259 val |= RTYVAL(setup->retry_limit); 260 pciu_write(RETVALREG, val); 261 262 val = pciu_read(PCIAPCNTREG); 263 val &= ~(TKYGNT | PAPC); 264 265 switch (setup->arbiter_priority_control) { 266 case PCI_ARBITRATION_MODE_ALTERNATE_0: 267 val |= PAPC_ALTERNATE_0; 268 break; 269 case PCI_ARBITRATION_MODE_ALTERNATE_B: 270 val |= PAPC_ALTERNATE_B; 271 break; 272 default: 273 val |= PAPC_FAIR; 274 break; 275 } 276 277 if (setup->take_away_gnt_mode == PCI_TAKE_AWAY_GNT_ENABLE) 278 val |= TKYGNT_ENABLE; 279 280 pciu_write(PCIAPCNTREG, val); 281 282 pciu_write(COMMANDREG, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | 283 PCI_COMMAND_MASTER | PCI_COMMAND_PARITY | 284 PCI_COMMAND_SERR); 285 286 /* Clear bus error */ 287 pciu_read(BUSERRADREG); 288 289 pciu_write(PCIENREG, PCIU_CONFIG_DONE); 290 291 if (setup->mem_resource != NULL) 292 vr41xx_pci_controller.mem_resource = setup->mem_resource; 293 294 if (setup->io_resource != NULL) { 295 vr41xx_pci_controller.io_resource = setup->io_resource; 296 } else { 297 set_io_port_base(IO_PORT_BASE); 298 ioport_resource.start = IO_PORT_RESOURCE_START; 299 ioport_resource.end = IO_PORT_RESOURCE_END; 300 } 301 302 register_pci_controller(&vr41xx_pci_controller); 303 304 return 0; 305} 306 307arch_initcall(vr41xx_pciu_init); 308