1/*
2 * Copyright 2001 MontaVista Software Inc.
3 * Author: MontaVista Software, Inc.
4 *              ahennessy@mvista.com
5 *
6 * Copyright (C) 2000-2001 Toshiba Corporation
7 * Copyright (C) 2004 by Ralf Baechle (ralf@linux-mips.org)
8 *
9 * Based on arch/mips/ddb5xxx/ddb5477/pci_ops.c
10 *
11 *     Define the pci_ops for JMR3927.
12 *
13 * Much of the code is derived from the original DDB5074 port by
14 * Geert Uytterhoeven <geert@sonycom.com>
15 *
16 *  This program is free software; you can redistribute  it and/or modify it
17 *  under  the terms of  the GNU General  Public License as published by the
18 *  Free Software Foundation;  either version 2 of the  License, or (at your
19 *  option) any later version.
20 *
21 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
22 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
23 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
24 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
25 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
27 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
29 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *  You should have received a copy of the  GNU General Public License along
33 *  with this program; if not, write  to the Free Software Foundation, Inc.,
34 *  675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36#include <linux/types.h>
37#include <linux/pci.h>
38#include <linux/kernel.h>
39#include <linux/init.h>
40
41#include <asm/addrspace.h>
42#include <asm/jmr3927/jmr3927.h>
43
44static inline int mkaddr(unsigned char bus, unsigned char dev_fn,
45	unsigned char where)
46{
47	if (bus == 0 && dev_fn >= PCI_DEVFN(TX3927_PCIC_MAX_DEVNU, 0))
48		return PCIBIOS_DEVICE_NOT_FOUND;
49
50	tx3927_pcicptr->ica = ((bus & 0xff) << 0x10) |
51	                      ((dev_fn & 0xff) << 0x08) |
52	                      (where & 0xfc);
53
54	/* clear M_ABORT and Disable M_ABORT Int. */
55	tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
56	tx3927_pcicptr->pcistatim &= ~PCI_STATUS_REC_MASTER_ABORT;
57
58	return PCIBIOS_SUCCESSFUL;
59}
60
61static inline int check_abort(void)
62{
63	if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
64		tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
65		tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
66		return PCIBIOS_DEVICE_NOT_FOUND;
67
68	return PCIBIOS_SUCCESSFUL;
69}
70
71static int jmr3927_pci_read_config(struct pci_bus *bus, unsigned int devfn,
72	int where, int size, u32 * val)
73{
74	int ret;
75
76	ret = mkaddr(bus->number, devfn, where);
77	if (ret)
78		return ret;
79
80	switch (size) {
81	case 1:
82		*val = *(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3));
83		break;
84
85	case 2:
86		*val = le16_to_cpu(*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)));
87		break;
88
89	case 4:
90		*val = le32_to_cpu(tx3927_pcicptr->icd);
91		break;
92	}
93
94	return check_abort();
95}
96
97static int jmr3927_pci_write_config(struct pci_bus *bus, unsigned int devfn,
98	int where, int size, u32 val)
99{
100	int ret;
101
102	ret = mkaddr(bus->number, devfn, where);
103	if (ret)
104		return ret;
105
106	switch (size) {
107	case 1:
108		*(volatile u8 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 3)) = val;
109		break;
110
111	case 2:
112		*(volatile u16 *) ((unsigned long) & tx3927_pcicptr->icd | (where & 2)) =
113	    cpu_to_le16(val);
114		break;
115
116	case 4:
117		tx3927_pcicptr->icd = cpu_to_le32(val);
118	}
119
120	if (tx3927_pcicptr->pcistat & PCI_STATUS_REC_MASTER_ABORT)
121		tx3927_pcicptr->pcistat |= PCI_STATUS_REC_MASTER_ABORT;
122		tx3927_pcicptr->pcistatim |= PCI_STATUS_REC_MASTER_ABORT;
123		return PCIBIOS_DEVICE_NOT_FOUND;
124
125	return check_abort();
126}
127
128struct pci_ops jmr3927_pci_ops = {
129	jmr3927_pci_read_config,
130	jmr3927_pci_write_config,
131};
132