2005-04-17 02:20:36 +04:00
/*
* 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>
2005-10-31 02:03:48 +03:00
# include <linux/string.h>
2009-04-05 14:40:41 +04:00
# include <linux/platform_device.h>
# include <linux/slab.h>
2005-10-31 02:03:48 +03:00
2013-10-04 11:38:53 +04:00
# include <asm/byteorder.h>
2005-04-17 02:20:36 +04:00
# include <asm/setup.h>
# include <asm/amigahw.h>
# include "zorro.h"
/*
* Zorro Expansion Devices
*/
2009-04-05 14:40:41 +04:00
unsigned int zorro_num_autocon ;
2013-06-29 12:40:20 +04:00
struct zorro_dev_init zorro_autocon_init [ ZORRO_NUM_AUTO ] __initdata ;
struct zorro_dev * zorro_autocon ;
2005-04-17 02:20:36 +04:00
/*
2009-04-05 14:40:41 +04:00
* Zorro bus
2005-04-17 02:20:36 +04:00
*/
2009-04-05 14:40:41 +04:00
struct zorro_bus {
struct device dev ;
2013-06-29 12:40:20 +04:00
struct zorro_dev devices [ 0 ] ;
2005-04-17 02:20:36 +04:00
} ;
/*
* Find Zorro Devices
*/
struct zorro_dev * zorro_find_device ( zorro_id id , struct zorro_dev * from )
{
2009-04-05 14:40:41 +04:00
struct zorro_dev * z ;
2005-04-17 02:20:36 +04:00
2009-04-05 14:40:41 +04:00
if ( ! zorro_num_autocon )
return NULL ;
2005-04-17 02:20:36 +04:00
2009-04-05 14:40:41 +04:00
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 ;
2005-04-17 02:20:36 +04:00
}
2009-04-05 14:40:41 +04:00
EXPORT_SYMBOL ( zorro_find_device ) ;
2005-04-17 02:20:36 +04:00
/*
* Bitmask indicating portions of available Zorro II RAM that are unused
* by the system . Every bit represents a 64 K chunk , for a maximum of 8 MB
* ( 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 ) ;
2009-04-05 14:40:41 +04:00
EXPORT_SYMBOL ( zorro_unused_z2ram ) ;
2005-04-17 02:20:36 +04:00
static void __init mark_region ( unsigned long start , unsigned long end ,
int flag )
{
if ( flag )
2009-04-05 14:40:41 +04:00
start + = Z2RAM_CHUNKMASK ;
2005-04-17 02:20:36 +04:00
else
2009-04-05 14:40:41 +04:00
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 ;
}
2005-04-17 02:20:36 +04:00
}
2009-04-05 14:40:41 +04:00
static struct resource __init * zorro_find_parent_resource (
struct platform_device * bridge , struct zorro_dev * z )
2005-04-17 02:20:36 +04:00
{
2009-04-05 14:40:41 +04:00
int i ;
2005-04-17 02:20:36 +04:00
2009-04-05 14:40:41 +04:00
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 ;
2005-04-17 02:20:36 +04:00
}
2009-04-05 14:40:41 +04:00
static int __init amiga_zorro_probe ( struct platform_device * pdev )
2005-04-17 02:20:36 +04:00
{
2009-04-05 14:40:41 +04:00
struct zorro_bus * bus ;
2013-06-29 12:40:20 +04:00
struct zorro_dev_init * zi ;
2009-04-05 14:40:41 +04:00
struct zorro_dev * z ;
struct resource * r ;
unsigned int i ;
int error ;
/* Initialize the Zorro bus */
2013-06-29 12:40:20 +04:00
bus = kzalloc ( sizeof ( * bus ) +
zorro_num_autocon * sizeof ( bus - > devices [ 0 ] ) ,
GFP_KERNEL ) ;
2009-04-05 14:40:41 +04:00
if ( ! bus )
return - ENOMEM ;
2013-06-29 12:40:20 +04:00
zorro_autocon = bus - > devices ;
2009-04-05 14:40:41 +04:00
bus - > dev . parent = & pdev - > dev ;
2013-10-16 13:28:54 +04:00
dev_set_name ( & bus - > dev , zorro_bus_type . name ) ;
2009-04-05 14:40:41 +04:00
error = device_register ( & bus - > dev ) ;
2008-12-30 16:21:19 +03:00
if ( error ) {
2009-04-05 14:40:41 +04:00
pr_err ( " Zorro: Error registering zorro_bus \n " ) ;
2010-09-19 16:55:21 +04:00
put_device ( & bus - > dev ) ;
2009-04-05 14:40:41 +04:00
kfree ( bus ) ;
return error ;
2008-12-30 16:21:19 +03:00
}
2009-04-05 14:40:41 +04:00
platform_set_drvdata ( pdev , bus ) ;
pr_info ( " Zorro: Probing AutoConfig expansion devices: %u device%s \n " ,
zorro_num_autocon , zorro_num_autocon = = 1 ? " " : " s " ) ;
2011-09-22 23:47:38 +04:00
/* First identify all devices ... */
2009-04-05 14:40:41 +04:00
for ( i = 0 ; i < zorro_num_autocon ; i + + ) {
2013-06-29 12:40:20 +04:00
zi = & zorro_autocon_init [ i ] ;
2009-04-05 14:40:41 +04:00
z = & zorro_autocon [ i ] ;
2013-06-29 12:40:20 +04:00
z - > rom = zi - > rom ;
2013-10-04 11:38:53 +04:00
z - > id = ( be16_to_cpu ( z - > rom . er_Manufacturer ) < < 16 ) |
( z - > rom . er_Product < < 8 ) ;
2009-04-05 14:40:41 +04:00
if ( z - > id = = ZORRO_PROD_GVP_EPC_BASE ) {
/* GVP quirk */
2013-06-29 12:40:20 +04:00
unsigned long magic = zi - > boardaddr + 0x8000 ;
2009-04-05 14:40:41 +04:00
z - > id | = * ( u16 * ) ZTWO_VADDR ( magic ) & GVP_PRODMASK ;
}
2013-06-29 12:40:20 +04:00
z - > slotaddr = zi - > slotaddr ;
z - > slotsize = zi - > slotsize ;
2009-04-05 14:40:41 +04:00
sprintf ( z - > name , " Zorro device %08x " , z - > id ) ;
zorro_name_device ( z ) ;
2013-06-29 12:40:20 +04:00
z - > resource . start = zi - > boardaddr ;
z - > resource . end = zi - > boardaddr + zi - > boardsize - 1 ;
2009-04-05 14:40:41 +04:00
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 ) ;
z - > dev . parent = & bus - > dev ;
z - > dev . bus = & zorro_bus_type ;
2013-10-16 13:28:54 +04:00
z - > dev . id = i ;
2011-09-22 23:47:38 +04:00
}
/* ... then register them */
for ( i = 0 ; i < zorro_num_autocon ; i + + ) {
z = & zorro_autocon [ i ] ;
2009-04-05 14:40:41 +04:00
error = device_register ( & z - > dev ) ;
if ( error ) {
dev_err ( & bus - > dev , " Error registering device %s \n " ,
z - > name ) ;
2010-09-19 16:55:21 +04:00
put_device ( & z - > dev ) ;
2009-04-05 14:40:41 +04:00
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 ;
2005-04-17 02:20:36 +04:00
}
2009-04-05 14:40:41 +04:00
static struct platform_driver amiga_zorro_driver = {
. driver = {
. name = " amiga-zorro " ,
. owner = THIS_MODULE ,
} ,
} ;
2005-04-17 02:20:36 +04:00
2009-04-05 14:40:41 +04:00
static int __init amiga_zorro_init ( void )
{
return platform_driver_probe ( & amiga_zorro_driver , amiga_zorro_probe ) ;
}
module_init ( amiga_zorro_init ) ;
2005-04-17 02:20:36 +04:00
MODULE_LICENSE ( " GPL " ) ;