10Sduke/* $NetBSD: apple_smc_acpi.c,v 1.5 2021/01/29 15:49:55 thorpej Exp $ */ 23447Skvn 30Sduke/* 40Sduke * Apple System Management Controller: ACPI Attachment 50Sduke */ 60Sduke 70Sduke/*- 80Sduke * Copyright (c) 2013 The NetBSD Foundation, Inc. 90Sduke * All rights reserved. 100Sduke * 110Sduke * This code is derived from software contributed to The NetBSD Foundation 120Sduke * by Taylor R. Campbell. 130Sduke * 140Sduke * Redistribution and use in source and binary forms, with or without 150Sduke * modification, are permitted provided that the following conditions 160Sduke * are met: 170Sduke * 1. Redistributions of source code must retain the above copyright 180Sduke * notice, this list of conditions and the following disclaimer. 191472Strims * 2. Redistributions in binary form must reproduce the above copyright 201472Strims * notice, this list of conditions and the following disclaimer in the 211472Strims * documentation and/or other materials provided with the distribution. 220Sduke * 230Sduke * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 240Sduke * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 251879Sstefank * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 261879Sstefank * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 271879Sstefank * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 281879Sstefank * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 291879Sstefank * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 301879Sstefank * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 311879Sstefank * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 320Sduke * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 330Sduke * POSSIBILITY OF SUCH DAMAGE. 340Sduke */ 350Sduke 360Sduke#include <sys/cdefs.h> 370Sduke__KERNEL_RCSID(0, "$NetBSD: apple_smc_acpi.c,v 1.5 2021/01/29 15:49:55 thorpej Exp $"); 380Sduke 390Sduke#include <sys/types.h> 400Sduke#include <sys/param.h> 410Sduke#include <sys/bus.h> 420Sduke#include <sys/module.h> 430Sduke 443447Skvn#include <dev/acpi/acpireg.h> 453447Skvn#include <dev/acpi/acpivar.h> 463447Skvn 470Sduke#include <dev/ic/apple_smcreg.h> 480Sduke#include <dev/ic/apple_smcvar.h> 490Sduke 5010006Sthartmann#define _COMPONENT ACPI_RESOURCE_COMPONENT 510SdukeACPI_MODULE_NAME ("apple_smc_acpi") 520Sduke 530Sdukestruct apple_smc_acpi_softc { 540Sduke struct apple_smc_tag sc_smc; 550Sduke}; 560Sduke 570Sdukestatic int apple_smc_acpi_match(device_t, cfdata_t, void *); 5810006Sthartmannstatic void apple_smc_acpi_attach(device_t, device_t, void *); 590Sdukestatic int apple_smc_acpi_detach(device_t, int); 600Sdukestatic int apple_smc_acpi_rescan(device_t, const char *, const int *); 610Sdukestatic void apple_smc_acpi_child_detached(device_t, device_t); 620Sduke 630SdukeCFATTACH_DECL2_NEW(apple_smc_acpi, sizeof(struct apple_smc_acpi_softc), 640Sduke apple_smc_acpi_match, 650Sduke apple_smc_acpi_attach, 660Sduke apple_smc_acpi_detach, 670Sduke NULL /* activate */, 680Sduke apple_smc_acpi_rescan, 690Sduke apple_smc_acpi_child_detached); 700Sduke 710Sdukestatic const struct device_compatible_entry compat_data[] = { 720Sduke { .compat = "APP0001" }, 730Sduke DEVICE_COMPAT_EOL 740Sduke}; 750Sduke 760Sdukestatic int 770Sdukeapple_smc_acpi_match(device_t parent, cfdata_t match, void *aux) 780Sduke{ 790Sduke struct acpi_attach_args *aa = aux; 800Sduke 810Sduke return acpi_compatible_match(aa, compat_data); 820Sduke} 830Sduke 840Sdukestatic void 850Sdukeapple_smc_acpi_attach(device_t parent, device_t self, void *aux) 860Sduke{ 870Sduke struct apple_smc_acpi_softc *sc = device_private(self); 880Sduke struct apple_smc_tag *smc = &sc->sc_smc; 890Sduke struct acpi_attach_args *aa = aux; 900Sduke struct acpi_resources res; 910Sduke struct acpi_io *io; 920Sduke int rv; 930Sduke 940Sduke smc->smc_dev = self; 950Sduke 960Sduke aprint_normal("\n"); 970Sduke aprint_naive("\n"); 980Sduke 990Sduke rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", 1000Sduke &res, &acpi_resource_parse_ops_default); 1010Sduke if (ACPI_FAILURE(rv)) { 1020Sduke aprint_error_dev(self, "couldn't parse SMC resources: %s\n", 1030Sduke AcpiFormatException(rv)); 1040Sduke goto out0; 1050Sduke } 1060Sduke 1070Sduke io = acpi_res_io(&res, 0); 1080Sduke if (io == NULL) { 1090Sduke aprint_error_dev(self, "no I/O resource\n"); 1100Sduke goto out1; 1110Sduke } 1120Sduke 1130Sduke if (io->ar_length < APPLE_SMC_REGSIZE) { 1140Sduke aprint_error_dev(self, "I/O resources too small: %"PRId32"\n", 1150Sduke io->ar_length); 1160Sduke goto out1; 1170Sduke } 1180Sduke 1190Sduke if (bus_space_map(aa->aa_iot, io->ar_base, io->ar_length, 0, 1200Sduke &smc->smc_bsh) != 0) { 1210Sduke aprint_error_dev(self, "unable to map I/O registers\n"); 1220Sduke goto out1; 1230Sduke } 1240Sduke 1250Sduke smc->smc_bst = aa->aa_iot; 1260Sduke smc->smc_size = io->ar_length; 1270Sduke 1280Sduke apple_smc_attach(smc); 1290Sduke 1300Sdukeout1: acpi_resource_cleanup(&res); 1310Sdukeout0: return; 1320Sduke} 1330Sduke 1340Sdukestatic int 1350Sdukeapple_smc_acpi_detach(device_t self, int flags) 1360Sduke{ 1370Sduke struct apple_smc_acpi_softc *sc = device_private(self); 1380Sduke struct apple_smc_tag *smc = &sc->sc_smc; 1390Sduke int error; 1400Sduke 1410Sduke if (smc->smc_size != 0) { 1420Sduke error = apple_smc_detach(smc, flags); 143145Srasbold if (error) 144145Srasbold return error; 145145Srasbold 146145Srasbold bus_space_unmap(smc->smc_bst, smc->smc_bsh, smc->smc_size); 147145Srasbold smc->smc_size = 0; 148145Srasbold } 14910006Sthartmann 150145Srasbold return 0; 151145Srasbold} 152145Srasbold 1530Sdukestatic int 1540Sdukeapple_smc_acpi_rescan(device_t self, const char *ifattr, const int *locs) 1550Sduke{ 1560Sduke struct apple_smc_acpi_softc *const sc = device_private(self); 1570Sduke 1580Sduke return apple_smc_rescan(&sc->sc_smc, ifattr, locs); 1590Sduke} 1600Sduke 1610Sdukestatic void 16210006Sthartmannapple_smc_acpi_child_detached(device_t self, device_t child) 1630Sduke{ 1640Sduke struct apple_smc_acpi_softc *const sc = device_private(self); 1650Sduke 1660Sduke apple_smc_child_detached(&sc->sc_smc, child); 1670Sduke} 1680Sduke 1690SdukeMODULE(MODULE_CLASS_DRIVER, apple_smc_acpi, "apple_smc"); 1700Sduke 1710Sduke#ifdef _MODULE 1720Sduke#include "ioconf.c" 1730Sduke#endif 1740Sduke 1750Sdukestatic int 1760Sdukeapple_smc_acpi_modcmd(modcmd_t cmd, void *arg __unused) 1770Sduke{ 1780Sduke#ifdef _MODULE 17910006Sthartmann int error; 1800Sduke#endif 1810Sduke 1820Sduke switch (cmd) { 1830Sduke case MODULE_CMD_INIT: 1840Sduke#ifdef _MODULE 1850Sduke error = config_init_component(cfdriver_ioconf_apple_smc_acpi, 1860Sduke cfattach_ioconf_apple_smc_acpi, 1870Sduke cfdata_ioconf_apple_smc_acpi); 1880Sduke if (error) 1890Sduke return error; 1900Sduke#endif 1910Sduke return 0; 1920Sduke 1930Sduke case MODULE_CMD_FINI: 19410006Sthartmann#ifdef _MODULE 1950Sduke error = config_fini_component(cfdriver_ioconf_apple_smc_acpi, 19610006Sthartmann cfattach_ioconf_apple_smc_acpi, 1970Sduke cfdata_ioconf_apple_smc_acpi); 1980Sduke if (error) 1990Sduke return error; 2000Sduke#endif 2010Sduke return 0; 2020Sduke 2030Sduke default: 2040Sduke return ENOTTY; 2050Sduke } 2060Sduke} 20710006Sthartmann