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#include <linux/pci.h> 23#include <linux/kernel.h> 24#include <linux/types.h> 25 26#include <asm/addrspace.h> 27#include <asm/debug.h> 28 29#include <asm/ddb5xxx/ddb5xxx.h> 30 31/* 32 * config_swap structure records what set of pdar/pmr are used 33 * to access pci config space. It also provides a place hold the 34 * original values for future restoring. 35 */ 36struct pci_config_swap { 37 u32 pdar; 38 u32 pmr; 39 u32 config_base; 40 u32 config_size; 41 u32 pdar_backup; 42 u32 pmr_backup; 43}; 44 45/* 46 * On DDB5477, we have two sets of swap registers, for ext PCI and IOPCI. 47 */ 48struct pci_config_swap ext_pci_swap = { 49 DDB_PCIW0, 50 DDB_PCIINIT00, 51 DDB_PCI0_CONFIG_BASE, 52 DDB_PCI0_CONFIG_SIZE 53}; 54struct pci_config_swap io_pci_swap = { 55 DDB_IOPCIW0, 56 DDB_PCIINIT01, 57 DDB_PCI1_CONFIG_BASE, 58 DDB_PCI1_CONFIG_SIZE 59}; 60 61 62/* 63 * access config space 64 */ 65static inline u32 ddb_access_config_base(struct pci_config_swap *swap, u32 bus, /* 0 means top level bus */ 66 u32 slot_num) 67{ 68 u32 pci_addr = 0; 69 u32 pciinit_offset = 0; 70 u32 virt_addr; 71 u32 option; 72 73 /* minimum pdar (window) size is 2MB */ 74 db_assert(swap->config_size >= (2 << 20)); 75 76 db_assert(slot_num < (1 << 5)); 77 db_assert(bus < (1 << 8)); 78 79 /* backup registers */ 80 swap->pdar_backup = ddb_in32(swap->pdar); 81 swap->pmr_backup = ddb_in32(swap->pmr); 82 83 /* set the pdar (pci window) register */ 84 ddb_set_pdar(swap->pdar, swap->config_base, swap->config_size, 32, /* 32 bit wide */ 85 0, /* not on local memory bus */ 86 0); /* not visible from PCI bus (N/A) */ 87 88 /* 89 * calcuate the absolute pci config addr; 90 * according to the spec, we start scanning from adr:11 (0x800) 91 */ 92 if (bus == 0) { 93 /* type 0 config */ 94 pci_addr = 0x800 << slot_num; 95 } else { 96 /* type 1 config */ 97 pci_addr = (bus << 16) | (slot_num << 11); 98 } 99 100 /* 101 * if pci_addr is less than pci config window size, we set 102 * pciinit_offset to 0 and adjust the virt_address. 103 * Otherwise we will try to adjust pciinit_offset. 104 */ 105 if (pci_addr < swap->config_size) { 106 virt_addr = KSEG1ADDR(swap->config_base + pci_addr); 107 pciinit_offset = 0; 108 } else { 109 db_assert((pci_addr & (swap->config_size - 1)) == 0); 110 virt_addr = KSEG1ADDR(swap->config_base); 111 pciinit_offset = pci_addr; 112 } 113 114 /* set the pmr register */ 115 option = DDB_PCI_ACCESS_32; 116 if (bus != 0) 117 option |= DDB_PCI_CFGTYPE1; 118 ddb_set_pmr(swap->pmr, DDB_PCICMD_CFG, pciinit_offset, option); 119 120 return virt_addr; 121} 122 123static inline void ddb_close_config_base(struct pci_config_swap *swap) 124{ 125 ddb_out32(swap->pdar, swap->pdar_backup); 126 ddb_out32(swap->pmr, swap->pmr_backup); 127} 128 129static int read_config_dword(struct pci_config_swap *swap, 130 struct pci_bus *bus, u32 devfn, u32 where, 131 u32 * val) 132{ 133 u32 bus_num, slot_num, func_num; 134 u32 base; 135 136 db_assert((where & 3) == 0); 137 db_assert(where < (1 << 8)); 138 139 /* check if the bus is top-level */ 140 if (bus->parent != NULL) { 141 bus_num = bus->number; 142 db_assert(bus_num != 0); 143 } else { 144 bus_num = 0; 145 } 146 147 slot_num = PCI_SLOT(devfn); 148 func_num = PCI_FUNC(devfn); 149 base = ddb_access_config_base(swap, bus_num, slot_num); 150 *val = *(volatile u32 *) (base + (func_num << 8) + where); 151 ddb_close_config_base(swap); 152 return PCIBIOS_SUCCESSFUL; 153} 154 155static int read_config_word(struct pci_config_swap *swap, 156 struct pci_bus *bus, u32 devfn, u32 where, 157 u16 * val) 158{ 159 int status; 160 u32 result; 161 162 db_assert((where & 1) == 0); 163 164 status = read_config_dword(swap, bus, devfn, where & ~3, &result); 165 if (where & 2) 166 result >>= 16; 167 *val = result & 0xffff; 168 return status; 169} 170 171static int read_config_byte(struct pci_config_swap *swap, 172 struct pci_bus *bus, u32 devfn, u32 where, 173 u8 * val) 174{ 175 int status; 176 u32 result; 177 178 status = read_config_dword(swap, bus, devfn, where & ~3, &result); 179 if (where & 1) 180 result >>= 8; 181 if (where & 2) 182 result >>= 16; 183 *val = result & 0xff; 184 185 return status; 186} 187 188static int write_config_dword(struct pci_config_swap *swap, 189 struct pci_bus *bus, u32 devfn, u32 where, 190 u32 val) 191{ 192 u32 bus_num, slot_num, func_num; 193 u32 base; 194 195 db_assert((where & 3) == 0); 196 db_assert(where < (1 << 8)); 197 198 /* check if the bus is top-level */ 199 if (bus->parent != NULL) { 200 bus_num = bus->number; 201 db_assert(bus_num != 0); 202 } else { 203 bus_num = 0; 204 } 205 206 slot_num = PCI_SLOT(devfn); 207 func_num = PCI_FUNC(devfn); 208 base = ddb_access_config_base(swap, bus_num, slot_num); 209 *(volatile u32 *) (base + (func_num << 8) + where) = val; 210 ddb_close_config_base(swap); 211 return PCIBIOS_SUCCESSFUL; 212} 213 214static int write_config_word(struct pci_config_swap *swap, 215 struct pci_bus *bus, u32 devfn, u32 where, u16 val) 216{ 217 int status, shift = 0; 218 u32 result; 219 220 db_assert((where & 1) == 0); 221 222 status = read_config_dword(swap, bus, devfn, where & ~3, &result); 223 if (status != PCIBIOS_SUCCESSFUL) 224 return status; 225 226 if (where & 2) 227 shift += 16; 228 result &= ~(0xffff << shift); 229 result |= val << shift; 230 return write_config_dword(swap, bus, devfn, where & ~3, result); 231} 232 233static int write_config_byte(struct pci_config_swap *swap, 234 struct pci_bus *bus, u32 devfn, u32 where, u8 val) 235{ 236 int status, shift = 0; 237 u32 result; 238 239 status = read_config_dword(swap, bus, devfn, where & ~3, &result); 240 if (status != PCIBIOS_SUCCESSFUL) 241 return status; 242 243 if (where & 2) 244 shift += 16; 245 if (where & 1) 246 shift += 8; 247 result &= ~(0xff << shift); 248 result |= val << shift; 249 return write_config_dword(swap, bus, devfn, where & ~3, result); 250} 251 252#define MAKE_PCI_OPS(prefix, rw, pciswap, star) \ 253static int prefix##_##rw##_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 star val) \ 254{ \ 255 if (size == 1) \ 256 return rw##_config_byte(pciswap, bus, devfn, where, (u8 star)val); \ 257 else if (size == 2) \ 258 return rw##_config_word(pciswap, bus, devfn, where, (u16 star)val); \ 259 /* Size must be 4 */ \ 260 return rw##_config_dword(pciswap, bus, devfn, where, val); \ 261} 262 263MAKE_PCI_OPS(extpci, read, &ext_pci_swap, *) 264MAKE_PCI_OPS(extpci, write, &ext_pci_swap,) 265 266MAKE_PCI_OPS(iopci, read, &io_pci_swap, *) 267MAKE_PCI_OPS(iopci, write, &io_pci_swap,) 268 269struct pci_ops ddb5477_ext_pci_ops = { 270 .read = extpci_read_config, 271 .write = extpci_write_config 272}; 273 274 275struct pci_ops ddb5477_io_pci_ops = { 276 .read = iopci_read_config, 277 .write = iopci_write_config 278}; 279