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/slab.h> 20 21#include <asm/setup.h> 22#include <asm/amigahw.h> 23 24#include "zorro.h" 25 26 27 /* 28 * Zorro Expansion Devices 29 */ 30 31unsigned int zorro_num_autocon; 32struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; 33 34 35 /* 36 * Zorro bus 37 */ 38 39struct zorro_bus { 40 struct list_head devices; /* list of devices on this bus */ 41 struct device dev; 42}; 43 44 45 /* 46 * Find Zorro Devices 47 */ 48 49struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) 50{ 51 struct zorro_dev *z; 52 53 if (!zorro_num_autocon) 54 return NULL; 55 56 for (z = from ? from+1 : &zorro_autocon[0]; 57 z < zorro_autocon+zorro_num_autocon; 58 z++) 59 if (id == ZORRO_WILDCARD || id == z->id) 60 return z; 61 return NULL; 62} 63EXPORT_SYMBOL(zorro_find_device); 64 65 66 67DECLARE_BITMAP(zorro_unused_z2ram, 128); 68EXPORT_SYMBOL(zorro_unused_z2ram); 69 70 71static void __init mark_region(unsigned long start, unsigned long end, 72 int flag) 73{ 74 if (flag) 75 start += Z2RAM_CHUNKMASK; 76 else 77 end += Z2RAM_CHUNKMASK; 78 start &= ~Z2RAM_CHUNKMASK; 79 end &= ~Z2RAM_CHUNKMASK; 80 81 if (end <= Z2RAM_START || start >= Z2RAM_END) 82 return; 83 start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; 84 end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; 85 while (start < end) { 86 u32 chunk = start>>Z2RAM_CHUNKSHIFT; 87 if (flag) 88 set_bit(chunk, zorro_unused_z2ram); 89 else 90 clear_bit(chunk, zorro_unused_z2ram); 91 start += Z2RAM_CHUNKSIZE; 92 } 93} 94 95 96static struct resource __init *zorro_find_parent_resource( 97 struct platform_device *bridge, struct zorro_dev *z) 98{ 99 int i; 100 101 for (i = 0; i < bridge->num_resources; i++) { 102 struct resource *r = &bridge->resource[i]; 103 if (zorro_resource_start(z) >= r->start && 104 zorro_resource_end(z) <= r->end) 105 return r; 106 } 107 return &iomem_resource; 108} 109 110 111 112static int __init amiga_zorro_probe(struct platform_device *pdev) 113{ 114 struct zorro_bus *bus; 115 struct zorro_dev *z; 116 struct resource *r; 117 unsigned int i; 118 int error; 119 120 /* Initialize the Zorro bus */ 121 bus = kzalloc(sizeof(*bus), GFP_KERNEL); 122 if (!bus) 123 return -ENOMEM; 124 125 INIT_LIST_HEAD(&bus->devices); 126 bus->dev.parent = &pdev->dev; 127 dev_set_name(&bus->dev, "zorro"); 128 error = device_register(&bus->dev); 129 if (error) { 130 pr_err("Zorro: Error registering zorro_bus\n"); 131 kfree(bus); 132 return error; 133 } 134 platform_set_drvdata(pdev, bus); 135 136 /* Register all devices */ 137 pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", 138 zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); 139 140 for (i = 0; i < zorro_num_autocon; i++) { 141 z = &zorro_autocon[i]; 142 z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); 143 if (z->id == ZORRO_PROD_GVP_EPC_BASE) { 144 /* GVP quirk */ 145 unsigned long magic = zorro_resource_start(z)+0x8000; 146 z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; 147 } 148 sprintf(z->name, "Zorro device %08x", z->id); 149 zorro_name_device(z); 150 z->resource.name = z->name; 151 r = zorro_find_parent_resource(pdev, z); 152 error = request_resource(r, &z->resource); 153 if (error) 154 dev_err(&bus->dev, 155 "Address space collision on device %s %pR\n", 156 z->name, &z->resource); 157 dev_set_name(&z->dev, "%02x", i); 158 z->dev.parent = &bus->dev; 159 z->dev.bus = &zorro_bus_type; 160 error = device_register(&z->dev); 161 if (error) { 162 dev_err(&bus->dev, "Error registering device %s\n", 163 z->name); 164 continue; 165 } 166 error = zorro_create_sysfs_dev_files(z); 167 if (error) 168 dev_err(&z->dev, "Error creating sysfs files\n"); 169 } 170 171 /* Mark all available Zorro II memory */ 172 zorro_for_each_dev(z) { 173 if (z->rom.er_Type & ERTF_MEMLIST) 174 mark_region(zorro_resource_start(z), 175 zorro_resource_end(z)+1, 1); 176 } 177 178 /* Unmark all used Zorro II memory */ 179 for (i = 0; i < m68k_num_memory; i++) 180 if (m68k_memory[i].addr < 16*1024*1024) 181 mark_region(m68k_memory[i].addr, 182 m68k_memory[i].addr+m68k_memory[i].size, 183 0); 184 185 return 0; 186} 187 188static struct platform_driver amiga_zorro_driver = { 189 .driver = { 190 .name = "amiga-zorro", 191 .owner = THIS_MODULE, 192 }, 193}; 194 195static int __init amiga_zorro_init(void) 196{ 197 return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); 198} 199 200module_init(amiga_zorro_init); 201 202MODULE_LICENSE("GPL"); 203