• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/mn10300/unit-asb2305/
1/* ASB2305 PCI resource stuff
2 *
3 * Copyright (C) 2001 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 * - Derived from arch/i386/pci-i386.c
6 *   - Copyright 1997--2000 Martin Mares <mj@suse.cz>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public Licence
10 * as published by the Free Software Foundation; either version
11 * 2 of the Licence, or (at your option) any later version.
12 */
13#include <linux/types.h>
14#include <linux/kernel.h>
15#include <linux/pci.h>
16#include <linux/init.h>
17#include <linux/ioport.h>
18#include <linux/errno.h>
19#include "pci-asb2305.h"
20
21/*
22 * We need to avoid collisions with `mirrored' VGA ports
23 * and other strange ISA hardware, so we always want the
24 * addresses to be allocated in the 0x000-0x0ff region
25 * modulo 0x400.
26 *
27 * Why? Because some silly external IO cards only decode
28 * the low 10 bits of the IO address. The 0x00-0xff region
29 * is reserved for motherboard devices that decode all 16
30 * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
31 * but we want to try to avoid allocating at 0x2900-0x2bff
32 * which might have be mirrored at 0x0100-0x03ff..
33 */
34resource_size_t pcibios_align_resource(void *data, const struct resource *res,
35				resource_size_t size, resource_size_t align)
36{
37	resource_size_t start = res->start;
38
39
40	if ((res->flags & IORESOURCE_IO) && (start & 0x300))
41		start = (start + 0x3ff) & ~0x3ff;
42
43	return start;
44}
45
46
47static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
48{
49	struct pci_bus *bus;
50	struct pci_dev *dev;
51	int idx;
52	struct resource *r, *pr;
53
54	/* Depth-First Search on bus tree */
55	list_for_each_entry(bus, bus_list, node) {
56		dev = bus->self;
57		if (dev) {
58			for (idx = PCI_BRIDGE_RESOURCES;
59			     idx < PCI_NUM_RESOURCES;
60			     idx++) {
61				r = &dev->resource[idx];
62				if (!r->flags)
63					continue;
64				pr = pci_find_parent_resource(dev, r);
65				if (!r->start ||
66				    !pr ||
67				    request_resource(pr, r) < 0) {
68					printk(KERN_ERR "PCI:"
69					       " Cannot allocate resource"
70					       " region %d of bridge %s\n",
71					       idx, pci_name(dev));
72					/* Something is wrong with the region.
73					 * Invalidate the resource to prevent
74					 * child resource allocations in this
75					 * range. */
76					r->start = r->end = 0;
77					r->flags = 0;
78				}
79			}
80		}
81		pcibios_allocate_bus_resources(&bus->children);
82	}
83}
84
85static void __init pcibios_allocate_resources(int pass)
86{
87	struct pci_dev *dev = NULL;
88	int idx, disabled;
89	u16 command;
90	struct resource *r, *pr;
91
92	for_each_pci_dev(dev) {
93		pci_read_config_word(dev, PCI_COMMAND, &command);
94		for (idx = 0; idx < 6; idx++) {
95			r = &dev->resource[idx];
96			if (r->parent)		/* Already allocated */
97				continue;
98			if (!r->start)		/* Address not assigned */
99				continue;
100			if (r->flags & IORESOURCE_IO)
101				disabled = !(command & PCI_COMMAND_IO);
102			else
103				disabled = !(command & PCI_COMMAND_MEMORY);
104			if (pass == disabled) {
105				DBG("PCI[%s]: Resource %08lx-%08lx"
106				    " (f=%lx, d=%d, p=%d)\n",
107				    pci_name(dev), r->start, r->end, r->flags,
108				    disabled, pass);
109				pr = pci_find_parent_resource(dev, r);
110				if (!pr || request_resource(pr, r) < 0) {
111					printk(KERN_ERR "PCI:"
112					       " Cannot allocate resource"
113					       " region %d of device %s\n",
114					       idx, pci_name(dev));
115					/* We'll assign a new address later */
116					r->end -= r->start;
117					r->start = 0;
118				}
119			}
120		}
121		if (!pass) {
122			r = &dev->resource[PCI_ROM_RESOURCE];
123			if (r->flags & IORESOURCE_ROM_ENABLE) {
124				/* Turn the ROM off, leave the resource region,
125				 * but keep it unregistered. */
126				u32 reg;
127				DBG("PCI: Switching off ROM of %s\n",
128				    pci_name(dev));
129				r->flags &= ~IORESOURCE_ROM_ENABLE;
130				pci_read_config_dword(
131					dev, dev->rom_base_reg, &reg);
132				pci_write_config_dword(
133					dev, dev->rom_base_reg,
134					reg & ~PCI_ROM_ADDRESS_ENABLE);
135			}
136		}
137	}
138}
139
140static int __init pcibios_assign_resources(void)
141{
142	struct pci_dev *dev = NULL;
143	struct resource *r, *pr;
144
145	if (!(pci_probe & PCI_ASSIGN_ROMS)) {
146		/* Try to use BIOS settings for ROMs, otherwise let
147		   pci_assign_unassigned_resources() allocate the new
148		   addresses. */
149		for_each_pci_dev(dev) {
150			r = &dev->resource[PCI_ROM_RESOURCE];
151			if (!r->flags || !r->start)
152				continue;
153			pr = pci_find_parent_resource(dev, r);
154			if (!pr || request_resource(pr, r) < 0) {
155				r->end -= r->start;
156				r->start = 0;
157			}
158		}
159	}
160
161	pci_assign_unassigned_resources();
162
163	return 0;
164}
165
166fs_initcall(pcibios_assign_resources);
167
168void __init pcibios_resource_survey(void)
169{
170	DBG("PCI: Allocating resources\n");
171	pcibios_allocate_bus_resources(&pci_root_buses);
172	pcibios_allocate_resources(0);
173	pcibios_allocate_resources(1);
174}
175
176/*
177 *  If we set up a device for bus mastering, we need to check the latency
178 *  timer as certain crappy BIOSes forget to set it properly.
179 */
180unsigned int pcibios_max_latency = 255;
181
182void pcibios_set_master(struct pci_dev *dev)
183{
184	u8 lat;
185
186	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
187
188	if (lat < 16)
189		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
190	else if (lat > pcibios_max_latency)
191		lat = pcibios_max_latency;
192	else
193		return;
194
195	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
196}
197
198int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
199			enum pci_mmap_state mmap_state, int write_combine)
200{
201	unsigned long prot;
202
203	/* Leave vm_pgoff as-is, the PCI space address is the physical
204	 * address on this platform.
205	 */
206	vma->vm_flags |= VM_LOCKED | VM_IO;
207
208	prot = pgprot_val(vma->vm_page_prot);
209	prot &= ~_PAGE_CACHE;
210	vma->vm_page_prot = __pgprot(prot);
211
212	/* Write-combine setting is ignored */
213	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
214			       vma->vm_end - vma->vm_start,
215			       vma->vm_page_prot))
216		return -EAGAIN;
217
218	return 0;
219}
220