1/*********************************************************************** 2 * Copyright 2001 MontaVista Software Inc. 3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 * 5 * arch/mips/ddb5xxx/ddb5477/pci_ops.c 6 * Define the pci_ops for DB5477. 7 * 8 * Much of the code is derived from the original DDB5074 port by 9 * Geert Uytterhoeven <geert@sonycom.com> 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15 *********************************************************************** 16 */ 17 18/* 19 * DDB5477 has two PCI channels, external PCI and IOPIC (internal) 20 * Therefore we provide two sets of pci_ops. 21 */ 22 23#include <linux/config.h> 24#include <linux/pci.h> 25#include <linux/kernel.h> 26#include <linux/types.h> 27 28#include <asm/addrspace.h> 29#include <asm/debug.h> 30 31#include <asm/ddb5xxx/ddb5xxx.h> 32 33/* 34 * config_swap structure records what set of pdar/pmr are used 35 * to access pci config space. It also provides a place hold the 36 * original values for future restoring. 37 */ 38struct pci_config_swap { 39 u32 pdar; 40 u32 pmr; 41 u32 config_base; 42 u32 config_size; 43 u32 pdar_backup; 44 u32 pmr_backup; 45}; 46 47/* 48 * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. 49 */ 50struct pci_config_swap ext_pci_swap = { 51 DDB_PCIW0, 52 DDB_PCIINIT00, 53 DDB_PCI0_CONFIG_BASE, 54 DDB_PCI0_CONFIG_SIZE 55}; 56struct pci_config_swap io_pci_swap = { 57 DDB_IOPCIW0, 58 DDB_PCIINIT01, 59 DDB_PCI1_CONFIG_BASE, 60 DDB_PCI1_CONFIG_SIZE 61}; 62 63 64/* 65 * access config space 66 */ 67static inline u32 ddb_access_config_base(struct pci_config_swap *swap, 68 u32 bus,/* 0 means top level bus */ 69 u32 slot_num) 70{ 71 u32 pci_addr = 0; 72 u32 pciinit_offset = 0; 73 u32 virt_addr = swap->config_base; 74 u32 option; 75 76 /* minimum pdar (window) size is 2MB */ 77 db_assert(swap->config_size >= (2 << 20)); 78 79 db_assert(slot_num < (1 << 5)); 80 db_assert(bus < (1 << 8)); 81 82 /* backup registers */ 83 swap->pdar_backup = ddb_in32(swap->pdar); 84 swap->pmr_backup = ddb_in32(swap->pmr); 85 86 /* set the pdar (pci window) register */ 87 ddb_set_pdar(swap->pdar, 88 swap->config_base, 89 swap->config_size, 90 32, /* 32 bit wide */ 91 0, /* not on local memory bus */ 92 0); /* not visible from PCI bus (N/A) */ 93 94 /* 95 * calcuate the absolute pci config addr; 96 * according to the spec, we start scanning from adr:11 (0x800) 97 */ 98 if (bus == 0) { 99 /* type 0 config */ 100 pci_addr = 0x800 << slot_num; 101 } else { 102 /* type 1 config */ 103 pci_addr = (bus << 16) | (slot_num << 11); 104 } 105 106 /* 107 * if pci_addr is less than pci config window size, we set 108 * pciinit_offset to 0 and adjust the virt_address. 109 * Otherwise we will try to adjust pciinit_offset. 110 */ 111 if (pci_addr < swap->config_size) { 112 virt_addr = KSEG1ADDR(swap->config_base + pci_addr); 113 pciinit_offset = 0; 114 } else { 115 db_assert( (pci_addr & (swap->config_size - 1)) == 0); 116 virt_addr = KSEG1ADDR(swap->config_base); 117 pciinit_offset = pci_addr; 118 } 119 120 /* set the pmr register */ 121 option = DDB_PCI_ACCESS_32; 122 if (bus != 0) option |= DDB_PCI_CFGTYPE1; 123 ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); 124 125 return virt_addr; 126} 127 128static inline void ddb_close_config_base(struct pci_config_swap *swap) 129{ 130 ddb_out32(swap->pdar, swap->pdar_backup); 131 ddb_out32(swap->pmr, swap->pmr_backup); 132} 133 134static int read_config_dword(struct pci_config_swap *swap, 135 struct pci_dev *dev, 136 u32 where, 137 u32 *val) 138{ 139 u32 bus, slot_num, func_num; 140 u32 base; 141 142 db_assert((where & 3) == 0); 143 db_assert(where < (1 << 8)); 144 145 /* check if the bus is top-level */ 146 if (dev->bus->parent != NULL) { 147 bus = dev->bus->number; 148 db_assert(bus != 0); 149 } else { 150 bus = 0; 151 } 152 153 slot_num = PCI_SLOT(dev->devfn); 154 func_num = PCI_FUNC(dev->devfn); 155 base = ddb_access_config_base(swap, bus, slot_num); 156 *val = *(volatile u32*) (base + (func_num << 8) + where); 157 ddb_close_config_base(swap); 158 return PCIBIOS_SUCCESSFUL; 159} 160 161static int read_config_word(struct pci_config_swap *swap, 162 struct pci_dev *dev, 163 u32 where, 164 u16 *val) 165{ 166 int status; 167 u32 result; 168 169 db_assert((where & 1) == 0); 170 171 status = read_config_dword(swap, dev, where & ~3, &result); 172 if (where & 2) result >>= 16; 173 *val = result & 0xffff; 174 return status; 175} 176 177static int read_config_byte(struct pci_config_swap *swap, 178 struct pci_dev *dev, 179 u32 where, 180 u8 *val) 181{ 182 int status; 183 u32 result; 184 185 status = read_config_dword(swap, dev, where & ~3, &result); 186 if (where & 1) result >>= 8; 187 if (where & 2) result >>= 16; 188 *val = result & 0xff; 189 return status; 190} 191 192static int write_config_dword(struct pci_config_swap *swap, 193 struct pci_dev *dev, 194 u32 where, 195 u32 val) 196{ 197 u32 bus, slot_num, func_num; 198 u32 base; 199 200 db_assert((where & 3) == 0); 201 db_assert(where < (1 << 8)); 202 203 /* check if the bus is top-level */ 204 if (dev->bus->parent != NULL) { 205 bus = dev->bus->number; 206 db_assert(bus != 0); 207 } else { 208 bus = 0; 209 } 210 211 slot_num = PCI_SLOT(dev->devfn); 212 func_num = PCI_FUNC(dev->devfn); 213 base = ddb_access_config_base(swap, bus, slot_num); 214 *(volatile u32*) (base + (func_num << 8) + where) = val; 215 ddb_close_config_base(swap); 216 return PCIBIOS_SUCCESSFUL; 217} 218 219static int write_config_word(struct pci_config_swap *swap, 220 struct pci_dev *dev, 221 u32 where, 222 u16 val) 223{ 224 int status, shift=0; 225 u32 result; 226 227 db_assert((where & 1) == 0); 228 229 status = read_config_dword(swap, dev, where & ~3, &result); 230 if (status != PCIBIOS_SUCCESSFUL) return status; 231 232 if (where & 2) 233 shift += 16; 234 result &= ~(0xffff << shift); 235 result |= val << shift; 236 return write_config_dword(swap, dev, where & ~3, result); 237} 238 239static int write_config_byte(struct pci_config_swap *swap, 240 struct pci_dev *dev, 241 u32 where, 242 u8 val) 243{ 244 int status, shift=0; 245 u32 result; 246 247 status = read_config_dword(swap, dev, where & ~3, &result); 248 if (status != PCIBIOS_SUCCESSFUL) return status; 249 250 if (where & 2) 251 shift += 16; 252 if (where & 1) 253 shift += 8; 254 result &= ~(0xff << shift); 255 result |= val << shift; 256 return write_config_dword(swap, dev, where & ~3, result); 257} 258 259#define MAKE_PCI_OPS(prefix, rw, unitname, unittype, pciswap) \ 260static int prefix##_##rw##_config_##unitname(struct pci_dev *dev, int where, unittype val) \ 261{ \ 262 return rw##_config_##unitname(pciswap, \ 263 dev, \ 264 where, \ 265 val); \ 266} 267 268MAKE_PCI_OPS(extpci, read, byte, u8 *, &ext_pci_swap) 269MAKE_PCI_OPS(extpci, read, word, u16 *, &ext_pci_swap) 270MAKE_PCI_OPS(extpci, read, dword, u32 *, &ext_pci_swap) 271 272MAKE_PCI_OPS(iopci, read, byte, u8 *, &io_pci_swap) 273MAKE_PCI_OPS(iopci, read, word, u16 *, &io_pci_swap) 274MAKE_PCI_OPS(iopci, read, dword, u32 *, &io_pci_swap) 275 276MAKE_PCI_OPS(extpci, write, byte, u8, &ext_pci_swap) 277MAKE_PCI_OPS(extpci, write, word, u16, &ext_pci_swap) 278MAKE_PCI_OPS(extpci, write, dword, u32, &ext_pci_swap) 279 280MAKE_PCI_OPS(iopci, write, byte, u8, &io_pci_swap) 281MAKE_PCI_OPS(iopci, write, word, u16, &io_pci_swap) 282MAKE_PCI_OPS(iopci, write, dword, u32, &io_pci_swap) 283 284struct pci_ops ddb5477_ext_pci_ops ={ 285 extpci_read_config_byte, 286 extpci_read_config_word, 287 extpci_read_config_dword, 288 extpci_write_config_byte, 289 extpci_write_config_word, 290 extpci_write_config_dword 291}; 292 293 294struct pci_ops ddb5477_io_pci_ops ={ 295 iopci_read_config_byte, 296 iopci_read_config_word, 297 iopci_read_config_dword, 298 iopci_write_config_byte, 299 iopci_write_config_word, 300 iopci_write_config_dword 301}; 302 303