Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Oct 2018 04:52:37 +0000 (UTC)
From:      Oleksandr Tymoshenko <gonzo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r339523 - in head/sys: conf dev/amdgpio modules modules/amdgpio
Message-ID:  <201810210452.w9L4qbTc067553@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gonzo
Date: Sun Oct 21 04:52:37 2018
New Revision: 339523
URL: https://svnweb.freebsd.org/changeset/base/339523

Log:
  Add amdgpio, driver for GPIO controller on AMD-based x86_64 platforms
  
  Submitted by:	Rajesh Kumar <rajbsd@gmail.com>
  Differential Revision:	https://reviews.freebsd.org/D16865

Added:
  head/sys/dev/amdgpio/
  head/sys/dev/amdgpio/amdgpio.c   (contents, props changed)
  head/sys/dev/amdgpio/amdgpio.h   (contents, props changed)
  head/sys/modules/amdgpio/
  head/sys/modules/amdgpio/Makefile   (contents, props changed)
Modified:
  head/sys/conf/files.amd64
  head/sys/modules/Makefile

Modified: head/sys/conf/files.amd64
==============================================================================
--- head/sys/conf/files.amd64	Sun Oct 21 02:39:13 2018	(r339522)
+++ head/sys/conf/files.amd64	Sun Oct 21 04:52:37 2018	(r339523)
@@ -208,6 +208,7 @@ dev/acpi_support/acpi_wmi_if.m	standard
 dev/agp/agp_amd64.c		optional	agp
 dev/agp/agp_i810.c		optional	agp
 dev/agp/agp_via.c		optional	agp
+dev/amdgpio/amdgpio.c		optional	amdgpio
 dev/amdsbwd/amdsbwd.c		optional	amdsbwd
 dev/amdsmn/amdsmn.c		optional	amdsmn | amdtemp
 dev/amdtemp/amdtemp.c		optional	amdtemp

Added: head/sys/dev/amdgpio/amdgpio.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/amdgpio/amdgpio.c	Sun Oct 21 04:52:37 2018	(r339523)
@@ -0,0 +1,468 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Advanced Micro Devices
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_acpi.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/gpio.h>
+#include <sys/interrupt.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+
+#include <contrib/dev/acpica/include/acpi.h>
+#include <contrib/dev/acpica/include/accommon.h>
+
+#include <dev/acpica/acpivar.h>
+#include <dev/gpio/gpiobusvar.h>
+
+#include "gpio_if.h"
+#include "amdgpio.h"
+
+static struct resource_spec amdgpio_spec[] = {
+	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
+	{ -1, 0, 0 }
+};
+
+static inline uint32_t
+amdgpio_read_4(struct amdgpio_softc *sc, bus_size_t off)
+{
+	return (bus_read_4(sc->sc_res[0], off));
+}
+
+static inline void
+amdgpio_write_4(struct amdgpio_softc *sc, bus_size_t off,
+		uint32_t val)
+{
+	bus_write_4(sc->sc_res[0], off, val);
+}
+
+static bool
+amdgpio_is_pin_output(struct amdgpio_softc *sc, uint32_t pin)
+{
+	uint32_t reg, val;
+	bool ret;
+
+	/* Get the current pin state */
+	AMDGPIO_LOCK(sc);
+
+	reg = AMDGPIO_PIN_REGISTER(pin);
+	val = amdgpio_read_4(sc, reg);
+
+	if (val & BIT(OUTPUT_ENABLE_OFF))
+		ret = true;
+	else
+		ret = false;
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (ret);
+}
+
+static device_t
+amdgpio_get_bus(device_t dev)
+{
+	struct amdgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	dprintf("busdev %p\n", sc->sc_busdev);
+	return (sc->sc_busdev);
+}
+
+static int
+amdgpio_pin_max(device_t dev, int *maxpin)
+{
+	struct amdgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	*maxpin = sc->sc_npins - 1;
+	dprintf("npins %d maxpin %d\n", sc->sc_npins, *maxpin);
+
+	return (0);
+}
+
+static bool
+amdgpio_valid_pin(struct amdgpio_softc *sc, int pin)
+{
+	dprintf("pin %d\n", pin);
+	if (sc->sc_res[0] == NULL)
+		return (false);
+
+	if ((sc->sc_gpio_pins[pin].gp_pin == pin) &&
+		(sc->sc_gpio_pins[pin].gp_caps != 0))
+		return (true);
+
+	return (false);
+}
+
+static int
+amdgpio_pin_getname(device_t dev, uint32_t pin, char *name)
+{
+	struct amdgpio_softc *sc;
+
+	dprintf("pin %d\n", pin);
+	sc = device_get_softc(dev);
+
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	/* Set a very simple name */
+	snprintf(name, GPIOMAXNAME, "%s", sc->sc_gpio_pins[pin].gp_name);
+	name[GPIOMAXNAME - 1] = '\0';
+
+	dprintf("pin %d name %s\n", pin, name);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_getcaps(device_t dev, uint32_t pin, uint32_t *caps)
+{
+	struct amdgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+	dprintf("pin %d\n", pin);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	*caps = sc->sc_gpio_pins[pin].gp_caps;
+
+	dprintf("pin %d caps 0x%x\n", pin, *caps);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags)
+{
+	struct amdgpio_softc *sc;
+
+	sc = device_get_softc(dev);
+
+
+	dprintf("pin %d\n", pin);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	AMDGPIO_LOCK(sc);
+
+	*flags = sc->sc_gpio_pins[pin].gp_flags;
+
+	dprintf("pin %d flags 0x%x\n", pin, *flags);
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_setflags(device_t dev, uint32_t pin, uint32_t flags)
+{
+	struct amdgpio_softc *sc;
+	uint32_t reg, val, allowed;
+
+	sc = device_get_softc(dev);
+
+	dprintf("pin %d flags 0x%x\n", pin, flags);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	allowed = GPIO_PIN_INPUT | GPIO_PIN_OUTPUT;
+
+	/*
+	 * Only directtion flag allowed
+	 */
+	if (flags & ~allowed)
+		return (EINVAL);
+
+	/*
+	 * Not both directions simultaneously
+	 */
+	if ((flags & allowed) == allowed)
+		return (EINVAL);
+
+	/* Set the GPIO mode and state */
+	AMDGPIO_LOCK(sc);
+
+	reg = AMDGPIO_PIN_REGISTER(pin);
+	val = amdgpio_read_4(sc, reg);
+
+	if (flags & GPIO_PIN_INPUT) {
+		val &= ~BIT(OUTPUT_ENABLE_OFF);
+		sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_INPUT;
+	} else {
+		val |= BIT(OUTPUT_ENABLE_OFF);
+		sc->sc_gpio_pins[pin].gp_flags = GPIO_PIN_OUTPUT;
+	}
+
+	amdgpio_write_4(sc, reg, val);
+
+	dprintf("pin %d flags 0x%x val 0x%x gp_flags 0x%x\n",
+		pin, flags, val, sc->sc_gpio_pins[pin].gp_flags);
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_get(device_t dev, uint32_t pin, unsigned int *value)
+{
+	struct amdgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+
+	dprintf("pin %d\n", pin);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	*value = 0;
+
+	AMDGPIO_LOCK(sc);
+
+	reg = AMDGPIO_PIN_REGISTER(pin);
+	val = amdgpio_read_4(sc, reg);
+
+	if (val & BIT(OUTPUT_VALUE_OFF))
+		*value = GPIO_PIN_HIGH;
+	else
+		*value = GPIO_PIN_LOW;
+
+	dprintf("pin %d value 0x%x\n", pin, *value);
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_set(device_t dev, uint32_t pin, unsigned int value)
+{
+	struct amdgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+
+	dprintf("pin %d value 0x%x\n", pin, value);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	if (!amdgpio_is_pin_output(sc, pin))
+		return (EINVAL);
+
+	AMDGPIO_LOCK(sc);
+
+	reg = AMDGPIO_PIN_REGISTER(pin);
+	val = amdgpio_read_4(sc, reg);
+
+	if (value == GPIO_PIN_LOW)
+		val &= ~BIT(OUTPUT_VALUE_OFF);
+	else
+		val |= BIT(OUTPUT_VALUE_OFF);
+
+	amdgpio_write_4(sc, reg, val);
+
+	dprintf("pin %d value 0x%x val 0x%x\n", pin, value, val);
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+amdgpio_pin_toggle(device_t dev, uint32_t pin)
+{
+	struct amdgpio_softc *sc;
+	uint32_t reg, val;
+
+	sc = device_get_softc(dev);
+
+	dprintf("pin %d\n", pin);
+	if (!amdgpio_valid_pin(sc, pin))
+		return (EINVAL);
+
+	if (!amdgpio_is_pin_output(sc, pin))
+		return (EINVAL);
+
+	/* Toggle the pin */
+	AMDGPIO_LOCK(sc);
+
+	reg = AMDGPIO_PIN_REGISTER(pin);
+	val = amdgpio_read_4(sc, reg);
+	dprintf("pin %d value before 0x%x\n", pin, val);
+	val = val ^ BIT(OUTPUT_VALUE_OFF);
+	dprintf("pin %d value after 0x%x\n", pin, val);
+	amdgpio_write_4(sc, reg, val);
+
+	AMDGPIO_UNLOCK(sc);
+
+	return (0);
+}
+
+static int
+amdgpio_probe(device_t dev)
+{
+	static char *gpio_ids[] = { "AMD0030", "AMDI0030", NULL };
+
+	if (acpi_disabled("gpio") ||
+		ACPI_ID_PROBE(device_get_parent(dev), dev, gpio_ids) == NULL)
+	return (ENXIO);
+
+	device_set_desc(dev, "AMD GPIO Controller");
+	return (0);
+}
+
+static int
+amdgpio_attach(device_t dev)
+{
+	struct amdgpio_softc *sc;
+	int i, pin, bank;
+
+	sc = device_get_softc(dev);
+	sc->sc_dev = dev;
+	sc->sc_handle = acpi_get_handle(dev);
+
+	AMDGPIO_LOCK_INIT(sc);
+
+	sc->sc_nbanks = AMD_GPIO_NUM_PIN_BANK;
+	sc->sc_npins = AMD_GPIO_PINS_MAX;
+	sc->sc_bank_prefix = AMD_GPIO_PREFIX;
+	sc->sc_pin_info = kernzp_pins;
+	sc->sc_ngroups = nitems(kernzp_groups);
+	sc->sc_groups = kernzp_groups;
+
+	if (bus_alloc_resources(dev, amdgpio_spec, sc->sc_res)) {
+		device_printf(dev, "could not allocate resources\n");
+		goto err_rsrc;
+	}
+
+	sc->sc_bst = rman_get_bustag(sc->sc_res[0]);
+	sc->sc_bsh = rman_get_bushandle(sc->sc_res[0]);
+
+	/* Initialize all possible pins to be Invalid */
+	for (i = 0; i < AMD_GPIO_PINS_MAX ; i++) {
+		snprintf(sc->sc_gpio_pins[i].gp_name, GPIOMAXNAME,
+			"Unexposed PIN %d\n", i);
+		sc->sc_gpio_pins[i].gp_pin = -1;
+		sc->sc_gpio_pins[i].gp_caps = 0;
+		sc->sc_gpio_pins[i].gp_flags = 0;
+	}
+
+	/* Initialize only driver exposed pins with appropriate capabilities */
+	for (i = 0; i < AMD_GPIO_PINS_EXPOSED ; i++) {
+		pin = kernzp_pins[i].pin_num;
+		bank = pin/AMD_GPIO_PINS_PER_BANK;
+		snprintf(sc->sc_gpio_pins[pin].gp_name, GPIOMAXNAME, "%s%d_%s\n",
+			AMD_GPIO_PREFIX, bank, kernzp_pins[i].pin_name);
+		sc->sc_gpio_pins[pin].gp_pin = pin;
+		sc->sc_gpio_pins[pin].gp_caps = AMDGPIO_DEFAULT_CAPS;
+		sc->sc_gpio_pins[pin].gp_flags = (amdgpio_is_pin_output(sc, pin)?
+						GPIO_PIN_OUTPUT : GPIO_PIN_INPUT);
+	}
+
+	sc->sc_busdev = gpiobus_attach_bus(dev);
+	if (sc->sc_busdev == NULL) {
+		device_printf(dev, "could not attach gpiobus\n");
+		goto err_bus;
+	}
+
+	return (0);
+
+err_bus:
+	bus_release_resources(dev, amdgpio_spec, sc->sc_res);
+
+err_rsrc:
+	AMDGPIO_LOCK_DESTROY(sc);
+
+	return (ENXIO);
+}
+
+
+static int
+amdgpio_detach(device_t dev)
+{
+	struct amdgpio_softc *sc;
+	sc = device_get_softc(dev);
+
+	if (sc->sc_busdev)
+		gpiobus_detach_bus(dev);
+
+	bus_release_resources(dev, amdgpio_spec, sc->sc_res);
+
+	AMDGPIO_LOCK_DESTROY(sc);
+
+	return (0);
+}
+
+static device_method_t amdgpio_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe, amdgpio_probe),
+	DEVMETHOD(device_attach, amdgpio_attach),
+	DEVMETHOD(device_detach, amdgpio_detach),
+
+	/* GPIO protocol */
+	DEVMETHOD(gpio_get_bus, amdgpio_get_bus),
+	DEVMETHOD(gpio_pin_max, amdgpio_pin_max),
+	DEVMETHOD(gpio_pin_getname, amdgpio_pin_getname),
+	DEVMETHOD(gpio_pin_getcaps, amdgpio_pin_getcaps),
+	DEVMETHOD(gpio_pin_getflags, amdgpio_pin_getflags),
+	DEVMETHOD(gpio_pin_setflags, amdgpio_pin_setflags),
+	DEVMETHOD(gpio_pin_get, amdgpio_pin_get),
+	DEVMETHOD(gpio_pin_set, amdgpio_pin_set),
+	DEVMETHOD(gpio_pin_toggle, amdgpio_pin_toggle),
+
+	DEVMETHOD_END
+};
+
+static driver_t amdgpio_driver = {
+	"gpio",
+	amdgpio_methods,
+	sizeof(struct amdgpio_softc),
+};
+
+static devclass_t amdgpio_devclass;
+DRIVER_MODULE(amdgpio, acpi, amdgpio_driver, amdgpio_devclass, 0, 0);
+MODULE_DEPEND(amdgpio, acpi, 1, 1, 1);
+MODULE_DEPEND(amdgpio, gpiobus, 1, 1, 1);
+MODULE_VERSION(amdgpio, 1);

Added: head/sys/dev/amdgpio/amdgpio.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/dev/amdgpio/amdgpio.h	Sun Oct 21 04:52:37 2018	(r339523)
@@ -0,0 +1,332 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018 Advanced Micro Devices
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifdef	DEBUG
+#define	dprintf(fmt, args...) do {	\
+	printf("%s(): ", __func__);	\
+	printf(fmt,##args);		\
+} while (0)
+#else
+#define	dprintf(fmt, args...)
+#endif
+
+#define	AMD_GPIO_PREFIX			"AMDGPIO"
+
+#define	AMD_GPIO_NUM_PIN_BANK		4
+#define	AMD_GPIO_PINS_PER_BANK		64
+#define	AMD_GPIO_PINS_MAX		256 /* 4 banks * 64 pins */
+
+/* Number of pins in each bank */
+#define	AMD_GPIO_PINS_BANK0		63
+#define	AMD_GPIO_PINS_BANK1		64
+#define	AMD_GPIO_PINS_BANK2		56
+#define	AMD_GPIO_PINS_BANK3		32
+#define	AMD_GPIO_PIN_PRESENT		(AMD_GPIO_PINS_BANK0 + \
+					AMD_GPIO_PINS_BANK1 + \
+					AMD_GPIO_PINS_BANK2 + \
+					AMD_GPIO_PINS_BANK3)
+#define	AMDGPIO_DEFAULT_CAPS		(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT)
+
+/* Register related macros */
+#define	AMDGPIO_PIN_REGISTER(pin)	(pin * 4)
+
+#define	WAKE_INT_MASTER_REG		0xfc
+#define	EOI_MASK			(1 << 29)
+#define	WAKE_INT_STATUS_REG0		0x2f8
+#define	WAKE_INT_STATUS_REG1		0x2fc
+
+/* Bit definition of 32 bits of each pin register */
+#define	DB_TMR_OUT_OFF			0
+#define	DB_TMR_OUT_UNIT_OFF		4
+#define	DB_CNTRL_OFF			5
+#define	DB_TMR_LARGE_OFF		7
+#define	LEVEL_TRIG_OFF			8
+#define	ACTIVE_LEVEL_OFF		9
+#define	INTERRUPT_ENABLE_OFF		11
+#define	INTERRUPT_MASK_OFF		12
+#define	WAKE_CNTRL_OFF_S0I3		13
+#define	WAKE_CNTRL_OFF_S3		14
+#define	WAKE_CNTRL_OFF_S4		15
+#define	PIN_STS_OFF			16
+#define	DRV_STRENGTH_SEL_OFF		17
+#define	PULL_UP_SEL_OFF			19
+#define	PULL_UP_ENABLE_OFF		20
+#define	PULL_DOWN_ENABLE_OFF		21
+#define	OUTPUT_VALUE_OFF		22
+#define	OUTPUT_ENABLE_OFF		23
+#define	SW_CNTRL_IN_OFF			24
+#define	SW_CNTRL_EN_OFF			25
+#define	INTERRUPT_STS_OFF		28
+#define	WAKE_STS_OFF			29
+
+#define	DB_TMR_OUT_MASK			0xFUL
+#define	DB_CNTRL_MASK			0x3UL
+#define	ACTIVE_LEVEL_MASK		0x3UL
+#define	DRV_STRENGTH_SEL_MASK		0x3UL
+
+#define	DB_TYPE_NO_DEBOUNCE		0x0UL
+#define	DB_TYPE_PRESERVE_LOW_GLITCH	0x1UL
+#define	DB_TYPE_PRESERVE_HIGH_GLITCH	0x2UL
+#define	DB_TYPE_REMOVE_GLITCH		0x3UL
+
+#define	EDGE_TRIGGER			0x0UL
+#define	LEVEL_TRIGGER			0x1UL
+
+#define	ACTIVE_HIGH			0x0UL
+#define	ACTIVE_LOW			0x1UL
+#define	BOTH_EDGE			0x2UL
+
+#define	ENABLE_INTERRUPT		0x1UL
+#define	DISABLE_INTERRUPT		0x0UL
+
+#define	ENABLE_INTERRUPT_MASK		0x0UL
+#define	DISABLE_INTERRUPT_MASK		0x1UL
+#define	CLR_INTR_STAT			0x1UL
+
+#define	BIT(bit)			(1 << bit)
+#define	GPIO_PIN_INFO(p, n)		{ .pin_num = (p), .pin_name = (n) }
+
+struct pin_info {
+	int pin_num;
+	char *pin_name;
+};
+
+/* Pins exposed to drivers */
+static const struct pin_info kernzp_pins[] = {
+	GPIO_PIN_INFO(0, "PIN_0"),
+	GPIO_PIN_INFO(1, "PIN_1"),
+	GPIO_PIN_INFO(2, "PIN_2"),
+	GPIO_PIN_INFO(3, "PIN_3"),
+	GPIO_PIN_INFO(4, "PIN_4"),
+	GPIO_PIN_INFO(5, "PIN_5"),
+	GPIO_PIN_INFO(6, "PIN_6"),
+	GPIO_PIN_INFO(7, "PIN_7"),
+	GPIO_PIN_INFO(8, "PIN_8"),
+	GPIO_PIN_INFO(9, "PIN_9"),
+	GPIO_PIN_INFO(10, "PIN_10"),
+	GPIO_PIN_INFO(11, "PIN_11"),
+	GPIO_PIN_INFO(12, "PIN_12"),
+	GPIO_PIN_INFO(13, "PIN_13"),
+	GPIO_PIN_INFO(14, "PIN_14"),
+	GPIO_PIN_INFO(15, "PIN_15"),
+	GPIO_PIN_INFO(16, "PIN_16"),
+	GPIO_PIN_INFO(17, "PIN_17"),
+	GPIO_PIN_INFO(18, "PIN_18"),
+	GPIO_PIN_INFO(19, "PIN_19"),
+	GPIO_PIN_INFO(20, "PIN_20"),
+	GPIO_PIN_INFO(23, "PIN_23"),
+	GPIO_PIN_INFO(24, "PIN_24"),
+	GPIO_PIN_INFO(25, "PIN_25"),
+	GPIO_PIN_INFO(26, "PIN_26"),
+	GPIO_PIN_INFO(39, "PIN_39"),
+	GPIO_PIN_INFO(40, "PIN_40"),
+	GPIO_PIN_INFO(43, "PIN_43"),
+	GPIO_PIN_INFO(46, "PIN_46"),
+	GPIO_PIN_INFO(47, "PIN_47"),
+	GPIO_PIN_INFO(48, "PIN_48"),
+	GPIO_PIN_INFO(49, "PIN_49"),
+	GPIO_PIN_INFO(50, "PIN_50"),
+	GPIO_PIN_INFO(51, "PIN_51"),
+	GPIO_PIN_INFO(52, "PIN_52"),
+	GPIO_PIN_INFO(53, "PIN_53"),
+	GPIO_PIN_INFO(54, "PIN_54"),
+	GPIO_PIN_INFO(55, "PIN_55"),
+	GPIO_PIN_INFO(56, "PIN_56"),
+	GPIO_PIN_INFO(57, "PIN_57"),
+	GPIO_PIN_INFO(58, "PIN_58"),
+	GPIO_PIN_INFO(59, "PIN_59"),
+	GPIO_PIN_INFO(60, "PIN_60"),
+	GPIO_PIN_INFO(61, "PIN_61"),
+	GPIO_PIN_INFO(62, "PIN_62"),
+	GPIO_PIN_INFO(64, "PIN_64"),
+	GPIO_PIN_INFO(65, "PIN_65"),
+	GPIO_PIN_INFO(66, "PIN_66"),
+	GPIO_PIN_INFO(68, "PIN_68"),
+	GPIO_PIN_INFO(69, "PIN_69"),
+	GPIO_PIN_INFO(70, "PIN_70"),
+	GPIO_PIN_INFO(71, "PIN_71"),
+	GPIO_PIN_INFO(72, "PIN_72"),
+	GPIO_PIN_INFO(74, "PIN_74"),
+	GPIO_PIN_INFO(75, "PIN_75"),
+	GPIO_PIN_INFO(76, "PIN_76"),
+	GPIO_PIN_INFO(84, "PIN_84"),
+	GPIO_PIN_INFO(85, "PIN_85"),
+	GPIO_PIN_INFO(86, "PIN_86"),
+	GPIO_PIN_INFO(87, "PIN_87"),
+	GPIO_PIN_INFO(88, "PIN_88"),
+	GPIO_PIN_INFO(89, "PIN_89"),
+	GPIO_PIN_INFO(90, "PIN_90"),
+	GPIO_PIN_INFO(91, "PIN_91"),
+	GPIO_PIN_INFO(92, "PIN_92"),
+	GPIO_PIN_INFO(93, "PIN_93"),
+	GPIO_PIN_INFO(95, "PIN_95"),
+	GPIO_PIN_INFO(96, "PIN_96"),
+	GPIO_PIN_INFO(97, "PIN_97"),
+	GPIO_PIN_INFO(98, "PIN_98"),
+	GPIO_PIN_INFO(99, "PIN_99"),
+	GPIO_PIN_INFO(100, "PIN_100"),
+	GPIO_PIN_INFO(101, "PIN_101"),
+	GPIO_PIN_INFO(102, "PIN_102"),
+	GPIO_PIN_INFO(113, "PIN_113"),
+	GPIO_PIN_INFO(114, "PIN_114"),
+	GPIO_PIN_INFO(115, "PIN_115"),
+	GPIO_PIN_INFO(116, "PIN_116"),
+	GPIO_PIN_INFO(117, "PIN_117"),
+	GPIO_PIN_INFO(118, "PIN_118"),
+	GPIO_PIN_INFO(119, "PIN_119"),
+	GPIO_PIN_INFO(120, "PIN_120"),
+	GPIO_PIN_INFO(121, "PIN_121"),
+	GPIO_PIN_INFO(122, "PIN_122"),
+	GPIO_PIN_INFO(126, "PIN_126"),
+	GPIO_PIN_INFO(129, "PIN_129"),
+	GPIO_PIN_INFO(130, "PIN_130"),
+	GPIO_PIN_INFO(131, "PIN_131"),
+	GPIO_PIN_INFO(132, "PIN_132"),
+	GPIO_PIN_INFO(133, "PIN_133"),
+	GPIO_PIN_INFO(135, "PIN_135"),
+	GPIO_PIN_INFO(136, "PIN_136"),
+	GPIO_PIN_INFO(137, "PIN_137"),
+	GPIO_PIN_INFO(138, "PIN_138"),
+	GPIO_PIN_INFO(139, "PIN_139"),
+	GPIO_PIN_INFO(140, "PIN_140"),
+	GPIO_PIN_INFO(141, "PIN_141"),
+	GPIO_PIN_INFO(142, "PIN_142"),
+	GPIO_PIN_INFO(143, "PIN_143"),
+	GPIO_PIN_INFO(144, "PIN_144"),
+	GPIO_PIN_INFO(145, "PIN_145"),
+	GPIO_PIN_INFO(146, "PIN_146"),
+	GPIO_PIN_INFO(147, "PIN_147"),
+	GPIO_PIN_INFO(148, "PIN_148"),
+	GPIO_PIN_INFO(166, "PIN_166"),
+	GPIO_PIN_INFO(167, "PIN_167"),
+	GPIO_PIN_INFO(168, "PIN_168"),
+	GPIO_PIN_INFO(169, "PIN_169"),
+	GPIO_PIN_INFO(170, "PIN_170"),
+	GPIO_PIN_INFO(171, "PIN_171"),
+	GPIO_PIN_INFO(172, "PIN_172"),
+	GPIO_PIN_INFO(173, "PIN_173"),
+	GPIO_PIN_INFO(174, "PIN_174"),
+	GPIO_PIN_INFO(175, "PIN_175"),
+	GPIO_PIN_INFO(176, "PIN_176"),
+	GPIO_PIN_INFO(177, "PIN_177"),
+};
+
+#define	AMD_GPIO_PINS_EXPOSED	nitems(kernzp_pins)
+
+static const unsigned i2c0_pins[] = {145, 146};
+static const unsigned i2c1_pins[] = {147, 148};
+static const unsigned i2c2_pins[] = {113, 114};
+static const unsigned i2c3_pins[] = {19, 20};
+static const unsigned i2c4_pins[] = {149, 150};
+static const unsigned i2c5_pins[] = {151, 152};
+
+static const unsigned uart0_pins[] = {135, 136, 137, 138, 139};
+static const unsigned uart1_pins[] = {140, 141, 142, 143, 144};
+
+struct amd_pingroup {
+	const char *name;
+	const unsigned *pins;
+	unsigned npins;
+};
+
+static const struct amd_pingroup kernzp_groups[] = {
+	{
+		.name = "i2c0",
+		.pins = i2c0_pins,
+		.npins = 2,
+	},
+	{
+		.name = "i2c1",
+		.pins = i2c1_pins,
+		.npins = 2,
+	},
+	{
+		.name = "i2c2",
+		.pins = i2c2_pins,
+		.npins = 2,
+	},
+	{
+		.name = "i2c3",
+		.pins = i2c3_pins,
+		.npins = 2,
+	},
+	{
+		.name = "i2c4",
+		.pins = i2c4_pins,
+		.npins = 2,
+	},
+	{
+		.name = "i2c5",
+		.pins = i2c5_pins,
+		.npins = 2,
+	},
+	{
+		.name = "uart0",
+		.pins = uart0_pins,
+		.npins = 5,
+	},
+	{
+		.name = "uart1",
+		.pins = uart1_pins,
+		.npins = 5,
+	},
+};
+
+/* Macros for driver mutex locking */
+#define	AMDGPIO_LOCK_INIT(_sc)	\
+	mtx_init(&_sc->sc_mtx, device_get_nameunit((_sc)->sc_dev),	\
+		"amdgpio", MTX_SPIN)
+#define	AMDGPIO_LOCK_DESTROY(_sc)	mtx_destroy(&(_sc)->sc_mtx)
+#define	AMDGPIO_LOCK(_sc)		mtx_lock_spin(&(_sc)->sc_mtx)
+#define	AMDGPIO_UNLOCK(_sc)		mtx_unlock_spin(&(_sc)->sc_mtx)
+#define	AMDGPIO_ASSERT_LOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
+#define	AMDGPIO_ASSERT_UNLOCKED(_sc)	mtx_assert(&(_sc)->sc_mtx, MA_NOTOWNED)
+
+struct amdgpio_softc {
+	ACPI_HANDLE		sc_handle;
+	device_t		sc_dev;
+	device_t		sc_busdev;
+	const char*		sc_bank_prefix;
+	int			sc_nbanks;
+	int			sc_npins;
+	int			sc_ngroups;
+	struct mtx		sc_mtx;
+	struct resource		*sc_res[AMD_GPIO_NUM_PIN_BANK + 1];
+	bus_space_tag_t		sc_bst;
+	bus_space_handle_t	sc_bsh;
+	struct gpio_pin		sc_gpio_pins[AMD_GPIO_PINS_MAX];
+	const struct pin_info	*sc_pin_info;
+	const struct amd_pingroup *sc_groups;
+};
+
+struct amdgpio_sysctl {
+	struct amdgpio_softc	*sc;
+	uint32_t		pin;
+};

Modified: head/sys/modules/Makefile
==============================================================================
--- head/sys/modules/Makefile	Sun Oct 21 02:39:13 2018	(r339522)
+++ head/sys/modules/Makefile	Sun Oct 21 04:52:37 2018	(r339523)
@@ -34,6 +34,7 @@ SUBDIR=	\
 	ale \
 	alq \
 	${_amd_ecc_inject} \
+	${_amdgpio} \
 	${_amdsbwd} \
 	${_amdsmn} \
 	${_amdtemp} \
@@ -717,6 +718,7 @@ _x86bios=	x86bios
 .endif
 
 .if ${MACHINE_CPUARCH} == "amd64"
+_amdgpio=	amdgpio
 _ccp=		ccp
 _efirt=		efirt
 _iavf=		iavf

Added: head/sys/modules/amdgpio/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/modules/amdgpio/Makefile	Sun Oct 21 04:52:37 2018	(r339523)
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${SRCTOP}/sys/dev/amdgpio
+KMOD=  amdgpio
+SRCS=  amdgpio.c
+SRCS+= acpi_if.h device_if.h bus_if.h gpio_if.h pic_if.h opt_acpi.h opt_platform.h
+
+.include <bsd.kmod.mk>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201810210452.w9L4qbTc067553>