• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/sh/drivers/pci/
1/*
2 * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
3 *
4 * Copyright (C) 2002 - 2009  Paul Mundt
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License v2. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/pci.h>
11#include <linux/io.h>
12#include <asm/addrspace.h>
13#include "pci-sh4.h"
14
15/*
16 * Direct access to PCI hardware...
17 */
18#define CONFIG_CMD(bus, devfn, where) \
19	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
20
21static DEFINE_SPINLOCK(sh4_pci_lock);
22
23/*
24 * Functions for accessing PCI configuration space with type 1 accesses
25 */
26static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
27			   int where, int size, u32 *val)
28{
29	struct pci_channel *chan = bus->sysdata;
30	unsigned long flags;
31	u32 data;
32
33	/*
34	 * PCIPDR may only be accessed as 32 bit words,
35	 * so we must do byte alignment by hand
36	 */
37	spin_lock_irqsave(&sh4_pci_lock, flags);
38	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
39	data = pci_read_reg(chan, SH4_PCIPDR);
40	spin_unlock_irqrestore(&sh4_pci_lock, flags);
41
42	switch (size) {
43	case 1:
44		*val = (data >> ((where & 3) << 3)) & 0xff;
45		break;
46	case 2:
47		*val = (data >> ((where & 2) << 3)) & 0xffff;
48		break;
49	case 4:
50		*val = data;
51		break;
52	default:
53		return PCIBIOS_FUNC_NOT_SUPPORTED;
54	}
55
56	return PCIBIOS_SUCCESSFUL;
57}
58
59/*
60 * Since SH4 only does 32bit access we'll have to do a read,
61 * mask,write operation.
62 * We'll allow an odd byte offset, though it should be illegal.
63 */
64static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
65			 int where, int size, u32 val)
66{
67	struct pci_channel *chan = bus->sysdata;
68	unsigned long flags;
69	int shift;
70	u32 data;
71
72	spin_lock_irqsave(&sh4_pci_lock, flags);
73	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
74	data = pci_read_reg(chan, SH4_PCIPDR);
75	spin_unlock_irqrestore(&sh4_pci_lock, flags);
76
77	switch (size) {
78	case 1:
79		shift = (where & 3) << 3;
80		data &= ~(0xff << shift);
81		data |= ((val & 0xff) << shift);
82		break;
83	case 2:
84		shift = (where & 2) << 3;
85		data &= ~(0xffff << shift);
86		data |= ((val & 0xffff) << shift);
87		break;
88	case 4:
89		data = val;
90		break;
91	default:
92		return PCIBIOS_FUNC_NOT_SUPPORTED;
93	}
94
95	pci_write_reg(chan, data, SH4_PCIPDR);
96
97	return PCIBIOS_SUCCESSFUL;
98}
99
100struct pci_ops sh4_pci_ops = {
101	.read		= sh4_pci_read,
102	.write		= sh4_pci_write,
103};
104
105int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
106{
107	/* Nothing to do. */
108	return 0;
109}
110