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
This commit is contained in:
Oleksandr Tymoshenko 2018-10-21 04:52:37 +00:00
parent c9bd5bee1a
commit 8ce574de3b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=339523
5 changed files with 811 additions and 0 deletions

View File

@ -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

468
sys/dev/amdgpio/amdgpio.c Normal file
View File

@ -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);

332
sys/dev/amdgpio/amdgpio.h Normal file
View File

@ -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;
};

View File

@ -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

View File

@ -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>