1/*
2 * Link physical devices with ACPI devices support
3 *
4 * Copyright (c) 2005 David Shaohua Li <shaohua.li@intel.com>
5 * Copyright (c) 2005 Intel Corp.
6 *
7 * This file is released under the GPLv2.
8 */
9#include <linux/init.h>
10#include <linux/list.h>
11#include <linux/device.h>
12#include <linux/rwsem.h>
13#include <linux/acpi.h>
14
15#define ACPI_GLUE_DEBUG	0
16#if ACPI_GLUE_DEBUG
17#define DBG(x...) printk(PREFIX x)
18#else
19#define DBG(x...)
20#endif
21static LIST_HEAD(bus_type_list);
22static DECLARE_RWSEM(bus_type_sem);
23
24int register_acpi_bus_type(struct acpi_bus_type *type)
25{
26	if (acpi_disabled)
27		return -ENODEV;
28	if (type && type->bus && type->find_device) {
29		down_write(&bus_type_sem);
30		list_add_tail(&type->list, &bus_type_list);
31		up_write(&bus_type_sem);
32		printk(KERN_INFO PREFIX "bus type %s registered\n",
33		       type->bus->name);
34		return 0;
35	}
36	return -ENODEV;
37}
38
39EXPORT_SYMBOL(register_acpi_bus_type);
40
41int unregister_acpi_bus_type(struct acpi_bus_type *type)
42{
43	if (acpi_disabled)
44		return 0;
45	if (type) {
46		down_write(&bus_type_sem);
47		list_del_init(&type->list);
48		up_write(&bus_type_sem);
49		printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
50		       type->bus->name);
51		return 0;
52	}
53	return -ENODEV;
54}
55
56EXPORT_SYMBOL(unregister_acpi_bus_type);
57
58static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
59{
60	struct acpi_bus_type *tmp, *ret = NULL;
61
62	down_read(&bus_type_sem);
63	list_for_each_entry(tmp, &bus_type_list, list) {
64		if (tmp->bus == type) {
65			ret = tmp;
66			break;
67		}
68	}
69	up_read(&bus_type_sem);
70	return ret;
71}
72
73static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle)
74{
75	struct acpi_bus_type *tmp;
76	int ret = -ENODEV;
77
78	down_read(&bus_type_sem);
79	list_for_each_entry(tmp, &bus_type_list, list) {
80		if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) {
81			ret = 0;
82			break;
83		}
84	}
85	up_read(&bus_type_sem);
86	return ret;
87}
88
89/* Get device's handler per its address under its parent */
90struct acpi_find_child {
91	acpi_handle handle;
92	acpi_integer address;
93};
94
95static acpi_status
96do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
97{
98	acpi_status status;
99	struct acpi_device_info *info;
100	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
101	struct acpi_find_child *find = context;
102
103	status = acpi_get_object_info(handle, &buffer);
104	if (ACPI_SUCCESS(status)) {
105		info = buffer.pointer;
106		if (info->address == find->address)
107			find->handle = handle;
108		kfree(buffer.pointer);
109	}
110	return AE_OK;
111}
112
113acpi_handle acpi_get_child(acpi_handle parent, acpi_integer address)
114{
115	struct acpi_find_child find = { NULL, address };
116
117	if (!parent)
118		return NULL;
119	acpi_walk_namespace(ACPI_TYPE_DEVICE, parent,
120			    1, do_acpi_find_child, &find, NULL);
121	return find.handle;
122}
123
124EXPORT_SYMBOL(acpi_get_child);
125
126/* Link ACPI devices with physical devices */
127static void acpi_glue_data_handler(acpi_handle handle,
128				   u32 function, void *context)
129{
130	/* we provide an empty handler */
131}
132
133/* Note: a success call will increase reference count by one */
134struct device *acpi_get_physical_device(acpi_handle handle)
135{
136	acpi_status status;
137	struct device *dev;
138
139	status = acpi_get_data(handle, acpi_glue_data_handler, (void **)&dev);
140	if (ACPI_SUCCESS(status))
141		return get_device(dev);
142	return NULL;
143}
144
145EXPORT_SYMBOL(acpi_get_physical_device);
146
147static int acpi_bind_one(struct device *dev, acpi_handle handle)
148{
149	acpi_status status;
150
151	if (dev->archdata.acpi_handle) {
152		printk(KERN_WARNING PREFIX
153		       "Drivers changed 'acpi_handle' for %s\n", dev->bus_id);
154		return -EINVAL;
155	}
156	get_device(dev);
157	status = acpi_attach_data(handle, acpi_glue_data_handler, dev);
158	if (ACPI_FAILURE(status)) {
159		put_device(dev);
160		return -EINVAL;
161	}
162	dev->archdata.acpi_handle = handle;
163
164	return 0;
165}
166
167static int acpi_unbind_one(struct device *dev)
168{
169	if (!dev->archdata.acpi_handle)
170		return 0;
171	if (dev == acpi_get_physical_device(dev->archdata.acpi_handle)) {
172		/* acpi_get_physical_device increase refcnt by one */
173		put_device(dev);
174		acpi_detach_data(dev->archdata.acpi_handle,
175				 acpi_glue_data_handler);
176		dev->archdata.acpi_handle = NULL;
177		/* acpi_bind_one increase refcnt by one */
178		put_device(dev);
179	} else {
180		printk(KERN_ERR PREFIX
181		       "Oops, 'acpi_handle' corrupt for %s\n", dev->bus_id);
182	}
183	return 0;
184}
185
186static int acpi_platform_notify(struct device *dev)
187{
188	struct acpi_bus_type *type;
189	acpi_handle handle;
190	int ret = -EINVAL;
191
192	if (!dev->bus || !dev->parent) {
193		/* bridge devices genernally haven't bus or parent */
194		ret = acpi_find_bridge_device(dev, &handle);
195		goto end;
196	}
197	type = acpi_get_bus_type(dev->bus);
198	if (!type) {
199		DBG("No ACPI bus support for %s\n", dev->bus_id);
200		ret = -EINVAL;
201		goto end;
202	}
203	if ((ret = type->find_device(dev, &handle)) != 0)
204		DBG("Can't get handler for %s\n", dev->bus_id);
205      end:
206	if (!ret)
207		acpi_bind_one(dev, handle);
208
209#if ACPI_GLUE_DEBUG
210	if (!ret) {
211		struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
212
213		acpi_get_name(dev->archdata.acpi_handle,
214			      ACPI_FULL_PATHNAME, &buffer);
215		DBG("Device %s -> %s\n", dev->bus_id, (char *)buffer.pointer);
216		kfree(buffer.pointer);
217	} else
218		DBG("Device %s -> No ACPI support\n", dev->bus_id);
219#endif
220
221	return ret;
222}
223
224static int acpi_platform_notify_remove(struct device *dev)
225{
226	acpi_unbind_one(dev);
227	return 0;
228}
229
230static int __init init_acpi_device_notify(void)
231{
232	if (acpi_disabled)
233		return 0;
234	if (platform_notify || platform_notify_remove) {
235		printk(KERN_ERR PREFIX "Can't use platform_notify\n");
236		return 0;
237	}
238	platform_notify = acpi_platform_notify;
239	platform_notify_remove = acpi_platform_notify_remove;
240	return 0;
241}
242
243arch_initcall(init_acpi_device_notify);
244
245
246#if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
247
248#ifdef CONFIG_PM
249static u32 rtc_handler(void *context)
250{
251	acpi_clear_event(ACPI_EVENT_RTC);
252	acpi_disable_event(ACPI_EVENT_RTC, 0);
253	return ACPI_INTERRUPT_HANDLED;
254}
255
256static inline void rtc_wake_setup(void)
257{
258	acpi_install_fixed_event_handler(ACPI_EVENT_RTC, rtc_handler, NULL);
259}
260
261static void rtc_wake_on(struct device *dev)
262{
263	acpi_clear_event(ACPI_EVENT_RTC);
264	acpi_enable_event(ACPI_EVENT_RTC, 0);
265}
266
267static void rtc_wake_off(struct device *dev)
268{
269	acpi_disable_event(ACPI_EVENT_RTC, 0);
270}
271#else
272#define rtc_wake_setup()	do{}while(0)
273#define rtc_wake_on		NULL
274#define rtc_wake_off		NULL
275#endif
276
277/* Every ACPI platform has a mc146818 compatible "cmos rtc".  Here we find
278 * its device node and pass extra config data.  This helps its driver use
279 * capabilities that the now-obsolete mc146818 didn't have, and informs it
280 * that this board's RTC is wakeup-capable (per ACPI spec).
281 */
282#include <linux/mc146818rtc.h>
283
284static struct cmos_rtc_board_info rtc_info;
285
286
287/* PNP devices are registered in a subsys_initcall();
288 * ACPI specifies the PNP IDs to use.
289 */
290#include <linux/pnp.h>
291
292static int __init pnp_match(struct device *dev, void *data)
293{
294	static const char *ids[] = { "PNP0b00", "PNP0b01", "PNP0b02", };
295	struct pnp_dev *pnp = to_pnp_dev(dev);
296	int i;
297
298	for (i = 0; i < ARRAY_SIZE(ids); i++) {
299		if (compare_pnp_id(pnp->id, ids[i]) != 0)
300			return 1;
301	}
302	return 0;
303}
304
305static struct device *__init get_rtc_dev(void)
306{
307	return bus_find_device(&pnp_bus_type, NULL, NULL, pnp_match);
308}
309
310static int __init acpi_rtc_init(void)
311{
312	struct device *dev = get_rtc_dev();
313
314	if (dev) {
315		rtc_wake_setup();
316		rtc_info.wake_on = rtc_wake_on;
317		rtc_info.wake_off = rtc_wake_off;
318
319		if (acpi_gbl_FADT.month_alarm && !acpi_gbl_FADT.day_alarm) {
320			DBG("bogus FADT month_alarm\n");
321			acpi_gbl_FADT.month_alarm = 0;
322		}
323
324		rtc_info.rtc_day_alarm = acpi_gbl_FADT.day_alarm;
325		rtc_info.rtc_mon_alarm = acpi_gbl_FADT.month_alarm;
326		rtc_info.rtc_century = acpi_gbl_FADT.century;
327
328		/* NOTE:  S4_RTC_WAKE is NOT currently useful to Linux */
329		if (acpi_gbl_FADT.flags & ACPI_FADT_S4_RTC_WAKE)
330			printk(PREFIX "RTC can wake from S4\n");
331
332
333		dev->platform_data = &rtc_info;
334
335		/* RTC always wakes from S1/S2/S3, and often S4/STD */
336		device_init_wakeup(dev, 1);
337
338		put_device(dev);
339	} else
340		DBG("RTC unavailable?\n");
341	return 0;
342}
343/* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */
344fs_initcall(acpi_rtc_init);
345
346#endif
347