From 1fb9cda823edd2c9d48da214d43fc74b9c62bcac Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Fri, 11 Aug 2017 13:39:09 +0200 Subject: [PATCH] Add 'gpio' command and enable it by default This adds 'gpio' command, which allows to manipulate GPIO subsystem: - change direction - change output value - read input value (useful for scripts) - enable/disable JTAG - manage special/dedicated GPIO functions - list current configuration and available functions For QCA95xx series, this allows full management of GPIO output and input functionalities (mux). For AR933x, due to its capabilities, function management is more simple and allows only enabling or disabling selected bits in GPIO_FUNCTION_{1,2} registers. Example commands: - list GPIO configuration: gpio l - list available functions: gpio l f - set GPIO10 output to high: gpio s 10 - get GPIO10 input value: gpio i 10 --- u-boot/common/Makefile | 1 + u-boot/common/cmd_qcagpio.c | 758 ++++++++++++++++++++++ u-boot/include/cmd_qcagpio.h | 882 ++++++++++++++++++++++++++ u-boot/include/configs/qca9k_common.h | 1 + 4 files changed, 1642 insertions(+) create mode 100644 u-boot/common/cmd_qcagpio.c create mode 100644 u-boot/include/cmd_qcagpio.h diff --git a/u-boot/common/Makefile b/u-boot/common/Makefile index f22b1c4..6df605b 100644 --- a/u-boot/common/Makefile +++ b/u-boot/common/Makefile @@ -38,6 +38,7 @@ COBJS = main.o \ cmd_itest.o \ cmd_load.o \ cmd_qcaclk.o \ + cmd_qcagpio.o \ command.o \ console.o \ devices.o \ diff --git a/u-boot/common/cmd_qcagpio.c b/u-boot/common/cmd_qcagpio.c new file mode 100644 index 0000000..460905e --- /dev/null +++ b/u-boot/common/cmd_qcagpio.c @@ -0,0 +1,758 @@ +/* + * Copyright (C) 2017 Piotr Dymacz + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_CMD_GPIO) + +#define _GPIO_OUT_MUX_MAX 127 +#define _GPIO_NUM_MAX (QCA_GPIO_COUNT - 1) + +#if (SOC_TYPE & QCA_AR933X_SOC) +static void gpio_set_func(u32 func, u32 enable) +{ + u32 val; + + if (func < gpio_funcs_1_cnt) { + val = qca_soc_reg_read(QCA_GPIO_FUNC_1_REG); + + if (enable) + val |= gpio_funcs_1[func].reg_mask; + else + val &= ~gpio_funcs_1[func].reg_mask; + + qca_soc_reg_write(QCA_GPIO_FUNC_1_REG, val); + + return; + } + + func -= gpio_funcs_1_cnt; + val = qca_soc_reg_read(QCA_GPIO_FUNC_2_REG); + + if (enable) + val |= gpio_funcs_2[func].reg_mask; + else + val &= ~gpio_funcs_2[func].reg_mask; + + qca_soc_reg_write(QCA_GPIO_FUNC_2_REG, val); +} +#else +static void gpio_func_gate(u8 disable, u8 enable) +{ + u32 val; + + switch (disable) { + case QCA_GPIO_OUT_MUX_CLK_OBS0_VAL: + val = QCA_GPIO_FUNC_CLK_OBS0_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS1_VAL: + val = QCA_GPIO_FUNC_CLK_OBS1_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS2_VAL: + val = QCA_GPIO_FUNC_CLK_OBS2_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS3_VAL: + val = QCA_GPIO_FUNC_CLK_OBS3_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS4_VAL: + val = QCA_GPIO_FUNC_CLK_OBS4_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS5_VAL: + val = QCA_GPIO_FUNC_CLK_OBS5_EN_MASK; + break; +#if (SOC_TYPE & QCA_AR934X_SOC) ||\ + (SOC_TYPE & QCA_QCA953X_SOC) ||\ + (SOC_TYPE & QCA_QCA956X_SOC) + case QCA_GPIO_OUT_MUX_CLK_OBS6_VAL: + val = QCA_GPIO_FUNC_CLK_OBS6_EN_MASK; + break; +#endif +#if (SOC_TYPE & QCA_AR934X_SOC) + case QCA_GPIO_OUT_MUX_CLK_OBS7_VAL: + val = QCA_GPIO_FUNC_CLK_OBS7_EN_MASK; + break; +#endif +#if (SOC_TYPE & QCA_QCA953X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) ||\ + (SOC_TYPE & QCA_QCA956X_SOC) + case QCA_GPIO_OUT_MUX_SRIF_OUT_VAL: + val = QCA_GPIO_FUNC_GPIO_SRIF_EN_MASK; + break; +#endif + default: + val = 0; + break; + } + + if (val) + qca_soc_reg_read_clear(QCA_GPIO_FUNC_REG, val); + + switch (enable) { + case QCA_GPIO_OUT_MUX_CLK_OBS0_VAL: + val = QCA_GPIO_FUNC_CLK_OBS0_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS1_VAL: + val = QCA_GPIO_FUNC_CLK_OBS1_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS2_VAL: + val = QCA_GPIO_FUNC_CLK_OBS2_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS3_VAL: + val = QCA_GPIO_FUNC_CLK_OBS3_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS4_VAL: + val = QCA_GPIO_FUNC_CLK_OBS4_EN_MASK; + break; + case QCA_GPIO_OUT_MUX_CLK_OBS5_VAL: + val = QCA_GPIO_FUNC_CLK_OBS5_EN_MASK; + break; +#if (SOC_TYPE & QCA_AR934X_SOC) ||\ + (SOC_TYPE & QCA_QCA953X_SOC) ||\ + (SOC_TYPE & QCA_QCA956X_SOC) + case QCA_GPIO_OUT_MUX_CLK_OBS6_VAL: + val = QCA_GPIO_FUNC_CLK_OBS6_EN_MASK; + break; +#endif +#if (SOC_TYPE & QCA_AR934X_SOC) + case QCA_GPIO_OUT_MUX_CLK_OBS7_VAL: + val = QCA_GPIO_FUNC_CLK_OBS7_EN_MASK; + break; +#endif +#if (SOC_TYPE & QCA_QCA953X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) ||\ + (SOC_TYPE & QCA_QCA956X_SOC) + case QCA_GPIO_OUT_MUX_SRIF_OUT_VAL: + val = QCA_GPIO_FUNC_GPIO_SRIF_EN_MASK; + break; +#endif + default: + val = 0; + break; + } + + if (val) + qca_soc_reg_read_set(QCA_GPIO_FUNC_REG, val); +} + +static u32 gpio_in_func_to_gpio(u8 func) +{ + u32 val, reg, shift; + + if (func > (gpio_in_funcs_cnt - 1)) + return _GPIO_OUT_MUX_MAX; + + reg = QCA_GPIO_IN_EN0_REG + (4 * (gpio_in_funcs[func].offset / 4)); + shift = 8 * (gpio_in_funcs[func].offset % 4); + + val = qca_soc_reg_read(reg); + val &= (0xff << shift); + val = val >> shift; + + return val; +} + +static u8 gpio_get_out_func(u32 gpio_num) +{ + u32 val, reg, shift; + + reg = QCA_GPIO_OUT_FUNC0_REG + (4 * (gpio_num / 4)); + shift = 8 * (gpio_num % 4); + + val = qca_soc_reg_read(reg); + val &= (0xff << shift); + val = val >> shift; + + return (u8)val; +} + +static void gpio_set_in_out_func(u32 gpio_num, u8 func, u32 output) +{ + u32 val, reg, shift; + + if (output) { + reg = QCA_GPIO_OUT_FUNC0_REG + (4 * (gpio_num / 4)); + shift = 8 * (gpio_num % 4); + } else { + if (func > (gpio_in_funcs_cnt - 1)) + return; + + reg = QCA_GPIO_IN_EN0_REG + (4 * (gpio_in_funcs[func].offset / 4)); + shift = 8 * (gpio_in_funcs[func].offset % 4); + } + + val = qca_soc_reg_read(reg); + val &= ~(0xff << shift); + + if (output) + val |= (func << shift); + else + val |= (gpio_num << shift); + + qca_soc_reg_write(reg, val); +} +#endif /* SOC_TYPE & QCA_AR933X_SOC */ + +static void gpio_set_jtag(u32 enable) +{ +#if (SOC_TYPE & QCA_AR933X_SOC) + if (enable) + qca_soc_reg_read_clear(QCA_GPIO_FUNC_1_REG, + QCA_GPIO_FUNC_1_JTAG_DIS_MASK); + else + qca_soc_reg_read_set(QCA_GPIO_FUNC_1_REG, + QCA_GPIO_FUNC_1_JTAG_DIS_MASK); +#else + if (enable) + qca_soc_reg_read_clear(QCA_GPIO_FUNC_REG, + QCA_GPIO_FUNC_JTAG_DIS_MASK); + else + qca_soc_reg_read_set(QCA_GPIO_FUNC_REG, + QCA_GPIO_FUNC_JTAG_DIS_MASK); +#endif +} + +static void gpio_set_val(u32 gpio_mask, u32 high) +{ + if (high) + qca_soc_reg_write(QCA_GPIO_SET_REG, gpio_mask); + else + qca_soc_reg_write(QCA_GPIO_CLEAR_REG, gpio_mask); +} + +static void gpio_set_dir(u32 gpio_mask, u32 output) +{ + if (gpio_mask & QCA_GPIO_JTAG_MASK) + gpio_set_jtag(0); + +#if (SOC_TYPE & QCA_AR933X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) + if (output) + qca_soc_reg_read_set(QCA_GPIO_OE_REG, gpio_mask); + else + qca_soc_reg_read_clear(QCA_GPIO_OE_REG, gpio_mask); +#else + if (output) + qca_soc_reg_read_clear(QCA_GPIO_OE_REG, gpio_mask); + else + qca_soc_reg_read_set(QCA_GPIO_OE_REG, gpio_mask); +#endif +} + +static void gpio_list_cfg(void) +{ + u32 gpio_in_reg, gpio_out_reg, gpio_oe_reg; + u32 gpio_num, gpio_mask; + u32 output, val; + u32 jtag_en = 1; + +#if (SOC_TYPE & ~QCA_AR933X_SOC) + u8 func, i; +#endif + +#if defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_H) ||\ + defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_L) ||\ + defined(CONFIG_QCA_GPIO_MASK_LED_ACT_H) ||\ + defined(CONFIG_QCA_GPIO_MASK_LED_ACT_L) + u32 mask_h = 0, mask_l = 0; +#endif + + puts("\n"); +#if (SOC_TYPE & ~QCA_AR933X_SOC) + puts(" # | DIR | VAL | DEF | LED | BTN | JTAG | FUNCTION\n" + " ----+-----+-----+-----+-----+-----+------+----------\n"); +#else + puts(" # | DIR | VAL | DEF | LED | BTN | JTAG\n" + " ----+-----+-----+-----+-----+-----+------\n"); +#endif + + gpio_oe_reg = qca_soc_reg_read(QCA_GPIO_OE_REG); + gpio_in_reg = qca_soc_reg_read(QCA_GPIO_IN_REG); + gpio_out_reg = qca_soc_reg_read(QCA_GPIO_OUT_REG); + +#if (SOC_TYPE & QCA_AR933X_SOC) + val = qca_soc_reg_read(QCA_GPIO_FUNC_1_REG); + if (val & QCA_GPIO_FUNC_1_JTAG_DIS_MASK) + jtag_en = 0; +#else + val = qca_soc_reg_read(QCA_GPIO_FUNC_REG); + if (val & QCA_GPIO_FUNC_JTAG_DIS_MASK) + jtag_en = 0; +#endif + + for (gpio_num = 0; gpio_num < QCA_GPIO_COUNT; gpio_num++) { + gpio_mask = (1 << gpio_num); + + /* GPIO number */ + printf("%4d", gpio_num); + puts(" | "); + +#if (SOC_TYPE & QCA_AR933X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) + output = 0; + if (gpio_mask & gpio_oe_reg) + output = 1; +#else + output = 1; + if (gpio_mask & gpio_oe_reg) + output = 0; +#endif + + /* GPIO direction */ + if (output) { + printf("%-3s", "out"); + val = gpio_mask & gpio_out_reg; + } else { + printf("%-3s", "in"); + val = gpio_mask & gpio_in_reg; + } + + puts(" | "); + + /* GPIO value */ + if (val) + printf("%-3s", "hi"); + else + printf("%-3s", "lo"); + + puts(" | "); + + /* GPIO default value */ +#if defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_H) ||\ + defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_L) + + #if defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_H) + mask_h = CONFIG_QCA_GPIO_MASK_OUT_INIT_H; + #endif + + #if defined(CONFIG_QCA_GPIO_MASK_OUT_INIT_L) + mask_l = CONFIG_QCA_GPIO_MASK_OUT_INIT_L; + #endif + + if (output) { + if (gpio_mask & mask_h) + printf("%-3s", "hi"); + else if (gpio_mask & mask_l) + printf("%-3s", "lo"); + else + printf("%-3s", "-"); + } else + printf("%-3s", "-"); +#else + printf("%-3s", "-"); +#endif + puts(" | "); + + /* GPIO in LED mask */ +#if defined(CONFIG_QCA_GPIO_MASK_LED_ACT_H) ||\ + defined(CONFIG_QCA_GPIO_MASK_LED_ACT_L) + #if defined(CONFIG_QCA_GPIO_MASK_LED_ACT_H) + mask_h = CONFIG_QCA_GPIO_MASK_LED_ACT_H; + #endif + + #if defined(CONFIG_QCA_GPIO_MASK_LED_ACT_L) + mask_l = CONFIG_QCA_GPIO_MASK_LED_ACT_L; + #endif + + if (output) { + if (gpio_mask & mask_h) + printf("%-3s", "hi"); + else if (gpio_mask & mask_l) + printf("%-3s", "lo"); + else + printf("%-3s", "-"); + } else + printf("%-3s", "-"); +#else + printf("%-3s", "-"); +#endif + puts(" | "); + + /* GPIO configured as RST button */ +#if defined(CONFIG_GPIO_RESET_BTN) + if (!output && (gpio_mask & (1 << CONFIG_GPIO_RESET_BTN))) + #if defined(CONFIG_GPIO_RESET_BTN_ACTIVE_LOW) + printf("%-3s", "lo"); + #else + printf("%-3s", "hi"); + #endif + else + printf("%-3s", "-"); +#else + printf("%-3s", "-"); +#endif + puts(" | "); + + /* JTAG enabled? */ + if (jtag_en && (gpio_mask & QCA_GPIO_JTAG_MASK)) + printf("%-4s", "en"); + else + printf("%-4s", "-"); + +#if (SOC_TYPE & ~QCA_AR933X_SOC) + puts(" | "); + + /* GPIO input/output function */ + val = 0; + if (output) { + func = gpio_get_out_func(gpio_num); + for (i = 0; i < gpio_out_funcs_cnt; i++) + if (gpio_out_funcs[i].value == func) { + printf("%s (%d)", + gpio_out_funcs[i].name, func); + + val = 1; + } + + if (!val) + printf("%s (%d)", "unknown", func); + } else { + for (i = 0; i < gpio_in_funcs_cnt; i++) { + if (gpio_num == gpio_in_func_to_gpio((u8)i)) { + if (val) + printf(",\n%43s %s (%d)", "|", + gpio_in_funcs[i].name, i); + else + printf("%s (%d)", + gpio_in_funcs[i].name, i); + + val = 1; + } + } + + if (!val) + puts("gpio (-)"); + } +#endif + + puts("\n"); + } + + puts("\n"); +} + +#if (SOC_TYPE & QCA_AR933X_SOC) +static void gpio_list_funcs(void) +{ + u32 i, j, n, val; + u32 found; + + puts("\n"); + puts(" # | EN | FUNCTION | RELATED GPIOs\n" + " ----+----+----------------+---------------\n"); + + val = qca_soc_reg_read(QCA_GPIO_FUNC_1_REG); + for (i = 0; i < gpio_funcs_1_cnt; i++) { + printf("%4d", i); + puts(" | "); + + if (val & gpio_funcs_1[i].reg_mask) + puts("en"); + else + puts(" "); + + puts(" | "); + printf("%-14s", gpio_funcs_1[i].name); + puts(" | "); + + found = 0; + if (gpio_funcs_1[i].gpio_mask) { + for (n = 0; n < _GPIO_NUM_MAX; n++) { + if (gpio_funcs_1[i].gpio_mask & (1 << n)) { + if (found) + puts(", "); + + printf("%2d", n); + found = 1; + } + } + } + + if (found) + puts("\n"); + else + puts("-\n"); + } + + j = gpio_funcs_1_cnt; + val = qca_soc_reg_read(QCA_GPIO_FUNC_2_REG); + for (i = 0; i < gpio_funcs_2_cnt; i++) { + printf("%4d", j); + puts(" | "); + + if (val & gpio_funcs_2[i].reg_mask) + puts("en"); + else + puts(" "); + + puts(" | "); + printf("%-14s", gpio_funcs_2[i].name); + puts(" | "); + + found = 0; + if (gpio_funcs_2[i].gpio_mask) { + for (n = 0; n < _GPIO_NUM_MAX; n++) { + if (gpio_funcs_2[i].gpio_mask & (1 << n)) { + if (found) + puts(", "); + + printf("%2d", n); + found = 1; + } + } + } + + if (found) + puts("\n"); + else + puts("-\n"); + + j++; + } + + puts("\n"); +} +#else +static void gpio_list_in_out_funcs(void) +{ + u32 i; + + puts("\n"); + puts(" # | DIR | FUNCTION\n" + " -----+-----+----------\n"); + + for (i = 0; i < gpio_in_funcs_cnt; i++) { + printf("%5d", i); + puts(" | "); + printf("%-3s", "in"); + puts(" | "); + printf("%s\n", gpio_in_funcs[i].name); + } + + puts(" -----+-----+---------\n"); + + for (i = 0; i < gpio_out_funcs_cnt; i++) { + printf("%5d", gpio_out_funcs[i].value); + puts(" | "); + printf("%-3s", "out"); + puts(" | "); + printf("%s\n", gpio_out_funcs[i].name); + } + + puts("\n"); +} +#endif + +int do_gpio(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + u32 gpio_mask, gpio_num = 0; + u32 output = 1; + u32 func = 0; + u32 val = 0; + +#if (SOC_TYPE & QCA_AR933X_SOC) + u32 func_max = gpio_funcs_1_cnt + gpio_funcs_2_cnt - 2; + u32 func_en; +#else + u32 func_max = gpio_in_funcs_cnt - 1; + u32 func_old; +#endif + + /* We need at least one arg */ + if (argc == 1) { +usage: + print_cmd_help(cmdtp); + return 1; + } + + switch (*argv[1]) { + case 'f': + if (argc < 4) + goto usage; + +#if (SOC_TYPE & QCA_AR933X_SOC) + func = simple_strtoul(argv[2], NULL, 10); + if (func > func_max) { + printf_err("GPIO function is out of range (0~%d)\n", + func_max); + + return 1; + } + + switch (*argv[3]) { + case 'e': + func_en = 1; + break; + case 'd': + func_en = 0; + break; + default: + goto usage; + } + + gpio_set_func(func, func_en); + + return 0; +#else + if (strcmp(argv[1], "fin") == 0) + output = 0; + else if (strcmp(argv[1], "fout") == 0) + func_max = _GPIO_OUT_MUX_MAX; + else + goto usage; + + func = simple_strtoul(argv[3], NULL, 10); + if (func > func_max) { + printf_err("GPIO function is out of range (0~%d)\n", + func_max); + + return 1; + } + + break; +#endif + case 'j': + if (argc < 2) + goto usage; + + switch (*argv[2]) { + case 'e': + gpio_set_jtag(1); + break; + case 'd': + gpio_set_jtag(0); + break; + default: + goto usage; + } + + return 0; + case 'l': + if (argc < 3) + gpio_list_cfg(); + else if (*argv[2] == 'f') +#if (SOC_TYPE & QCA_AR933X_SOC) + gpio_list_funcs(); +#else + gpio_list_in_out_funcs(); +#endif + else + goto usage; + + return 0; + case 's': + case 'c': + case 't': + case 'i': + if (argc < 3) + goto usage; + + if (*argv[1] == 's') + val = 1; + + break; + default: + goto usage; + } + + gpio_num = simple_strtoul(argv[2], NULL, 10); + if (gpio_num > _GPIO_NUM_MAX) { + printf_err("GPIO must be in range 0~%d\n", _GPIO_NUM_MAX); + return 1; + } + + gpio_mask = (1 << gpio_num); + + switch (*argv[1]) { + case 's': + case 'c': +#if (SOC_TYPE & ~QCA_AR933X_SOC) + case 'f': + if (output) + func_old = gpio_get_out_func(gpio_num); +#endif + + gpio_set_dir(gpio_mask, output); + +#if (SOC_TYPE & ~QCA_AR933X_SOC) + gpio_set_in_out_func(gpio_num, (u8)func, output); +#endif + + if ((*argv[1] == 's') || (*argv[1] == 'c')) + gpio_set_val(gpio_mask, val); + +#if (SOC_TYPE & ~QCA_AR933X_SOC) + if (output && (func != func_old)) + gpio_func_gate(func_old, func); +#endif + + break; + case 't': + val = qca_soc_reg_read(QCA_GPIO_OE_REG); +#if (SOC_TYPE & QCA_AR933X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) + if (!(gpio_mask & val)) { +#else + if (gpio_mask & val) { +#endif + printf_err("GPIO is not set as output\n"); + return 1; + } + +#if (SOC_TYPE & ~QCA_AR933X_SOC) + func = (u32)gpio_get_out_func(gpio_num); + if (func > 0) { + printf_err("GPIO out function is not set to GPIO\n"); + return 1; + } +#endif + + val = qca_soc_reg_read(QCA_GPIO_OUT_REG); + if (gpio_mask & val) + gpio_set_val(gpio_mask, 0); + else + gpio_set_val(gpio_mask, 1); + + break; + case 'i': + gpio_set_dir(gpio_mask, 0); + + if (!(gpio_mask & qca_soc_reg_read(QCA_GPIO_IN_REG))) + return 1; + } + + return 0; +} + +U_BOOT_CMD(gpio, 4, 0, do_gpio, + "control GPIO\n", + "lear|nput|et|oggle \n" + "\t- setup as in/out and change/get its value\n" +#if (SOC_TYPE & QCA_AR933X_SOC) + "gpio unction nable|isable\n" + "\t- enable/disable function \n" +#else + "gpio \n" + "\t- set in/out function to \n" +#endif + "gpio tag nable|isable\n" + "\t- enable/disable JTAG\n" + "gpio ist\n" + "\t- show current GPIO configuration\n" + "gpio ist unctions\n" +#if (SOC_TYPE & QCA_AR933X_SOC) + "\t- show all GPIO functions\n" +#else + "\t- show all known GPIO in/out functions\n" +#endif +); + +#endif /* CONFIG_CMD_GPIO */ diff --git a/u-boot/include/cmd_qcagpio.h b/u-boot/include/cmd_qcagpio.h new file mode 100644 index 0000000..ca75e66 --- /dev/null +++ b/u-boot/include/cmd_qcagpio.h @@ -0,0 +1,882 @@ +/* + * Copyright (C) 2017 Piotr Dymacz + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include + +#ifndef _CMD_QCAGPIO_H_ +#define _CMD_QCAGPIO_H_ + +#if defined(CONFIG_CMD_GPIO) + +#if (SOC_TYPE & QCA_AR933X_SOC) + +typedef struct { + u32 reg_mask; + u32 gpio_mask; + char *name; +} gpio_func; + +static const gpio_func gpio_funcs_1[] = { + { + .reg_mask = QCA_GPIO_FUNC_1_UART_EN_MASK, + .gpio_mask = GPIO9 | GPIO10, + .name = "uart" + }, { + .reg_mask = QCA_GPIO_FUNC_1_UART_RTS_CTS_EN_MASK, + .gpio_mask = GPIO11 | GPIO12, + .name = "uart_rts_cts" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED0_EN_MASK, + .gpio_mask = GPIO13, + .name = "switch_led0" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED1_EN_MASK, + .gpio_mask = GPIO14, + .name = "switch_led1" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED2_EN_MASK, + .gpio_mask = GPIO15, + .name = "switch_led2" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED3_EN_MASK, + .gpio_mask = GPIO16, + .name = "switch_led3" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED4_EN_MASK, + .gpio_mask = GPIO17, + .name = "switch_led4" + }, { + .reg_mask = QCA_GPIO_FUNC_1_SPI_CS_EN1_MASK, + .gpio_mask = GPIO9, + .name = "spi_cs1" + }, { + .reg_mask = QCA_GPIO_FUNC_1_SPI_CS_EN2_MASK, + .gpio_mask = GPIO10, + .name = "spi_cs2" + }, { + .reg_mask = QCA_GPIO_FUNC_1_SPI_EN_MASK, + .gpio_mask = GPIO2 | GPIO3 | GPIO4 | GPIO5, + .name = "spi" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED_ACT_MASK, + .gpio_mask = 0, + .name = "switch_led_act" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED_COLL_MASK, + .gpio_mask = 0, + .name = "switch_led_col" + }, { + .reg_mask = QCA_GPIO_FUNC_1_ETH_SW_LED_DUPL_MASK, + .gpio_mask = 0, + .name = "switch_led_dup" + }, { + .reg_mask = QCA_GPIO_FUNC_1_I2S_EN_MASK, + .gpio_mask = GPIO6 | GPIO7 | GPIO8 | GPIO11 | GPIO12, + .name = "i2s" + }, { + .reg_mask = QCA_GPIO_FUNC_1_I2S_MCLK_EN_MASK, + .gpio_mask = GPIO21, + .name = "i2s_mck_on21" + }, { + .reg_mask = QCA_GPIO_FUNC_1_I2S_22_18_EN_MASK, + .gpio_mask = GPIO18 | GPIO19 | GPIO20 | GPIO21 | GPIO22, + .name = "i2s_on_18_22" + }, { + .reg_mask = QCA_GPIO_FUNC_1_SPDIF_EN_MASK, + .gpio_mask = 0, + .name = "spdif" + }, { + .reg_mask = QCA_GPIO_FUNC_1_SPDIF_TCK_EN_MASK, + .gpio_mask = 0, + .name = "spdif_on_tck" + }, +}; + +static const gpio_func gpio_funcs_2[] = { + { + .reg_mask = QCA_GPIO_FUNC_2_MIC_DIS_MASK, + .gpio_mask = 0, + .name = "mic_dis" + }, { + .reg_mask = QCA_GPIO_FUNC_2_I2S_ON_LED_MASK, + .gpio_mask = GPIO14 | GPIO15 | GPIO16, + .name = "i2s_on_led" + }, { + .reg_mask = QCA_GPIO_FUNC_2_SPDIF_ON23_MASK, + .gpio_mask = GPIO23, + .name = "spdif_on_23" + }, { + .reg_mask = QCA_GPIO_FUNC_2_I2SCK_ON1_MASK, + .gpio_mask = GPIO1, + .name = "i2s_clk_on_1" + }, { + .reg_mask = QCA_GPIO_FUNC_2_I2SWS_ON0_MASK, + .gpio_mask = GPIO0, + .name = "i2s_ws_on_0" + }, { + .reg_mask = QCA_GPIO_FUNC_2_I2SSD_ON12_MASK, + .gpio_mask = GPIO12, + .name = "i2s_sd_on_12" + }, { + .reg_mask = QCA_GPIO_FUNC_2_WPS_DIS_MASK, + .gpio_mask = GPIO12, + .name = "wps_dis" + }, { + .reg_mask = QCA_GPIO_FUNC_2_JUMPSTART_DIS_MASK, + .gpio_mask = GPIO11, + .name = "jumpstart_dis" + }, { + .reg_mask = QCA_GPIO_FUNC_2_WLAN_LED_ON0_MASK, + .gpio_mask = GPIO0, + .name = "wlan_led1_on_0" + }, { + .reg_mask = QCA_GPIO_FUNC_2_USB_LED_ON1_MASK, + .gpio_mask = GPIO1, + .name = "wlan_led2_on_1" + }, { + .reg_mask = QCA_GPIO_FUNC_2_LNA_ON28_MASK, + .gpio_mask = GPIO28, + .name = "ext_lna_on_28" + }, { + .reg_mask = QCA_GPIO_FUNC_2_SLIC_EN_MASK, + .gpio_mask = GPIO6 | GPIO7 | GPIO8 | GPIO11 | GPIO12, + .name = "slic" + }, { + .reg_mask = QCA_GPIO_FUNC_2_SLIC_ON18_22_MASK, + .gpio_mask = GPIO18 | GPIO19 | GPIO20 | GPIO21 | GPIO22, + .name = "slic_on_18_22" + }, { + .reg_mask = QCA_GPIO_FUNC_2_SLIC_DIO_MUX_EN_MASK, + .gpio_mask = 0, + .name = "slic_dio_mux" + }, +}; + +static u32 gpio_funcs_1_cnt = sizeof(gpio_funcs_1) / sizeof(gpio_func); +static u32 gpio_funcs_2_cnt = sizeof(gpio_funcs_2) / sizeof(gpio_func); + +#else + +typedef struct { + u8 offset; + char *name; +} gpio_in_func; + +typedef struct { + u8 value; + char *name; +} gpio_out_func; + +/* + * TODO: + * split gpio input functions per SoC version, not just family + */ +static const gpio_in_func gpio_in_funcs[] = { +#if (SOC_TYPE & QCA_AR934X_SOC) ||\ + (SOC_TYPE & QCA_QCA955X_SOC) + /* QCA_GPIO_IN_EN0_REG (0x18040044) */ + { + .offset = 0, + .name = "spi_miso" + }, { + .offset = 1, + .name = "uart0_rx" + }, + /* QCA_GPIO_IN_EN1_REG (0x18040048) */ + { + .offset = 4, + .name = "i2s_mic_ws" + }, { + .offset = 5, + .name = "i2s_mic_sd" + }, { + .offset = 6, + .name = "i2s_ext_clk" + }, { + .offset = 7, + .name = "i2s_ext_mck" + }, + /* QCA_GPIO_IN_EN2_REG (0x1804004C) */ + { + .offset = 8, + .name = "eth_rx_err" + }, { + .offset = 9, + .name = "eth_rx_col" + }, { + .offset = 10, + .name = "eth_rx_crs" + }, +#if (SOC_TYPE & QCA_QCA955X_SOC) + { + .offset = 11, + .name = "slic_ext_mclk" + }, +#endif + /* QCA_GPIO_IN_EN3_REG (0x18040050) */ +#if (SOC_TYPE & QCA_AR934X_SOC) + { + .offset = 14, + .name = "boot_ext_mdo" + }, { + .offset = 15, + .name = "boot_ext_mdc" + }, +#elif (SOC_TYPE & QCA_QCA955X_SOC) + { + .offset = 12, + .name = "boot_ext_mdo" + }, { + .offset = 13, + .name = "boot_ext_mdc" + }, { + .offset = 14, + .name = "mii_ge1_mdi" + }, +#endif + /* QCA_GPIO_IN_EN4_REG (0x18040054) */ + { + .offset = 16, + .name = "slic_data_in" + }, { + .offset = 17, + .name = "slic_pcm_fs_in" + }, +#if (SOC_TYPE & QCA_QCA955X_SOC) + { + .offset = 18, + .name = "i2c_clk" + }, { + .offset = 19, + .name = "i2c_sda" + }, +#endif + /* QCA_GPIO_IN_EN9_REG (0x18040068) */ + { + .offset = 38, + .name = "uart1_rx" + }, { + .offset = 39, + .name = "uart1_cts" + }, +#elif (SOC_TYPE & QCA_QCA953X_SOC) + /* QCA_GPIO_IN_EN0_REG (0x18040044) */ + { + .offset = 0, + .name = "spi_miso" + }, { + .offset = 1, + .name = "uart0_rx" + }, +#elif (SOC_TYPE & QCA_QCA956X_SOC) + /* QCA_GPIO_IN_EN0_REG (0x18040044) */ + { + .offset = 1, + .name = "uart0_rx" + }, + /* QCA_GPIO_IN_EN3_REG (0x18040050) */ + { + .offset = 14, + .name = "mii_ge0_mdi" + }, +#endif +}; + +/* + * TODO: + * split gpio output functions per SoC version, not just family + */ +static const gpio_out_func gpio_out_funcs[] = { + { + .value = 0, + .name = "gpio" + }, +#if (SOC_TYPE & QCA_AR934X_SOC) + { + .value = QCA_GPIO_OUT_MUX_NAND_CS0_VAL, /* 1 */ + .name = "nand_cs" + }, { + .value = 2, + .name = "boot_rxt_mdi" + }, { + .value = 4, + .name = "slic_data_out" + }, { + .value = 5, + .name = "slic_pcm_fs" + }, { + .value = 6, + .name = "slic_pcm_clk" + }, { + .value = 7, + .name = "spi_cs1" + }, { + .value = 8, + .name = "spi_cs2" + }, { + .value = 9, + .name = "spi_cs0" + }, { + .value = QCA_GPIO_OUT_MUX_SPI_CLK_VAL, /* 10 */ + .name = "spi_clk" + }, { + .value = 11, + .name = "spi_mosi" + }, { + .value = 12, + .name = "i2s_clk" + }, { + .value = 13, + .name = "i2s_ws" + }, { + .value = 14, + .name = "i2s_sd" + }, { + .value = 15, + .name = "i2s_mck" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS0_VAL, /* 16 */ + .name = "clk_obs0" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS1_VAL, /* 17 */ + .name = "clk_obs1" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS2_VAL, /* 18 */ + .name = "clk_obs2" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS3_VAL, /* 19 */ + .name = "clk_obs3" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS4_VAL, /* 20 */ + .name = "clk_obs4" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS5_VAL, /* 21 */ + .name = "clk_obs5" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS6_VAL, /* 22 */ + .name = "clk_obs6" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS7_VAL, /* 23 */ + .name = "clk_obs7" + }, { + .value = 24, + .name = "uart0_tx" + }, { + .value = 25, + .name = "spdif_out" + }, { + .value = 26, + .name = "led_act0" + }, { + .value = 27, + .name = "led_act1" + }, { + .value = 28, + .name = "led_act2" + }, { + .value = 29, + .name = "led_act3" + }, { + .value = 30, + .name = "led_act4" + }, { + .value = 31, + .name = "led_col0" + }, { + .value = 32, + .name = "led_col1" + }, { + .value = 33, + .name = "led_col2" + }, { + .value = 34, + .name = "led_col3" + }, { + .value = 35, + .name = "led_col4" + }, { + .value = 36, + .name = "led_dup0" + }, { + .value = 37, + .name = "led_dup1" + }, { + .value = 38, + .name = "led_dup2" + }, { + .value = 39, + .name = "led_dup3" + }, { + .value = 40, + .name = "led_dup4" + }, { + .value = 41, + .name = "led_link0" + }, { + .value = 42, + .name = "led_link1" + }, { + .value = 43, + .name = "led_link2" + }, { + .value = 44, + .name = "led_link3" + }, { + .value = 45, + .name = "led_link4" + }, { + .value = 46, + .name = "ext_lna0" + }, { + .value = 47, + .name = "ext_lna1" + }, { + .value = 48, + .name = "tx_frame" + }, { + .value = 49, + .name = "wlan_act" + }, { + .value = 50, + .name = "led_net_en" + }, { + .value = 51, + .name = "led_pwr_en" + }, { + .value = 72, + .name = "wmac_glue_wow" + }, { + .value = 73, + .name = "bt_act" + }, { + .value = 74, + .name = "rx_clear_extension" + }, { + .value = 78, + .name = "eth_tx_err" + }, { + .value = 79, + .name = "uart1_tx" + }, { + .value = 80, + .name = "uart1_rts" + }, { + .value = 84, + .name = "ddr_dq_oe" + }, { + .value = 87, + .name = "usb_suspend" + }, +#elif (SOC_TYPE & QCA_QCA953X_SOC) + { + .value = QCA_GPIO_OUT_MUX_SYS_RST_L_VAL, /* 1 */ + .name = "sys_rst_l" + }, { + .value = QCA_GPIO_OUT_MUX_SPI_CLK_VAL, /* 8 */ + .name = "spi_clk" + }, { + .value = 9, + .name = "spi_cs0" + }, { + .value = 10, + .name = "spi_cs1" + }, { + .value = 11, + .name = "spi_cs2" + }, { + .value = 12, + .name = "spi_mosi" + }, { + .value = 22, + .name = "uart0_tx" + }, { + .value = QCA_GPIO_OUT_MUX_SRIF_OUT_VAL, /* 23 */ + .name = "srif_out" + }, { + .value = 26, + .name = "led_act0" + }, { + .value = 27, + .name = "led_act1" + }, { + .value = 28, + .name = "led_act2" + }, { + .value = 29, + .name = "led_act3" + }, { + .value = 30, + .name = "led_act4" + }, { + .value = 31, + .name = "led_col0" + }, { + .value = 32, + .name = "led_col1" + }, { + .value = 33, + .name = "led_col2" + }, { + .value = 34, + .name = "led_col3" + }, { + .value = 35, + .name = "led_col4" + }, { + .value = 36, + .name = "led_dup0" + }, { + .value = 37, + .name = "led_dup1" + }, { + .value = 38, + .name = "led_dup2" + }, { + .value = 39, + .name = "led_dup3" + }, { + .value = 40, + .name = "led_dup4" + }, { + .value = 41, + .name = "led_link0" + }, { + .value = 42, + .name = "led_link1" + }, { + .value = 43, + .name = "led_link2" + }, { + .value = 44, + .name = "led_link3" + }, { + .value = 45, + .name = "led_link4" + }, { + .value = QCA_GPIO_OUT_MUX_SMART_ANT_CTRL_BIT2_VAL, /* 48 */ + .name = "smart_ant_ctl_b2" + }, { + .value = QCA_GPIO_OUT_MUX_SMART_ANT_CTRL_BIT3_VAL, /* 49 */ + .name = "smart_ant_ctl_b3" + }, { + .value = 50, + .name = "ext_lna0" + }, { + .value = 51, + .name = "ext_lna1" + }, { + .value = 52, + .name = "tx_frame" + }, { + .value = 53, + .name = "wlan_act" + }, { + .value = 54, + .name = "led_net_en" + }, { + .value = 55, + .name = "led_pwr_en" + }, { + .value = 78, + .name = "rx_clear_extension" + }, { + .value = 86, + .name = "usb_suspend" + }, { + .value = 88, + .name = "ddr_dq_oe" + }, { + .value = 89, + .name = "clk_req_rc_n" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS0_VAL, /* 90 */ + .name = "clk_obs0" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS1_VAL, /* 91 */ + .name = "clk_obs1" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS2_VAL, /* 92 */ + .name = "clk_obs2" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS3_VAL, /* 93 */ + .name = "clk_obs3" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS4_VAL, /* 94 */ + .name = "clk_obs4" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS5_VAL, /* 95 */ + .name = "clk_obs5" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS6_VAL, /* 96 */ + .name = "clk_obs6" + }, +#elif (SOC_TYPE & QCA_QCA955X_SOC) + { + .value = 1, + .name = "mii_ext_mdi" + }, { + .value = 3, + .name = "slic_data_out" + }, { + .value = 4, + .name = "slic_pcm_fs" + }, { + .value = 5, + .name = "slic_pcm_clk" + }, { + .value = QCA_GPIO_OUT_MUX_SPI_CLK_VAL, /* 8 */ + .name = "spi_clk" + }, { + .value = 9, + .name = "spi_cs0" + }, { + .value = 10, + .name = "spi_cs1" + }, { + .value = 11, + .name = "spi_cs2" + }, { + .value = 12, + .name = "spi_mosi" + }, { + .value = 13, + .name = "i2s_clk" + }, { + .value = 14, + .name = "i2s_ws" + }, { + .value = 15, + .name = "i2s_sd" + }, { + .value = 16, + .name = "i2s_mck" + }, { + .value = 17, + .name = "spdif_out" + }, { + .value = 18, + .name = "uart1_tx" + }, { + .value = 19, + .name = "uart1_rts" + }, { + .value = 22, + .name = "uart0_tx" + }, { + .value = QCA_GPIO_OUT_MUX_SRIF_OUT_VAL, /* 23 */ + .name = "srif_out" + }, { + .value = 24, + .name = "led_sgmii_speed0" + }, { + .value = 25, + .name = "led_sgmii_speed1" + }, { + .value = 26, + .name = "led_sgmii_dup" + }, { + .value = 27, + .name = "led_sgmii_link" + }, { + .value = 28, + .name = "led_sgmii_speed0_inv" + }, { + .value = 29, + .name = "led_sgmii_speed1_inv" + }, { + .value = 30, + .name = "led_sgmii_dup_inv" + }, { + .value = 31, + .name = "led_sgmii_link_inv" + }, { + .value = 32, + .name = "ge1_mii_mdo" + }, { + .value = 33, + .name = "ge1_mii_mdc" + }, { + .value = 38, + .name = "swcom_b2" + }, { + .value = 39, + .name = "swcom_b3" + }, { + .value = QCA_GPIO_OUT_MUX_SMART_ANT_CTRL_BIT2_VAL, /* 40 */ + .name = "smart_ant_ctl_b2" + }, { + .value = QCA_GPIO_OUT_MUX_SMART_ANT_CTRL_BIT3_VAL, /* 41 */ + .name = "smart_ant_ctl_b3" + }, { + .value = 42, + .name = "ext_lna0" + }, { + .value = 43, + .name = "ext_lna1" + }, { + .value = 44, + .name = "tx_frame" + }, { + .value = 45, + .name = "wlan_act" + }, { + .value = 46, + .name = "led_net_en" + }, { + .value = 47, + .name = "led_pwr_en" + }, { + .value = 68, + .name = "wmac_glue_wow" + }, { + .value = 70, + .name = "rx_clear_extension" + }, { + .value = 71, + .name = "shift_strobe" + }, { + .value = 72, + .name = "shift_data" + }, { + .value = 73, + .name = "nand_cs1" + }, { + .value = 74, + .name = "usb_suspend" + }, { + .value = 75, + .name = "eth_tx_err" + }, { + .value = 76, + .name = "ddr_dq_oe" + }, { + .value = 77, + .name = "clk_req_ep_n" + }, { + .value = 78, + .name = "clk_req_rc_n" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS0_VAL, /* 79 */ + .name = "clk_obs0" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS1_VAL, /* 80 */ + .name = "clk_obs1" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS2_VAL, /* 81 */ + .name = "clk_obs2" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS3_VAL, /* 82 */ + .name = "clk_obs3" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS4_VAL, /* 83 */ + .name = "clk_obs4" + }, { + .value = QCA_GPIO_OUT_MUX_CLK_OBS5_VAL, /* 84 */ + .name = "clk_obs5" + }, +#elif (SOC_TYPE & QCA_QCA956X_SOC) + { + .value = 18, + .name = "uart1_tx" + }, { + .value = 19, + .name = "uart1_rts" + }, { + .value = 22, + .name = "uart0_tx" + }, { + .value = 23, + .name = "srif_out" + }, { + .value = 24, + .name = "led_sgmii_speed0" + }, { + .value = 25, + .name = "led_sgmii_speed1" + }, { + .value = 26, + .name = "led_sgmii_dup" + }, { + .value = 27, + .name = "led_sgmii_link" + }, { + .value = 28, + .name = "led_sgmii_speed0_inv" + }, { + .value = 29, + .name = "led_sgmii_speed1_inv" + }, { + .value = 30, + .name = "led_sgmii_dup_inv" + }, { + .value = 31, + .name = "led_sgmii_link_inv" + }, { + .value = 37, + .name = "spi_cs1" + }, { + .value = 38, + .name = "swcom_b2" + }, { + .value = 39, + .name = "swcom_b3" + }, { + .value = 40, + .name = "smart_ant_ctl_b2" + }, { + .value = 41, + .name = "smart_ant_ctl_b3" + }, { + .value = 42, + .name = "ext_lna0" + }, { + .value = 43, + .name = "ext_lna1" + }, { + .value = 44, + .name = "tx_frame" + }, { + .value = 45, + .name = "wlan_act" + }, { + .value = 46, + .name = "led_net_en" + }, { + .value = 47, + .name = "led_pwr_en" + }, { + .value = 69, + .name = "bt_act" + }, { + .value = 70, + .name = "rx_clear_extension" + }, { + .value = 73, + .name = "i2c_clk" + }, { + .value = 77, + .name = "i2c_sda" + }, { + .value = 78, + .name = "clk_req_rc_n" + }, { + .value = 89, + .name = "sgmii_lckdt" + }, { + .value = 115, + .name = "pcie2_rst_l" + }, +#endif +}; + +static u32 gpio_in_funcs_cnt = sizeof(gpio_in_funcs) / sizeof(gpio_in_func); +static u32 gpio_out_funcs_cnt = sizeof(gpio_out_funcs) / sizeof(gpio_out_func); + +#endif /* SOC_TYPE & QCA_AR933X_SOC */ + +#endif /* CONFIG_CMD_GPIO */ + +#endif /* _CMD_QCAGPIO_H_ */ diff --git a/u-boot/include/configs/qca9k_common.h b/u-boot/include/configs/qca9k_common.h index 4cd3505..80838d8 100644 --- a/u-boot/include/configs/qca9k_common.h +++ b/u-boot/include/configs/qca9k_common.h @@ -105,6 +105,7 @@ #define CONFIG_CMD_ECHO #define CONFIG_CMD_ENV #define CONFIG_CMD_FLASH +#define CONFIG_CMD_GPIO #define CONFIG_CMD_HTTPD #define CONFIG_CMD_IMI #define CONFIG_CMD_ITEST -- 2.25.1