1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License.  See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
7 */
8#include <linux/kernel.h>
9#include <linux/types.h>
10#include <linux/pci.h>
11
12#include <asm/marvell.h>
13
14static int mv_read_config(struct pci_bus *bus, unsigned int devfn,
15	int where, int size, u32 * val)
16{
17	struct mv_pci_controller *mvbc = bus->sysdata;
18	unsigned long address_reg, data_reg;
19	u32 address;
20
21	address_reg = mvbc->config_addr;
22	data_reg = mvbc->config_vreg;
23
24	/* Accessing device 31 crashes those Marvells.  Since years.
25	   Will they ever make sane controllers ... */
26	if (PCI_SLOT(devfn) == 31)
27		return PCIBIOS_DEVICE_NOT_FOUND;
28
29	address = (bus->number << 16) | (devfn << 8) |
30	          (where & 0xfc) | 0x80000000;
31
32	/* start the configuration cycle */
33	MV_WRITE(address_reg, address);
34
35	switch (size) {
36	case 1:
37		*val = MV_READ_8(data_reg + (where & 0x3));
38		break;
39
40	case 2:
41		*val = MV_READ_16(data_reg + (where & 0x3));
42		break;
43
44	case 4:
45		*val = MV_READ(data_reg);
46		break;
47	}
48
49	return PCIBIOS_SUCCESSFUL;
50}
51
52static int mv_write_config(struct pci_bus *bus, unsigned int devfn,
53	int where, int size, u32 val)
54{
55	struct mv_pci_controller *mvbc = bus->sysdata;
56	unsigned long address_reg, data_reg;
57	u32 address;
58
59	address_reg = mvbc->config_addr;
60	data_reg = mvbc->config_vreg;
61
62	/* Accessing device 31 crashes those Marvells.  Since years.
63	   Will they ever make sane controllers ... */
64	if (PCI_SLOT(devfn) == 31)
65		return PCIBIOS_DEVICE_NOT_FOUND;
66
67	address = (bus->number << 16) | (devfn << 8) |
68	          (where & 0xfc) | 0x80000000;
69
70	/* start the configuration cycle */
71	MV_WRITE(address_reg, address);
72
73	switch (size) {
74	case 1:
75		MV_WRITE_8(data_reg + (where & 0x3), val);
76		break;
77
78	case 2:
79		MV_WRITE_16(data_reg + (where & 0x3), val);
80		break;
81
82	case 4:
83		MV_WRITE(data_reg, val);
84		break;
85	}
86
87	return PCIBIOS_SUCCESSFUL;
88}
89
90struct pci_ops mv_pci_ops = {
91	.read	= mv_read_config,
92	.write	= mv_write_config
93};
94