Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * arch/ppc/syslib/ppc_sys.c | |
3 | * | |
4 | * PPC System library functions | |
5 | * | |
4c8d3d99 | 6 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
1da177e4 LT |
7 | * |
8 | * Copyright 2005 Freescale Semiconductor Inc. | |
88adfe70 | 9 | * Copyright 2005 MontaVista, Inc. by Vitaly Bordug <vbordug@ru.mvista.com> |
1da177e4 LT |
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 | ||
8c65b4a6 | 17 | #include <linux/string.h> |
1da177e4 LT |
18 | #include <asm/ppc_sys.h> |
19 | ||
20 | int (*ppc_sys_device_fixup) (struct platform_device * pdev); | |
21 | ||
22 | static int ppc_sys_inited; | |
23 | ||
24 | void __init identify_ppc_sys_by_id(u32 id) | |
25 | { | |
26 | unsigned int i = 0; | |
27 | while (1) { | |
28 | if ((ppc_sys_specs[i].mask & id) == ppc_sys_specs[i].value) | |
29 | break; | |
30 | i++; | |
31 | } | |
32 | ||
33 | cur_ppc_sys_spec = &ppc_sys_specs[i]; | |
34 | ||
35 | return; | |
36 | } | |
37 | ||
38 | void __init identify_ppc_sys_by_name(char *name) | |
39 | { | |
88adfe70 KG |
40 | unsigned int i = 0; |
41 | while (ppc_sys_specs[i].ppc_sys_name[0]) | |
42 | { | |
43 | if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name)) | |
44 | break; | |
45 | i++; | |
46 | } | |
47 | cur_ppc_sys_spec = &ppc_sys_specs[i]; | |
1da177e4 LT |
48 | return; |
49 | } | |
50 | ||
88adfe70 KG |
51 | static int __init count_sys_specs(void) |
52 | { | |
53 | int i = 0; | |
54 | while (ppc_sys_specs[i].ppc_sys_name[0]) | |
55 | i++; | |
56 | return i; | |
57 | } | |
58 | ||
59 | static int __init find_chip_by_name_and_id(char *name, u32 id) | |
60 | { | |
61 | int ret = -1; | |
62 | unsigned int i = 0; | |
63 | unsigned int j = 0; | |
64 | unsigned int dups = 0; | |
65 | ||
66 | unsigned char matched[count_sys_specs()]; | |
67 | ||
68 | while (ppc_sys_specs[i].ppc_sys_name[0]) { | |
69 | if (!strcmp(ppc_sys_specs[i].ppc_sys_name, name)) | |
70 | matched[j++] = i; | |
71 | i++; | |
72 | } | |
1461b4ea VB |
73 | |
74 | ret = i; | |
75 | ||
88adfe70 KG |
76 | if (j != 0) { |
77 | for (i = 0; i < j; i++) { | |
78 | if ((ppc_sys_specs[matched[i]].mask & id) == | |
79 | ppc_sys_specs[matched[i]].value) { | |
80 | ret = matched[i]; | |
81 | dups++; | |
82 | } | |
83 | } | |
84 | ret = (dups == 1) ? ret : (-1 * dups); | |
85 | } | |
86 | return ret; | |
87 | } | |
88 | ||
89 | void __init identify_ppc_sys_by_name_and_id(char *name, u32 id) | |
90 | { | |
91 | int i = find_chip_by_name_and_id(name, id); | |
92 | BUG_ON(i < 0); | |
93 | cur_ppc_sys_spec = &ppc_sys_specs[i]; | |
94 | } | |
95 | ||
1da177e4 LT |
96 | /* Update all memory resources by paddr, call before platform_device_register */ |
97 | void __init | |
98 | ppc_sys_fixup_mem_resource(struct platform_device *pdev, phys_addr_t paddr) | |
99 | { | |
100 | int i; | |
101 | for (i = 0; i < pdev->num_resources; i++) { | |
102 | struct resource *r = &pdev->resource[i]; | |
103 | if ((r->flags & IORESOURCE_MEM) == IORESOURCE_MEM) { | |
104 | r->start += paddr; | |
105 | r->end += paddr; | |
106 | } | |
107 | } | |
108 | } | |
109 | ||
110 | /* Get platform_data pointer out of platform device, call before platform_device_register */ | |
111 | void *__init ppc_sys_get_pdata(enum ppc_sys_devices dev) | |
112 | { | |
113 | return ppc_sys_platform_devices[dev].dev.platform_data; | |
114 | } | |
115 | ||
116 | void ppc_sys_device_remove(enum ppc_sys_devices dev) | |
117 | { | |
118 | unsigned int i; | |
119 | ||
120 | if (ppc_sys_inited) { | |
121 | platform_device_unregister(&ppc_sys_platform_devices[dev]); | |
122 | } else { | |
123 | if (cur_ppc_sys_spec == NULL) | |
124 | return; | |
125 | for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) | |
126 | if (cur_ppc_sys_spec->device_list[i] == dev) | |
127 | cur_ppc_sys_spec->device_list[i] = -1; | |
128 | } | |
129 | } | |
130 | ||
131 | static int __init ppc_sys_init(void) | |
132 | { | |
133 | unsigned int i, dev_id, ret = 0; | |
134 | ||
135 | BUG_ON(cur_ppc_sys_spec == NULL); | |
136 | ||
137 | for (i = 0; i < cur_ppc_sys_spec->num_devices; i++) { | |
138 | dev_id = cur_ppc_sys_spec->device_list[i]; | |
139 | if (dev_id != -1) { | |
140 | if (ppc_sys_device_fixup != NULL) | |
141 | ppc_sys_device_fixup(&ppc_sys_platform_devices | |
142 | [dev_id]); | |
143 | if (platform_device_register | |
144 | (&ppc_sys_platform_devices[dev_id])) { | |
145 | ret = 1; | |
146 | printk(KERN_ERR | |
147 | "unable to register device %d\n", | |
148 | dev_id); | |
149 | } | |
150 | } | |
151 | } | |
152 | ||
153 | ppc_sys_inited = 1; | |
154 | return ret; | |
155 | } | |
156 | ||
157 | subsys_initcall(ppc_sys_init); |