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