|  | /* | 
|  | * This file is subject to the terms and conditions of the GNU General Public | 
|  | * License.  See the file "COPYING" in the main directory of this archive | 
|  | * for more details. | 
|  | * | 
|  | * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org) | 
|  | */ | 
|  | #include <linux/kernel.h> | 
|  | #include <linux/types.h> | 
|  | #include <linux/pci.h> | 
|  |  | 
|  | #include <asm/marvell.h> | 
|  |  | 
|  | static int mv_read_config(struct pci_bus *bus, unsigned int devfn, | 
|  | int where, int size, u32 * val) | 
|  | { | 
|  | struct mv_pci_controller *mvbc = bus->sysdata; | 
|  | unsigned long address_reg, data_reg; | 
|  | u32 address; | 
|  |  | 
|  | address_reg = mvbc->config_addr; | 
|  | data_reg = mvbc->config_vreg; | 
|  |  | 
|  | /* Accessing device 31 crashes those Marvells.  Since years. | 
|  | Will they ever make sane controllers ... */ | 
|  | if (PCI_SLOT(devfn) == 31) | 
|  | return PCIBIOS_DEVICE_NOT_FOUND; | 
|  |  | 
|  | address = (bus->number << 16) | (devfn << 8) | | 
|  | (where & 0xfc) | 0x80000000; | 
|  |  | 
|  | /* start the configuration cycle */ | 
|  | MV_WRITE(address_reg, address); | 
|  |  | 
|  | switch (size) { | 
|  | case 1: | 
|  | *val = MV_READ_8(data_reg + (where & 0x3)); | 
|  | break; | 
|  |  | 
|  | case 2: | 
|  | *val = MV_READ_16(data_reg + (where & 0x3)); | 
|  | break; | 
|  |  | 
|  | case 4: | 
|  | *val = MV_READ(data_reg); | 
|  | break; | 
|  | } | 
|  |  | 
|  | return PCIBIOS_SUCCESSFUL; | 
|  | } | 
|  |  | 
|  | static int mv_write_config(struct pci_bus *bus, unsigned int devfn, | 
|  | int where, int size, u32 val) | 
|  | { | 
|  | struct mv_pci_controller *mvbc = bus->sysdata; | 
|  | unsigned long address_reg, data_reg; | 
|  | u32 address; | 
|  |  | 
|  | address_reg = mvbc->config_addr; | 
|  | data_reg = mvbc->config_vreg; | 
|  |  | 
|  | /* Accessing device 31 crashes those Marvells.  Since years. | 
|  | Will they ever make sane controllers ... */ | 
|  | if (PCI_SLOT(devfn) == 31) | 
|  | return PCIBIOS_DEVICE_NOT_FOUND; | 
|  |  | 
|  | address = (bus->number << 16) | (devfn << 8) | | 
|  | (where & 0xfc) | 0x80000000; | 
|  |  | 
|  | /* start the configuration cycle */ | 
|  | MV_WRITE(address_reg, address); | 
|  |  | 
|  | switch (size) { | 
|  | case 1: | 
|  | MV_WRITE_8(data_reg + (where & 0x3), val); | 
|  | break; | 
|  |  | 
|  | case 2: | 
|  | MV_WRITE_16(data_reg + (where & 0x3), val); | 
|  | break; | 
|  |  | 
|  | case 4: | 
|  | MV_WRITE(data_reg, val); | 
|  | break; | 
|  | } | 
|  |  | 
|  | return PCIBIOS_SUCCESSFUL; | 
|  | } | 
|  |  | 
|  | struct pci_ops mv_pci_ops = { | 
|  | .read	= mv_read_config, | 
|  | .write	= mv_write_config | 
|  | }; |