1139749Simp/*- 2102445Sjhb * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 3102445Sjhb * Copyright (c) 2000, Michael Smith <msmith@freebsd.org> 4102445Sjhb * Copyright (c) 2000, BSDi 5102445Sjhb * All rights reserved. 6102445Sjhb * 7102445Sjhb * Redistribution and use in source and binary forms, with or without 8102445Sjhb * modification, are permitted provided that the following conditions 9102445Sjhb * are met: 10102445Sjhb * 1. Redistributions of source code must retain the above copyright 11102445Sjhb * notice unmodified, this list of conditions, and the following 12102445Sjhb * disclaimer. 13102445Sjhb * 2. Redistributions in binary form must reproduce the above copyright 14102445Sjhb * notice, this list of conditions and the following disclaimer in the 15102445Sjhb * documentation and/or other materials provided with the distribution. 16102445Sjhb * 17102445Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18102445Sjhb * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19102445Sjhb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20102445Sjhb * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21102445Sjhb * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22102445Sjhb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23102445Sjhb * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24102445Sjhb * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25102445Sjhb * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26102445Sjhb * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27102445Sjhb */ 28102445Sjhb 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD$"); 31119418Sobrien 32102445Sjhb#include <sys/param.h> 33102445Sjhb#include <sys/systm.h> 34102445Sjhb#include <sys/bus.h> 35102445Sjhb#include <sys/kernel.h> 36102445Sjhb#include <sys/malloc.h> 37102445Sjhb#include <sys/module.h> 38102445Sjhb 39193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 40193530Sjkim#include <contrib/dev/acpica/include/accommon.h> 41193530Sjkim 42102445Sjhb#include <dev/acpica/acpivar.h> 43102445Sjhb 44102445Sjhb#include <sys/pciio.h> 45102445Sjhb#include <dev/pci/pcireg.h> 46102445Sjhb#include <dev/pci/pcivar.h> 47102445Sjhb#include <dev/pci/pci_private.h> 48102445Sjhb 49102445Sjhb#include "pcib_if.h" 50102445Sjhb#include "pci_if.h" 51102445Sjhb 52129829Snjl/* Hooks for the ACPI CA debugging infrastructure. */ 53102445Sjhb#define _COMPONENT ACPI_BUS 54102445SjhbACPI_MODULE_NAME("PCI") 55102445Sjhb 56102445Sjhbstruct acpi_pci_devinfo { 57129829Snjl struct pci_devinfo ap_dinfo; 58129829Snjl ACPI_HANDLE ap_handle; 59131341Snjl int ap_flags; 60102445Sjhb}; 61102445Sjhb 62133619SnjlACPI_SERIAL_DECL(pci_powerstate, "ACPI PCI power methods"); 63133619Snjl 64138200Snjl/* Be sure that ACPI and PCI power states are equivalent. */ 65138200SnjlCTASSERT(ACPI_STATE_D0 == PCI_POWERSTATE_D0); 66138200SnjlCTASSERT(ACPI_STATE_D1 == PCI_POWERSTATE_D1); 67138200SnjlCTASSERT(ACPI_STATE_D2 == PCI_POWERSTATE_D2); 68138200SnjlCTASSERT(ACPI_STATE_D3 == PCI_POWERSTATE_D3); 69138200Snjl 70130978Sjhbstatic int acpi_pci_attach(device_t dev); 71130978Sjhbstatic int acpi_pci_child_location_str_method(device_t cbdev, 72130978Sjhb device_t child, char *buf, size_t buflen); 73102445Sjhbstatic int acpi_pci_probe(device_t dev); 74102445Sjhbstatic int acpi_pci_read_ivar(device_t dev, device_t child, int which, 75129829Snjl uintptr_t *result); 76131341Snjlstatic int acpi_pci_write_ivar(device_t dev, device_t child, int which, 77131341Snjl uintptr_t value); 78130978Sjhbstatic ACPI_STATUS acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, 79130978Sjhb void *context, void **status); 80102445Sjhbstatic int acpi_pci_set_powerstate_method(device_t dev, device_t child, 81129829Snjl int state); 82130978Sjhbstatic void acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child); 83102445Sjhb 84102445Sjhbstatic device_method_t acpi_pci_methods[] = { 85102445Sjhb /* Device interface */ 86102445Sjhb DEVMETHOD(device_probe, acpi_pci_probe), 87102445Sjhb DEVMETHOD(device_attach, acpi_pci_attach), 88102445Sjhb 89102445Sjhb /* Bus interface */ 90102445Sjhb DEVMETHOD(bus_read_ivar, acpi_pci_read_ivar), 91131341Snjl DEVMETHOD(bus_write_ivar, acpi_pci_write_ivar), 92127680Stakawata DEVMETHOD(bus_child_location_str, acpi_pci_child_location_str_method), 93102445Sjhb 94102445Sjhb /* PCI interface */ 95128016Sjhb DEVMETHOD(pci_set_powerstate, acpi_pci_set_powerstate_method), 96102445Sjhb 97246128Ssbz DEVMETHOD_END 98102445Sjhb}; 99102445Sjhb 100154600Sjhbstatic devclass_t pci_devclass; 101102445Sjhb 102232403SjhbDEFINE_CLASS_1(pci, acpi_pci_driver, acpi_pci_methods, sizeof(struct pci_softc), 103232403Sjhb pci_driver); 104102445SjhbDRIVER_MODULE(acpi_pci, pcib, acpi_pci_driver, pci_devclass, 0, 0); 105128071SnjlMODULE_DEPEND(acpi_pci, acpi, 1, 1, 1); 106128071SnjlMODULE_DEPEND(acpi_pci, pci, 1, 1, 1); 107102445SjhbMODULE_VERSION(acpi_pci, 1); 108102445Sjhb 109102445Sjhbstatic int 110102445Sjhbacpi_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 111102445Sjhb{ 112102445Sjhb struct acpi_pci_devinfo *dinfo; 113102445Sjhb 114131341Snjl dinfo = device_get_ivars(child); 115102445Sjhb switch (which) { 116127681Snjl case ACPI_IVAR_HANDLE: 117102445Sjhb *result = (uintptr_t)dinfo->ap_handle; 118127681Snjl return (0); 119131341Snjl case ACPI_IVAR_FLAGS: 120131341Snjl *result = (uintptr_t)dinfo->ap_flags; 121131341Snjl return (0); 122102445Sjhb } 123127681Snjl return (pci_read_ivar(dev, child, which, result)); 124102445Sjhb} 125102445Sjhb 126127680Stakawatastatic int 127131341Snjlacpi_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 128131341Snjl{ 129131341Snjl struct acpi_pci_devinfo *dinfo; 130131341Snjl 131131341Snjl dinfo = device_get_ivars(child); 132131341Snjl switch (which) { 133131341Snjl case ACPI_IVAR_HANDLE: 134131341Snjl dinfo->ap_handle = (ACPI_HANDLE)value; 135131341Snjl return (0); 136131341Snjl case ACPI_IVAR_FLAGS: 137131341Snjl dinfo->ap_flags = (int)value; 138131341Snjl return (0); 139131341Snjl } 140131341Snjl return (pci_write_ivar(dev, child, which, value)); 141131341Snjl} 142131341Snjl 143131341Snjlstatic int 144127680Stakawataacpi_pci_child_location_str_method(device_t cbdev, device_t child, char *buf, 145127680Stakawata size_t buflen) 146127680Stakawata{ 147127680Stakawata struct acpi_pci_devinfo *dinfo = device_get_ivars(child); 148127681Snjl 149127680Stakawata pci_child_location_str_method(cbdev, child, buf, buflen); 150127680Stakawata 151127681Snjl if (dinfo->ap_handle) { 152132136Stakawata strlcat(buf, " handle=", buflen); 153127680Stakawata strlcat(buf, acpi_name(dinfo->ap_handle), buflen); 154127680Stakawata } 155127680Stakawata return (0); 156127680Stakawata} 157127680Stakawata 158102445Sjhb/* 159102445Sjhb * PCI power manangement 160102445Sjhb */ 161102445Sjhbstatic int 162102445Sjhbacpi_pci_set_powerstate_method(device_t dev, device_t child, int state) 163102445Sjhb{ 164128247Snjl ACPI_HANDLE h; 165128016Sjhb ACPI_STATUS status; 166138200Snjl int old_state, error; 167102445Sjhb 168133619Snjl error = 0; 169138200Snjl if (state < ACPI_STATE_D0 || state > ACPI_STATE_D3) 170128016Sjhb return (EINVAL); 171128016Sjhb 172128016Sjhb /* 173128016Sjhb * We set the state using PCI Power Management outside of setting 174128016Sjhb * the ACPI state. This means that when powering down a device, we 175128016Sjhb * first shut it down using PCI, and then using ACPI, which lets ACPI 176128016Sjhb * try to power down any Power Resources that are now no longer used. 177128016Sjhb * When powering up a device, we let ACPI set the state first so that 178128016Sjhb * it can enable any needed Power Resources before changing the PCI 179128016Sjhb * power state. 180128016Sjhb */ 181133619Snjl ACPI_SERIAL_BEGIN(pci_powerstate); 182128016Sjhb old_state = pci_get_powerstate(child); 183214110Sjkim if (old_state < state && pci_do_power_suspend) { 184128016Sjhb error = pci_set_powerstate_method(dev, child, state); 185128016Sjhb if (error) 186133619Snjl goto out; 187128016Sjhb } 188130210Snjl h = acpi_get_handle(child); 189138200Snjl status = acpi_pwr_switch_consumer(h, state); 190214072Sjkim if (ACPI_SUCCESS(status)) { 191214072Sjkim if (bootverbose) 192214072Sjkim device_printf(dev, "set ACPI power state D%d on %s\n", 193214072Sjkim state, acpi_name(h)); 194214072Sjkim } else if (status != AE_NOT_FOUND) 195130208Snjl device_printf(dev, 196214072Sjkim "failed to set ACPI power state D%d on %s: %s\n", 197138200Snjl state, acpi_name(h), AcpiFormatException(status)); 198214068Sjkim if (old_state > state && pci_do_power_resume) 199133619Snjl error = pci_set_powerstate_method(dev, child, state); 200133619Snjl 201133619Snjlout: 202133619Snjl ACPI_SERIAL_END(pci_powerstate); 203133619Snjl return (error); 204102445Sjhb} 205102445Sjhb 206130978Sjhbstatic void 207130978Sjhbacpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child) 208130978Sjhb{ 209130978Sjhb ACPI_STATUS status; 210130978Sjhb device_t child; 211130978Sjhb 212130978Sjhb /* 213223207Sjhb * Occasionally a PCI device may show up as an ACPI device 214223207Sjhb * with a _HID. (For example, the TabletPC TC1000 has a 215223207Sjhb * second PCI-ISA bridge that has a _HID for an 216223207Sjhb * acpi_sysresource device.) In that case, leave ACPI-CA's 217223207Sjhb * device data pointing at the ACPI-enumerated device. 218130978Sjhb */ 219130978Sjhb child = acpi_get_device(handle); 220130978Sjhb if (child != NULL) { 221130978Sjhb KASSERT(device_get_parent(child) == 222130978Sjhb devclass_get_device(devclass_find("acpi"), 0), 223130978Sjhb ("%s: child (%s)'s parent is not acpi0", __func__, 224130978Sjhb acpi_name(handle))); 225223207Sjhb return; 226130978Sjhb } 227130978Sjhb 228130978Sjhb /* 229130978Sjhb * Update ACPI-CA to use the PCI enumerated device_t for this handle. 230130978Sjhb */ 231131009Snjl status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child); 232130978Sjhb if (ACPI_FAILURE(status)) 233130978Sjhb printf("WARNING: Unable to attach object data to %s - %s\n", 234130978Sjhb acpi_name(handle), AcpiFormatException(status)); 235130978Sjhb} 236130978Sjhb 237102445Sjhbstatic ACPI_STATUS 238102445Sjhbacpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context, 239102445Sjhb void **status) 240102445Sjhb{ 241102445Sjhb struct acpi_pci_devinfo *dinfo; 242102445Sjhb device_t *devlist; 243102445Sjhb int devcount, i, func, slot; 244102445Sjhb UINT32 address; 245102445Sjhb 246102445Sjhb ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); 247102445Sjhb 248126560Snjl if (ACPI_FAILURE(acpi_GetInteger(handle, "_ADR", &address))) 249129829Snjl return_ACPI_STATUS (AE_OK); 250135574Sjhb slot = ACPI_ADR_PCI_SLOT(address); 251135574Sjhb func = ACPI_ADR_PCI_FUNC(address); 252102445Sjhb if (device_get_children((device_t)context, &devlist, &devcount) != 0) 253129829Snjl return_ACPI_STATUS (AE_OK); 254102445Sjhb for (i = 0; i < devcount; i++) { 255102445Sjhb dinfo = device_get_ivars(devlist[i]); 256102445Sjhb if (dinfo->ap_dinfo.cfg.func == func && 257102445Sjhb dinfo->ap_dinfo.cfg.slot == slot) { 258102445Sjhb dinfo->ap_handle = handle; 259130978Sjhb acpi_pci_update_device(handle, devlist[i]); 260131009Snjl break; 261102445Sjhb } 262102445Sjhb } 263102445Sjhb free(devlist, M_TEMP); 264129829Snjl return_ACPI_STATUS (AE_OK); 265102445Sjhb} 266102445Sjhb 267102445Sjhbstatic int 268102445Sjhbacpi_pci_probe(device_t dev) 269102445Sjhb{ 270102445Sjhb 271102445Sjhb if (acpi_get_handle(dev) == NULL) 272102445Sjhb return (ENXIO); 273129829Snjl device_set_desc(dev, "ACPI PCI bus"); 274102445Sjhb return (0); 275102445Sjhb} 276102445Sjhb 277102445Sjhbstatic int 278102445Sjhbacpi_pci_attach(device_t dev) 279102445Sjhb{ 280232403Sjhb int busno, domain, error; 281102445Sjhb 282232403Sjhb error = pci_attach_common(dev); 283232403Sjhb if (error) 284232403Sjhb return (error); 285232403Sjhb 286102445Sjhb /* 287102445Sjhb * Since there can be multiple independantly numbered PCI 288158457Sjhb * busses on systems with multiple PCI domains, we can't use 289158457Sjhb * the unit number to decide which bus we are probing. We ask 290172394Smarius * the parent pcib what our domain and bus numbers are. 291102445Sjhb */ 292172394Smarius domain = pcib_get_domain(dev); 293102445Sjhb busno = pcib_get_bus(dev); 294102445Sjhb 295102445Sjhb /* 296102445Sjhb * First, PCI devices are added as in the normal PCI bus driver. 297102445Sjhb * Afterwards, the ACPI namespace under the bridge driver is 298102445Sjhb * walked to save ACPI handles to all the devices that appear in 299102445Sjhb * the ACPI namespace as immediate descendants of the bridge. 300102445Sjhb * 301102445Sjhb * XXX: Sometimes PCI devices show up in the ACPI namespace that 302102445Sjhb * pci_add_children() doesn't find. We currently just ignore 303102445Sjhb * these devices. 304102445Sjhb */ 305172394Smarius pci_add_children(dev, domain, busno, sizeof(struct acpi_pci_devinfo)); 306129829Snjl AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, 307199337Sjkim acpi_pci_save_handle, NULL, dev, NULL); 308102445Sjhb 309102445Sjhb return (bus_generic_attach(dev)); 310102445Sjhb} 311