diff options
Diffstat (limited to 'src/soc/nvidia/tegra')
-rw-r--r-- | src/soc/nvidia/tegra/gpio.c | 240 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/gpio.h | 63 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/pingroup.c | 35 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/pingroup.h | 43 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/pinmux.c | 35 | ||||
-rw-r--r-- | src/soc/nvidia/tegra/pinmux.h | 44 |
6 files changed, 460 insertions, 0 deletions
diff --git a/src/soc/nvidia/tegra/gpio.c b/src/soc/nvidia/tegra/gpio.c new file mode 100644 index 0000000000..d4b5bddd49 --- /dev/null +++ b/src/soc/nvidia/tegra/gpio.c @@ -0,0 +1,240 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <console/console.h> +#include <soc/addressmap.h> +#include <stddef.h> +#include <stdint.h> + +#include "gpio.h" +#include "pinmux.h" + +static void gpio_input_common(int gpio_index, int pinmux_index, + uint32_t pconfig) +{ + pconfig |= PINMUX_INPUT_ENABLE; + gpio_set_int_enable(gpio_index, 0); + gpio_set_mode(gpio_index, GPIO_MODE_GPIO); + gpio_set_out_enable(gpio_index, 0); + pinmux_set_config(pinmux_index, pconfig); +} + +void gpio_input(int gpio_index, int pinmux_index) +{ + gpio_input_common(gpio_index, pinmux_index, PINMUX_PULL_NONE); +} + +void gpio_input_pullup(int gpio_index, int pinmux_index) +{ + gpio_input_common(gpio_index, pinmux_index, PINMUX_PULL_UP); +} + +void gpio_input_pulldown(int gpio_index, int pinmux_index) +{ + gpio_input_common(gpio_index, pinmux_index, PINMUX_PULL_DOWN); +} + +void gpio_output(int gpio_index, int pinmux_index, int value) +{ + uint32_t pconfig = PINMUX_PULL_NONE; + + pinmux_set_config(pinmux_index, pconfig | PINMUX_TRISTATE); + gpio_set_int_enable(gpio_index, 0); + gpio_set_mode(gpio_index, GPIO_MODE_GPIO); + gpio_set_out_enable(gpio_index, 1); + gpio_set_out_value(gpio_index, value); + pinmux_set_config(pinmux_index, pconfig); +} + +enum { + GPIO_GPIOS_PER_PORT = 8, + GPIO_PORTS_PER_BANK = 4, + GPIO_BANKS = 8, + + GPIO_GPIOS_PER_BANK = GPIO_GPIOS_PER_PORT * GPIO_PORTS_PER_BANK, + GPIO_GPIOS = GPIO_BANKS * GPIO_GPIOS_PER_BANK +}; + +struct gpio_bank { + // Values + uint32_t config[GPIO_PORTS_PER_BANK]; + uint32_t out_enable[GPIO_PORTS_PER_BANK]; + uint32_t out_value[GPIO_PORTS_PER_BANK]; + uint32_t in_value[GPIO_PORTS_PER_BANK]; + uint32_t int_status[GPIO_PORTS_PER_BANK]; + uint32_t int_enable[GPIO_PORTS_PER_BANK]; + uint32_t int_level[GPIO_PORTS_PER_BANK]; + uint32_t int_clear[GPIO_PORTS_PER_BANK]; + + // Masks + uint32_t config_mask[GPIO_PORTS_PER_BANK]; + uint32_t out_enable_mask[GPIO_PORTS_PER_BANK]; + uint32_t out_value_mask[GPIO_PORTS_PER_BANK]; + uint32_t in_value_mask[GPIO_PORTS_PER_BANK]; + uint32_t int_status_mask[GPIO_PORTS_PER_BANK]; + uint32_t int_enable_mask[GPIO_PORTS_PER_BANK]; + uint32_t int_level_mask[GPIO_PORTS_PER_BANK]; + uint32_t int_clear_mask[GPIO_PORTS_PER_BANK]; +}; + +static const struct gpio_bank *gpio_banks = (void *)TEGRA_GPIO_BASE; + +static uint32_t gpio_read_port(int index, size_t offset) +{ + int bank = index / GPIO_GPIOS_PER_BANK; + int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT; + + return read32((uint8_t *)&gpio_banks[bank] + offset + + port * sizeof(uint32_t)); +} + +static void gpio_write_port(int index, size_t offset, + uint32_t mask, uint32_t value) +{ + int bank = index / GPIO_GPIOS_PER_BANK; + int port = (index - bank * GPIO_GPIOS_PER_BANK) / GPIO_GPIOS_PER_PORT; + + uint32_t reg = read32((uint8_t *)&gpio_banks[bank] + offset + + port * sizeof(uint32_t)); + uint32_t new_reg = (reg & ~mask) | (value & mask); + + if (new_reg != reg) { + write32(new_reg, (uint8_t *)&gpio_banks[bank] + offset + + port * sizeof(uint32_t)); + } +} + +void gpio_set_mode(int gpio_index, enum gpio_mode mode) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, config), + 1 << bit, mode ? (1 << bit) : 0); +} + +int gpio_get_mode(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, config)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_lock(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, config), + 1 << bit, 1 << bit); +} + +int gpio_get_lock(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT + GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, config)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_out_enable(int gpio_index, int enable) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, out_enable), + 1 << bit, enable ? (1 << bit) : 0); +} + +int gpio_get_out_enable(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, out_enable)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_out_value(int gpio_index, int value) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, out_value), + 1 << bit, value ? (1 << bit) : 0); +} + +int gpio_get_out_value(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, out_value)); + return (port & (1 << bit)) != 0; +} + +int gpio_get_in_value(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, in_value)); + return (port & (1 << bit)) != 0; +} + +int gpio_get_int_status(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, int_status)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_int_enable(int gpio_index, int enable) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, int_enable), + 1 << bit, enable ? (1 << bit) : 0); +} + +int gpio_get_int_enable(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, int_enable)); + return (port & (1 << bit)) != 0; +} + +void gpio_set_int_level(int gpio_index, int high_rise, int edge, int delta) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t value = (high_rise ? (0x000001 << bit) : 0) | + (edge ? (0x000100 << bit) : 0) | + (delta ? (0x010000 << bit) : 0); + gpio_write_port(gpio_index, offsetof(struct gpio_bank, config), + 0x010101 << bit, value); +} + +void gpio_get_int_level(int gpio_index, int *high_rise, int *edge, int *delta) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + uint32_t port = gpio_read_port(gpio_index, + offsetof(struct gpio_bank, int_level)); + *high_rise = ((port & (0x000001 << bit)) != 0); + *edge = ((port & (0x000100 << bit)) != 0); + *delta = ((port & (0x010000 << bit)) != 0); +} + +void gpio_set_int_clear(int gpio_index) +{ + int bit = gpio_index % GPIO_GPIOS_PER_PORT; + gpio_write_port(gpio_index, offsetof(struct gpio_bank, int_clear), + 1 << bit, 1 << bit); +} diff --git a/src/soc/nvidia/tegra/gpio.h b/src/soc/nvidia/tegra/gpio.h new file mode 100644 index 0000000000..b62dc90906 --- /dev/null +++ b/src/soc/nvidia/tegra/gpio.h @@ -0,0 +1,63 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_GPIO_H__ +#define __SOC_NVIDIA_TEGRA_GPIO_H__ + +#include <stdint.h> + +/* Higher level functions for common GPIO configurations. */ + +void gpio_input(int gpio_index, int pinmux_index); +void gpio_input_pullup(int gpio_index, int pinmux_index); +void gpio_input_pulldown(int gpio_index, int pinmux_index); +void gpio_output(int gpio_index, int pinmux_index, int value); + +/* Functions to modify specific GPIO control values. */ + +enum gpio_mode { + GPIO_MODE_SPIO = 0, + GPIO_MODE_GPIO = 1 +}; +void gpio_set_mode(int gpio_index, enum gpio_mode); +int gpio_get_mode(int gpio_index); + +// Lock a GPIO with extreme caution since they can't be unlocked. +void gpio_set_lock(int gpio_index); +int gpio_get_lock(int gpio_index); + +void gpio_set_out_enable(int gpio_index, int enable); +int gpio_get_out_enable(int gpio_index); + +void gpio_set_out_value(int gpio_index, int value); +int gpio_get_out_value(int gpio_index); + +int gpio_get_in_value(int gpio_index); + +int gpio_get_int_status(int gpio_index); + +void gpio_set_int_enable(int gpio_index, int enable); +int gpio_get_int_enable(int gpio_index); + +void gpio_set_int_level(int gpio_index, int high_rise, int edge, int delta); +void gpio_get_int_level(int gpio_index, int *high_rise, int *edge, int *delta); + +void gpio_set_int_clear(int gpio_index); + +#endif /* __SOC_NVIDIA_TEGRA_GPIO_H__ */ diff --git a/src/soc/nvidia/tegra/pingroup.c b/src/soc/nvidia/tegra/pingroup.c new file mode 100644 index 0000000000..858cb44e34 --- /dev/null +++ b/src/soc/nvidia/tegra/pingroup.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <soc/addressmap.h> + +#include "pingroup.h" + +static uint32_t *pingroup_regs = (void *)TEGRA_APB_PINGROUP_BASE; + +void pingroup_set_config(int group_index, uint32_t config) +{ + write32(config, &pingroup_regs[group_index]); +} + +uint32_t pingroup_get_config(int group_index) +{ + return read32(&pingroup_regs[group_index]); +} diff --git a/src/soc/nvidia/tegra/pingroup.h b/src/soc/nvidia/tegra/pingroup.h new file mode 100644 index 0000000000..f04b66541d --- /dev/null +++ b/src/soc/nvidia/tegra/pingroup.h @@ -0,0 +1,43 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_PINGROUP_H__ +#define __SOC_NVIDIA_TEGRA_PINGROUP_H__ + +#include <stdint.h> + +void pingroup_set_config(int group_index, uint32_t config); +uint32_t pingroup_get_config(int group_index); + +enum { + PINGROUP_HSM = 1 << 2, + PINGROUP_SCHMT = 1 << 3, + PINGROUP_LPMD_SHIFT = 4, + PINGROUP_LPMD_MASK = 3 << 4, + PINGROUP_DRVDN_SHIFT = 12, + PINGROUP_DRVDN_MASK = 0x7f << 12, + PINGROUP_DRVUP_SHIFT = 20, + PINGROUP_DRVUP_MASK = 0x7f << 20, + PINGROUP_SLWR_SHIFT = 28, + PINGROUP_SLWR_MASK = 0x3 << 28, + PINGROUP_SLWF_SHIFT = 30, + PINGROUP_SLWF_MASK = 0x3 << 30 +}; + +#endif /* __SOC_NVIDIA_TEGRA_PINGROUP_H__ */ diff --git a/src/soc/nvidia/tegra/pinmux.c b/src/soc/nvidia/tegra/pinmux.c new file mode 100644 index 0000000000..6e4b3ff195 --- /dev/null +++ b/src/soc/nvidia/tegra/pinmux.c @@ -0,0 +1,35 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <arch/io.h> +#include <soc/addressmap.h> + +#include "pinmux.h" + +static uint32_t *pinmux_regs = (void *)TEGRA_APB_PINMUX_BASE; + +void pinmux_set_config(int pin_index, uint32_t config) +{ + write32(config, &pinmux_regs[pin_index]); +} + +uint32_t pinmux_get_config(int pin_index) +{ + return read32(&pinmux_regs[pin_index]); +} diff --git a/src/soc/nvidia/tegra/pinmux.h b/src/soc/nvidia/tegra/pinmux.h new file mode 100644 index 0000000000..e42135d9a4 --- /dev/null +++ b/src/soc/nvidia/tegra/pinmux.h @@ -0,0 +1,44 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2013 Google 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __SOC_NVIDIA_TEGRA_PINMUX_H__ +#define __SOC_NVIDIA_TEGRA_PINMUX_H__ + +#include <stdint.h> + +void pinmux_set_config(int pin_index, uint32_t config); +uint32_t pinmux_get_config(int pin_index); + +enum { + PINMUX_FUNC_MASK = 3 << 0, + + PINMUX_PULL_MASK = 3 << 2, + PINMUX_PULL_NONE = 0 << 2, + PINMUX_PULL_DOWN = 1 << 2, + PINMUX_PULL_UP = 2 << 2, + + PINMUX_TRISTATE = 1 << 4, + PINMUX_INPUT_ENABLE = 1 << 5, + PINMUX_OPEN_DRAIN = 1 << 6, + PINMUX_LOCK = 1 << 7, + PINMUX_IO_RESET = 1 << 8, + PINMUX_RCV_SEL = 1 << 9 +}; + +#endif /* __SOC_NVIDIA_TEGRA_PINMUX_H__ */ |