diff --git a/board/nm/netbird_v2/Makefile b/board/nm/netbird_v2/Makefile index c4b21a1d3a..ee26014efb 100644 --- a/board/nm/netbird_v2/Makefile +++ b/board/nm/netbird_v2/Makefile @@ -10,4 +10,4 @@ ifeq ($(CONFIG_SKIP_LOWLEVEL_INIT),) obj-y := mux.o endif -obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o shield.o shield_can.o shield_comio.o fileaccess.o +obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o shield.o shield_can.o shield_comio.o shield_gnsscan.o fileaccess.o diff --git a/board/nm/netbird_v2/board.c b/board/nm/netbird_v2/board.c index eb35af8033..b533512996 100644 --- a/board/nm/netbird_v2/board.c +++ b/board/nm/netbird_v2/board.c @@ -40,6 +40,7 @@ #include "shield.h" #include "shield_can.h" #include "shield_comio.h" +#include "shield_gnsscan.h" #include "fileaccess.h" DECLARE_GLOBAL_DATA_PTR; @@ -82,6 +83,7 @@ static BD_Context bdctx[3]; /* The descriptor context */ #define SHIELD_COM_IO 0 #define SHIELD_DUALCAN 1 +#define SHIELD_GNSSCAN 2 static int _bd_init(void) { @@ -597,6 +599,16 @@ static struct shield_command known_shield_commands[] = { "fdt set $can1 status okay;", can_shield_init }, + { + SHIELD_GNSSCAN, + "gnsscan", + "shield gnsscan termination off", + "fdt get value serial0 /aliases serial0;" \ + "fdt get value can1 /aliases d_can1;" \ + "fdt set $serial0 status okay;" \ + "fdt set $can1 status okay;", + gnsscan_shield_init + }, }; static const struct shield_command* get_shield_command(int shield_id) diff --git a/board/nm/netbird_v2/shield.c b/board/nm/netbird_v2/shield.c index 6a06d05765..5189ddefbd 100644 --- a/board/nm/netbird_v2/shield.c +++ b/board/nm/netbird_v2/shield.c @@ -67,7 +67,8 @@ static int do_shieldmode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv U_BOOT_CMD( shield, 6, 1, do_shieldmode, "Set the shield mode", - "dualcan termination on|off on|off\n" + "shield dualcan termination on|off on|off\n" "shield comio mode rs232|rs485 [termination on|off]\n" + "shield gnsscan termination on|off\n" ); diff --git a/board/nm/netbird_v2/shield_gnsscan.c b/board/nm/netbird_v2/shield_gnsscan.c new file mode 100644 index 0000000000..ea41731d8c --- /dev/null +++ b/board/nm/netbird_v2/shield_gnsscan.c @@ -0,0 +1,143 @@ +#undef DEBUG + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +#define NETBIRD_GPIO_RST_SHIELD_N GPIO_TO_PIN(0, 27) +#define NETBIRD_GPIO_EN_CAN_TERM_N GPIO_TO_PIN(0, 7) + + +static int shield_slot_initialized = 0; + +static struct module_pin_mux gnsscan_shield_netbird_pin_mux_final[] = { + /* Leave UART0 unconfigured because we want to configure it as needed by linux (can/spi/uart/etc) */ + {OFFSET(uart0_rxd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E15) UART0_RXD */ + {OFFSET(uart0_txd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E16) UART0_TXD */ + {OFFSET(uart0_ctsn), (MODE(2) | PULLUDEN | PULLUP_EN)}, /* CAN1 tx */ + {OFFSET(uart0_rtsn), (MODE(2) | PULLUDDIS | RXACTIVE)}, /* CAN1 rx */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* EN_CAN1_TERM_N */ + {-1}, +}; + +static int request_gpios(void) +{ + int ret; + + debug("Shield configure gpios\n"); + ret = shield_gpio_request_as_input(NETBIRD_GPIO_RST_SHIELD_N, "shield-rst"); + if ((ret < 0)) + return -1; + ret = shield_gpio_request_as_input(NETBIRD_GPIO_EN_CAN_TERM_N, "shield-can-term-n"); + if ((ret < 0)) + return -1; + + shield_slot_initialized = 1; + return 0; +} + +static int configure_shieldmode(int mode) +{ + int ret; + + if (mode < 0 || mode > 1) { + debug("Invalid shield mode %d\n", mode); + return -1; + } + + debug("Shield type gnsscan\n"); + debug ("Set shield mode to %d\n", mode); + + if (!shield_slot_initialized) { + if (request_gpios()) { + puts("Failed to request gpios\n"); + return -1; + } + } + + debug("Set final gnsscan shield muxing\n"); + configure_module_pin_mux(gnsscan_shield_netbird_pin_mux_final); + + debug("Make sure shield module is in reset\n"); + ret = gpio_direction_output(NETBIRD_GPIO_RST_SHIELD_N, 0); + if (ret < 0) { + puts("Can not set shield-rst as output\n"); + return -1; + } + udelay(10); + + debug("Set termination on/off\n"); + ret = gpio_direction_output(NETBIRD_GPIO_EN_CAN_TERM_N, mode); + if (ret < 0) { + puts("Can not set shield-can-term as output\n"); + return -1; + } + udelay(10); + + debug("Take shield out of reset\n"); + gpio_set_value(NETBIRD_GPIO_RST_SHIELD_N, 1); + udelay(10); + + return 0; + +} + +static int get_termination(const char* termination) +{ + if (strcmp("on", termination) == 0) { + return 1; + } + else if (strcmp("off", termination) == 0) { + return 0; + } + + debug ("Invalid termination mode %s (falling back to off)", termination); + return -1; +} + +static int get_mode_from_args(char * const argv[], int argc) +{ +#define CAN_PORTS 1 + int terminations[CAN_PORTS]; + int i; + + assert(argc == (CAN_PORTS + 1)); + + if (strcmp ("termination", argv[0])) { + debug("The only option for dualcan is terminations\n"); + return -1; + } + + for (i = 0; i < CAN_PORTS; i ++) { + terminations[i] = get_termination(argv[i + 1]); + if (terminations[i] < 0) { + return -1; + } + } + + /* Termination is inverse */ + return (!terminations[0] << 0); +} + +static int set_shieldmode(char * const argv[], int argc) +{ + if (argc != 2) { + debug("Too few arguments for gnsscan\n"); + return -1; + } + + return configure_shieldmode(get_mode_from_args(argv, argc)); +} + +struct shield_t gnsscan_shield = { + "gnsscan", set_shieldmode +}; + +void gnsscan_shield_init(void) +{ + shield_register(&gnsscan_shield); +} + diff --git a/board/nm/netbird_v2/shield_gnsscan.h b/board/nm/netbird_v2/shield_gnsscan.h new file mode 100644 index 0000000000..3b5dcb41f3 --- /dev/null +++ b/board/nm/netbird_v2/shield_gnsscan.h @@ -0,0 +1,9 @@ +#ifndef SHIELD_GNSSCAN_H +#define SHIELD_GNSSCAN_H + +int shield_gnsscan_init(void); +int shield_gnscan_setmode(int mode); + +void gnsscan_shield_init(void); + +#endif // SHIELD_CAN_H