OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [pci/] [pci-acpi.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * File:        pci-acpi.c
3
 * Purpose:     Provide PCI support in ACPI
4
 *
5
 * Copyright (C) 2005 David Shaohua Li <shaohua.li@intel.com>
6
 * Copyright (C) 2004 Tom Long Nguyen <tom.l.nguyen@intel.com>
7
 * Copyright (C) 2004 Intel Corp.
8
 */
9
 
10
#include <linux/delay.h>
11
#include <linux/init.h>
12
#include <linux/pci.h>
13
#include <linux/module.h>
14
#include <acpi/acpi.h>
15
#include <acpi/acnamesp.h>
16
#include <acpi/acresrc.h>
17
#include <acpi/acpi_bus.h>
18
 
19
#include <linux/pci-acpi.h>
20
#include "pci.h"
21
 
22
static u32 ctrlset_buf[3] = {0, 0, 0};
23
static u32 global_ctrlsets = 0;
24
static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
25
 
26
static acpi_status
27
acpi_query_osc (
28
        acpi_handle     handle,
29
        u32             level,
30
        void            *context,
31
        void            **retval )
32
{
33
        acpi_status             status;
34
        struct acpi_object_list input;
35
        union acpi_object       in_params[4];
36
        struct acpi_buffer      output = {ACPI_ALLOCATE_BUFFER, NULL};
37
        union acpi_object       *out_obj;
38
        u32                     osc_dw0;
39
        acpi_status *ret_status = (acpi_status *)retval;
40
 
41
 
42
        /* Setting up input parameters */
43
        input.count = 4;
44
        input.pointer = in_params;
45
        in_params[0].type                = ACPI_TYPE_BUFFER;
46
        in_params[0].buffer.length       = 16;
47
        in_params[0].buffer.pointer      = OSC_UUID;
48
        in_params[1].type               = ACPI_TYPE_INTEGER;
49
        in_params[1].integer.value      = 1;
50
        in_params[2].type               = ACPI_TYPE_INTEGER;
51
        in_params[2].integer.value      = 3;
52
        in_params[3].type               = ACPI_TYPE_BUFFER;
53
        in_params[3].buffer.length      = 12;
54
        in_params[3].buffer.pointer     = (u8 *)context;
55
 
56
        status = acpi_evaluate_object(handle, "_OSC", &input, &output);
57
        if (ACPI_FAILURE (status)) {
58
                *ret_status = status;
59
                return status;
60
        }
61
        out_obj = output.pointer;
62
 
63
        if (out_obj->type != ACPI_TYPE_BUFFER) {
64
                printk(KERN_DEBUG
65
                        "Evaluate _OSC returns wrong type\n");
66
                status = AE_TYPE;
67
                goto query_osc_out;
68
        }
69
        osc_dw0 = *((u32 *) out_obj->buffer.pointer);
70
        if (osc_dw0) {
71
                if (osc_dw0 & OSC_REQUEST_ERROR)
72
                        printk(KERN_DEBUG "_OSC request fails\n");
73
                if (osc_dw0 & OSC_INVALID_UUID_ERROR)
74
                        printk(KERN_DEBUG "_OSC invalid UUID\n");
75
                if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
76
                        printk(KERN_DEBUG "_OSC invalid revision\n");
77
                if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
78
                        /* Update Global Control Set */
79
                        global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8));
80
                        status = AE_OK;
81
                        goto query_osc_out;
82
                }
83
                status = AE_ERROR;
84
                goto query_osc_out;
85
        }
86
 
87
        /* Update Global Control Set */
88
        global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8));
89
        status = AE_OK;
90
 
91
query_osc_out:
92
        kfree(output.pointer);
93
        *ret_status = status;
94
        return status;
95
}
96
 
97
 
98
static acpi_status
99
acpi_run_osc (
100
        acpi_handle     handle,
101
        void            *context)
102
{
103
        acpi_status             status;
104
        struct acpi_object_list input;
105
        union acpi_object       in_params[4];
106
        struct acpi_buffer      output = {ACPI_ALLOCATE_BUFFER, NULL};
107
        union acpi_object       *out_obj;
108
        u32                     osc_dw0;
109
 
110
        /* Setting up input parameters */
111
        input.count = 4;
112
        input.pointer = in_params;
113
        in_params[0].type                = ACPI_TYPE_BUFFER;
114
        in_params[0].buffer.length       = 16;
115
        in_params[0].buffer.pointer      = OSC_UUID;
116
        in_params[1].type               = ACPI_TYPE_INTEGER;
117
        in_params[1].integer.value      = 1;
118
        in_params[2].type               = ACPI_TYPE_INTEGER;
119
        in_params[2].integer.value      = 3;
120
        in_params[3].type               = ACPI_TYPE_BUFFER;
121
        in_params[3].buffer.length      = 12;
122
        in_params[3].buffer.pointer     = (u8 *)context;
123
 
124
        status = acpi_evaluate_object(handle, "_OSC", &input, &output);
125
        if (ACPI_FAILURE (status))
126
                return status;
127
 
128
        out_obj = output.pointer;
129
        if (out_obj->type != ACPI_TYPE_BUFFER) {
130
                printk(KERN_DEBUG
131
                        "Evaluate _OSC returns wrong type\n");
132
                status = AE_TYPE;
133
                goto run_osc_out;
134
        }
135
        osc_dw0 = *((u32 *) out_obj->buffer.pointer);
136
        if (osc_dw0) {
137
                if (osc_dw0 & OSC_REQUEST_ERROR)
138
                        printk(KERN_DEBUG "_OSC request fails\n");
139
                if (osc_dw0 & OSC_INVALID_UUID_ERROR)
140
                        printk(KERN_DEBUG "_OSC invalid UUID\n");
141
                if (osc_dw0 & OSC_INVALID_REVISION_ERROR)
142
                        printk(KERN_DEBUG "_OSC invalid revision\n");
143
                if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) {
144
                        printk(KERN_DEBUG "_OSC FW not grant req. control\n");
145
                        status = AE_SUPPORT;
146
                        goto run_osc_out;
147
                }
148
                status = AE_ERROR;
149
                goto run_osc_out;
150
        }
151
        status = AE_OK;
152
 
153
run_osc_out:
154
        kfree(output.pointer);
155
        return status;
156
}
157
 
158
/**
159
 * pci_osc_support_set - register OS support to Firmware
160
 * @flags: OS support bits
161
 *
162
 * Update OS support fields and doing a _OSC Query to obtain an update
163
 * from Firmware on supported control bits.
164
 **/
165
acpi_status pci_osc_support_set(u32 flags)
166
{
167
        u32 temp;
168
        acpi_status retval;
169
 
170
        if (!(flags & OSC_SUPPORT_MASKS)) {
171
                return AE_TYPE;
172
        }
173
        ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS);
174
 
175
        /* do _OSC query for all possible controls */
176
        temp = ctrlset_buf[OSC_CONTROL_TYPE];
177
        ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
178
        ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS;
179
        acpi_get_devices ( PCI_ROOT_HID_STRING,
180
                        acpi_query_osc,
181
                        ctrlset_buf,
182
                        (void **) &retval );
183
        ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE;
184
        ctrlset_buf[OSC_CONTROL_TYPE] = temp;
185
        if (ACPI_FAILURE(retval)) {
186
                /* no osc support at all */
187
                ctrlset_buf[OSC_SUPPORT_TYPE] = 0;
188
        }
189
        return AE_OK;
190
}
191
EXPORT_SYMBOL(pci_osc_support_set);
192
 
193
/**
194
 * pci_osc_control_set - commit requested control to Firmware
195
 * @handle: acpi_handle for the target ACPI object
196
 * @flags: driver's requested control bits
197
 *
198
 * Attempt to take control from Firmware on requested control bits.
199
 **/
200
acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
201
{
202
        acpi_status     status;
203
        u32             ctrlset;
204
 
205
        ctrlset = (flags & OSC_CONTROL_MASKS);
206
        if (!ctrlset) {
207
                return AE_TYPE;
208
        }
209
        if (ctrlset_buf[OSC_SUPPORT_TYPE] &&
210
                ((global_ctrlsets & ctrlset) != ctrlset)) {
211
                return AE_SUPPORT;
212
        }
213
        ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
214
        status = acpi_run_osc(handle, ctrlset_buf);
215
        if (ACPI_FAILURE (status)) {
216
                ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
217
        }
218
 
219
        return status;
220
}
221
EXPORT_SYMBOL(pci_osc_control_set);
222
 
223
#ifdef CONFIG_ACPI_SLEEP
224
/*
225
 * _SxD returns the D-state with the highest power
226
 * (lowest D-state number) supported in the S-state "x".
227
 *
228
 * If the devices does not have a _PRW
229
 * (Power Resources for Wake) supporting system wakeup from "x"
230
 * then the OS is free to choose a lower power (higher number
231
 * D-state) than the return value from _SxD.
232
 *
233
 * But if _PRW is enabled at S-state "x", the OS
234
 * must not choose a power lower than _SxD --
235
 * unless the device has an _SxW method specifying
236
 * the lowest power (highest D-state number) the device
237
 * may enter while still able to wake the system.
238
 *
239
 * ie. depending on global OS policy:
240
 *
241
 * if (_PRW at S-state x)
242
 *      choose from highest power _SxD to lowest power _SxW
243
 * else // no _PRW at S-state x
244
 *      choose highest power _SxD or any lower power
245
 *
246
 * currently we simply return _SxD, if present.
247
 */
248
 
249
static pci_power_t acpi_pci_choose_state(struct pci_dev *pdev,
250
        pm_message_t state)
251
{
252
        int acpi_state;
253
 
254
        acpi_state = acpi_pm_device_sleep_state(&pdev->dev,
255
                device_may_wakeup(&pdev->dev), NULL);
256
        if (acpi_state < 0)
257
                return PCI_POWER_ERROR;
258
 
259
        switch (acpi_state) {
260
        case ACPI_STATE_D0:
261
                return PCI_D0;
262
        case ACPI_STATE_D1:
263
                return PCI_D1;
264
        case ACPI_STATE_D2:
265
                return PCI_D2;
266
        case ACPI_STATE_D3:
267
                return PCI_D3hot;
268
        }
269
        return PCI_POWER_ERROR;
270
}
271
#endif
272
 
273
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
274
{
275
        acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->dev);
276
        acpi_handle tmp;
277
        static int state_conv[] = {
278
                [0] = 0,
279
                [1] = 1,
280
                [2] = 2,
281
                [3] = 3,
282
                [4] = 3
283
        };
284
        int acpi_state = state_conv[(int __force) state];
285
 
286
        if (!handle)
287
                return -ENODEV;
288
        /* If the ACPI device has _EJ0, ignore the device */
289
        if (ACPI_SUCCESS(acpi_get_handle(handle, "_EJ0", &tmp)))
290
                return 0;
291
        return acpi_bus_set_power(handle, acpi_state);
292
}
293
 
294
 
295
/* ACPI bus type */
296
static int acpi_pci_find_device(struct device *dev, acpi_handle *handle)
297
{
298
        struct pci_dev * pci_dev;
299
        acpi_integer    addr;
300
 
301
        pci_dev = to_pci_dev(dev);
302
        /* Please ref to ACPI spec for the syntax of _ADR */
303
        addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
304
        *handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
305
        if (!*handle)
306
                return -ENODEV;
307
        return 0;
308
}
309
 
310
static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
311
{
312
        int num;
313
        unsigned int seg, bus;
314
 
315
        /*
316
         * The string should be the same as root bridge's name
317
         * Please look at 'pci_scan_bus_parented'
318
         */
319
        num = sscanf(dev->bus_id, "pci%04x:%02x", &seg, &bus);
320
        if (num != 2)
321
                return -ENODEV;
322
        *handle = acpi_get_pci_rootbridge_handle(seg, bus);
323
        if (!*handle)
324
                return -ENODEV;
325
        return 0;
326
}
327
 
328
static struct acpi_bus_type acpi_pci_bus = {
329
        .bus = &pci_bus_type,
330
        .find_device = acpi_pci_find_device,
331
        .find_bridge = acpi_pci_find_root_bridge,
332
};
333
 
334
static int __init acpi_pci_init(void)
335
{
336
        int ret;
337
 
338
        if (acpi_gbl_FADT.boot_flags & BAF_MSI_NOT_SUPPORTED) {
339
                printk(KERN_INFO"ACPI FADT declares the system doesn't support MSI, so disable it\n");
340
                pci_no_msi();
341
        }
342
        ret = register_acpi_bus_type(&acpi_pci_bus);
343
        if (ret)
344
                return 0;
345
#ifdef  CONFIG_ACPI_SLEEP
346
        platform_pci_choose_state = acpi_pci_choose_state;
347
#endif
348
        platform_pci_set_power_state = acpi_pci_set_power_state;
349
        return 0;
350
}
351
arch_initcall(acpi_pci_init);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.