soc/amd/stoneyridge: Move GPIO support to common
The banked GPIO functionality in the AcpiMmio block has been consistent since the Mullins product. Move the basic support into a common directory. Each product's pin availability, MUXes, and other details must remain specific to the product. The relocated source also drops the weak configure_gevent_smi() that reports SMI is not available. The stoneyridge port relies on SMI to do its initialization, similar to modern soc/intel devices. This is the plan for future soc/amd ports, so make a missing function a build error instead of a runtime warning. BUG=b:131682806 Change-Id: I9cda00210a74de2bd1308ad43e2b867d24a67845 Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/32651 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
committed by
Martin Roth
parent
eb5b0d05a7
commit
251d305e73
@@ -23,5 +23,5 @@ void bootblock_mainboard_early_init(void)
|
|||||||
size_t num_gpios;
|
size_t num_gpios;
|
||||||
const struct soc_amd_gpio *gpios;
|
const struct soc_amd_gpio *gpios;
|
||||||
gpios = early_gpio_table(&num_gpios);
|
gpios = early_gpio_table(&num_gpios);
|
||||||
sb_program_gpios(gpios, num_gpios);
|
program_gpios(gpios, num_gpios);
|
||||||
}
|
}
|
||||||
|
@@ -82,7 +82,7 @@ static void mainboard_init(void *chip_info)
|
|||||||
size_t num_gpios;
|
size_t num_gpios;
|
||||||
const struct soc_amd_gpio *gpios;
|
const struct soc_amd_gpio *gpios;
|
||||||
gpios = gpio_table(&num_gpios);
|
gpios = gpio_table(&num_gpios);
|
||||||
sb_program_gpios(gpios, num_gpios);
|
program_gpios(gpios, num_gpios);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************
|
/*************************************************
|
||||||
|
@@ -29,7 +29,7 @@ void bootblock_mainboard_early_init(void)
|
|||||||
mainboard_ec_init();
|
mainboard_ec_init();
|
||||||
|
|
||||||
gpios = variant_early_gpio_table(&num_gpios);
|
gpios = variant_early_gpio_table(&num_gpios);
|
||||||
sb_program_gpios(gpios, num_gpios);
|
program_gpios(gpios, num_gpios);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bootblock_mainboard_init(void)
|
void bootblock_mainboard_init(void)
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <soc/nvs.h>
|
#include <soc/nvs.h>
|
||||||
#include <soc/pci_devs.h>
|
#include <soc/pci_devs.h>
|
||||||
#include <soc/southbridge.h>
|
#include <soc/southbridge.h>
|
||||||
|
#include <soc/smi.h>
|
||||||
#include <amdblocks/acpimmio.h>
|
#include <amdblocks/acpimmio.h>
|
||||||
#include <variant/ec.h>
|
#include <variant/ec.h>
|
||||||
#include <variant/thermal.h>
|
#include <variant/thermal.h>
|
||||||
@@ -126,7 +127,7 @@ static void mainboard_init(void *chip_info)
|
|||||||
mainboard_ec_init();
|
mainboard_ec_init();
|
||||||
|
|
||||||
gpios = variant_gpio_table(&num_gpios);
|
gpios = variant_gpio_table(&num_gpios);
|
||||||
sb_program_gpios(gpios, num_gpios);
|
program_gpios(gpios, num_gpios);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some platforms use SCI not generated by a GPIO pin (event above 23).
|
* Some platforms use SCI not generated by a GPIO pin (event above 23).
|
||||||
|
@@ -34,7 +34,7 @@ void mainboard_romstage_entry(int s3_resume)
|
|||||||
const struct soc_amd_gpio *gpios;
|
const struct soc_amd_gpio *gpios;
|
||||||
|
|
||||||
gpios = variant_romstage_gpio_table(&num_gpios);
|
gpios = variant_romstage_gpio_table(&num_gpios);
|
||||||
sb_program_gpios(gpios, num_gpios);
|
program_gpios(gpios, num_gpios);
|
||||||
|
|
||||||
variant_romstage_entry(s3_resume);
|
variant_romstage_entry(s3_resume);
|
||||||
}
|
}
|
||||||
|
8
src/soc/amd/common/block/gpio_banks/Kconfig
Normal file
8
src/soc/amd/common/block/gpio_banks/Kconfig
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
config SOC_AMD_COMMON_BLOCK_BANKED_GPIOS
|
||||||
|
bool
|
||||||
|
depends on SOC_AMD_COMMON_BLOCK_ACPIMMIO
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Select this option to use the newer style banks of GPIO signals.
|
||||||
|
These are at offsets +0x1500, +0x1600, and +0x1700 from the AcpiMmio
|
||||||
|
base.
|
6
src/soc/amd/common/block/gpio_banks/Makefile.inc
Normal file
6
src/soc/amd/common/block/gpio_banks/Makefile.inc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
bootblock-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
||||||
|
verstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
||||||
|
romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
||||||
|
postcar-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
||||||
|
ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
||||||
|
smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
|
310
src/soc/amd/common/block/gpio_banks/gpio.c
Normal file
310
src/soc/amd/common/block/gpio_banks/gpio.c
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Google Inc.
|
||||||
|
* Copyright (C) 2015 Intel Corporation
|
||||||
|
* Copyright (C) 2017 Advanced Micro Devices, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <device/mmio.h>
|
||||||
|
#include <device/device.h>
|
||||||
|
#include <console/console.h>
|
||||||
|
#include <gpio.h>
|
||||||
|
#include <amdblocks/acpimmio.h>
|
||||||
|
#include <soc/gpio.h>
|
||||||
|
#include <soc/smi.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static int get_gpio_gevent(uint8_t gpio, const struct soc_amd_event *table,
|
||||||
|
size_t items)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < items; i++) {
|
||||||
|
if ((table + i)->gpio == gpio)
|
||||||
|
return (int)(table + i)->event;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask)
|
||||||
|
{
|
||||||
|
uint32_t reg32;
|
||||||
|
|
||||||
|
value &= mask;
|
||||||
|
reg32 = read32(address);
|
||||||
|
reg32 &= ~mask;
|
||||||
|
reg32 |= value;
|
||||||
|
write32(address, reg32);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void program_smi(uint32_t flag, int gevent_num)
|
||||||
|
{
|
||||||
|
uint32_t trigger;
|
||||||
|
|
||||||
|
trigger = flag & FLAGS_TRIGGER_MASK;
|
||||||
|
/*
|
||||||
|
* Only level trigger is allowed for SMI. Trigger values are 0
|
||||||
|
* through 3, with 0-1 being level trigger and 2-3 being edge
|
||||||
|
* trigger. GPIO_TRIGGER_EDGE_LOW is 2, so trigger has to be
|
||||||
|
* less than GPIO_TRIGGER_EDGE_LOW.
|
||||||
|
*/
|
||||||
|
assert(trigger < GPIO_TRIGGER_EDGE_LOW);
|
||||||
|
|
||||||
|
if (trigger == GPIO_TRIGGER_LEVEL_HIGH)
|
||||||
|
configure_gevent_smi(gevent_num, SMI_MODE_SMI,
|
||||||
|
SMI_SCI_LVL_HIGH);
|
||||||
|
if (trigger == GPIO_TRIGGER_LEVEL_LOW)
|
||||||
|
configure_gevent_smi(gevent_num, SMI_MODE_SMI,
|
||||||
|
SMI_SCI_LVL_LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level)
|
||||||
|
{
|
||||||
|
uint32_t trigger;
|
||||||
|
|
||||||
|
trigger = flag & FLAGS_TRIGGER_MASK;
|
||||||
|
switch (trigger) {
|
||||||
|
case GPIO_TRIGGER_LEVEL_LOW:
|
||||||
|
*edge = SCI_TRIGGER_LEVEL;
|
||||||
|
*level = 0;
|
||||||
|
break;
|
||||||
|
case GPIO_TRIGGER_LEVEL_HIGH:
|
||||||
|
*edge = SCI_TRIGGER_LEVEL;
|
||||||
|
*level = 1;
|
||||||
|
break;
|
||||||
|
case GPIO_TRIGGER_EDGE_LOW:
|
||||||
|
*edge = SCI_TRIGGER_EDGE;
|
||||||
|
*level = 0;
|
||||||
|
break;
|
||||||
|
case GPIO_TRIGGER_EDGE_HIGH:
|
||||||
|
*edge = SCI_TRIGGER_EDGE;
|
||||||
|
*level = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t gpio_get_address(gpio_t gpio_num)
|
||||||
|
{
|
||||||
|
uintptr_t gpio_address;
|
||||||
|
|
||||||
|
if (gpio_num < 64)
|
||||||
|
gpio_address = GPIO_BANK0_CONTROL(gpio_num);
|
||||||
|
else if (gpio_num < 128)
|
||||||
|
gpio_address = GPIO_BANK1_CONTROL(gpio_num);
|
||||||
|
else
|
||||||
|
gpio_address = GPIO_BANK2_CONTROL(gpio_num);
|
||||||
|
|
||||||
|
return gpio_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gpio_get(gpio_t gpio_num)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
|
||||||
|
return !!(reg & GPIO_PIN_STS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_set(gpio_t gpio_num, int value)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
reg &= ~GPIO_OUTPUT_MASK;
|
||||||
|
reg |= !!value << GPIO_OUTPUT_SHIFT;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_input_pulldown(gpio_t gpio_num)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
reg &= ~GPIO_PULLUP_ENABLE;
|
||||||
|
reg |= GPIO_PULLDOWN_ENABLE;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_input_pullup(gpio_t gpio_num)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
reg &= ~GPIO_PULLDOWN_ENABLE;
|
||||||
|
reg |= GPIO_PULLUP_ENABLE;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_input(gpio_t gpio_num)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
reg &= ~GPIO_OUTPUT_ENABLE;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_output(gpio_t gpio_num, int value)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
||||||
|
|
||||||
|
reg = read32((void *)gpio_address);
|
||||||
|
reg |= GPIO_OUTPUT_ENABLE;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
gpio_set(gpio_num, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *gpio_acpi_path(gpio_t gpio)
|
||||||
|
{
|
||||||
|
return "\\_SB.GPIO";
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t gpio_acpi_pin(gpio_t gpio)
|
||||||
|
{
|
||||||
|
return gpio;
|
||||||
|
}
|
||||||
|
|
||||||
|
__weak void soc_gpio_hook(uint8_t gpio, uint8_t mux) {}
|
||||||
|
|
||||||
|
void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
|
||||||
|
{
|
||||||
|
uint32_t *gpio_ptr, *inter_master;
|
||||||
|
uint32_t control, control_flags, edge_level, direction;
|
||||||
|
uint32_t mask, bit_edge, bit_level;
|
||||||
|
uint8_t mux, index, gpio;
|
||||||
|
int gevent_num;
|
||||||
|
const struct soc_amd_event *gev_tbl;
|
||||||
|
size_t gev_items;
|
||||||
|
|
||||||
|
inter_master = (uint32_t *)(uintptr_t)(ACPIMMIO_GPIO0_BASE
|
||||||
|
+ GPIO_MASTER_SWITCH);
|
||||||
|
direction = 0;
|
||||||
|
edge_level = 0;
|
||||||
|
mask = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable blocking wake/interrupt status generation while updating
|
||||||
|
* debounce registers. Otherwise when a debounce register is updated
|
||||||
|
* the whole GPIO controller will zero out all interrupt enable status
|
||||||
|
* bits while the delay happens. This could cause us to drop the bits
|
||||||
|
* due to the read-modify-write that happens on each register.
|
||||||
|
*
|
||||||
|
* Additionally disable interrupt generation so we don't get any
|
||||||
|
* spurious interrupts while updating the registers.
|
||||||
|
*/
|
||||||
|
mem_read_write32(inter_master, 0, GPIO_MASK_STS_EN | GPIO_INTERRUPT_EN);
|
||||||
|
|
||||||
|
soc_get_gpio_event_table(&gev_tbl, &gev_items);
|
||||||
|
|
||||||
|
for (index = 0; index < size; index++) {
|
||||||
|
gpio = gpio_list_ptr[index].gpio;
|
||||||
|
mux = gpio_list_ptr[index].function;
|
||||||
|
control = gpio_list_ptr[index].control;
|
||||||
|
control_flags = gpio_list_ptr[index].flags;
|
||||||
|
|
||||||
|
iomux_write8(gpio, mux & AMD_GPIO_MUX_MASK);
|
||||||
|
iomux_read8(gpio); /* Flush posted write */
|
||||||
|
|
||||||
|
soc_gpio_hook(gpio, mux);
|
||||||
|
|
||||||
|
gpio_ptr = (uint32_t *)gpio_get_address(gpio);
|
||||||
|
|
||||||
|
if (control_flags & GPIO_SPECIAL_FLAG) {
|
||||||
|
gevent_num = get_gpio_gevent(gpio, gev_tbl, gev_items);
|
||||||
|
if (gevent_num < 0) {
|
||||||
|
printk(BIOS_WARNING, "Warning: GPIO pin %d has"
|
||||||
|
" no associated gevent!\n", gpio);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
switch (control_flags & GPIO_SPECIAL_MASK) {
|
||||||
|
case GPIO_DEBOUNCE_FLAG:
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
GPIO_DEBOUNCE_MASK);
|
||||||
|
break;
|
||||||
|
case GPIO_WAKE_FLAG:
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
INT_WAKE_MASK);
|
||||||
|
break;
|
||||||
|
case GPIO_INT_FLAG:
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
AMD_GPIO_CONTROL_MASK);
|
||||||
|
break;
|
||||||
|
case GPIO_SMI_FLAG:
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
INT_SCI_SMI_MASK);
|
||||||
|
program_smi(control_flags, gevent_num);
|
||||||
|
break;
|
||||||
|
case GPIO_SCI_FLAG:
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
INT_SCI_SMI_MASK);
|
||||||
|
get_sci_config_bits(control_flags, &bit_edge,
|
||||||
|
&bit_level);
|
||||||
|
edge_level |= bit_edge << gevent_num;
|
||||||
|
direction |= bit_level << gevent_num;
|
||||||
|
mask |= (1 << gevent_num);
|
||||||
|
soc_route_sci(gevent_num);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printk(BIOS_WARNING, "Error, flags 0x%08x\n",
|
||||||
|
control_flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mem_read_write32(gpio_ptr, control,
|
||||||
|
AMD_GPIO_CONTROL_MASK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Re-enable interrupt status generation.
|
||||||
|
*
|
||||||
|
* We leave MASK_STATUS disabled because the kernel may reconfigure the
|
||||||
|
* debounce registers while the drivers load. This will cause interrupts
|
||||||
|
* to be missed during boot.
|
||||||
|
*/
|
||||||
|
mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN);
|
||||||
|
|
||||||
|
/* Set all SCI trigger direction (high/low) */
|
||||||
|
mem_read_write32((uint32_t *)
|
||||||
|
(uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_TRIG),
|
||||||
|
direction, mask);
|
||||||
|
|
||||||
|
/* Set all SCI trigger level (edge/level) */
|
||||||
|
mem_read_write32((uint32_t *)
|
||||||
|
(uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_LEVEL),
|
||||||
|
edge_level, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gpio_interrupt_status(gpio_t gpio)
|
||||||
|
{
|
||||||
|
uintptr_t gpio_address = gpio_get_address(gpio);
|
||||||
|
uint32_t reg = read32((void *)gpio_address);
|
||||||
|
|
||||||
|
if (reg & GPIO_INT_STATUS) {
|
||||||
|
/* Clear interrupt status, preserve wake status */
|
||||||
|
reg &= ~GPIO_WAKE_STATUS;
|
||||||
|
write32((void *)gpio_address, reg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
308
src/soc/amd/common/block/include/amdblocks/gpio_banks.h
Normal file
308
src/soc/amd/common/block/include/amdblocks/gpio_banks.h
Normal file
@@ -0,0 +1,308 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the coreboot project.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Advanced Micro Devices, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; version 2 of the License.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AMDBLOCK_GPIO_BANKS_H__
|
||||||
|
#define __AMDBLOCK_GPIO_BANKS_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
struct soc_amd_gpio {
|
||||||
|
uint8_t gpio;
|
||||||
|
uint8_t function;
|
||||||
|
uint32_t control;
|
||||||
|
uint32_t flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct soc_amd_event {
|
||||||
|
uint8_t gpio;
|
||||||
|
uint8_t event;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIO_BANK0_CONTROL(gpio) (ACPIMMIO_GPIO0_BASE + ((gpio) * 4))
|
||||||
|
#define GPIO_BANK1_CONTROL(gpio) (ACPIMMIO_GPIO1_BASE + (((gpio) - 64) * 4))
|
||||||
|
#define GPIO_BANK2_CONTROL(gpio) (ACPIMMIO_GPIO2_BASE + (((gpio) - 128) * 4))
|
||||||
|
|
||||||
|
#define GPIO_MASTER_SWITCH 0xFC
|
||||||
|
#define GPIO_MASK_STS_EN BIT(28)
|
||||||
|
#define GPIO_INTERRUPT_EN BIT(30)
|
||||||
|
|
||||||
|
#define GPIO_PIN_IN (1 << 0) /* for byte access */
|
||||||
|
#define GPIO_PIN_OUT (1 << 6) /* for byte access */
|
||||||
|
|
||||||
|
#define GPIO_EDGE_TRIG (0 << 8)
|
||||||
|
#define GPIO_LEVEL_TRIG (1 << 8)
|
||||||
|
#define GPIO_TRIGGER_MASK (1 << 8)
|
||||||
|
|
||||||
|
#define GPIO_ACTIVE_HIGH (0 << 9)
|
||||||
|
#define GPIO_ACTIVE_LOW (1 << 9)
|
||||||
|
#define GPIO_ACTIVE_BOTH (2 << 9)
|
||||||
|
#define GPIO_ACTIVE_MASK (3 << 9)
|
||||||
|
|
||||||
|
#define GPIO_INT_STATUS_EN (1 << 11)
|
||||||
|
#define GPIO_INT_DELIVERY_EN (1 << 12)
|
||||||
|
#define GPIO_INTERRUPT_MASK (3 << 11)
|
||||||
|
#define GPIO_S0I3_WAKE_EN (1 << 13)
|
||||||
|
#define GPIO_S3_WAKE_EN (1 << 14)
|
||||||
|
#define GPIO_S4_S5_WAKE_EN (1 << 15)
|
||||||
|
|
||||||
|
#define GPIO_PIN_STS (1 << 16)
|
||||||
|
#define GPIO_PULLUP_ENABLE (1 << 20)
|
||||||
|
#define GPIO_PULLDOWN_ENABLE (1 << 21)
|
||||||
|
#define GPIO_OUTPUT_SHIFT 22
|
||||||
|
#define GPIO_OUTPUT_MASK (1 << GPIO_OUTPUT_SHIFT)
|
||||||
|
#define GPIO_OUTPUT_VALUE (1 << GPIO_OUTPUT_SHIFT)
|
||||||
|
#define GPIO_OUTPUT_ENABLE (1 << 23)
|
||||||
|
|
||||||
|
#define GPIO_INT_STATUS (1 << 28)
|
||||||
|
#define GPIO_WAKE_STATUS (1 << 29)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GEVENT_0,
|
||||||
|
GEVENT_1,
|
||||||
|
GEVENT_2,
|
||||||
|
GEVENT_3,
|
||||||
|
GEVENT_4,
|
||||||
|
GEVENT_5,
|
||||||
|
GEVENT_6,
|
||||||
|
GEVENT_7,
|
||||||
|
GEVENT_8,
|
||||||
|
GEVENT_9,
|
||||||
|
GEVENT_10,
|
||||||
|
GEVENT_11,
|
||||||
|
GEVENT_12,
|
||||||
|
GEVENT_13,
|
||||||
|
GEVENT_14,
|
||||||
|
GEVENT_15,
|
||||||
|
GEVENT_16,
|
||||||
|
GEVENT_17,
|
||||||
|
GEVENT_18,
|
||||||
|
GEVENT_19,
|
||||||
|
GEVENT_20,
|
||||||
|
GEVENT_21,
|
||||||
|
GEVENT_22,
|
||||||
|
GEVENT_23,
|
||||||
|
GEVENT_24,
|
||||||
|
GEVENT_25,
|
||||||
|
GEVENT_26,
|
||||||
|
GEVENT_27,
|
||||||
|
GEVENT_28,
|
||||||
|
GEVENT_29,
|
||||||
|
GEVENT_30,
|
||||||
|
GEVENT_31,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIO_OUTPUT_OUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_VALUE)
|
||||||
|
#define GPIO_OUTPUT_OUT_LOW GPIO_OUTPUT_ENABLE
|
||||||
|
|
||||||
|
#define GPIO_PULL_PULL_UP GPIO_PULLUP_ENABLE
|
||||||
|
#define GPIO_PULL_PULL_DOWN GPIO_PULLDOWN_ENABLE
|
||||||
|
#define GPIO_PULL_PULL_NONE 0
|
||||||
|
|
||||||
|
#define AMD_GPIO_CONTROL_MASK 0x00f4ff00
|
||||||
|
#define AMD_GPIO_MUX_MASK 0x03
|
||||||
|
|
||||||
|
/* Definitions for PAD_INT. */
|
||||||
|
#define GPIO_INT_EDGE_HIGH (GPIO_ACTIVE_HIGH | GPIO_EDGE_TRIG)
|
||||||
|
#define GPIO_INT_EDGE_LOW (GPIO_ACTIVE_LOW | GPIO_EDGE_TRIG)
|
||||||
|
#define GPIO_INT_BOTH_EDGES (GPIO_ACTIVE_BOTH | GPIO_EDGE_TRIG)
|
||||||
|
#define GPIO_INT_LEVEL_HIGH (GPIO_ACTIVE_HIGH | GPIO_LEVEL_TRIG)
|
||||||
|
#define GPIO_INT_LEVEL_LOW (GPIO_ACTIVE_LOW | GPIO_LEVEL_TRIG)
|
||||||
|
|
||||||
|
enum {
|
||||||
|
GPIO_TRIGGER_LEVEL_LOW,
|
||||||
|
GPIO_TRIGGER_LEVEL_HIGH,
|
||||||
|
GPIO_TRIGGER_EDGE_LOW,
|
||||||
|
GPIO_TRIGGER_EDGE_HIGH,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GPIO_TRIGGER_INVALID -1
|
||||||
|
#define SCI_TRIGGER_EDGE 0
|
||||||
|
#define SCI_TRIGGER_LEVEL 1
|
||||||
|
|
||||||
|
#define GPIO_SPECIAL_FLAG (1 << 31)
|
||||||
|
#define GPIO_DEBOUNCE_FLAG (1 << 30)
|
||||||
|
#define GPIO_WAKE_FLAG (1 << 29)
|
||||||
|
#define GPIO_INT_FLAG (1 << 28)
|
||||||
|
#define GPIO_SMI_FLAG (1 << 27)
|
||||||
|
#define GPIO_SCI_FLAG (1 << 26)
|
||||||
|
#define GPIO_FLAG_DEBOUNCE (GPIO_SPECIAL_FLAG | GPIO_DEBOUNCE_FLAG)
|
||||||
|
#define GPIO_FLAG_WAKE (GPIO_SPECIAL_FLAG | GPIO_WAKE_FLAG)
|
||||||
|
#define GPIO_FLAG_INT (GPIO_SPECIAL_FLAG | GPIO_INT_FLAG)
|
||||||
|
#define GPIO_FLAG_SCI (GPIO_SPECIAL_FLAG | GPIO_SCI_FLAG)
|
||||||
|
#define GPIO_FLAG_SMI (GPIO_SPECIAL_FLAG | GPIO_SMI_FLAG)
|
||||||
|
|
||||||
|
#define FLAGS_TRIGGER_MASK 0x00000003
|
||||||
|
#define GPIO_SPECIAL_MASK 0x7c000000
|
||||||
|
#define GPIO_DEBOUNCE_MASK 0x000000ff
|
||||||
|
#define INT_TRIGGER_MASK 0x00000700
|
||||||
|
#define INT_WAKE_MASK 0x0000e700
|
||||||
|
#define INT_SCI_SMI_MASK 0x00f40000
|
||||||
|
|
||||||
|
#define IN_GLITCH_SHIFT 5
|
||||||
|
#define GLITCH_LOW 1
|
||||||
|
#define GLITCH_HIGH 2
|
||||||
|
#define GLITCH_NONE 3
|
||||||
|
#define GPIO_IN_PRESERVE_LOW_GLITCH (GLITCH_LOW << IN_GLITCH_SHIFT)
|
||||||
|
#define GPIO_IN_PRESERVE_HIGH_GLITCH (GLITCH_HIGH << IN_GLITCH_SHIFT)
|
||||||
|
#define GPIO_IN_REMOVE_GLITCH (GLITCH_NONE << IN_GLITCH_SHIFT)
|
||||||
|
|
||||||
|
#define GPIO_TIMEBASE_61uS 0
|
||||||
|
#define GPIO_TIMEBASE_183uS (1 << 4)
|
||||||
|
#define GPIO_TIMEBASE_15560uS (1 << 7)
|
||||||
|
#define GPIO_TIMEBASE_62440uS (GPIO_TIMEBASE_183uS | \
|
||||||
|
GPIO_TIMEBASE_15560uS)
|
||||||
|
#define GPIO_IN_DEBOUNCE_DISABLED (0 | GPIO_TIMEBASE_61uS)
|
||||||
|
#define GPIO_IN_60uS (1 | GPIO_TIMEBASE_61uS)
|
||||||
|
#define GPIO_IN_120uS (2 | GPIO_TIMEBASE_61uS)
|
||||||
|
#define GPIO_IN_200uS (3 | GPIO_TIMEBASE_61uS)
|
||||||
|
#define GPIO_IN_500uS (8 | GPIO_TIMEBASE_61uS)
|
||||||
|
#define GPIO_IN_1mS (5 | GPIO_TIMEBASE_183uS)
|
||||||
|
#define GPIO_IN_2mS (11 | GPIO_TIMEBASE_183uS)
|
||||||
|
#define GPIO_IN_15mS (1 | GPIO_TIMEBASE_15560uS)
|
||||||
|
#define GPIO_IN_50mS (3 | GPIO_TIMEBASE_15560uS)
|
||||||
|
#define GPIO_IN_100mS (6 | GPIO_TIMEBASE_15560uS)
|
||||||
|
#define GPIO_IN_200mS (13 | GPIO_TIMEBASE_15560uS)
|
||||||
|
#define GPIO_IN_500mS (8 | GPIO_TIMEBASE_62440uS)
|
||||||
|
|
||||||
|
#define GPIO_EVENT_INT_STATUS GPIO_INT_STATUS_EN
|
||||||
|
#define GPIO_EVENT_INT_DELIVER GPIO_INT_DELIVERY_EN
|
||||||
|
#define GPIO_EVENT_INT_STATUS_DELIVER (GPIO_INT_STATUS_EN | \
|
||||||
|
GPIO_INT_DELIVERY_EN)
|
||||||
|
#define GPIO_WAKE_S0i3 (1 << 13)
|
||||||
|
#define GPIO_WAKE_S3 (1 << 14)
|
||||||
|
#define GPIO_WAKE_S4_S5 (1 << 15)
|
||||||
|
#define GPIO_WAKE_S0i3_S4_S5 (GPIO_WAKE_S0i3 | GPIO_WAKE_S4_S5)
|
||||||
|
#define GPIO_WAKE_S3_S4_S5 (GPIO_WAKE_S3 | GPIO_WAKE_S4_S5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Several macros are available to declare programming of GPIO pins, and if
|
||||||
|
* needed, more than 1 macro can be used for any pin. However, some macros
|
||||||
|
* will have no effect if combined. For example debounce only affects input
|
||||||
|
* or one of the interrupts. Some macros should not be combined, such as SMI
|
||||||
|
* and regular interrupt. The defined macros and their parameters are:
|
||||||
|
* PAD_NF Define native alternate function for the pin.
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* function the native function
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* PAD_GPI The pin is a GPIO input
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* PAD_GPO The pin is a GPIO output
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* direction high or low
|
||||||
|
* PAD_INT The pin is regular interrupt that works while booting
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
|
||||||
|
* action STATUS, DELIVER, STATUS_DELIVER
|
||||||
|
* PAD_SCI The pin is a SCI source
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH
|
||||||
|
* PAD_SMI The pin is a SMI source
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* trigger LEVEL_LOW, LEVEL_HIGH
|
||||||
|
* PAD_WAKE The pin can wake, use after PAD_INT or PAD_SCI
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* pull pull up, pull down or no pull
|
||||||
|
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
|
||||||
|
* type S0i3, S3, S4_S5 or S4_S5 combinations (S0i3_S3 invalid)
|
||||||
|
* PAD_DEBOUNCE The input or interrupt will be debounced, invalid after
|
||||||
|
* PAD_NF
|
||||||
|
* pin the pin to be programmed
|
||||||
|
* debounce_type preserve low glitch, preserve high glitch, no glitch
|
||||||
|
* debounce_time the debounce time
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Native function pad configuration */
|
||||||
|
#define PAD_NF(pin, func, pull) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## func, \
|
||||||
|
.control = GPIO_PULL ## _ ## pull, \
|
||||||
|
.flags = 0 }
|
||||||
|
/* General purpose input pad configuration */
|
||||||
|
#define PAD_GPI(pin, pull) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = GPIO_PULL ## _ ## pull, \
|
||||||
|
.flags = 0 }
|
||||||
|
/* General purpose output pad configuration */
|
||||||
|
#define PAD_GPO(pin, direction) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = GPIO_OUTPUT ## _OUT_ ## direction, \
|
||||||
|
.flags = 0 }
|
||||||
|
/* Auxiliary macro for legacy interrupt and wake */
|
||||||
|
#define PAD_AUX1(pull, trigger) (GPIO_PULL ## _ ## pull | \
|
||||||
|
GPIO_INT ## _ ## trigger)
|
||||||
|
/* Legacy interrupt pad configuration */
|
||||||
|
#define PAD_INT(pin, pull, trigger, action) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = (PAD_AUX1(pull, trigger) | \
|
||||||
|
GPIO_EVENT_INT ## _ ## action), \
|
||||||
|
.flags = GPIO_FLAG_INT }
|
||||||
|
/* Auxiliary macro for SCI and SMI */
|
||||||
|
#define PAD_AUX2(trigger, flag) (GPIO_TRIGGER ## _ ## trigger | flag)
|
||||||
|
/* SCI pad configuration */
|
||||||
|
#define PAD_SCI(pin, pull, trigger) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = GPIO_PULL ## _ ## pull, \
|
||||||
|
.flags = PAD_AUX2(trigger, GPIO_FLAG_SCI) }
|
||||||
|
/* SMI pad configuration */
|
||||||
|
#define PAD_SMI(pin, pull, trigger) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = GPIO_PULL ## _ ## pull, \
|
||||||
|
.flags = PAD_AUX2(trigger, GPIO_FLAG_SMI) }
|
||||||
|
/* WAKE pad configuration */
|
||||||
|
#define PAD_WAKE(pin, pull, trigger, type) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = (PAD_AUX1(pull, trigger) | \
|
||||||
|
GPIO_WAKE ## _ ## type), \
|
||||||
|
.flags = GPIO_FLAG_WAKE }
|
||||||
|
/* pin debounce configuration */
|
||||||
|
#define PAD_DEBOUNCE(pin, type, time) \
|
||||||
|
{ .gpio = (pin), \
|
||||||
|
.function = pin ## _IOMUX_ ## GPIOxx, \
|
||||||
|
.control = (GPIO_IN ## _ ## type | GPIO_IN ## _ ## time), \
|
||||||
|
.flags = GPIO_FLAG_DEBOUNCE }
|
||||||
|
|
||||||
|
typedef uint32_t gpio_t;
|
||||||
|
|
||||||
|
/* Get the address of the control register of a particular pin */
|
||||||
|
uintptr_t gpio_get_address(gpio_t gpio_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief program a particular set of GPIO
|
||||||
|
*
|
||||||
|
* @param gpio_list_ptr = pointer to array of gpio configurations
|
||||||
|
* @param size = number of entries in array
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size);
|
||||||
|
/* Return the interrupt status and clear if set. */
|
||||||
|
int gpio_interrupt_status(gpio_t gpio);
|
||||||
|
/* Implemented by soc, provides table of avaialable GPIO mapping to Gevents */
|
||||||
|
void soc_get_gpio_event_table(const struct soc_amd_event **table, size_t *items);
|
||||||
|
/* May be implemented by soc to handle special cases */
|
||||||
|
void soc_gpio_hook(uint8_t gpio, uint8_t mux);
|
||||||
|
|
||||||
|
#endif /* __AMDBLOCK_GPIO_BANKS_H__ */
|
@@ -47,6 +47,7 @@ config CPU_SPECIFIC_OPTIONS
|
|||||||
select SOC_AMD_COMMON
|
select SOC_AMD_COMMON
|
||||||
select SOC_AMD_COMMON_BLOCK
|
select SOC_AMD_COMMON_BLOCK
|
||||||
select SOC_AMD_COMMON_BLOCK_ACPIMMIO
|
select SOC_AMD_COMMON_BLOCK_ACPIMMIO
|
||||||
|
select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS
|
||||||
select SOC_AMD_COMMON_BLOCK_PCI
|
select SOC_AMD_COMMON_BLOCK_PCI
|
||||||
select SOC_AMD_COMMON_BLOCK_PI
|
select SOC_AMD_COMMON_BLOCK_PI
|
||||||
select SOC_AMD_COMMON_BLOCK_PSP
|
select SOC_AMD_COMMON_BLOCK_PSP
|
||||||
|
@@ -317,9 +317,9 @@ static void acpigen_soc_get_gpio_in_local5(uintptr_t addr)
|
|||||||
|
|
||||||
static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
|
static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
|
||||||
{
|
{
|
||||||
if (gpio_num >= GPIO_TOTAL_PINS) {
|
if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
|
||||||
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
|
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
|
||||||
" %d\n", gpio_num, GPIO_TOTAL_PINS);
|
" %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
|
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
|
||||||
@@ -347,9 +347,9 @@ static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
|
|||||||
|
|
||||||
static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
|
static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
|
||||||
{
|
{
|
||||||
if (gpio_num >= GPIO_TOTAL_PINS) {
|
if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
|
||||||
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
|
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
|
||||||
" %d\n", gpio_num, GPIO_TOTAL_PINS);
|
" %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
|
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
|
||||||
|
@@ -28,4 +28,4 @@ Device(PCI0) {
|
|||||||
#include "sb_fch.asl"
|
#include "sb_fch.asl"
|
||||||
|
|
||||||
/* Add GPIO library */
|
/* Add GPIO library */
|
||||||
#include <gpio_lib.asl>
|
#include <soc/amd/common/acpi/gpio_bank_lib.asl>
|
||||||
|
@@ -15,14 +15,11 @@
|
|||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <device/mmio.h>
|
#include <stdint.h>
|
||||||
#include <device/device.h>
|
#include <amdblocks/gpio_banks.h>
|
||||||
#include <console/console.h>
|
|
||||||
#include <gpio.h>
|
|
||||||
#include <amdblocks/acpimmio.h>
|
#include <amdblocks/acpimmio.h>
|
||||||
#include <soc/gpio.h>
|
#include <soc/gpio.h>
|
||||||
#include <assert.h>
|
#include <soc/smi.h>
|
||||||
#include "chip.h"
|
|
||||||
|
|
||||||
static const struct soc_amd_event gpio_event_table[] = {
|
static const struct soc_amd_event gpio_event_table[] = {
|
||||||
{ GPIO_1, GEVENT_19 },
|
{ GPIO_1, GEVENT_19 },
|
||||||
@@ -51,290 +48,20 @@ static const struct soc_amd_event gpio_event_table[] = {
|
|||||||
{ GPIO_69, GEVENT_17 },
|
{ GPIO_69, GEVENT_17 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_gpio_gevent(uint8_t gpio)
|
void soc_route_sci(uint8_t event)
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(gpio_event_table); i++) {
|
|
||||||
if (gpio_event_table[i].gpio == gpio)
|
|
||||||
return (int)gpio_event_table[i].event;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask)
|
|
||||||
{
|
|
||||||
uint32_t reg32;
|
|
||||||
|
|
||||||
value &= mask;
|
|
||||||
reg32 = read32(address);
|
|
||||||
reg32 &= ~mask;
|
|
||||||
reg32 |= value;
|
|
||||||
write32(address, reg32);
|
|
||||||
}
|
|
||||||
|
|
||||||
__weak void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
|
|
||||||
{
|
|
||||||
printk(BIOS_WARNING, "Warning: SMI disabled!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void program_smi(uint32_t flag, int gevent_num)
|
|
||||||
{
|
|
||||||
uint32_t trigger;
|
|
||||||
|
|
||||||
trigger = flag & FLAGS_TRIGGER_MASK;
|
|
||||||
/*
|
|
||||||
* Only level trigger is allowed for SMI. Trigger values are 0
|
|
||||||
* through 3, with 0-1 being level trigger and 2-3 being edge
|
|
||||||
* trigger. GPIO_TRIGGER_EDGE_LOW is 2, so trigger has to be
|
|
||||||
* less than GPIO_TRIGGER_EDGE_LOW.
|
|
||||||
*/
|
|
||||||
assert(trigger < GPIO_TRIGGER_EDGE_LOW);
|
|
||||||
|
|
||||||
if (trigger == GPIO_TRIGGER_LEVEL_HIGH)
|
|
||||||
configure_gevent_smi(gevent_num, SMI_MODE_SMI,
|
|
||||||
SMI_SCI_LVL_HIGH);
|
|
||||||
if (trigger == GPIO_TRIGGER_LEVEL_LOW)
|
|
||||||
configure_gevent_smi(gevent_num, SMI_MODE_SMI,
|
|
||||||
SMI_SCI_LVL_LOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void route_sci(uint8_t event)
|
|
||||||
{
|
{
|
||||||
smi_write8(SMI_SCI_MAP(event), event);
|
smi_write8(SMI_SCI_MAP(event), event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level)
|
void soc_get_gpio_event_table(const struct soc_amd_event **table, size_t *items)
|
||||||
{
|
{
|
||||||
uint32_t trigger;
|
*table = gpio_event_table;
|
||||||
|
*items = ARRAY_SIZE(gpio_event_table);
|
||||||
trigger = flag & FLAGS_TRIGGER_MASK;
|
|
||||||
switch (trigger) {
|
|
||||||
case GPIO_TRIGGER_LEVEL_LOW:
|
|
||||||
*edge = SCI_TRIGGER_LEVEL;
|
|
||||||
*level = 0;
|
|
||||||
break;
|
|
||||||
case GPIO_TRIGGER_LEVEL_HIGH:
|
|
||||||
*edge = SCI_TRIGGER_LEVEL;
|
|
||||||
*level = 1;
|
|
||||||
break;
|
|
||||||
case GPIO_TRIGGER_EDGE_LOW:
|
|
||||||
*edge = SCI_TRIGGER_EDGE;
|
|
||||||
*level = 0;
|
|
||||||
break;
|
|
||||||
case GPIO_TRIGGER_EDGE_HIGH:
|
|
||||||
*edge = SCI_TRIGGER_EDGE;
|
|
||||||
*level = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t gpio_get_address(gpio_t gpio_num)
|
void soc_gpio_hook(uint8_t gpio, uint8_t mux)
|
||||||
{
|
{
|
||||||
uintptr_t gpio_address;
|
/* Always program Gevent when WAKE_L_AGPIO2 is configured as WAKE_L */
|
||||||
|
if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK))
|
||||||
if (gpio_num < 64)
|
soc_route_sci(GPIO_2_EVENT);
|
||||||
gpio_address = GPIO_BANK0_CONTROL(gpio_num);
|
|
||||||
else if (gpio_num < 128)
|
|
||||||
gpio_address = GPIO_BANK1_CONTROL(gpio_num);
|
|
||||||
else
|
|
||||||
gpio_address = GPIO_BANK2_CONTROL(gpio_num);
|
|
||||||
|
|
||||||
return gpio_address;
|
|
||||||
}
|
|
||||||
|
|
||||||
int gpio_get(gpio_t gpio_num)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
|
|
||||||
return !!(reg & GPIO_PIN_STS);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_set(gpio_t gpio_num, int value)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
reg &= ~GPIO_OUTPUT_MASK;
|
|
||||||
reg |= !!value << GPIO_OUTPUT_SHIFT;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_input_pulldown(gpio_t gpio_num)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
reg &= ~GPIO_PULLUP_ENABLE;
|
|
||||||
reg |= GPIO_PULLDOWN_ENABLE;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_input_pullup(gpio_t gpio_num)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
reg &= ~GPIO_PULLDOWN_ENABLE;
|
|
||||||
reg |= GPIO_PULLUP_ENABLE;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_input(gpio_t gpio_num)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
reg &= ~GPIO_OUTPUT_ENABLE;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gpio_output(gpio_t gpio_num, int value)
|
|
||||||
{
|
|
||||||
uint32_t reg;
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio_num);
|
|
||||||
|
|
||||||
reg = read32((void *)gpio_address);
|
|
||||||
reg |= GPIO_OUTPUT_ENABLE;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
gpio_set(gpio_num, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *gpio_acpi_path(gpio_t gpio)
|
|
||||||
{
|
|
||||||
return "\\_SB.GPIO";
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t gpio_acpi_pin(gpio_t gpio)
|
|
||||||
{
|
|
||||||
return gpio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
|
|
||||||
{
|
|
||||||
uint32_t *gpio_ptr, *inter_master;
|
|
||||||
uint32_t control, control_flags, edge_level, direction;
|
|
||||||
uint32_t mask, bit_edge, bit_level;
|
|
||||||
uint8_t mux, index, gpio;
|
|
||||||
int gevent_num;
|
|
||||||
|
|
||||||
inter_master = (uint32_t *)(uintptr_t)(ACPIMMIO_GPIO0_BASE
|
|
||||||
+ GPIO_MASTER_SWITCH);
|
|
||||||
direction = 0;
|
|
||||||
edge_level = 0;
|
|
||||||
mask = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Disable blocking wake/interrupt status generation while updating
|
|
||||||
* debounce registers. Otherwise when a debounce register is updated
|
|
||||||
* the whole GPIO controller will zero out all interrupt enable status
|
|
||||||
* bits while the delay happens. This could cause us to drop the bits
|
|
||||||
* due to the read-modify-write that happens on each register.
|
|
||||||
*
|
|
||||||
* Additionally disable interrupt generation so we don't get any
|
|
||||||
* spurious interrupts while updating the registers.
|
|
||||||
*/
|
|
||||||
mem_read_write32(inter_master, 0, GPIO_MASK_STS_EN | GPIO_INTERRUPT_EN);
|
|
||||||
|
|
||||||
for (index = 0; index < size; index++) {
|
|
||||||
gpio = gpio_list_ptr[index].gpio;
|
|
||||||
mux = gpio_list_ptr[index].function;
|
|
||||||
control = gpio_list_ptr[index].control;
|
|
||||||
control_flags = gpio_list_ptr[index].flags;
|
|
||||||
|
|
||||||
iomux_write8(gpio, mux & AMD_GPIO_MUX_MASK);
|
|
||||||
iomux_read8(gpio); /* Flush posted write */
|
|
||||||
/* special case if pin 2 is assigned to wake */
|
|
||||||
if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK))
|
|
||||||
route_sci(GPIO_2_EVENT);
|
|
||||||
gpio_ptr = (uint32_t *)gpio_get_address(gpio);
|
|
||||||
|
|
||||||
if (control_flags & GPIO_SPECIAL_FLAG) {
|
|
||||||
gevent_num = get_gpio_gevent(gpio);
|
|
||||||
if (gevent_num < 0) {
|
|
||||||
printk(BIOS_WARNING, "Warning: GPIO pin %d has"
|
|
||||||
" no associated gevent!\n", gpio);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (control_flags & GPIO_SPECIAL_MASK) {
|
|
||||||
case GPIO_DEBOUNCE_FLAG:
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
GPIO_DEBOUNCE_MASK);
|
|
||||||
break;
|
|
||||||
case GPIO_WAKE_FLAG:
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
INT_WAKE_MASK);
|
|
||||||
break;
|
|
||||||
case GPIO_INT_FLAG:
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
AMD_GPIO_CONTROL_MASK);
|
|
||||||
break;
|
|
||||||
case GPIO_SMI_FLAG:
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
INT_SCI_SMI_MASK);
|
|
||||||
program_smi(control_flags, gevent_num);
|
|
||||||
break;
|
|
||||||
case GPIO_SCI_FLAG:
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
INT_SCI_SMI_MASK);
|
|
||||||
get_sci_config_bits(control_flags, &bit_edge,
|
|
||||||
&bit_level);
|
|
||||||
edge_level |= bit_edge << gevent_num;
|
|
||||||
direction |= bit_level << gevent_num;
|
|
||||||
mask |= (1 << gevent_num);
|
|
||||||
route_sci(gevent_num);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
printk(BIOS_WARNING, "Error, flags 0x%08x\n",
|
|
||||||
control_flags);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mem_read_write32(gpio_ptr, control,
|
|
||||||
AMD_GPIO_CONTROL_MASK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Re-enable interrupt status generation.
|
|
||||||
*
|
|
||||||
* We leave MASK_STATUS disabled because the kernel may reconfigure the
|
|
||||||
* debounce registers while the drivers load. This will cause interrupts
|
|
||||||
* to be missed during boot.
|
|
||||||
*/
|
|
||||||
mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN);
|
|
||||||
|
|
||||||
/* Set all SCI trigger direction (high/low) */
|
|
||||||
mem_read_write32((uint32_t *)
|
|
||||||
(uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_TRIG),
|
|
||||||
direction, mask);
|
|
||||||
|
|
||||||
/* Set all SCI trigger level (edge/level) */
|
|
||||||
mem_read_write32((uint32_t *)
|
|
||||||
(uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_LEVEL),
|
|
||||||
edge_level, mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
int gpio_interrupt_status(gpio_t gpio)
|
|
||||||
{
|
|
||||||
uintptr_t gpio_address = gpio_get_address(gpio);
|
|
||||||
uint32_t reg = read32((void *)gpio_address);
|
|
||||||
|
|
||||||
if (reg & GPIO_INT_STATUS) {
|
|
||||||
/* Clear interrupt status, preserve wake status */
|
|
||||||
reg &= ~GPIO_WAKE_STATUS;
|
|
||||||
write32((void *)gpio_address, reg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@@ -203,7 +203,7 @@ void sb_reset_i2c_slaves(void)
|
|||||||
/* Save and reprogram I2C SCL pins */
|
/* Save and reprogram I2C SCL pins */
|
||||||
for (i = 0; i < saved_pins_count; i++)
|
for (i = 0; i < saved_pins_count; i++)
|
||||||
save_i2c_pin_registers(i2c_2_gpi[i].gpio, &save_table[i]);
|
save_i2c_pin_registers(i2c_2_gpi[i].gpio, &save_table[i]);
|
||||||
sb_program_gpios(i2c_2_gpi, saved_pins_count);
|
program_gpios(i2c_2_gpi, saved_pins_count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Toggle SCL back and forth 9 times under 100KHz. A single read is
|
* Toggle SCL back and forth 9 times under 100KHz. A single read is
|
||||||
|
@@ -21,59 +21,13 @@
|
|||||||
|
|
||||||
#ifndef __ACPI__
|
#ifndef __ACPI__
|
||||||
#include <soc/iomap.h>
|
#include <soc/iomap.h>
|
||||||
#include <soc/smi.h>
|
#include <amdblocks/gpio_banks.h>
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
struct soc_amd_gpio {
|
/* The following sections describe only the GPIOs defined for this SOC */
|
||||||
uint8_t gpio;
|
|
||||||
uint8_t function;
|
|
||||||
uint32_t control;
|
|
||||||
uint32_t flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct soc_amd_event {
|
#define SOC_GPIO_TOTAL_PINS 149
|
||||||
uint8_t gpio;
|
|
||||||
uint8_t event;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GPIO_MASTER_SWITCH 0xFC
|
/* Bank 0: GPIO_0 - GPIO_62 */
|
||||||
#define GPIO_MASK_STS_EN BIT(28)
|
|
||||||
#define GPIO_INTERRUPT_EN BIT(30)
|
|
||||||
|
|
||||||
#define GPIO_TOTAL_PINS 149
|
|
||||||
#define GPIO_PIN_IN (1 << 0) /* for byte access */
|
|
||||||
#define GPIO_PIN_OUT (1 << 6) /* for byte access */
|
|
||||||
|
|
||||||
#define GPIO_EDGE_TRIG (0 << 8)
|
|
||||||
#define GPIO_LEVEL_TRIG (1 << 8)
|
|
||||||
#define GPIO_TRIGGER_MASK (1 << 8)
|
|
||||||
|
|
||||||
#define GPIO_ACTIVE_HIGH (0 << 9)
|
|
||||||
#define GPIO_ACTIVE_LOW (1 << 9)
|
|
||||||
#define GPIO_ACTIVE_BOTH (2 << 9)
|
|
||||||
#define GPIO_ACTIVE_MASK (3 << 9)
|
|
||||||
|
|
||||||
#define GPIO_INT_STATUS_EN (1 << 11)
|
|
||||||
#define GPIO_INT_DELIVERY_EN (1 << 12)
|
|
||||||
#define GPIO_INTERRUPT_MASK (3 << 11)
|
|
||||||
#define GPIO_S0I3_WAKE_EN (1 << 13)
|
|
||||||
#define GPIO_S3_WAKE_EN (1 << 14)
|
|
||||||
#define GPIO_S4_S5_WAKE_EN (1 << 15)
|
|
||||||
|
|
||||||
#define GPIO_PIN_STS (1 << 16)
|
|
||||||
#define GPIO_PULLUP_ENABLE (1 << 20)
|
|
||||||
#define GPIO_PULLDOWN_ENABLE (1 << 21)
|
|
||||||
#define GPIO_OUTPUT_SHIFT 22
|
|
||||||
#define GPIO_OUTPUT_MASK (1 << GPIO_OUTPUT_SHIFT)
|
|
||||||
#define GPIO_OUTPUT_VALUE (1 << GPIO_OUTPUT_SHIFT)
|
|
||||||
#define GPIO_OUTPUT_ENABLE (1 << 23)
|
|
||||||
|
|
||||||
#define GPIO_INT_STATUS (1 << 28)
|
|
||||||
#define GPIO_WAKE_STATUS (1 << 29)
|
|
||||||
|
|
||||||
/* GPIO_0 - GPIO_62 */
|
|
||||||
#define GPIO_BANK0_CONTROL(gpio) \
|
|
||||||
(AMD_SB_ACPI_MMIO_ADDR + 0x1500 + ((gpio) * 4))
|
|
||||||
#define GPIO_0 0
|
#define GPIO_0 0
|
||||||
#define GPIO_1 1
|
#define GPIO_1 1
|
||||||
#define GPIO_2 2
|
#define GPIO_2 2
|
||||||
@@ -105,9 +59,7 @@ struct soc_amd_event {
|
|||||||
#define GPIO_40 40
|
#define GPIO_40 40
|
||||||
#define GPIO_42 42
|
#define GPIO_42 42
|
||||||
|
|
||||||
/* GPIO_64 - GPIO_127 */
|
/* Bank 1: GPIO_64 - GPIO_127 */
|
||||||
#define GPIO_BANK1_CONTROL(gpio) \
|
|
||||||
(AMD_SB_ACPI_MMIO_ADDR + 0x1600 + (((gpio) - 64) * 4))
|
|
||||||
#define GPIO_64 64
|
#define GPIO_64 64
|
||||||
#define GPIO_65 65
|
#define GPIO_65 65
|
||||||
#define GPIO_66 66
|
#define GPIO_66 66
|
||||||
@@ -150,10 +102,7 @@ struct soc_amd_event {
|
|||||||
#define GPIO_122 122
|
#define GPIO_122 122
|
||||||
#define GPIO_126 126
|
#define GPIO_126 126
|
||||||
|
|
||||||
/* GPIO_128 - GPIO_183 */
|
/* Bank 2: GPIO_128 - GPIO_183 */
|
||||||
#define GPIO_BANK2_CONTROL(gpio) \
|
|
||||||
(AMD_SB_ACPI_MMIO_ADDR + 0x1700 + (((gpio) - 128) * 4))
|
|
||||||
/* GPIO_128 Reserved */
|
|
||||||
#define GPIO_129 129
|
#define GPIO_129 129
|
||||||
#define GPIO_130 130
|
#define GPIO_130 130
|
||||||
#define GPIO_131 131
|
#define GPIO_131 131
|
||||||
@@ -353,230 +302,7 @@ struct soc_amd_event {
|
|||||||
#define GPIO_148_IOMUX_I2C1_SDA 0
|
#define GPIO_148_IOMUX_I2C1_SDA 0
|
||||||
#define GPIO_148_IOMUX_GPIOxx 1
|
#define GPIO_148_IOMUX_GPIOxx 1
|
||||||
|
|
||||||
enum {
|
|
||||||
GEVENT_0,
|
|
||||||
GEVENT_1,
|
|
||||||
GEVENT_2,
|
|
||||||
GEVENT_3,
|
|
||||||
GEVENT_4,
|
|
||||||
GEVENT_5,
|
|
||||||
GEVENT_6,
|
|
||||||
GEVENT_7,
|
|
||||||
GEVENT_8,
|
|
||||||
GEVENT_9,
|
|
||||||
GEVENT_10,
|
|
||||||
GEVENT_11,
|
|
||||||
GEVENT_12,
|
|
||||||
GEVENT_13,
|
|
||||||
GEVENT_14,
|
|
||||||
GEVENT_15,
|
|
||||||
GEVENT_16,
|
|
||||||
GEVENT_17,
|
|
||||||
GEVENT_18,
|
|
||||||
GEVENT_19,
|
|
||||||
GEVENT_20,
|
|
||||||
GEVENT_21,
|
|
||||||
GEVENT_22,
|
|
||||||
GEVENT_23,
|
|
||||||
};
|
|
||||||
#define GPIO_2_EVENT GEVENT_8
|
#define GPIO_2_EVENT GEVENT_8
|
||||||
|
|
||||||
#define GPIO_OUTPUT_OUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_VALUE)
|
|
||||||
#define GPIO_OUTPUT_OUT_LOW GPIO_OUTPUT_ENABLE
|
|
||||||
|
|
||||||
#define GPIO_PULL_PULL_UP GPIO_PULLUP_ENABLE
|
|
||||||
#define GPIO_PULL_PULL_DOWN GPIO_PULLDOWN_ENABLE
|
|
||||||
#define GPIO_PULL_PULL_NONE 0
|
|
||||||
|
|
||||||
#define AMD_GPIO_CONTROL_MASK 0x00f4ff00
|
|
||||||
#define AMD_GPIO_MUX_MASK 0x03
|
|
||||||
|
|
||||||
/* Definitions for PAD_INT. */
|
|
||||||
#define GPIO_INT_EDGE_HIGH (GPIO_ACTIVE_HIGH | GPIO_EDGE_TRIG)
|
|
||||||
#define GPIO_INT_EDGE_LOW (GPIO_ACTIVE_LOW | GPIO_EDGE_TRIG)
|
|
||||||
#define GPIO_INT_BOTH_EDGES (GPIO_ACTIVE_BOTH | GPIO_EDGE_TRIG)
|
|
||||||
#define GPIO_INT_LEVEL_HIGH (GPIO_ACTIVE_HIGH | GPIO_LEVEL_TRIG)
|
|
||||||
#define GPIO_INT_LEVEL_LOW (GPIO_ACTIVE_LOW | GPIO_LEVEL_TRIG)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
GPIO_TRIGGER_LEVEL_LOW,
|
|
||||||
GPIO_TRIGGER_LEVEL_HIGH,
|
|
||||||
GPIO_TRIGGER_EDGE_LOW,
|
|
||||||
GPIO_TRIGGER_EDGE_HIGH,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define GPIO_TRIGGER_INVALID -1
|
|
||||||
#define SCI_TRIGGER_EDGE 0
|
|
||||||
#define SCI_TRIGGER_LEVEL 1
|
|
||||||
|
|
||||||
#define GPIO_SPECIAL_FLAG (1 << 31)
|
|
||||||
#define GPIO_DEBOUNCE_FLAG (1 << 30)
|
|
||||||
#define GPIO_WAKE_FLAG (1 << 29)
|
|
||||||
#define GPIO_INT_FLAG (1 << 28)
|
|
||||||
#define GPIO_SMI_FLAG (1 << 27)
|
|
||||||
#define GPIO_SCI_FLAG (1 << 26)
|
|
||||||
#define GPIO_FLAG_DEBOUNCE (GPIO_SPECIAL_FLAG | GPIO_DEBOUNCE_FLAG)
|
|
||||||
#define GPIO_FLAG_WAKE (GPIO_SPECIAL_FLAG | GPIO_WAKE_FLAG)
|
|
||||||
#define GPIO_FLAG_INT (GPIO_SPECIAL_FLAG | GPIO_INT_FLAG)
|
|
||||||
#define GPIO_FLAG_SCI (GPIO_SPECIAL_FLAG | GPIO_SCI_FLAG)
|
|
||||||
#define GPIO_FLAG_SMI (GPIO_SPECIAL_FLAG | GPIO_SMI_FLAG)
|
|
||||||
|
|
||||||
#define FLAGS_TRIGGER_MASK 0x00000003
|
|
||||||
#define GPIO_SPECIAL_MASK 0x7c000000
|
|
||||||
#define GPIO_DEBOUNCE_MASK 0x000000ff
|
|
||||||
#define INT_TRIGGER_MASK 0x00000700
|
|
||||||
#define INT_WAKE_MASK 0x0000e700
|
|
||||||
#define INT_SCI_SMI_MASK 0x00f40000
|
|
||||||
|
|
||||||
#define IN_GLITCH_SHIFT 5
|
|
||||||
#define GLITCH_LOW 1
|
|
||||||
#define GLITCH_HIGH 2
|
|
||||||
#define GLITCH_NONE 3
|
|
||||||
#define GPIO_IN_PRESERVE_LOW_GLITCH (GLITCH_LOW << IN_GLITCH_SHIFT)
|
|
||||||
#define GPIO_IN_PRESERVE_HIGH_GLITCH (GLITCH_HIGH << IN_GLITCH_SHIFT)
|
|
||||||
#define GPIO_IN_REMOVE_GLITCH (GLITCH_NONE << IN_GLITCH_SHIFT)
|
|
||||||
|
|
||||||
#define GPIO_TIMEBASE_61uS 0
|
|
||||||
#define GPIO_TIMEBASE_183uS (1 << 4)
|
|
||||||
#define GPIO_TIMEBASE_15560uS (1 << 7)
|
|
||||||
#define GPIO_TIMEBASE_62440uS (GPIO_TIMEBASE_183uS | \
|
|
||||||
GPIO_TIMEBASE_15560uS)
|
|
||||||
#define GPIO_IN_DEBOUNCE_DISABLED (0 | GPIO_TIMEBASE_61uS)
|
|
||||||
#define GPIO_IN_60uS (1 | GPIO_TIMEBASE_61uS)
|
|
||||||
#define GPIO_IN_120uS (2 | GPIO_TIMEBASE_61uS)
|
|
||||||
#define GPIO_IN_200uS (3 | GPIO_TIMEBASE_61uS)
|
|
||||||
#define GPIO_IN_500uS (8 | GPIO_TIMEBASE_61uS)
|
|
||||||
#define GPIO_IN_1mS (5 | GPIO_TIMEBASE_183uS)
|
|
||||||
#define GPIO_IN_2mS (11 | GPIO_TIMEBASE_183uS)
|
|
||||||
#define GPIO_IN_15mS (1 | GPIO_TIMEBASE_15560uS)
|
|
||||||
#define GPIO_IN_50mS (3 | GPIO_TIMEBASE_15560uS)
|
|
||||||
#define GPIO_IN_100mS (6 | GPIO_TIMEBASE_15560uS)
|
|
||||||
#define GPIO_IN_200mS (13 | GPIO_TIMEBASE_15560uS)
|
|
||||||
#define GPIO_IN_500mS (8 | GPIO_TIMEBASE_62440uS)
|
|
||||||
|
|
||||||
#define GPIO_EVENT_INT_STATUS GPIO_INT_STATUS_EN
|
|
||||||
#define GPIO_EVENT_INT_DELIVER GPIO_INT_DELIVERY_EN
|
|
||||||
#define GPIO_EVENT_INT_STATUS_DELIVER (GPIO_INT_STATUS_EN | \
|
|
||||||
GPIO_INT_DELIVERY_EN)
|
|
||||||
#define GPIO_WAKE_S0i3 (1 << 13)
|
|
||||||
#define GPIO_WAKE_S3 (1 << 14)
|
|
||||||
#define GPIO_WAKE_S4_S5 (1 << 15)
|
|
||||||
#define GPIO_WAKE_S0i3_S4_S5 (GPIO_WAKE_S0i3 | GPIO_WAKE_S4_S5)
|
|
||||||
#define GPIO_WAKE_S3_S4_S5 (GPIO_WAKE_S3 | GPIO_WAKE_S4_S5)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Several macros are available to declare programming of GPIO pins, and if
|
|
||||||
* needed, more than 1 macro can be used for any pin. However, some macros
|
|
||||||
* will have no effect if combined. For example debounce only affects input
|
|
||||||
* or one of the interrupts. Some macros should not be combined, such as SMI
|
|
||||||
* and regular interrupt. The defined macros and their parameters are:
|
|
||||||
* PAD_NF Define native alternate function for the pin.
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* function the native function
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* PAD_GPI The pin is a GPIO input
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* PAD_GPO The pin is a GPIO output
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* direction high or low
|
|
||||||
* PAD_INT The pin is regular interrupt that works while booting
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
|
|
||||||
* action STATUS, DELIVER, STATUS_DELIVER
|
|
||||||
* PAD_SCI The pin is a SCI source
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH
|
|
||||||
* PAD_SMI The pin is a SMI source
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* trigger LEVEL_LOW, LEVEL_HIGH
|
|
||||||
* PAD_WAKE The pin can wake, use after PAD_INT or PAD_SCI
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* pull pull up, pull down or no pull
|
|
||||||
* trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
|
|
||||||
* type S0i3, S3, S4_S5 or S4_S5 combinations (S0i3_S3 invalid)
|
|
||||||
* PAD_DEBOUNCE The input or interrupt will be debounced, invalid after
|
|
||||||
* PAD_NF
|
|
||||||
* pin the pin to be programmed
|
|
||||||
* debounce_type preserve low glitch, preserve high glitch, no glitch
|
|
||||||
* debounce_time the debounce time
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Native function pad configuration */
|
|
||||||
#define PAD_NF(pin, func, pull) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## func, \
|
|
||||||
.control = GPIO_PULL ## _ ## pull, \
|
|
||||||
.flags = 0 }
|
|
||||||
/* General purpose input pad configuration */
|
|
||||||
#define PAD_GPI(pin, pull) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = GPIO_PULL ## _ ## pull, \
|
|
||||||
.flags = 0 }
|
|
||||||
/* General purpose output pad configuration */
|
|
||||||
#define PAD_GPO(pin, direction) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = GPIO_OUTPUT ## _OUT_ ## direction, \
|
|
||||||
.flags = 0 }
|
|
||||||
/* Auxiliary macro for legacy interrupt and wake */
|
|
||||||
#define PAD_AUX1(pull, trigger) (GPIO_PULL ## _ ## pull | \
|
|
||||||
GPIO_INT ## _ ## trigger)
|
|
||||||
/* Legacy interrupt pad configuration */
|
|
||||||
#define PAD_INT(pin, pull, trigger, action) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = (PAD_AUX1(pull, trigger) | \
|
|
||||||
GPIO_EVENT_INT ## _ ## action), \
|
|
||||||
.flags = GPIO_FLAG_INT }
|
|
||||||
/* Auxiliary macro for SCI and SMI */
|
|
||||||
#define PAD_AUX2(trigger, flag) (GPIO_TRIGGER ## _ ## trigger | flag)
|
|
||||||
/* SCI pad configuration */
|
|
||||||
#define PAD_SCI(pin, pull, trigger) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = GPIO_PULL ## _ ## pull, \
|
|
||||||
.flags = PAD_AUX2(trigger, GPIO_FLAG_SCI) }
|
|
||||||
/* SMI pad configuration */
|
|
||||||
#define PAD_SMI(pin, pull, trigger) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = GPIO_PULL ## _ ## pull, \
|
|
||||||
.flags = PAD_AUX2(trigger, GPIO_FLAG_SMI) }
|
|
||||||
/* WAKE pad configuration */
|
|
||||||
#define PAD_WAKE(pin, pull, trigger, type) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = (PAD_AUX1(pull, trigger) | \
|
|
||||||
GPIO_WAKE ## _ ## type), \
|
|
||||||
.flags = GPIO_FLAG_WAKE }
|
|
||||||
/* pin debounce configuration */
|
|
||||||
#define PAD_DEBOUNCE(pin, type, time) \
|
|
||||||
{ .gpio = (pin), \
|
|
||||||
.function = pin ## _IOMUX_ ## GPIOxx, \
|
|
||||||
.control = (GPIO_IN ## _ ## type | GPIO_IN ## _ ## time), \
|
|
||||||
.flags = GPIO_FLAG_DEBOUNCE }
|
|
||||||
|
|
||||||
typedef uint32_t gpio_t;
|
|
||||||
/* Get the address of the control register of a particular pin */
|
|
||||||
uintptr_t gpio_get_address(gpio_t gpio_num);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief program a particular set of GPIO
|
|
||||||
*
|
|
||||||
* @param gpio_list_ptr = pointer to array of gpio configurations
|
|
||||||
* @param size = number of entries in array
|
|
||||||
*
|
|
||||||
* @return none
|
|
||||||
*/
|
|
||||||
void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size);
|
|
||||||
|
|
||||||
/* Return the interrupt status and clear if set. */
|
|
||||||
int gpio_interrupt_status(gpio_t gpio);
|
|
||||||
|
|
||||||
#endif /* __ACPI__ */
|
#endif /* __ACPI__ */
|
||||||
#endif /* __STONEYRIDGE_GPIO_H__ */
|
#endif /* __STONEYRIDGE_GPIO_H__ */
|
||||||
|
@@ -233,6 +233,7 @@ void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level);
|
|||||||
void configure_scimap(const struct sci_source *sci);
|
void configure_scimap(const struct sci_source *sci);
|
||||||
void disable_gevent_smi(uint8_t gevent);
|
void disable_gevent_smi(uint8_t gevent);
|
||||||
void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes);
|
void gpe_configure_sci(const struct sci_source *scis, size_t num_gpes);
|
||||||
|
void soc_route_sci(uint8_t event);
|
||||||
|
|
||||||
#ifndef __SMM__
|
#ifndef __SMM__
|
||||||
void enable_smi_generation(void);
|
void enable_smi_generation(void);
|
||||||
|
Reference in New Issue
Block a user