diff --git a/board/nm/nmhw24/Makefile b/board/nm/nmhw24/Makefile index 3fd6fd7737..9c4b04f561 100644 --- a/board/nm/nmhw24/Makefile +++ b/board/nm/nmhw24/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 fileaccess.o da9063.o +obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o shield.o shield_can.o shield_comio.o fileaccess.o da9063.o diff --git a/board/nm/nmhw24/board.c b/board/nm/nmhw24/board.c index c842d37e23..8a80ba3299 100644 --- a/board/nm/nmhw24/board.c +++ b/board/nm/nmhw24/board.c @@ -35,11 +35,9 @@ #include "../common/board_descriptor.h" #include "board.h" #include "da9063.h" -#if 0 #include "shield.h" #include "shield_can.h" #include "shield_comio.h" -#endif #include "fileaccess.h" DECLARE_GLOBAL_DATA_PTR; @@ -676,9 +674,6 @@ static void check_fct(void) i2c_set_bus_num(old_bus); } -// TODO: activate -#if 0 - struct shield_command { int shield_id; const char *name; @@ -757,7 +752,6 @@ static void shield_init(void) shield_config(); } -#endif static bool get_button_state(void) { @@ -877,8 +871,7 @@ int board_late_init(void) check_reset_button(); set_console(); - // TODO: - // shield_init(); + shield_init(); set_status_led(1, 1); /* Orange */ set_indicator_led(0, 0); /* Off */ @@ -1017,7 +1010,6 @@ int board_fit_config_name_match(const char *name) #if defined(CONFIG_OF_BOARD_SETUP) && !defined(CONFIG_SPL_BUILD) -#if 0 static void ft_enable_node(void* blob, const char* name) { int node_ofs = -1; @@ -1028,53 +1020,30 @@ static void ft_enable_node(void* blob, const char* name) } } -static void ft_dio(void *blob, int shield_type) +static void ft_shields(void* blob) { - // TODO: Move switch case to calling function + int shield_type = -1; + + shield_type = bd_get_shield(0); switch (shield_type) { - /* If COM/IO shield is present enable its I/Os */ case SHIELD_COM_IO: ft_enable_node(blob, "/netbox_dio_comio"); - break; - - default: - ft_enable_node(blob, "/netbox_dio_default"); - break; - } -} - -static void ft_serial(void *blob, int shield_type) -{ - // TODO: Move switch case to calling function - switch (shield_type) { - /* If COM/IO shield is present enable uart1 (ttyS0) */ - case SHIELD_COM_IO: /* TODO: Should use alias serial0 */ ft_enable_node(blob, "/ocp/serial@44e09000"); break; - default: - break; - } -} - -static void ft_dcan(void *blob, int shield_type) -{ - // TODO: Move switch case to calling function - - switch (shield_type) { - /* If Dual CAN shield is present enable dcan0, dcan1N1 */ case SHIELD_DUALCAN: - /* TODO: Should use alias d_can0, d_can1 */ + /* TODO: Should use alias d_can0, d_can1 */ ft_enable_node(blob, "/ocp/can@481cc000"); ft_enable_node(blob, "/ocp/can@481d0000"); break; default: + ft_enable_node(blob, "/netbox_dio_default"); break; - } + }; + } -#endif static void ft_bootloader_version(void *blob) { @@ -1103,23 +1072,11 @@ static void ft_hw_info(void *blob) int ft_board_setup(void *blob, bd_t *bd) { -#if 0 - int shield_type = -1; -#endif - ft_bootloader_version(blob); ft_hw_info(blob); - -#if 0 - shield_type = bd_get_shield(0); - - // TODO: Add switch case here - ft_dio(blob, shield_type); - ft_serial(blob, shield_type); - ft_dcan(blob, shield_type); -#endif + ft_shields(blob); return 0; } -#endif +#endif /* defined(CONFIG_OF_BOARD_SETUP) && !defined(CONFIG_SPL_BUILD) */ diff --git a/board/nm/nmhw24/shield.c b/board/nm/nmhw24/shield.c new file mode 100644 index 0000000000..97f1394a9d --- /dev/null +++ b/board/nm/nmhw24/shield.c @@ -0,0 +1,73 @@ +#undef DEBUG + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +#define MAX_SHIELDS 16 + +static struct shield_t *shields[MAX_SHIELDS]; +static int shield_count = 0; + +/* Perhaps this function shouldn't leave in shields.c? */ +int shield_gpio_request_as_input(unsigned int gpio, const char *label) +{ + int ret; + + ret = gpio_request(gpio, label); + if ((ret < 0)) { + printf("Could not request shield slot %s gpio\n", label); + return -1; + } + + ret = gpio_direction_input(gpio); + if ((ret < 0)) { + printf("Could not configure shield slot %s gpio as input\n", label); + return -1; + } + + return 0; +} + +void shield_register(struct shield_t *shield) +{ + if (shield_count >= MAX_SHIELDS) { + printf("Max shield count reached (%d), please increment MAX_SHIELDS\n", MAX_SHIELDS); + return; + } + shields[shield_count++] = shield; +} + +int shield_set_mode(const char* shield_type, int argc, char * const argv[]) +{ + int i; + + for (i = 0; i < shield_count; i++) { + if (strcmp(shield_type, shields[i]->name) == 0) { + return shields[i]->setmode(argv, argc); + } + } + printf("## Error: No %s shield installed\n", shield_type); + /* Do not return error, to not show usage (request by rs) */ + return 0; +} + +static int do_shieldmode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc < 2) { + return -1; + } + + return shield_set_mode(argv[1], argc - 2, &argv[2]); +} + +U_BOOT_CMD( + shield, 6, 1, do_shieldmode, + "Set the shield mode", + "dualcan termination [on|off] [on|off]\n" + "shield comio mode [rs232|rs485] termination [on|off]\n" +); + diff --git a/board/nm/nmhw24/shield.h b/board/nm/nmhw24/shield.h new file mode 100644 index 0000000000..2ab27a0941 --- /dev/null +++ b/board/nm/nmhw24/shield.h @@ -0,0 +1,21 @@ +/**@file /home/eichenberger/projects/nbhw16/u-boot/board/nm/netbird_v2/shield.h + * @author eichenberger + * @version 704 + * @date + * Created: Wed 31 May 2017 02:56:16 PM CEST \n + * Last Update: Wed 31 May 2017 02:56:16 PM CEST + */ +#ifndef SHIELD_H +#define SHIELD_H + +struct shield_t{ + char name[64]; + int (*setmode)(char * const argv[], int argc); +}; + +int shield_setmode(int mode); +void shield_register(struct shield_t *shield); + +int shield_gpio_request_as_input(unsigned int gpio, const char *label); + +#endif // SHIELD_H diff --git a/board/nm/nmhw24/shield_can.c b/board/nm/nmhw24/shield_can.c new file mode 100644 index 0000000000..36fa0a66a7 --- /dev/null +++ b/board/nm/nmhw24/shield_can.c @@ -0,0 +1,195 @@ +#undef DEBUG + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +#define CAN_PORTS 2 + +#define NETBIRD_GPIO_RST_SHIELD_N GPIO_TO_PIN(0, 27) +#define NETBIRD_GPIO_LATCH GPIO_TO_PIN(0, 7) +#define NETBIRD_GPIO_MODE_0 GPIO_TO_PIN(1, 8) +#define NETBIRD_GPIO_MODE_1 GPIO_TO_PIN(1, 10) + + +static int shield_slot_initialized = 0; + + +static struct module_pin_mux can_shield_netbird_pin_mux_config[] = { + /* Leave UART0 unconfigured because we want to configure it as needed by linux (can/spi/uart/etc) */ + {OFFSET(uart0_ctsn), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (E18) gpio1_8 */ /* Mode 0 */ + {OFFSET(uart0_rxd), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (E15) gpio1_10 */ /* Mode 1 */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (C18) eCAP0_in_PWM0_out.gpio0[7] */ /* Latch EN */ + {-1}, +}; + +static struct module_pin_mux can_shield_netbird_pin_mux_final[] = { + {OFFSET(uart0_txd), (MODE(2) | PULLUDDIS | RXACTIVE)}, /* (E16) dcan0_rx */ + {OFFSET(uart0_rxd), (MODE(2) | PULLUDEN | PULLUP_EN)}, /* (E15) dcan0_tx */ + {OFFSET(uart0_rtsn), (MODE(2) | PULLUDDIS | RXACTIVE)}, /* (E17) dcan1_rx */ + {OFFSET(uart0_ctsn), (MODE(2) | PULLUDEN | PULLUP_EN)}, /* (E18) dcan1_tx */ + {-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_LATCH, "shield-load"); + if ((ret < 0)) + return -1; + ret = shield_gpio_request_as_input(NETBIRD_GPIO_MODE_0, "shield-mode0"); + if ((ret < 0)) + return -1; + ret = shield_gpio_request_as_input(NETBIRD_GPIO_MODE_1, "shield-mode1"); + if ((ret < 0)) + return -1; + + shield_slot_initialized = 1; + return 0; +} + +static int configure_shieldmode(int mode) +{ + int ret; + + if (mode < 0 || mode > 3) { + debug("Invalid shield mode %d\n", mode); + return -1; + } + + debug("Shield type dualcan\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("Configure shield pin muxing for configuration\n"); + configure_module_pin_mux(can_shield_netbird_pin_mux_config); + + 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 latch to high\n"); + ret = gpio_direction_output(NETBIRD_GPIO_LATCH, 1); + if (ret < 0) { + puts("Can not set shield-load as output\n"); + return -1; + } + udelay(10); + + debug("Write mode to GPIOs\n"); + ret = gpio_direction_output(NETBIRD_GPIO_MODE_0, mode & 0x01); + if (ret < 0) { + puts("Can not set shield-mode0 as output\n"); + return -1; + } + ret = gpio_direction_output(NETBIRD_GPIO_MODE_1, mode & 0x02); + if (ret < 0) { + puts("Can not set shield-mode1 as output\n"); + return -1; + } + udelay(10); + + debug("Set latch to low\n"); + gpio_set_value(NETBIRD_GPIO_LATCH, 0); + udelay(10); + + debug("Set mode0 and mode1 to highz again\n"); + ret = gpio_direction_input(NETBIRD_GPIO_MODE_0); + if ((ret < 0)) { + puts("Could not configure shield slot mode0 gpio as input\n"); + return -1; + } + + ret = gpio_direction_input(NETBIRD_GPIO_MODE_1); + if ((ret < 0)) { + puts("Could not configure shield slot mode1 gpio as input\n"); + return -1; + } + udelay(10); + + debug("Take shield out of reset\n"); + gpio_set_value(NETBIRD_GPIO_RST_SHIELD_N, 1); + udelay(10); + + debug("Set final can shield muxing\n"); + configure_module_pin_mux(can_shield_netbird_pin_mux_final); + + 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) +{ + 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 */ + /* TODO: Double check */ + return (!terminations[0] << 0) | (!terminations[1] << 1); +} + +static int set_shieldmode(char * const argv[], int argc) +{ + if (argc != 3) { + debug("Too few arguments for dualcan\n"); + return -1; + } + + return configure_shieldmode(get_mode_from_args(argv, argc)); +} + +/* TODO: Static ? */ +struct shield_t can_shield = { + "dualcan", set_shieldmode +}; + +void can_shield_init(void) +{ + shield_register(&can_shield); +} diff --git a/board/nm/nmhw24/shield_can.h b/board/nm/nmhw24/shield_can.h new file mode 100644 index 0000000000..21684cd4f7 --- /dev/null +++ b/board/nm/nmhw24/shield_can.h @@ -0,0 +1,9 @@ +#ifndef SHIELD_CAN_H +#define SHIELD_CAN_H + +int shield_can_init(void); +int shield_can_setmode(int mode); + +void can_shield_init(void); + +#endif // SHIELD_CAN_H diff --git a/board/nm/nmhw24/shield_comio.c b/board/nm/nmhw24/shield_comio.c new file mode 100644 index 0000000000..f43e992349 --- /dev/null +++ b/board/nm/nmhw24/shield_comio.c @@ -0,0 +1,252 @@ +#undef DEBUG + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +/* TODO: Double Check */ +#define NETBIRD_GPIO_RST_SHIELD_N GPIO_TO_PIN(0, 27) +#define NETBIRD_GPIO_LOAD GPIO_TO_PIN(1, 9) +/* TODO: Who configures UART0_RTSn, GPIO1_9 ? */ +#define NETBIRD_GPIO_MODE_0 GPIO_TO_PIN(1, 11) +#define NETBIRD_GPIO_MODE_1 GPIO_TO_PIN(1, 10) + +static int shield_slot_initialized = 0; + + +/* TODO: Naming -> config, final */ +static struct module_pin_mux shield_gpio_netbird_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(7) | PULLUDDIS)}, /* (E15) gpio1_10 */ /* Mode 0 */ + {OFFSET(uart0_txd), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (E16) gpio1_11 */ /* Mode 1 */ + {-1}, +}; + +static struct module_pin_mux shield_gpio_safe_netbird_pin_mux[] = { + /* Leave UART0 unconfigured (GPIO) because we want to configure it as needed by linux (can/spi/uart/etc) */ + {OFFSET(uart0_rxd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E15) gpio1_10 */ /* Mode 0 */ + {OFFSET(uart0_txd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E16) gpio1_11 */ /* Mode 1 */ + {-1}, +}; + + +static int request_gpios(void) +{ + int ret; + + debug("Extension slot init\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_LOAD, "shield-load"); + if ((ret < 0)) + return -1; + ret = shield_gpio_request_as_input(NETBIRD_GPIO_MODE_0, "shield-mode0"); + if ((ret < 0)) + return -1; + ret = shield_gpio_request_as_input(NETBIRD_GPIO_MODE_1, "shield-mode1"); + if ((ret < 0)) + return -1; + + shield_slot_initialized = 1; + return 0; +} + +static int configure_shieldmode(int mode) +{ + int ret; + + if (mode < 0 || mode > 3) { + debug ("Invalid shield mode %d\n", mode); + return -1; + } + + debug("Shield type comio\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("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("Enable gpio pull-ups\n"); + configure_module_pin_mux(shield_gpio_netbird_pin_mux); + + debug("Set load to low\n"); + ret = gpio_direction_output(NETBIRD_GPIO_LOAD, 0); + if (ret < 0) { + puts("Can not set shield-load as output\n"); + return -1; + } + udelay(10); + + debug("Write mode to GPIOs\n"); + ret = gpio_direction_output(NETBIRD_GPIO_MODE_0, mode & 0x01); + if (ret < 0) { + puts("Can not set shield-mode0 as output\n"); + return -1; + } + ret = gpio_direction_output(NETBIRD_GPIO_MODE_1, mode & 0x02); + if (ret < 0) { + puts("Can not set shield-mode1 as output\n"); + return -1; + } + udelay(10); + + debug("Set load to high\n"); + gpio_set_value(NETBIRD_GPIO_LOAD, 1); + udelay(10); + + debug("Set mode0 and mode1 to highz again\n"); + ret = gpio_direction_input(NETBIRD_GPIO_MODE_0); + if ((ret < 0)) { + puts("Could not configure shield slot mode0 gpio as input\n"); + return -1; + } + + ret = gpio_direction_input(NETBIRD_GPIO_MODE_1); + if ((ret < 0)) { + puts("Could not configure shield slot mode1 gpio as input\n"); + return -1; + } + udelay(10); + + debug("Disable pullups on shield gpios\n"); + configure_module_pin_mux(shield_gpio_safe_netbird_pin_mux); + udelay(10); + + debug("Take shield out of reset\n"); + gpio_set_value(NETBIRD_GPIO_RST_SHIELD_N, 1); + udelay(10); + + debug("Set gpio load as input again\n"); + ret = gpio_direction_input(NETBIRD_GPIO_LOAD); + if (ret < 0) { + puts("Can not configure shield slot load as input"); + return -1; + } + + return 0; +} + +enum mode_nr { + RS232, + RS485, + UNKNOWN +}; + +struct mode { + enum mode_nr nr; + const char* name; + int argc; +}; + +struct mode modes[] = { + { RS232, "rs232", 0 }, + { RS485, "rs485", 2 } +}; + +static const struct mode *get_mode(const char *mode) +{ + int i; + for (i = 0; i < ARRAY_SIZE(modes); i++) { + if (strcmp(modes[i].name, mode) == 0) { + return &modes[i]; + } + } + return NULL; +} + +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) +{ + int termination = 0; + int rs232 = 0; + const struct mode *selected_mode; + + assert(argc >= 2); + + if (strcmp ("mode", argv[0])) { + debug("Invalid arguments (see help)\n"); + return -1; + } + + selected_mode = get_mode(argv[1]); + if (selected_mode == NULL) { + debug("Mode %s not supported\n", argv[1]); + return -1; + } + + debug ("Mode %s, index %d, argc %d\n", selected_mode->name, + selected_mode->nr, selected_mode->argc); + + if (selected_mode->argc != argc - 2) { + debug("Invalid argument count for mode %s (should %d is %d)\n", + argv[1], selected_mode->argc, argc - 2); + return -1; + } + + if (selected_mode->nr == RS485) { + if (strcmp("termination", argv[2])) { + debug("Invalid arguments, do not configure termination\n"); + return -1; + } + + termination = get_termination(argv[3]); + if (termination < 0) { + debug("Invalid termination %s\n", argv[3]); + return -1; + } + } + else { + rs232 = 1; + } + + /* Termination is inverse */ + return (rs232 << 0) | ((!termination) << 1); +} + +int set_shieldmode(char * const argv[], int argc) +{ + if (argc < 2) { + debug("Too few arguments for comio\n"); + return -1; + } + + /* -1 will make configure_shieldmode to faile and is okay therefore */ + return configure_shieldmode(get_mode_from_args(argv, argc)); +} + +/* TODO: Static ? */ +struct shield_t comio_shield = { + "comio", set_shieldmode +}; + +void comio_shield_init(void) +{ + shield_register(&comio_shield); +} diff --git a/board/nm/nmhw24/shield_comio.h b/board/nm/nmhw24/shield_comio.h new file mode 100644 index 0000000000..2b2602e917 --- /dev/null +++ b/board/nm/nmhw24/shield_comio.h @@ -0,0 +1,6 @@ +#ifndef SHIELD_COMIO_H +#define SHIELD_COMIO_H + +void comio_shield_init(void); + +#endif // SHIELD_COMIO_H