hpet_acpi.c revision 1.9
11.9Sjruoho/* $NetBSD: hpet_acpi.c,v 1.9 2011/06/15 04:52:52 jruoho Exp $ */ 21.1Snjoly 31.1Snjoly/* 41.6Sjruoho * Copyright (c) 2006, 2011 Nicolas Joly 51.1Snjoly * All rights reserved. 61.1Snjoly * 71.1Snjoly * Redistribution and use in source and binary forms, with or without 81.1Snjoly * modification, are permitted provided that the following conditions 91.1Snjoly * are met: 101.1Snjoly * 1. Redistributions of source code must retain the above copyright 111.1Snjoly * notice, this list of conditions and the following disclaimer. 121.1Snjoly * 2. Redistributions in binary form must reproduce the above copyright 131.1Snjoly * notice, this list of conditions and the following disclaimer in the 141.1Snjoly * documentation and/or other materials provided with the distribution. 151.1Snjoly * 3. The name of the author may not be used to endorse or promote products 161.1Snjoly * derived from this software without specific prior written permission. 171.1Snjoly * 181.1Snjoly * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS 191.1Snjoly * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 201.1Snjoly * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 211.1Snjoly * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 221.1Snjoly * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 231.1Snjoly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 241.1Snjoly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 251.1Snjoly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 261.1Snjoly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 271.1Snjoly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 281.1Snjoly * POSSIBILITY OF SUCH DAMAGE. 291.1Snjoly */ 301.1Snjoly#include <sys/cdefs.h> 311.9Sjruoho__KERNEL_RCSID(0, "$NetBSD: hpet_acpi.c,v 1.9 2011/06/15 04:52:52 jruoho Exp $"); 321.1Snjoly 331.1Snjoly#include <sys/param.h> 341.5Sjruoho#include <sys/device.h> 351.5Sjruoho#include <sys/time.h> 361.5Sjruoho#include <sys/timetc.h> 371.1Snjoly 381.1Snjoly#include <dev/acpi/acpivar.h> 391.9Sjruoho 401.9Sjruoho#include <dev/ic/hpetreg.h> 411.1Snjoly#include <dev/ic/hpetvar.h> 421.1Snjoly 431.6Sjruoho#define _COMPONENT ACPI_RESOURCE_COMPONENT 441.6SjruohoACPI_MODULE_NAME ("acpi_hpet") 451.1Snjoly 461.6Sjruohostatic int hpet_acpi_dev_match(device_t, cfdata_t, void *); 471.6Sjruohostatic void hpet_acpi_dev_attach(device_t, device_t, void *); 481.6Sjruohostatic int hpet_acpi_tab_match(device_t, cfdata_t, void *); 491.6Sjruohostatic void hpet_acpi_tab_attach(device_t, device_t, void *); 501.7Sjruohostatic int hpet_acpi_detach(device_t, int); 511.1Snjoly 521.1Snjolystatic const char * const hpet_acpi_ids[] = { 531.1Snjoly "PNP0103", 541.6Sjruoho NULL 551.1Snjoly}; 561.1Snjoly 571.6SjruohoCFATTACH_DECL_NEW(hpet_acpi_tab, sizeof(struct hpet_softc), 581.7Sjruoho hpet_acpi_tab_match, hpet_acpi_tab_attach, hpet_acpi_detach, NULL); 591.6Sjruoho 601.6SjruohoCFATTACH_DECL_NEW(hpet_acpi_dev, sizeof(struct hpet_softc), 611.7Sjruoho hpet_acpi_dev_match, hpet_acpi_dev_attach, hpet_acpi_detach, NULL); 621.6Sjruoho 631.6Sjruohostatic int 641.6Sjruohohpet_acpi_tab_match(device_t parent, cfdata_t match, void *aux) 651.6Sjruoho{ 661.6Sjruoho ACPI_TABLE_HPET *hpet; 671.6Sjruoho ACPI_STATUS rv; 681.6Sjruoho 691.6Sjruoho rv = AcpiGetTable(ACPI_SIG_HPET, 1, (ACPI_TABLE_HEADER **)&hpet); 701.6Sjruoho 711.6Sjruoho if (ACPI_FAILURE(rv)) 721.6Sjruoho return 0; 731.6Sjruoho 741.6Sjruoho if (hpet->Address.Address == 0) 751.6Sjruoho return 0; 761.6Sjruoho 771.6Sjruoho if (hpet->Address.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) 781.6Sjruoho return 0; 791.6Sjruoho 801.6Sjruoho return 1; 811.6Sjruoho} 821.6Sjruoho 831.6Sjruohostatic void 841.6Sjruohohpet_acpi_tab_attach(device_t parent, device_t self, void *aux) 851.6Sjruoho{ 861.6Sjruoho struct hpet_softc *sc = device_private(self); 871.6Sjruoho struct acpi_attach_args *aa = aux; 881.6Sjruoho ACPI_TABLE_HPET *hpet; 891.6Sjruoho ACPI_STATUS rv; 901.6Sjruoho 911.7Sjruoho sc->sc_mapped = false; 921.7Sjruoho 931.6Sjruoho rv = AcpiGetTable(ACPI_SIG_HPET, 1, (ACPI_TABLE_HEADER **)&hpet); 941.6Sjruoho 951.6Sjruoho if (ACPI_FAILURE(rv)) 961.6Sjruoho return; 971.6Sjruoho 981.6Sjruoho sc->sc_memt = aa->aa_memt; 991.9Sjruoho sc->sc_mems = HPET_WINDOW_SIZE; 1001.6Sjruoho 1011.6Sjruoho if (hpet->Address.Address == 0xfed0000000000000UL) /* A quirk. */ 1021.6Sjruoho hpet->Address.Address >>= 32; 1031.6Sjruoho 1041.6Sjruoho if (bus_space_map(sc->sc_memt, hpet->Address.Address, 1051.7Sjruoho sc->sc_mems, 0, &sc->sc_memh) != 0) { 1061.6Sjruoho aprint_error(": failed to map mem space\n"); 1071.6Sjruoho return; 1081.6Sjruoho } 1091.6Sjruoho 1101.7Sjruoho sc->sc_mapped = true; 1111.7Sjruoho 1121.6Sjruoho aprint_naive("\n"); 1131.6Sjruoho aprint_normal(": mem 0x%"PRIx64"-0x%"PRIx64"\n", 1141.9Sjruoho hpet->Address.Address, hpet->Address.Address + sc->sc_mems); 1151.6Sjruoho 1161.6Sjruoho hpet_attach_subr(self); 1171.6Sjruoho} 1181.6Sjruoho 1191.1Snjolystatic int 1201.6Sjruohohpet_acpi_dev_match(device_t parent, cfdata_t match, void *aux) 1211.1Snjoly{ 1221.1Snjoly struct acpi_attach_args *aa = aux; 1231.1Snjoly 1241.1Snjoly if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 1251.1Snjoly return 0; 1261.1Snjoly 1271.1Snjoly return acpi_match_hid(aa->aa_node->ad_devinfo, hpet_acpi_ids); 1281.1Snjoly} 1291.1Snjoly 1301.1Snjolystatic void 1311.6Sjruohohpet_acpi_dev_attach(device_t parent, device_t self, void *aux) 1321.1Snjoly{ 1331.3Sxtraeme struct hpet_softc *sc = device_private(self); 1341.1Snjoly struct acpi_attach_args *aa = aux; 1351.1Snjoly struct acpi_resources res; 1361.1Snjoly struct acpi_mem *mem; 1371.1Snjoly ACPI_STATUS rv; 1381.1Snjoly 1391.7Sjruoho sc->sc_mapped = false; 1401.7Sjruoho 1411.3Sxtraeme rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", 1421.1Snjoly &res, &acpi_resource_parse_ops_default); 1431.6Sjruoho 1441.1Snjoly if (ACPI_FAILURE(rv)) 1451.1Snjoly return; 1461.1Snjoly 1471.1Snjoly mem = acpi_res_mem(&res, 0); 1481.6Sjruoho 1491.1Snjoly if (mem == NULL) { 1501.6Sjruoho aprint_error(": failed to find mem resource\n"); 1511.6Sjruoho goto out; 1521.6Sjruoho } 1531.6Sjruoho 1541.9Sjruoho if (mem->ar_length < HPET_WINDOW_SIZE) { 1551.6Sjruoho aprint_error(": invalid memory region size\n"); 1561.1Snjoly goto out; 1571.1Snjoly } 1581.1Snjoly 1591.1Snjoly sc->sc_memt = aa->aa_memt; 1601.7Sjruoho sc->sc_mems = mem->ar_length; 1611.6Sjruoho 1621.6Sjruoho if (bus_space_map(sc->sc_memt, mem->ar_base, 1631.7Sjruoho sc->sc_mems, 0, &sc->sc_memh) != 0) { 1641.6Sjruoho aprint_error(": failed to map mem space\n"); 1651.1Snjoly goto out; 1661.1Snjoly } 1671.1Snjoly 1681.7Sjruoho sc->sc_mapped = true; 1691.3Sxtraeme hpet_attach_subr(self); 1701.1Snjoly 1711.6Sjruohoout: 1721.1Snjoly acpi_resource_cleanup(&res); 1731.1Snjoly} 1741.7Sjruoho 1751.7Sjruohostatic int 1761.7Sjruohohpet_acpi_detach(device_t self, int flags) 1771.7Sjruoho{ 1781.7Sjruoho struct hpet_softc *sc = device_private(self); 1791.7Sjruoho int rv; 1801.7Sjruoho 1811.7Sjruoho if (sc->sc_mapped != true) 1821.7Sjruoho return 0; 1831.7Sjruoho 1841.7Sjruoho rv = hpet_detach(self, flags); 1851.8Sjruoho 1861.8Sjruoho if (rv != 0) 1871.8Sjruoho return rv; 1881.8Sjruoho 1891.7Sjruoho bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems); 1901.7Sjruoho 1911.8Sjruoho return 0; 1921.7Sjruoho} 193