This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / ppc / ocp / ocp-probe.c
1 /*
2  * FILE NAME: ocp-probe.c
3  *
4  * BRIEF MODULE DESCRIPTION:
5  * Device scanning & bus set routines
6  * Based on drivers/pci/probe, Copyright (c) 1997--1999 Martin Mares
7  *
8  * Maintained by: Armin <akuster@mvista.com>
9  *
10  *
11  *  This program is free software; you can redistribute  it and/or modify it
12  *  under  the terms of  the GNU General  Public License as published by the
13  *  Free Software Foundation;  either version 2 of the  License, or (at your
14  *  option) any later version.
15  *
16  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
17  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
18  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
19  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
20  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
22  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
24  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  *  You should have received a copy of the  GNU General Public License along
28  *  with this program; if not, write  to the Free Software Foundation, Inc.,
29  *  675 Mass Ave, Cambridge, MA 02139, USA.
30  */
31
32 #include <linux/init.h>
33 #include <linux/slab.h>
34 #include <linux/module.h>
35 #include <linux/device.h>
36 #include <asm/ocp.h>
37
38 LIST_HEAD(ocp_devices);
39 struct device *ocp_bus;
40
41 static struct ocp_device * __devinit
42 ocp_setup_dev(struct ocp_def *odef, unsigned int index)
43 {
44         struct ocp_device *dev;
45
46         dev = kmalloc(sizeof(*dev), GFP_KERNEL);
47         if (!dev)
48                 return NULL;
49         memset(dev, 0, sizeof(*dev));
50
51         dev->vendor = odef->vendor;
52         dev->device = odef->device;
53         dev->num = ocp_get_num(dev->device);
54         dev->paddr = odef->paddr;
55         dev->irq = odef->irq;
56         dev->pm = odef->pm;
57         dev->current_state = 4;
58
59         sprintf(dev->name, "OCP device %04x:%04x", dev->vendor, dev->device);
60
61         DBG("%s %s 0x%lx irq:%d pm:0x%lx \n", dev->slot_name, dev->name,
62             (unsigned long) dev->paddr, dev->irq, dev->pm);
63
64         /* now put in global tree */
65         sprintf(dev->dev.bus_id, "%d", index);
66         dev->dev.parent = ocp_bus;
67         dev->dev.bus = &ocp_bus_type;
68         device_register(&dev->dev);
69
70         return dev;
71 }
72
73 static struct device * __devinit ocp_alloc_primary_bus(void)
74 {
75         struct device *b;
76
77         b = kmalloc(sizeof(struct device), GFP_KERNEL);
78         if (b == NULL)
79                 return NULL;
80         memset(b, 0, sizeof(struct device));
81         strcpy(b->bus_id, "ocp");
82
83         device_register(b);
84
85         return b;
86 }
87
88 void __devinit ocp_setup_devices(struct ocp_def *odef)
89 {
90         int index;
91         struct ocp_device *dev;
92
93         if (ocp_bus == NULL)
94                 ocp_bus = ocp_alloc_primary_bus();
95         for (index = 0; odef->vendor != OCP_VENDOR_INVALID; ++index, ++odef) {
96                 dev = ocp_setup_dev(odef, index);
97                 if (dev != NULL)
98                         list_add_tail(&dev->global_list, &ocp_devices);
99         }
100 }
101
102 extern struct ocp_def core_ocp[];
103
104 static int __init
105 ocparch_init(void)
106 {
107         ocp_setup_devices(core_ocp);
108         return 0;
109 }
110
111 subsys_initcall(ocparch_init);
112
113 EXPORT_SYMBOL(ocp_devices);