zorro.c 5.0 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *    Zorro Bus Services
 *
 *    Copyright (C) 1995-2003 Geert Uytterhoeven
 *
 *    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.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/zorro.h>
#include <linux/bitops.h>
T
Tim Schmielau 已提交
17
#include <linux/string.h>
18 19
#include <linux/platform_device.h>
#include <linux/slab.h>
T
Tim Schmielau 已提交
20

L
Linus Torvalds 已提交
21 22 23 24 25 26 27 28 29 30
#include <asm/setup.h>
#include <asm/amigahw.h>

#include "zorro.h"


    /*
     *  Zorro Expansion Devices
     */

31
unsigned int zorro_num_autocon;
L
Linus Torvalds 已提交
32 33 34 35
struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO];


    /*
36
     *  Zorro bus
L
Linus Torvalds 已提交
37 38
     */

39 40 41
struct zorro_bus {
	struct list_head devices;	/* list of devices on this bus */
	struct device dev;
L
Linus Torvalds 已提交
42 43 44 45 46 47 48 49 50
};


    /*
     *  Find Zorro Devices
     */

struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from)
{
51
	struct zorro_dev *z;
L
Linus Torvalds 已提交
52

53 54
	if (!zorro_num_autocon)
		return NULL;
L
Linus Torvalds 已提交
55

56 57 58 59 60 61
	for (z = from ? from+1 : &zorro_autocon[0];
	     z < zorro_autocon+zorro_num_autocon;
	     z++)
		if (id == ZORRO_WILDCARD || id == z->id)
			return z;
	return NULL;
L
Linus Torvalds 已提交
62
}
63
EXPORT_SYMBOL(zorro_find_device);
L
Linus Torvalds 已提交
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81


    /*
     *  Bitmask indicating portions of available Zorro II RAM that are unused
     *  by the system. Every bit represents a 64K chunk, for a maximum of 8MB
     *  (128 chunks, physical 0x00200000-0x009fffff).
     *
     *  If you want to use (= allocate) portions of this RAM, you should clear
     *  the corresponding bits.
     *
     *  Possible uses:
     *      - z2ram device
     *      - SCSI DMA bounce buffers
     *
     *  FIXME: use the normal resource management
     */

DECLARE_BITMAP(zorro_unused_z2ram, 128);
82
EXPORT_SYMBOL(zorro_unused_z2ram);
L
Linus Torvalds 已提交
83 84 85 86 87 88


static void __init mark_region(unsigned long start, unsigned long end,
			       int flag)
{
	if (flag)
89
		start += Z2RAM_CHUNKMASK;
L
Linus Torvalds 已提交
90
	else
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
		end += Z2RAM_CHUNKMASK;
	start &= ~Z2RAM_CHUNKMASK;
	end &= ~Z2RAM_CHUNKMASK;

	if (end <= Z2RAM_START || start >= Z2RAM_END)
		return;
	start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START;
	end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START;
	while (start < end) {
		u32 chunk = start>>Z2RAM_CHUNKSHIFT;
		if (flag)
			set_bit(chunk, zorro_unused_z2ram);
		else
			clear_bit(chunk, zorro_unused_z2ram);
		start += Z2RAM_CHUNKSIZE;
	}
L
Linus Torvalds 已提交
107 108 109
}


110 111
static struct resource __init *zorro_find_parent_resource(
	struct platform_device *bridge, struct zorro_dev *z)
L
Linus Torvalds 已提交
112
{
113
	int i;
L
Linus Torvalds 已提交
114

115 116 117 118 119 120 121
	for (i = 0; i < bridge->num_resources; i++) {
		struct resource *r = &bridge->resource[i];
		if (zorro_resource_start(z) >= r->start &&
		    zorro_resource_end(z) <= r->end)
			return r;
	}
	return &iomem_resource;
L
Linus Torvalds 已提交
122 123 124 125
}



126
static int __init amiga_zorro_probe(struct platform_device *pdev)
L
Linus Torvalds 已提交
127
{
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
	struct zorro_bus *bus;
	struct zorro_dev *z;
	struct resource *r;
	unsigned int i;
	int error;

	/* Initialize the Zorro bus */
	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
	if (!bus)
		return -ENOMEM;

	INIT_LIST_HEAD(&bus->devices);
	bus->dev.parent = &pdev->dev;
	dev_set_name(&bus->dev, "zorro");
	error = device_register(&bus->dev);
143
	if (error) {
144 145 146
		pr_err("Zorro: Error registering zorro_bus\n");
		kfree(bus);
		return error;
147
	}
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
	platform_set_drvdata(pdev, bus);

	/* Register all devices */
	pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n",
		 zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s");

	for (i = 0; i < zorro_num_autocon; i++) {
		z = &zorro_autocon[i];
		z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8);
		if (z->id == ZORRO_PROD_GVP_EPC_BASE) {
			/* GVP quirk */
			unsigned long magic = zorro_resource_start(z)+0x8000;
			z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK;
		}
		sprintf(z->name, "Zorro device %08x", z->id);
		zorro_name_device(z);
		z->resource.name = z->name;
		r = zorro_find_parent_resource(pdev, z);
		error = request_resource(r, &z->resource);
		if (error)
			dev_err(&bus->dev,
				"Address space collision on device %s %pR\n",
				z->name, &z->resource);
		dev_set_name(&z->dev, "%02x", i);
		z->dev.parent = &bus->dev;
		z->dev.bus = &zorro_bus_type;
		error = device_register(&z->dev);
		if (error) {
			dev_err(&bus->dev, "Error registering device %s\n",
				z->name);
			continue;
		}
		error = zorro_create_sysfs_dev_files(z);
		if (error)
			dev_err(&z->dev, "Error creating sysfs files\n");
	}

	/* Mark all available Zorro II memory */
	zorro_for_each_dev(z) {
		if (z->rom.er_Type & ERTF_MEMLIST)
			mark_region(zorro_resource_start(z),
				    zorro_resource_end(z)+1, 1);
	}

	/* Unmark all used Zorro II memory */
	for (i = 0; i < m68k_num_memory; i++)
		if (m68k_memory[i].addr < 16*1024*1024)
			mark_region(m68k_memory[i].addr,
				    m68k_memory[i].addr+m68k_memory[i].size,
				    0);

	return 0;
L
Linus Torvalds 已提交
200 201
}

202 203 204 205 206 207
static struct platform_driver amiga_zorro_driver = {
	.driver   = {
		.name	= "amiga-zorro",
		.owner	= THIS_MODULE,
	},
};
L
Linus Torvalds 已提交
208

209 210 211 212 213 214
static int __init amiga_zorro_init(void)
{
	return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe);
}

module_init(amiga_zorro_init);
L
Linus Torvalds 已提交
215 216

MODULE_LICENSE("GPL");