zorro.c (5797B)
1/* 2 * Zorro Bus Services 3 * 4 * Copyright (C) 1995-2003 Geert Uytterhoeven 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11#include <linux/module.h> 12#include <linux/types.h> 13#include <linux/kernel.h> 14#include <linux/init.h> 15#include <linux/zorro.h> 16#include <linux/bitops.h> 17#include <linux/string.h> 18#include <linux/platform_device.h> 19#include <linux/dma-mapping.h> 20#include <linux/slab.h> 21 22#include <asm/byteorder.h> 23#include <asm/setup.h> 24#include <asm/amigahw.h> 25 26#include "zorro.h" 27 28 29 /* 30 * Zorro Expansion Devices 31 */ 32 33unsigned int zorro_num_autocon; 34struct zorro_dev_init zorro_autocon_init[ZORRO_NUM_AUTO] __initdata; 35struct zorro_dev *zorro_autocon; 36 37 38 /* 39 * Zorro bus 40 */ 41 42struct zorro_bus { 43 struct device dev; 44 struct zorro_dev devices[]; 45}; 46 47 48 /* 49 * Find Zorro Devices 50 */ 51 52struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) 53{ 54 struct zorro_dev *z; 55 56 if (!zorro_num_autocon) 57 return NULL; 58 59 for (z = from ? from+1 : &zorro_autocon[0]; 60 z < zorro_autocon+zorro_num_autocon; 61 z++) 62 if (id == ZORRO_WILDCARD || id == z->id) 63 return z; 64 return NULL; 65} 66EXPORT_SYMBOL(zorro_find_device); 67 68 69 /* 70 * Bitmask indicating portions of available Zorro II RAM that are unused 71 * by the system. Every bit represents a 64K chunk, for a maximum of 8MB 72 * (128 chunks, physical 0x00200000-0x009fffff). 73 * 74 * If you want to use (= allocate) portions of this RAM, you should clear 75 * the corresponding bits. 76 * 77 * Possible uses: 78 * - z2ram device 79 * - SCSI DMA bounce buffers 80 * 81 * FIXME: use the normal resource management 82 */ 83 84DECLARE_BITMAP(zorro_unused_z2ram, 128); 85EXPORT_SYMBOL(zorro_unused_z2ram); 86 87 88static void __init mark_region(unsigned long start, unsigned long end, 89 int flag) 90{ 91 if (flag) 92 start += Z2RAM_CHUNKMASK; 93 else 94 end += Z2RAM_CHUNKMASK; 95 start &= ~Z2RAM_CHUNKMASK; 96 end &= ~Z2RAM_CHUNKMASK; 97 98 if (end <= Z2RAM_START || start >= Z2RAM_END) 99 return; 100 start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; 101 end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; 102 while (start < end) { 103 u32 chunk = start>>Z2RAM_CHUNKSHIFT; 104 105 if (flag) 106 set_bit(chunk, zorro_unused_z2ram); 107 else 108 clear_bit(chunk, zorro_unused_z2ram); 109 start += Z2RAM_CHUNKSIZE; 110 } 111} 112 113 114static struct resource __init *zorro_find_parent_resource( 115 struct platform_device *bridge, struct zorro_dev *z) 116{ 117 int i; 118 119 for (i = 0; i < bridge->num_resources; i++) { 120 struct resource *r = &bridge->resource[i]; 121 122 if (zorro_resource_start(z) >= r->start && 123 zorro_resource_end(z) <= r->end) 124 return r; 125 } 126 return &iomem_resource; 127} 128 129 130 131static int __init amiga_zorro_probe(struct platform_device *pdev) 132{ 133 struct zorro_bus *bus; 134 struct zorro_dev_init *zi; 135 struct zorro_dev *z; 136 struct resource *r; 137 unsigned int i; 138 int error; 139 140 /* Initialize the Zorro bus */ 141 bus = kzalloc(struct_size(bus, devices, zorro_num_autocon), 142 GFP_KERNEL); 143 if (!bus) 144 return -ENOMEM; 145 146 zorro_autocon = bus->devices; 147 bus->dev.parent = &pdev->dev; 148 dev_set_name(&bus->dev, zorro_bus_type.name); 149 error = device_register(&bus->dev); 150 if (error) { 151 pr_err("Zorro: Error registering zorro_bus\n"); 152 put_device(&bus->dev); 153 kfree(bus); 154 return error; 155 } 156 platform_set_drvdata(pdev, bus); 157 158 pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", 159 zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); 160 161 /* First identify all devices ... */ 162 for (i = 0; i < zorro_num_autocon; i++) { 163 zi = &zorro_autocon_init[i]; 164 z = &zorro_autocon[i]; 165 166 z->rom = zi->rom; 167 z->id = (be16_to_cpu(z->rom.er_Manufacturer) << 16) | 168 (z->rom.er_Product << 8); 169 if (z->id == ZORRO_PROD_GVP_EPC_BASE) { 170 /* GVP quirk */ 171 unsigned long magic = zi->boardaddr + 0x8000; 172 173 z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; 174 } 175 z->slotaddr = zi->slotaddr; 176 z->slotsize = zi->slotsize; 177 sprintf(z->name, "Zorro device %08x", z->id); 178 zorro_name_device(z); 179 z->resource.start = zi->boardaddr; 180 z->resource.end = zi->boardaddr + zi->boardsize - 1; 181 z->resource.name = z->name; 182 r = zorro_find_parent_resource(pdev, z); 183 error = request_resource(r, &z->resource); 184 if (error && !(z->rom.er_Type & ERTF_MEMLIST)) 185 dev_err(&bus->dev, 186 "Address space collision on device %s %pR\n", 187 z->name, &z->resource); 188 z->dev.parent = &bus->dev; 189 z->dev.bus = &zorro_bus_type; 190 z->dev.id = i; 191 switch (z->rom.er_Type & ERT_TYPEMASK) { 192 case ERT_ZORROIII: 193 z->dev.coherent_dma_mask = DMA_BIT_MASK(32); 194 break; 195 196 case ERT_ZORROII: 197 default: 198 z->dev.coherent_dma_mask = DMA_BIT_MASK(24); 199 break; 200 } 201 z->dev.dma_mask = &z->dev.coherent_dma_mask; 202 } 203 204 /* ... then register them */ 205 for (i = 0; i < zorro_num_autocon; i++) { 206 z = &zorro_autocon[i]; 207 error = device_register(&z->dev); 208 if (error) { 209 dev_err(&bus->dev, "Error registering device %s\n", 210 z->name); 211 put_device(&z->dev); 212 continue; 213 } 214 } 215 216 /* Mark all available Zorro II memory */ 217 zorro_for_each_dev(z) { 218 if (z->rom.er_Type & ERTF_MEMLIST) 219 mark_region(zorro_resource_start(z), 220 zorro_resource_end(z)+1, 1); 221 } 222 223 /* Unmark all used Zorro II memory */ 224 for (i = 0; i < m68k_num_memory; i++) 225 if (m68k_memory[i].addr < 16*1024*1024) 226 mark_region(m68k_memory[i].addr, 227 m68k_memory[i].addr+m68k_memory[i].size, 228 0); 229 230 return 0; 231} 232 233static struct platform_driver amiga_zorro_driver = { 234 .driver = { 235 .name = "amiga-zorro", 236 }, 237}; 238 239static int __init amiga_zorro_init(void) 240{ 241 return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); 242} 243 244module_init(amiga_zorro_init); 245 246MODULE_LICENSE("GPL");