Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14909
-gerrit
commit 38acc1148488a5c7f62b74f22bac8272cdd7f506 Author: Akshay Saraswat akshay.s@samsung.com Date: Thu Aug 7 15:26:33 2014 +0530
Exynos7: Add GPIO/Pinmux setup
Adding GPIO/Pinmux support in Exynos7 to program GPIO pads specific to various IPs.
Change-Id: I339adf3274563364809eb948ecc9a711b07a77e5 Signed-off-by: Akshay Saraswat akshay.s@samsung.com Signed-off-by: Stefan Reinauer stefan.reinauer@coreboot.org --- src/soc/samsung/exynos7/Makefile.inc | 6 + src/soc/samsung/exynos7/bootblock.c | 9 + src/soc/samsung/exynos7/gpio.c | 225 +++++++++++ src/soc/samsung/exynos7/include/soc/gpio.h | 538 +++++++++++++++++++++++++++ src/soc/samsung/exynos7/include/soc/pinmux.h | 55 +++ src/soc/samsung/exynos7/pinmux.c | 277 ++++++++++++++ 6 files changed, 1110 insertions(+)
diff --git a/src/soc/samsung/exynos7/Makefile.inc b/src/soc/samsung/exynos7/Makefile.inc index eeb9fcf..898260d 100644 --- a/src/soc/samsung/exynos7/Makefile.inc +++ b/src/soc/samsung/exynos7/Makefile.inc @@ -22,23 +22,29 @@ bootblock-y += bootblock.c bootblock-y += clock.c bootblock-y += clock_init.c bootblock-y += dmc_init_lpddr4.c +bootblock-y += gpio.c bootblock-y += mct.c bootblock-y += monotonic_timer.c +bootblock-y += pinmux.c bootblock-y += power.c bootblock-y += timer.c
# ROMSTAGE : Run primitive tests and remaining basic stuff romstage-y += clock.c +romstage-y += gpio.c romstage-y += mct.c romstage-y += monotonic_timer.c +romstage-y += pinmux.c romstage-y += power.c romstage-y += timer.c
# RAMSTAGE : Prepare and load payload ramstage-y += clock.c ramstage-y += cpu.c +ramstage-y += gpio.c ramstage-y += mct.c ramstage-y += monotonic_timer.c +ramstage-y += pinmux.c ramstage-y += power.c ramstage-y += timer.c
diff --git a/src/soc/samsung/exynos7/bootblock.c b/src/soc/samsung/exynos7/bootblock.c index 7183731..71650e0 100644 --- a/src/soc/samsung/exynos7/bootblock.c +++ b/src/soc/samsung/exynos7/bootblock.c @@ -22,6 +22,7 @@ #include <soc/cpu.h> #include <soc/dmc.h> #include <soc/mct.h> +#include <soc/pinmux.h> #include <soc/power.h>
void bootblock_cpu_init(void) @@ -54,4 +55,12 @@ void bootblock_cpu_init(void)
/* Initialize SDRAM */ mem_ctrl_init_lpddr4(is_resume); + + /* Set GPIOs for UART */ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART0)) + exynos_pinmux_uart0(); + else if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART1)) + exynos_pinmux_uart1(); + else if (IS_ENABLED(CONFIG_CONSOLE_SERIAL_UART2)) + exynos_pinmux_uart2(); } diff --git a/src/soc/samsung/exynos7/gpio.c b/src/soc/samsung/exynos7/gpio.c new file mode 100644 index 0000000..9ffebd2 --- /dev/null +++ b/src/soc/samsung/exynos7/gpio.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * 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 <console/console.h> +#include <string.h> +#include <delay.h> +#include <assert.h> +#include <soc/gpio.h> +#include <soc/cpu.h> + +#define CON_MASK(x) (0xf << ((x) << 2)) +#define CON_SFR(x, v) ((v) << ((x) << 2)) + +#define DAT_MASK(x) (0x1 << (x)) +#define DAT_SET(x) (0x1 << (x)) + +#define PULL_MASK(x) (0x3 << ((x) << 1)) +#define PULL_MODE(x, v) ((v) << ((x) << 1)) + +#define DRV_MASK(x) (0x3 << ((x) << 1)) +#define DRV_SET(x, m) ((m) << ((x) << 1)) +#define RATE_MASK(x) (0x1 << (x + 16)) +#define RATE_SET(x) (0x1 << (x + 16)) + +void exynos_gpio_cfg_pin(struct exynos_gpio_bank *bank, int gpio, int cfg) +{ + unsigned int value; + + value = read32(&bank->con); + value &= ~CON_MASK(gpio); + value |= CON_SFR(gpio, cfg); + write32(&bank->con, value); +} + +void exynos_gpio_direction_output(struct exynos_gpio_bank *bank, int gpio, int en) +{ + unsigned int value; + + exynos_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_OUTPUT); + + value = read32(&bank->dat); + value &= ~DAT_MASK(gpio); + if (en) + value |= DAT_SET(gpio); + write32(&bank->dat, value); +} + +void exynos_gpio_direction_input(struct exynos_gpio_bank *bank, int gpio) +{ + exynos_gpio_cfg_pin(bank, gpio, EXYNOS_GPIO_INPUT); +} + +void exynos_gpio_set_value(struct exynos_gpio_bank *bank, int gpio, int en) +{ + unsigned int value; + + value = read32(&bank->dat); + value &= ~DAT_MASK(gpio); + if (en) + value |= DAT_SET(gpio); + write32(&bank->dat, value); +} + +unsigned int exynos_gpio_get_value(struct exynos_gpio_bank *bank, int gpio) +{ + unsigned int value; + + value = read32(&bank->dat); + return !!(value & DAT_MASK(gpio)); +} + +void exynos_gpio_set_pull(struct exynos_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = read32(&bank->pull); + value &= ~PULL_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_PULL_DOWN: + case EXYNOS_GPIO_PULL_UP: + value |= PULL_MODE(gpio, mode); + break; + default: + break; + } + + write32(&bank->pull, value); +} + +void exynos_gpio_set_drv(struct exynos_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = read32(&bank->drv); + value &= ~DRV_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_DRV_1X: + case EXYNOS_GPIO_DRV_2X: + case EXYNOS_GPIO_DRV_3X: + case EXYNOS_GPIO_DRV_4X: + value |= DRV_SET(gpio, mode); + break; + default: + return; + } + + write32(&bank->drv, value); +} + +void exynos_gpio_set_rate(struct exynos_gpio_bank *bank, int gpio, int mode) +{ + unsigned int value; + + value = read32(&bank->drv); + value &= ~RATE_MASK(gpio); + + switch (mode) { + case EXYNOS_GPIO_DRV_FAST: + case EXYNOS_GPIO_DRV_SLOW: + value |= RATE_SET(gpio); + break; + default: + return; + } + + write32(&bank->drv, value); +} + +static struct exynos_gpio_bank *exynos_gpio_get_bank(unsigned int gpio) +{ + const struct gpio_info *data; + unsigned int upto; + int i, count; + + data = get_gpio_data(); + count = get_bank_num(); + for (i = upto = 0; i < count; + i++, upto = data->max_gpio, data++) { + printk(BIOS_INFO, "i=%d, upto=%d\n", i, upto); + if (gpio < data->max_gpio) { + struct exynos_gpio_bank *bank; + bank = (struct exynos_gpio_bank *)data->reg_addr; + bank += (gpio - upto) / GPIO_PER_BANK; + printk(BIOS_INFO, "gpio=%d, bank=%p\n", gpio, bank); + return bank; + } + } + return NULL; +} + +int exynos_gpio_get_pin(unsigned gpio) +{ + return gpio % GPIO_PER_BANK; +} + +/* Common GPIO API */ +int gpio_request(unsigned gpio, const char *label) +{ + return 0; +} + +int gpio_free(unsigned gpio) +{ + return 0; +} + +int gpio_direction_input(unsigned gpio) +{ + exynos_gpio_direction_input(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio)); + return 0; +} + +int gpio_direction_output(unsigned gpio, int value) +{ + exynos_gpio_direction_output(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio), value); + return 0; +} + +int gpio_get_value(unsigned gpio) +{ + return (int) exynos_gpio_get_value(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio)); +} + +int gpio_set_value(unsigned gpio, int value) +{ + exynos_gpio_set_value(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio), value); + + return 0; +} + +void gpio_set_pull(int gpio, int value) +{ + exynos_gpio_set_pull(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio), value); +} + +void gpio_cfg_pin(int gpio, int cfg) +{ + exynos_gpio_cfg_pin(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio), cfg); +} + +void gpio_set_drv(int gpio, int drv) +{ + exynos_gpio_set_drv(exynos_gpio_get_bank(gpio), + exynos_gpio_get_pin(gpio), drv); +} diff --git a/src/soc/samsung/exynos7/include/soc/gpio.h b/src/soc/samsung/exynos7/include/soc/gpio.h new file mode 100644 index 0000000..c9c98b6 --- /dev/null +++ b/src/soc/samsung/exynos7/include/soc/gpio.h @@ -0,0 +1,538 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * 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 _CPU_SAMSUNG_EXYNOS7_GPIO_H_ +#define _CPU_SAMSUNG_EXYNOS7_GPIO_H_ + +#include <soc/cpu.h> + +struct exynos_gpio_bank { + unsigned int con; + unsigned int dat; + unsigned int pull; + unsigned int drv; + unsigned int pdn_con; + unsigned int pdn_pull; + unsigned char res1[8]; +}; + +struct exynos7_gpio_part1 { /* 0x1058_0000 - ALIVE */ + struct exynos_gpio_bank a0; + struct exynos_gpio_bank a1; + struct exynos_gpio_bank a2; + struct exynos_gpio_bank a3; +}; + +struct exynos7_gpio_part2 { /* 0x114B_0000 -AUD */ + struct exynos_gpio_bank z0; + struct exynos_gpio_bank z1; +}; + +struct exynos7_gpio_part3 { /* 0x1347_0000 - BUS0 */ + struct exynos_gpio_bank b0; + struct exynos_gpio_bank c0; + struct exynos_gpio_bank c1; + struct exynos_gpio_bank c2; + struct exynos_gpio_bank c3; + struct exynos_gpio_bank d0; + struct exynos_gpio_bank d1; + struct exynos_gpio_bank d2; + struct exynos_gpio_bank d4; + struct exynos_gpio_bank d5; + struct exynos_gpio_bank d6; + struct exynos_gpio_bank d7; + struct exynos_gpio_bank d8; + struct exynos_gpio_bank g0; + struct exynos_gpio_bank g3; +}; + +struct exynos7_gpio_part4 { /* 0x1487_0000 - BUS1 */ + struct exynos_gpio_bank reserved; + struct exynos_gpio_bank f0; + struct exynos_gpio_bank f1; + struct exynos_gpio_bank f2; + struct exynos_gpio_bank f3; + struct exynos_gpio_bank f4; + struct exynos_gpio_bank f5; + struct exynos_gpio_bank g1; + struct exynos_gpio_bank g2; + struct exynos_gpio_bank h1; + struct exynos_gpio_bank v6; +}; + +struct exynos7_gpio_part5 { /* 0x14cd_0000 - NFC */ + struct exynos_gpio_bank j0; +}; + +struct exynos7_gpio_part6 { /* 0x14ce_0000 - TOUCH */ + struct exynos_gpio_bank j1; +}; + +struct exynos7_gpio_part7 { /* 0x14c9_0000 - FF */ + struct exynos_gpio_bank g4; +}; + +struct exynos7_gpio_part8 { /* 0x14ca_0000 - ESE */ + struct exynos_gpio_bank v7; +}; + +struct exynos7_gpio_part9 { /* 0x10e6_0000 - FSYS0 */ + struct exynos_gpio_bank r4; +}; + +struct exynos7_gpio_part10 { /* 0x1569_0000 - FSYS1 */ + struct exynos_gpio_bank r0; + struct exynos_gpio_bank r1; + struct exynos_gpio_bank r2; + struct exynos_gpio_bank r3; +}; + +/* functions */ +void exynos_gpio_cfg_pin(struct exynos_gpio_bank *bank, int gpio, int cfg); +void exynos_gpio_direction_output(struct exynos_gpio_bank *bank, int gpio, int en); +void exynos_gpio_direction_input(struct exynos_gpio_bank *bank, int gpio); +void exynos_gpio_set_value(struct exynos_gpio_bank *bank, int gpio, int en); +unsigned int exynos_gpio_get_value(struct exynos_gpio_bank *bank, int gpio); +void exynos_gpio_set_pull(struct exynos_gpio_bank *bank, int gpio, int mode); +void exynos_gpio_set_drv(struct exynos_gpio_bank *bank, int gpio, int mode); +void exynos_gpio_set_rate(struct exynos_gpio_bank *bank, int gpio, int mode); +int exynos_gpio_get_pin(unsigned gpio); + +/* GPIO pins per bank */ +#define GPIO_PER_BANK 8 + +/* A list of valid GPIO numbers for the asm-generic/gpio.h interface */ +enum exynos7_gpio_pin { + /* GPIO_PART1_STARTS */ + EXYNOS7_GPIO_A00, /* 0 */ + EXYNOS7_GPIO_A01, + EXYNOS7_GPIO_A02, + EXYNOS7_GPIO_A03, + EXYNOS7_GPIO_A04, + EXYNOS7_GPIO_A05, + EXYNOS7_GPIO_A06, + EXYNOS7_GPIO_A07, + EXYNOS7_GPIO_A10, /* 8 */ + EXYNOS7_GPIO_A11, + EXYNOS7_GPIO_A12, + EXYNOS7_GPIO_A13, + EXYNOS7_GPIO_A14, + EXYNOS7_GPIO_A15, + EXYNOS7_GPIO_A16, + EXYNOS7_GPIO_A17, + EXYNOS7_GPIO_A20, /* 16 0x10 */ + EXYNOS7_GPIO_A21, + EXYNOS7_GPIO_A22, + EXYNOS7_GPIO_A23, + EXYNOS7_GPIO_A24, + EXYNOS7_GPIO_A25, + EXYNOS7_GPIO_A26, + EXYNOS7_GPIO_A27, + EXYNOS7_GPIO_A30, /* 24 0x18 */ + EXYNOS7_GPIO_A31, + EXYNOS7_GPIO_A32, + EXYNOS7_GPIO_A33, + EXYNOS7_GPIO_A34, + EXYNOS7_GPIO_A35, + EXYNOS7_GPIO_A36, + EXYNOS7_GPIO_A37, + + /* GPIO_PART2_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_1, /* 32 0x20 */ + EXYNOS7_GPIO_Z00 = EXYNOS7_GPIO_MAX_PORT_PART_1, + EXYNOS7_GPIO_Z01, + EXYNOS7_GPIO_Z02, + EXYNOS7_GPIO_Z03, + EXYNOS7_GPIO_Z04, + EXYNOS7_GPIO_Z05, + EXYNOS7_GPIO_Z06, + EXYNOS7_GPIO_Z07, + EXYNOS7_GPIO_Z10, /* 40 0x28 */ + EXYNOS7_GPIO_Z11, + EXYNOS7_GPIO_Z12, + EXYNOS7_GPIO_Z13, + EXYNOS7_GPIO_Z14, + EXYNOS7_GPIO_Z15, + EXYNOS7_GPIO_Z16, + EXYNOS7_GPIO_Z17, + + /* GPIO_PART3_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_2, /* 48 0x30 */ + EXYNOS7_GPIO_B00 = EXYNOS7_GPIO_MAX_PORT_PART_2, + EXYNOS7_GPIO_B01, + EXYNOS7_GPIO_B02, + EXYNOS7_GPIO_B03, + EXYNOS7_GPIO_B04, + EXYNOS7_GPIO_B05, + EXYNOS7_GPIO_B06, + EXYNOS7_GPIO_B07, + EXYNOS7_GPIO_C00, /* 56 0x38 */ + EXYNOS7_GPIO_C01, + EXYNOS7_GPIO_C02, + EXYNOS7_GPIO_C03, + EXYNOS7_GPIO_C04, + EXYNOS7_GPIO_C05, + EXYNOS7_GPIO_C06, + EXYNOS7_GPIO_C07, + EXYNOS7_GPIO_C10, /* 64 0x40 */ + EXYNOS7_GPIO_C11, + EXYNOS7_GPIO_C12, + EXYNOS7_GPIO_C13, + EXYNOS7_GPIO_C14, + EXYNOS7_GPIO_C15, + EXYNOS7_GPIO_C16, + EXYNOS7_GPIO_C17, + EXYNOS7_GPIO_C20, /* 72 0x48 */ + EXYNOS7_GPIO_C21, + EXYNOS7_GPIO_C22, + EXYNOS7_GPIO_C23, + EXYNOS7_GPIO_C24, + EXYNOS7_GPIO_C25, + EXYNOS7_GPIO_C26, + EXYNOS7_GPIO_C27, + EXYNOS7_GPIO_C30, /* 80 0x50 */ + EXYNOS7_GPIO_C31, + EXYNOS7_GPIO_C32, + EXYNOS7_GPIO_C33, + EXYNOS7_GPIO_C34, + EXYNOS7_GPIO_C35, + EXYNOS7_GPIO_C36, + EXYNOS7_GPIO_C37, + EXYNOS7_GPIO_D00, /* 88 0x58 */ + EXYNOS7_GPIO_D01, + EXYNOS7_GPIO_D02, + EXYNOS7_GPIO_D03, + EXYNOS7_GPIO_D04, + EXYNOS7_GPIO_D05, + EXYNOS7_GPIO_D06, + EXYNOS7_GPIO_D07, + EXYNOS7_GPIO_D10, /* 96 0x60 */ + EXYNOS7_GPIO_D11, + EXYNOS7_GPIO_D12, + EXYNOS7_GPIO_D13, + EXYNOS7_GPIO_D14, + EXYNOS7_GPIO_D15, + EXYNOS7_GPIO_D16, + EXYNOS7_GPIO_D17, + EXYNOS7_GPIO_D20, /* 104 0x68 */ + EXYNOS7_GPIO_D21, + EXYNOS7_GPIO_D22, + EXYNOS7_GPIO_D23, + EXYNOS7_GPIO_D24, + EXYNOS7_GPIO_D25, + EXYNOS7_GPIO_D26, + EXYNOS7_GPIO_D27, + EXYNOS7_GPIO_D40, /* 112 0x70 */ + EXYNOS7_GPIO_D41, + EXYNOS7_GPIO_D42, + EXYNOS7_GPIO_D43, + EXYNOS7_GPIO_D44, + EXYNOS7_GPIO_D45, + EXYNOS7_GPIO_D46, + EXYNOS7_GPIO_D47, + EXYNOS7_GPIO_D50, /* 120 0x78 */ + EXYNOS7_GPIO_D51, + EXYNOS7_GPIO_D52, + EXYNOS7_GPIO_D53, + EXYNOS7_GPIO_D54, + EXYNOS7_GPIO_D55, + EXYNOS7_GPIO_D56, + EXYNOS7_GPIO_D57, + EXYNOS7_GPIO_D60, /* 128 0x80 */ + EXYNOS7_GPIO_D61, + EXYNOS7_GPIO_D62, + EXYNOS7_GPIO_D63, + EXYNOS7_GPIO_D64, + EXYNOS7_GPIO_D65, + EXYNOS7_GPIO_D66, + EXYNOS7_GPIO_D67, + EXYNOS7_GPIO_D70, /* 136 0x88 */ + EXYNOS7_GPIO_D71, + EXYNOS7_GPIO_D72, + EXYNOS7_GPIO_D73, + EXYNOS7_GPIO_D74, + EXYNOS7_GPIO_D75, + EXYNOS7_GPIO_D76, + EXYNOS7_GPIO_D77, + EXYNOS7_GPIO_D80, /* 144 0x90 */ + EXYNOS7_GPIO_D81, + EXYNOS7_GPIO_D82, + EXYNOS7_GPIO_D83, + EXYNOS7_GPIO_D84, + EXYNOS7_GPIO_D85, + EXYNOS7_GPIO_D86, + EXYNOS7_GPIO_D87, + EXYNOS7_GPIO_G00, /* 152 0x98 */ + EXYNOS7_GPIO_G01, + EXYNOS7_GPIO_G02, + EXYNOS7_GPIO_G03, + EXYNOS7_GPIO_G04, + EXYNOS7_GPIO_G05, + EXYNOS7_GPIO_G06, + EXYNOS7_GPIO_G07, + EXYNOS7_GPIO_G30, /* 160 0xA0 */ + EXYNOS7_GPIO_G31, + EXYNOS7_GPIO_G32, + EXYNOS7_GPIO_G33, + EXYNOS7_GPIO_G34, + EXYNOS7_GPIO_G35, + EXYNOS7_GPIO_G36, + EXYNOS7_GPIO_G37, + + /* GPIO_PART4_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_3, /* 168 0xA8 */ + EXYNOS7_GPIO_F00 = (EXYNOS7_GPIO_MAX_PORT_PART_3 + 0x20), + EXYNOS7_GPIO_F01, + EXYNOS7_GPIO_F02, + EXYNOS7_GPIO_F03, + EXYNOS7_GPIO_F04, + EXYNOS7_GPIO_F05, + EXYNOS7_GPIO_F06, + EXYNOS7_GPIO_F07, + EXYNOS7_GPIO_F10, /* 208 0xD0 */ + EXYNOS7_GPIO_F11, + EXYNOS7_GPIO_F12, + EXYNOS7_GPIO_F13, + EXYNOS7_GPIO_F14, + EXYNOS7_GPIO_F15, + EXYNOS7_GPIO_F16, + EXYNOS7_GPIO_F17, + EXYNOS7_GPIO_F20, /* 216 0xD8 */ + EXYNOS7_GPIO_F21, + EXYNOS7_GPIO_F22, + EXYNOS7_GPIO_F23, + EXYNOS7_GPIO_F24, + EXYNOS7_GPIO_F25, + EXYNOS7_GPIO_F26, + EXYNOS7_GPIO_F27, + EXYNOS7_GPIO_F30, /* 224 0xE0 */ + EXYNOS7_GPIO_F31, + EXYNOS7_GPIO_F32, + EXYNOS7_GPIO_F33, + EXYNOS7_GPIO_F34, + EXYNOS7_GPIO_F35, + EXYNOS7_GPIO_F36, + EXYNOS7_GPIO_F37, + EXYNOS7_GPIO_F40, /* 232 0xE8 */ + EXYNOS7_GPIO_F41, + EXYNOS7_GPIO_F42, + EXYNOS7_GPIO_F43, + EXYNOS7_GPIO_F44, + EXYNOS7_GPIO_F45, + EXYNOS7_GPIO_F46, + EXYNOS7_GPIO_F47, + EXYNOS7_GPIO_F50, /* 240 0xF0 */ + EXYNOS7_GPIO_F51, + EXYNOS7_GPIO_F52, + EXYNOS7_GPIO_F53, + EXYNOS7_GPIO_F54, + EXYNOS7_GPIO_F55, + EXYNOS7_GPIO_F56, + EXYNOS7_GPIO_F57, + EXYNOS7_GPIO_G10, /* 248 0xF8 */ + EXYNOS7_GPIO_G11, + EXYNOS7_GPIO_G12, + EXYNOS7_GPIO_G13, + EXYNOS7_GPIO_G14, + EXYNOS7_GPIO_G15, + EXYNOS7_GPIO_G16, + EXYNOS7_GPIO_G17, + EXYNOS7_GPIO_G20, /* 256 0x100 */ + EXYNOS7_GPIO_G21, + EXYNOS7_GPIO_G22, + EXYNOS7_GPIO_G23, + EXYNOS7_GPIO_G24, + EXYNOS7_GPIO_G25, + EXYNOS7_GPIO_G26, + EXYNOS7_GPIO_G27, + EXYNOS7_GPIO_H10, /* 264 0x108 */ + EXYNOS7_GPIO_H11, + EXYNOS7_GPIO_H12, + EXYNOS7_GPIO_H13, + EXYNOS7_GPIO_H14, + EXYNOS7_GPIO_H15, + EXYNOS7_GPIO_H16, + EXYNOS7_GPIO_H17, + EXYNOS7_GPIO_V60, /* 272 0x110 */ + EXYNOS7_GPIO_V61, + EXYNOS7_GPIO_V62, + EXYNOS7_GPIO_V63, + EXYNOS7_GPIO_V64, + EXYNOS7_GPIO_V65, + EXYNOS7_GPIO_V66, + EXYNOS7_GPIO_V67, + + /* GPIO_PART5_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_4, /* 280 0x118 */ + EXYNOS7_GPIO_J00 = EXYNOS7_GPIO_MAX_PORT_PART_4, + EXYNOS7_GPIO_J01, + EXYNOS7_GPIO_J02, + EXYNOS7_GPIO_J03, + EXYNOS7_GPIO_J04, + EXYNOS7_GPIO_J05, + EXYNOS7_GPIO_J06, + EXYNOS7_GPIO_J07, + + /* GPIO_PART6_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_5, /* 288 0x120 */ + EXYNOS7_GPIO_J10 = EXYNOS7_GPIO_MAX_PORT_PART_5, + EXYNOS7_GPIO_J11, + EXYNOS7_GPIO_J12, + EXYNOS7_GPIO_J13, + EXYNOS7_GPIO_J14, + EXYNOS7_GPIO_J15, + EXYNOS7_GPIO_J16, + EXYNOS7_GPIO_J17, + + /* GPIO_PART7_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_6, /* 296 0x128 */ + EXYNOS7_GPIO_G40 = EXYNOS7_GPIO_MAX_PORT_PART_6, + EXYNOS7_GPIO_G41, + EXYNOS7_GPIO_G42, + EXYNOS7_GPIO_G43, + EXYNOS7_GPIO_G44, + EXYNOS7_GPIO_G45, + EXYNOS7_GPIO_G46, + EXYNOS7_GPIO_G47, + + /* GPIO_PART8_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_7, /* 304 0x130 */ + EXYNOS7_GPIO_V70 = EXYNOS7_GPIO_MAX_PORT_PART_7, + EXYNOS7_GPIO_V71, + EXYNOS7_GPIO_V72, + EXYNOS7_GPIO_V73, + EXYNOS7_GPIO_V74, + EXYNOS7_GPIO_V75, + EXYNOS7_GPIO_V76, + EXYNOS7_GPIO_V77, + + /* GPIO_PART9_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_8, /* 312 0x138 */ + EXYNOS7_GPIO_R40 = EXYNOS7_GPIO_MAX_PORT_PART_8, + EXYNOS7_GPIO_R41, + EXYNOS7_GPIO_R42, + EXYNOS7_GPIO_R43, + EXYNOS7_GPIO_R44, + EXYNOS7_GPIO_R45, + EXYNOS7_GPIO_R46, + EXYNOS7_GPIO_R47, + + /* GPIO_PART10_STARTS */ + EXYNOS7_GPIO_MAX_PORT_PART_9, /* 320 0x140 */ + EXYNOS7_GPIO_R00 = EXYNOS7_GPIO_MAX_PORT_PART_9, + EXYNOS7_GPIO_R01, + EXYNOS7_GPIO_R02, + EXYNOS7_GPIO_R03, + EXYNOS7_GPIO_R04, + EXYNOS7_GPIO_R05, + EXYNOS7_GPIO_R06, + EXYNOS7_GPIO_R07, + EXYNOS7_GPIO_R10, /* 328 0x148 */ + EXYNOS7_GPIO_R11, + EXYNOS7_GPIO_R12, + EXYNOS7_GPIO_R13, + EXYNOS7_GPIO_R14, + EXYNOS7_GPIO_R15, + EXYNOS7_GPIO_R16, + EXYNOS7_GPIO_R17, + EXYNOS7_GPIO_R20, /* 336 0x150 */ + EXYNOS7_GPIO_R21, + EXYNOS7_GPIO_R22, + EXYNOS7_GPIO_R23, + EXYNOS7_GPIO_R24, + EXYNOS7_GPIO_R25, + EXYNOS7_GPIO_R26, + EXYNOS7_GPIO_R27, + EXYNOS7_GPIO_R30, /* 344 0x158 */ + EXYNOS7_GPIO_R31, + EXYNOS7_GPIO_R32, + EXYNOS7_GPIO_R33, + EXYNOS7_GPIO_R34, + EXYNOS7_GPIO_R35, + EXYNOS7_GPIO_R36, + EXYNOS7_GPIO_R37, + + EXYNOS7_GPIO_MAX_PORT +}; + +struct gpio_info { + u64 reg_addr; /* Address of register for this part */ + u32 max_gpio; /* Maximum GPIO in this part */ +}; + +#define EXYNOS7_GPIO_NUM_PARTS 10 +static struct gpio_info exynos7_gpio_data[EXYNOS7_GPIO_NUM_PARTS] = { + { EXYNOS7_GPIO_ALIVE_BASE, EXYNOS7_GPIO_MAX_PORT_PART_1 }, + { EXYNOS7_GPIO_AUD_BASE, EXYNOS7_GPIO_MAX_PORT_PART_2 }, + { EXYNOS7_GPIO_BUS0_BASE, EXYNOS7_GPIO_MAX_PORT_PART_3 }, + { EXYNOS7_GPIO_BUS1_BASE, EXYNOS7_GPIO_MAX_PORT_PART_4 }, + { EXYNOS7_GPIO_NFC_BASE, EXYNOS7_GPIO_MAX_PORT_PART_5 }, + { EXYNOS7_GPIO_TOUCH_BASE, EXYNOS7_GPIO_MAX_PORT_PART_6 }, + { EXYNOS7_GPIO_FF_BASE, EXYNOS7_GPIO_MAX_PORT_PART_7 }, + { EXYNOS7_GPIO_ESE_BASE, EXYNOS7_GPIO_MAX_PORT_PART_8 }, + { EXYNOS7_GPIO_FSYS0_BASE, EXYNOS7_GPIO_MAX_PORT_PART_9 }, + { EXYNOS7_GPIO_FSYS1_BASE, EXYNOS7_GPIO_MAX_PORT }, +}; + +static inline struct gpio_info *get_gpio_data(void) +{ + return exynos7_gpio_data; +} + +static inline unsigned int get_bank_num(void) +{ + return EXYNOS7_GPIO_NUM_PARTS; +} + +#define name_to_gpio(n) exynos_name_to_gpio(n) +#define gpio_describe(str) exynos_gpio_describe(str) + +void gpio_cfg_pin(int gpio, int cfg); +void gpio_set_drv(int gpio, int drv); +int gpio_set_value(unsigned gpio, int value); +int gpio_get_value(unsigned gpio); +int gpio_request(unsigned gpio, const char *label); +int gpio_free(unsigned gpio); +int gpio_direction_input(unsigned gpio); +int gpio_direction_output(unsigned gpio, int value); + +/* Pin configurations */ +#define EXYNOS_GPIO_INPUT 0x0 +#define EXYNOS_GPIO_OUTPUT 0x1 +#define EXYNOS_GPIO_IRQ 0xf +#define EXYNOS_GPIO_FUNC(x) (x) + +/* Pull mode */ +#define EXYNOS_GPIO_PULL_NONE 0x0 +#define EXYNOS_GPIO_PULL_DOWN 0x1 +#define EXYNOS_GPIO_PULL_UP 0x3 + +/* Drive Strength level */ +#define EXYNOS_GPIO_DRV_1X 0x0 +#define EXYNOS_GPIO_DRV_3X 0x1 +#define EXYNOS_GPIO_DRV_2X 0x2 +#define EXYNOS_GPIO_DRV_4X 0x3 +#define EXYNOS_GPIO_DRV_FAST 0x0 +#define EXYNOS_GPIO_DRV_SLOW 0x1 + +/** + * Set GPIO pull mode. + * + * @param gpio GPIO pin + * @param mode Either GPIO_PULL_DOWN or GPIO_PULL_UP + */ +void gpio_set_pull(int gpio, int mode); + +#endif /* _CPU_SAMSUNG_EXYNOS7_GPIO_H_ */ diff --git a/src/soc/samsung/exynos7/include/soc/pinmux.h b/src/soc/samsung/exynos7/include/soc/pinmux.h new file mode 100644 index 0000000..c80600f --- /dev/null +++ b/src/soc/samsung/exynos7/include/soc/pinmux.h @@ -0,0 +1,55 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * 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 _CPU_SAMSUNG_EXYNOS7_PINMUX_H_ +#define _CPU_SAMSUNG_EXYNOS7_PINMUX_H_ + +/* + * Flags for setting specific configarations of peripherals. + * List will grow with support for more devices getting added. + */ +enum { + PINMUX_FLAG_NONE = 0x00000000, + + /* Flags for eMMC */ + PINMUX_FLAG_8BIT_MODE = 1 << 0, /* SDMMC 8-bit mode */ + + /* Flags for SROM controller */ + PINMUX_FLAG_BANK = 3 << 0, /* bank number (0-3) */ + PINMUX_FLAG_16BIT = 1 << 2, /* 16-bit width */ +}; + +void exynos_pinmux_uart0(void); +void exynos_pinmux_uart1(void); +void exynos_pinmux_uart2(void); + +void exynos_pinmux_mmc0(void); +void exynos_pinmux_mmc1(void); +void exynos_pinmux_mmc2(void); + +void exynos_pinmux_i2c0(void); +void exynos_pinmux_i2c1(void); +void exynos_pinmux_i2c2(void); +void exynos_pinmux_i2c3(void); +void exynos_pinmux_i2c4(void); +void exynos_pinmux_i2c5(void); +void exynos_pinmux_i2c6(void); +void exynos_pinmux_i2c7(void); +void exynos_pinmux_i2c8(void); +void exynos_pinmux_i2c9(void); +void exynos_pinmux_i2c10(void); +void exynos_pinmux_i2c11(void); + +#endif /* _CPU_SAMSUNG_EXYNOS7_PINMUX_H_ */ diff --git a/src/soc/samsung/exynos7/pinmux.c b/src/soc/samsung/exynos7/pinmux.c new file mode 100644 index 0000000..e41f260 --- /dev/null +++ b/src/soc/samsung/exynos7/pinmux.c @@ -0,0 +1,277 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2014 Samsung Electronics + * + * 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 <console/console.h> +#include <assert.h> +#include <stdlib.h> +#include <soc/gpio.h> +#include <soc/pinmux.h> +#include <soc/periph.h> + +static void exynos7_uart_config(int peripheral) +{ + struct exynos7_gpio_part3 *gpio_bus0 = + (struct exynos7_gpio_part3 *)EXYNOS7_GPIO_BUS0_BASE; + struct exynos_gpio_bank *bank = NULL; + int i, start = 0, count = 0, func = 0; + + switch (peripheral) { + case PERIPH_ID_UART0: + bank = &gpio_bus0->d0; + start = 0; + count = 4; + func = 2; + break; + case PERIPH_ID_UART1: + bank = &gpio_bus0->d1; + start = 0; + count = 4; + func = 2; + break; + case PERIPH_ID_UART2: + bank = &gpio_bus0->d1; + start = 4; + count = 2; + func = 2; + break; + case PERIPH_ID_UART3: + bank = &gpio_bus0->d5; + start = 0; + count = 2; + func = 3; + break; + } + for (i = start; i < start + count; i++) { + exynos_gpio_set_pull(bank, i, EXYNOS_GPIO_PULL_NONE); + exynos_gpio_cfg_pin(bank, i, EXYNOS_GPIO_FUNC(func)); + } +} + +void exynos_pinmux_uart0(void) +{ + exynos7_uart_config(PERIPH_ID_UART0); +} + +void exynos_pinmux_uart1(void) +{ + exynos7_uart_config(PERIPH_ID_UART1); +} + +void exynos_pinmux_uart2(void) +{ + exynos7_uart_config(PERIPH_ID_UART2); +} + +static int exynos7_mmc_config(int peripheral, int flags) +{ + struct exynos7_gpio_part9 *gpio_fsys0 = + (struct exynos7_gpio_part9 *)EXYNOS7_GPIO_FSYS0_BASE; + struct exynos7_gpio_part10 *gpio_fsys1 = + (struct exynos7_gpio_part10 *)EXYNOS7_GPIO_FSYS1_BASE; + struct exynos_gpio_bank *bank, *bank_data, *bank_ext_data; + int i, bank_bit, bank_bit_cnt; + int bank_data_bit, bank_ext_data_bit; + + switch (peripheral) { + case PERIPH_ID_SDMMC0: + bank = &gpio_fsys1->r0; + bank_data = &gpio_fsys1->r1; + bank_ext_data = &gpio_fsys1->r1; + bank_bit = 0; + bank_bit_cnt = 4; + bank_data_bit = 0; + bank_ext_data_bit = 4; + break; + case PERIPH_ID_SDMMC1: + bank = &gpio_fsys1->r2; + bank_data = &gpio_fsys1->r3; + bank_ext_data = &gpio_fsys1->r3; + bank_bit = 0; + bank_bit_cnt = 2; + bank_data_bit = 0; + bank_ext_data_bit = 4; + break; + case PERIPH_ID_SDMMC2: + bank = &gpio_fsys0->r4; + bank_data = &gpio_fsys0->r4; + bank_ext_data = NULL; + bank_bit = 0; + bank_bit_cnt = 4; + bank_data_bit = 4; + break; + default: + printk(BIOS_DEBUG, "%s: invalid peripheral %d", __func__, peripheral); + return -1; + } + if ((flags & PINMUX_FLAG_8BIT_MODE) && !bank_ext_data) { + printk(BIOS_DEBUG, "SDMMC device %d does not support 8bit mode", + peripheral); + return -1; + } + for (i = bank_bit; i < bank_bit_cnt; i++) { + exynos_gpio_cfg_pin(bank, i, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_set_pull(bank, i, EXYNOS_GPIO_PULL_NONE); + exynos_gpio_set_drv(bank, i, EXYNOS_GPIO_DRV_4X); + } + for (i = bank_data_bit; i < (bank_data_bit + 4); i++) { + exynos_gpio_cfg_pin(bank_data, i, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_set_pull(bank_data, i, EXYNOS_GPIO_PULL_UP); + exynos_gpio_set_drv(bank_data, i, EXYNOS_GPIO_DRV_4X); + } + if (flags & PINMUX_FLAG_8BIT_MODE) { + for (i = bank_ext_data_bit; i < (bank_ext_data_bit + 4); i++) { + exynos_gpio_cfg_pin(bank_ext_data, i, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_set_pull(bank_ext_data, i, EXYNOS_GPIO_PULL_UP); + exynos_gpio_set_drv(bank_ext_data, i, EXYNOS_GPIO_DRV_4X); + } + } + return 0; +} + +void exynos_pinmux_mmc0(void) +{ + exynos7_mmc_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE); +} + +void exynos_pinmux_mmc1(void) +{ + exynos7_mmc_config(PERIPH_ID_SDMMC1, PINMUX_FLAG_NONE); +} + +void exynos_pinmux_mmc2(void) +{ + exynos7_mmc_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE); +} + +static void exynos7_i2c_config(int peripheral) +{ + struct exynos7_gpio_part3 *gpio_bus0 = + (struct exynos7_gpio_part3 *)EXYNOS7_GPIO_BUS0_BASE; + struct exynos7_gpio_part5 *gpio_nfc = + (struct exynos7_gpio_part5 *)EXYNOS7_GPIO_NFC_BASE; + struct exynos7_gpio_part6 *gpio_touch = + (struct exynos7_gpio_part6 *)EXYNOS7_GPIO_TOUCH_BASE; + + switch (peripheral) { + case PERIPH_ID_I2C0: + exynos_gpio_cfg_pin(&gpio_bus0->d2, 0, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_bus0->d2, 1, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C1: + exynos_gpio_cfg_pin(&gpio_bus0->d2, 2, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_bus0->d2, 3, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C2: + exynos_gpio_cfg_pin(&gpio_bus0->d0, 2, EXYNOS_GPIO_FUNC(0x3)); + exynos_gpio_cfg_pin(&gpio_bus0->d0, 3, EXYNOS_GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C3: + exynos_gpio_cfg_pin(&gpio_bus0->d1, 2, EXYNOS_GPIO_FUNC(0x3)); + exynos_gpio_cfg_pin(&gpio_bus0->d1, 3, EXYNOS_GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C4: + exynos_gpio_cfg_pin(&gpio_bus0->g3, 0, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_bus0->g3, 1, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C5: + exynos_gpio_cfg_pin(&gpio_bus0->g3, 2, EXYNOS_GPIO_FUNC(0x3)); + exynos_gpio_cfg_pin(&gpio_bus0->g3, 3, EXYNOS_GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C6: + exynos_gpio_cfg_pin(&gpio_nfc->j0, 0, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_nfc->j0, 1, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C7: + exynos_gpio_cfg_pin(&gpio_touch->j1, 0, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_touch->j1, 1, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C8: + exynos_gpio_cfg_pin(&gpio_bus0->d5, 2, EXYNOS_GPIO_FUNC(0x3)); + exynos_gpio_cfg_pin(&gpio_bus0->d5, 3, EXYNOS_GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C9: + exynos_gpio_cfg_pin(&gpio_bus0->d2, 6, EXYNOS_GPIO_FUNC(0x3)); + exynos_gpio_cfg_pin(&gpio_bus0->d2, 7, EXYNOS_GPIO_FUNC(0x3)); + break; + case PERIPH_ID_I2C10: + exynos_gpio_cfg_pin(&gpio_bus0->b0, 0, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_bus0->b0, 1, EXYNOS_GPIO_FUNC(0x2)); + break; + case PERIPH_ID_I2C11: + exynos_gpio_cfg_pin(&gpio_bus0->b0, 2, EXYNOS_GPIO_FUNC(0x2)); + exynos_gpio_cfg_pin(&gpio_bus0->b0, 3, EXYNOS_GPIO_FUNC(0x2)); + break; + } +} + +void exynos_pinmux_i2c0(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C0); +} + +void exynos_pinmux_i2c1(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C1); +} + +void exynos_pinmux_i2c2(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C2); +} + +void exynos_pinmux_i2c3(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C3); +} + +void exynos_pinmux_i2c4(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C4); +} + +void exynos_pinmux_i2c5(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C5); +} + +void exynos_pinmux_i2c6(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C6); +} + +void exynos_pinmux_i2c7(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C7); +} + +void exynos_pinmux_i2c8(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C8); +} + +void exynos_pinmux_i2c9(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C9); +} + +void exynos_pinmux_i2c10(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C10); +} + +void exynos_pinmux_i2c11(void) +{ + exynos7_i2c_config(PERIPH_ID_I2C11); +}