diff --git a/board/nm/common/bdparser.h b/board/nm/common/bdparser.h index 1ddcaa7686..7df579561a 100644 --- a/board/nm/common/bdparser.h +++ b/board/nm/common/bdparser.h @@ -168,6 +168,8 @@ typedef enum _BD_Tags BD_Pd_Module5 = 4105, BD_Pd_Sim = 4122, PD_Dev_Tree = 4125, /**< "String" -> Devicetree file name */ + PD_SerDes = 4128, /**< "Uint16" -> SERDES Configuration (e.g. NB1800) */ + PD_Shield = 4129, /**< "String" -> Shield Population (e.g. CAN/RS485) for NB800 */ /* project specific tags */ BD_BootPart = 32768, /**< "UInt8" */ diff --git a/board/nm/common/board_descriptor.c b/board/nm/common/board_descriptor.c index 763a849489..4ab3339f53 100644 --- a/board/nm/common/board_descriptor.c +++ b/board/nm/common/board_descriptor.c @@ -109,6 +109,7 @@ static bd_bool_t _get_mac( bd_uint16_t tag, bd_uint_t index, bd_uint8_t pResult[ return BD_FALSE; } + static bd_bool_t _get_uint8( bd_uint16_t tag, bd_uint_t index, bd_uint8_t* pResult ) { int i; @@ -121,6 +122,18 @@ static bd_bool_t _get_uint8( bd_uint16_t tag, bd_uint_t index, bd_uint8_t* pResu return BD_FALSE; } +static bd_bool_t _get_uint16( bd_uint16_t tag, bd_uint_t index, bd_uint16_t* pResult ) { + int i; + + for (i = 0; i < bdctx_count; i++) { + if (BD_GetUInt16(&bdctx_list[i], tag, index, pResult)) { + return BD_TRUE; + } + } + + return BD_FALSE; +} + static bd_bool_t _get_uint32( bd_uint16_t tag, bd_uint_t index, bd_uint32_t* pResult ) { int i; @@ -227,6 +240,18 @@ int bd_get_devicetree(char* devicetreename, size_t len) return 0; } +int bd_get_shield(int shieldnr) +{ + bd_uint16_t shield = 0; + + if (!_get_uint16(PD_Shield, shieldnr, &shield) ) { + debug("%s() no shield populated\n", __func__); + return -1; + } + + return shield; +} + static u8 try_partition_read(void) { BD_PartitionEntry64 partition; diff --git a/board/nm/common/board_descriptor.h b/board/nm/common/board_descriptor.h index 5ab152f6fe..c33a796147 100644 --- a/board/nm/common/board_descriptor.h +++ b/board/nm/common/board_descriptor.h @@ -17,5 +17,6 @@ int bd_get_devicetree(char* devicetreename, size_t len); int bd_get_context(BD_Context *bdctx, uint32_t i2caddress, uint32_t offset); void bd_register_context_list(const BD_Context *list, size_t count); u8 bd_get_boot_partition(void); +int bd_get_shield(int shieldnr); #endif /* __BOARD_DESCRIPTOR_H */ diff --git a/board/nm/netbird/board.c b/board/nm/netbird/board.c index a6efd08f07..ed7caf5e08 100644 --- a/board/nm/netbird/board.c +++ b/board/nm/netbird/board.c @@ -42,7 +42,6 @@ DECLARE_GLOBAL_DATA_PTR; /* GPIO that controls power to DDR on EVM-SK */ -#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) #define GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 7) #define ICE_GPIO_DDR_VTT_EN GPIO_TO_PIN(0, 18) #define GPIO_PR1_MII_CTRL GPIO_TO_PIN(3, 4) diff --git a/board/nm/netbird_v2/Makefile b/board/nm/netbird_v2/Makefile index 9f85d4bd83..c4b21a1d3a 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 +obj-y += board.o ../common/bdparser.o ../common/board_descriptor.o shield.o shield_can.o shield_comio.o fileaccess.o diff --git a/board/nm/netbird_v2/board.c b/board/nm/netbird_v2/board.c index 68cd17aa08..8e791c85b5 100644 --- a/board/nm/netbird_v2/board.c +++ b/board/nm/netbird_v2/board.c @@ -37,6 +37,10 @@ #include "../common/bdparser.h" #include "../common/board_descriptor.h" #include "board.h" +#include "shield.h" +#include "shield_can.h" +#include "shield_comio.h" +#include "fileaccess.h" DECLARE_GLOBAL_DATA_PTR; @@ -324,9 +328,8 @@ int check_reset_button(void) return 1; } else { /* Boot into recovery for duration > 15s */ - /* set consoledev to external port */ - setenv("consoledev", "ttyO0"); + setenv("consoledev", "ttyS1"); printf("Booting recovery image...\n"); @@ -514,6 +517,93 @@ static void check_fct(void) } } + +static void set_fdtshieldcmd(const char *fdt_cmd) +{ + setenv("fdtshieldcmd", fdt_cmd); +} + +struct shield_command { + int shield_id; + const char *default_shieldcmd; + const char *fdtshieldcmd; +}; + +#define SHIELD_COM_IO 0 +#define SHIELD_DUALCAN 1 + +static struct shield_command known_shield_commands[] = { + { + SHIELD_COM_IO, + "shield comio mode rs232", + "fdt get value serial0 /aliases serial0;" \ + "fdt set $serial0 status okay" + }, + { + SHIELD_DUALCAN, + "shield dualcan termination off off", + "fdt get value can0 /aliases d_can0;" \ + "fdt get value can1 /aliases d_can1;" \ + "fdt set $can0 status okay;" \ + "fdt set $can1 status okay;" \ + }, +}; + +static const struct shield_command* get_shield_command(int shield_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(known_shield_commands); i++) { + if (known_shield_commands[i].shield_id == shield_id) { + return &known_shield_commands[i]; + } + } + + return NULL; +} + +static void shield_config(void) +{ +#define MAX_SHIELD_CMD_LEN 128 + char shieldcmd_linux[MAX_SHIELD_CMD_LEN]; + const char *shieldcmd; + const struct shield_command *cmd; + int len; + + int shield_id = bd_get_shield(0); + if (shield_id < 0) { + printf("No shield found in bd\n"); + return; + } + + cmd = get_shield_command(shield_id); + if (cmd == NULL) { + printf ("Unknown shield id %d\n", shield_id); + return; + } + + shieldcmd = cmd->default_shieldcmd; + + /* If a shield configuration set by linux take it without bd check, we asume that Linux knows + * what to do. */ + len = read_file("/root/boot/shieldcmd", shieldcmd_linux, MAX_SHIELD_CMD_LEN); + if (len > 0) { + puts("Shield command found in file, using it\n"); + shieldcmd = shieldcmd_linux; + } + + setenv("shieldcmd", shieldcmd); + + set_fdtshieldcmd(cmd->fdtshieldcmd); +} + +static void shield_init(void) +{ + can_shield_init(); + comio_shield_init(); + + shield_config(); +} #endif #ifdef CONFIG_BOARD_LATE_INIT @@ -533,6 +623,7 @@ int board_late_init(void) /* mmcblk0p1 => root0, mmcblk0p2 => root1 so +1 */ setenv_ulong("root_part", boot_partition + 1); + fs_set_console(); check_reset_button(); @@ -551,7 +642,10 @@ int board_late_init(void) enable_wlan_clock(); #if !defined(CONFIG_SPL_BUILD) + shield_init(); + check_fct(); + #endif return 0; diff --git a/board/nm/netbird_v2/board.h b/board/nm/netbird_v2/board.h index 8083c7d0d2..0b1beaaddd 100644 --- a/board/nm/netbird_v2/board.h +++ b/board/nm/netbird_v2/board.h @@ -24,4 +24,6 @@ void enable_uart4_pin_mux(void); void enable_uart5_pin_mux(void); void enable_i2c0_pin_mux(void); void enable_board_pin_mux(void); + +#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) #endif diff --git a/board/nm/netbird_v2/fileaccess.c b/board/nm/netbird_v2/fileaccess.c new file mode 100644 index 0000000000..58bcb9f582 --- /dev/null +++ b/board/nm/netbird_v2/fileaccess.c @@ -0,0 +1,71 @@ +#include +#include + +#define OVERLAY_PART "1:3" + +int read_file(const char* filename, char *buf, int size) +{ + loff_t filesize = 0; + loff_t len; + int ret; + + /* If consoldev is set take this as productive conosle instead of default console */ + if (fs_set_blk_dev("mmc", OVERLAY_PART, FS_TYPE_EXT) != 0) { + puts("Error, can not set blk device\n"); + return -1; + } + + + /* File does not exist, do not print an error message */ + if (fs_size(filename, &filesize)) { + return -1; + } + + if (filesize < size) + size = filesize; + + /* If consoldev is set take this as productive conosle instead of default console */ + if (fs_set_blk_dev("mmc", OVERLAY_PART, FS_TYPE_EXT) != 0) { + puts("Error, can not set blk device\n"); + return -1; + } + + + if ((ret = fs_read(filename, (ulong)buf, 0, size, &len))) { + printf("Can't read file %s (size %d, len %lld, ret %d)\n", filename, size, len, ret); + return -1; + } + + buf[len] = 0; + + return len; +} + +void fs_set_console(void) +{ + loff_t len; + char buf[50] = "\n"; + char *defaultconsole = getenv("defaultconsole"); + + if (defaultconsole == 0) { + /* This is the default console that should be used for e.g. recovery boot */ + sprintf(buf, "ttyS1"); + setenv("defaultconsole", buf); + } + + + /* If consoldev is set take this as productive conosle instead of default console */ + if (fs_set_blk_dev("mmc", OVERLAY_PART, FS_TYPE_EXT) != 0) { + puts("Error, can not set blk device\n"); + return; + } + + fs_read("/root/boot/consoledev", (ulong)buf, 0, 5, &len); + if ((len != 5) || (strstr(buf, "tty")!=buf) || ((buf[4]<'0') && (buf[4]>'1'))) { + puts("Using default console\n"); + return; + } + + setenv("defaultconsoel", buf); +} + diff --git a/board/nm/netbird_v2/fileaccess.h b/board/nm/netbird_v2/fileaccess.h new file mode 100644 index 0000000000..00bbaaea04 --- /dev/null +++ b/board/nm/netbird_v2/fileaccess.h @@ -0,0 +1,14 @@ +/**@file /home/eichenberger/projects/nbhw16/u-boot/board/nm/netbird_v2/fileaccess.h + * @author eichenberger + * @version 704 + * @date + * Created: Tue 06 Jun 2017 02:02:33 PM CEST \n + * Last Update: Tue 06 Jun 2017 02:02:33 PM CEST + */ +#ifndef FILEACCESS_H +#define FILEACCESS_H + +void fs_set_console(void); +int read_file(const char* filename, char *buf, int size); + +#endif // FILEACCESS_H diff --git a/board/nm/netbird_v2/mux.c b/board/nm/netbird_v2/mux.c index 1b4955b873..b0f6583a85 100644 --- a/board/nm/netbird_v2/mux.c +++ b/board/nm/netbird_v2/mux.c @@ -55,13 +55,15 @@ static struct module_pin_mux i2c0_pin_mux[] = { /* V2OK */ static struct module_pin_mux uart0_netbird_pin_mux[] = { - {OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (E15) UART0_RXD */ - {OFFSET(uart0_txd), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* (E16) UART0_TXD */ - {OFFSET(uart0_ctsn), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (E18) UART0_CTSN */ - {OFFSET(uart0_rtsn), (MODE(0) | PULLUDEN | PULLUP_EN)}, /* (E17) UART0_RTSN */ + /* 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(7) | PULLUDDIS | RXACTIVE )}, /* (E18) UART0_CTSN */ + {OFFSET(uart0_rtsn), (MODE(7) | PULLUDEN | PULLUP_EN )}, /* (E17) UART0_RTSN */ {-1}, }; + /* V2OK */ static struct module_pin_mux uart1_netbird_pin_mux[] = { {OFFSET(uart1_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (D16) uart1_rxd.uart1_rxd */ diff --git a/board/nm/netbird_v2/shield.c b/board/nm/netbird_v2/shield.c new file mode 100644 index 0000000000..7c03f0d11a --- /dev/null +++ b/board/nm/netbird_v2/shield.c @@ -0,0 +1,73 @@ +#define 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("Shield %s is unknown\n", shield_type); + return -1; +} + +static int do_shieldmode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc < 3) { + puts("Invalid command (see help)\n"); + 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/netbird_v2/shield.h b/board/nm/netbird_v2/shield.h new file mode 100644 index 0000000000..2ab27a0941 --- /dev/null +++ b/board/nm/netbird_v2/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/netbird_v2/shield_can.c b/board/nm/netbird_v2/shield_can.c new file mode 100644 index 0000000000..6335c7ac89 --- /dev/null +++ b/board/nm/netbird_v2/shield_can.c @@ -0,0 +1,191 @@ +#define DEBUG + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +#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)}, /* CAN1 tx */ + {OFFSET(uart0_rxd), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* CAN0 tx */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* Latch EN */ + {-1}, +}; + +static struct module_pin_mux can_shield_netbird_pin_mux_final[] = { + /* Leave UART0 unconfigured because we want to configure it as needed by linux (can/spi/uart/etc) */ + {OFFSET(uart0_ctsn), (MODE(2) | PULLUDEN | PULLUP_EN)}, /* CAN1 tx */ + {OFFSET(uart0_rtsn), (MODE(2) | PULLUDDIS | RXACTIVE)}, /* CAN1 rx */ + {OFFSET(uart0_txd), (MODE(2) | PULLUDDIS | RXACTIVE)}, /* CAN0 rx */ + {OFFSET(uart0_rxd), (MODE(2) | PULLUDEN | PULLUP_EN)}, /* CAN0 tx */ + {-1}, +}; + +static int request_gpios(void) +{ + int ret; + + debug("Shiled 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) { + printf("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; + } + + printf ("Invalid termination mode %s (falling back to off)", termination); + return 0; +} + +static int get_mode_from_args(char * const argv[], int argc) +{ +#define CAN_PORTS 2 + int terminations[CAN_PORTS]; + int i; + + assert(argc == (CAN_PORTS + 1)); + + if (strcmp ("termination", argv[0])) { + puts("The only option for dualcan is terminations\n"); + return -1; + } + + for (i = 0; i < CAN_PORTS; i ++) { + terminations[i] = get_termination(argv[i + 1]); + } + + /* Termination is inverse */ + return (!terminations[0] << 0) | (!terminations[1] << 1); +} + +static int set_shieldmode(char * const argv[], int argc) +{ + if (argc != 3) { + puts("Too few arguments for dualcan\n"); + return -1; + } + + configure_shieldmode(get_mode_from_args(argv, argc)); + return 0; +} + +struct shield_t can_shield = { + "dualcan", set_shieldmode +}; + +void can_shield_init(void) +{ + shield_register(&can_shield); +} + diff --git a/board/nm/netbird_v2/shield_can.h b/board/nm/netbird_v2/shield_can.h new file mode 100644 index 0000000000..21684cd4f7 --- /dev/null +++ b/board/nm/netbird_v2/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/netbird_v2/shield_comio.c b/board/nm/netbird_v2/shield_comio.c new file mode 100644 index 0000000000..3a75b6efb7 --- /dev/null +++ b/board/nm/netbird_v2/shield_comio.c @@ -0,0 +1,214 @@ +/* #define DEBUG */ + +#include +#include +#include + +#include "shield.h" +#include "board.h" + +#define NETBIRD_GPIO_RST_SHIELD_N GPIO_TO_PIN(0, 27) +#define NETBIRD_GPIO_LOAD GPIO_TO_PIN(1, 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; + + +/* V2OK */ +static struct module_pin_mux shield_gpio_safe_netbird_pin_mux[] = { + /* 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 */ + {-1}, +}; + +static struct module_pin_mux shield_gpio_netbird_pin_mux[] = { + /* Leave UART0 unconfigured because we want to configure it as needed by linux (can/spi/uart/etc) */ + {OFFSET(uart0_rxd), (MODE(7) | PULLUDDIS)}, /* (E15) UART0_RXD */ + {OFFSET(uart0_txd), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (E16) UART0_TXD */ + {-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) { + printf("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; + +} + +static int get_rs232(const char *mode) +{ + if (strcmp("rs232", mode) == 0) { + return 1; + } + else { + return 0; + } +} + +static int get_termination(const char* termination) +{ + if (strcmp("on", termination) == 0) { + return 1; + } + else if (strcmp("off", termination) == 0) { + return 0; + } + + printf ("Invalid termination mode %s (falling back to off)", termination); + return 0; +} + +static int get_mode_from_args(char * const argv[], int argc) +{ + int termination = 0; + int rs232 = 0; + + assert(argc >= 2); + + if (strcmp ("mode", argv[0])) { + puts("Invalid arguments (see help)\n"); + return -1; + } + + rs232 = get_rs232(argv[1]); + + if (argc > 2) { + if (rs232 || strcmp("termination", argv[2])) { + puts("Invalid arguments, do not configure termination\n"); + } + else { + termination = get_termination(argv[3]); + } + } + + /* Termination is inverse */ + return (rs232 << 0) | ((!termination) << 1); +} + +int set_shieldmode(char * const argv[], int argc) +{ + if (argc < 2) { + puts("Too few arguments for comio\n"); + return -1; + } + + configure_shieldmode(get_mode_from_args(argv, argc)); + + return 0; +} + +struct shield_t comio_shield = { + "comio", set_shieldmode +}; + +void comio_shield_init(void) +{ + shield_register(&comio_shield); +} + diff --git a/board/nm/netbird_v2/shield_comio.h b/board/nm/netbird_v2/shield_comio.h new file mode 100644 index 0000000000..2b2602e917 --- /dev/null +++ b/board/nm/netbird_v2/shield_comio.h @@ -0,0 +1,6 @@ +#ifndef SHIELD_COMIO_H +#define SHIELD_COMIO_H + +void comio_shield_init(void); + +#endif // SHIELD_COMIO_H diff --git a/include/configs/am335x_netbird_v2.h b/include/configs/am335x_netbird_v2.h index f6e439b86f..5806092425 100644 --- a/include/configs/am335x_netbird_v2.h +++ b/include/configs/am335x_netbird_v2.h @@ -58,7 +58,8 @@ "kernel_addr=" KERNEL_ADDR "\0" \ "load_addr=" LOAD_ADDR "\0" \ "root_part=1\0" /* Default root partition, overwritte in board file */ \ - "add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 console=ttyS1,115200 rootwait loglevel=4\0" \ + "defaultconsole=ttyS1\0" /* Default output console */ \ + "add_sd_bootargs=setenv bootargs $bootargs root=/dev/mmcblk0p$root_part rootfstype=ext4 console=$defaultconsole,115200 rootwait loglevel=4\0" \ "add_version_bootargs=setenv bootargs $bootargs\0" \ "fdt_skip_update=yes\0" \ "ethprime=cpsw\0" \ @@ -69,7 +70,7 @@ "sdboot=if mmc dev 1; then echo Copying Linux from SD to RAM...; "\ "if test -e mmc 1:$root_part /boot/$kernel_image; then run sdprod; " \ "else run sdbringup; fi; " \ - "run add_sd_bootargs; run add_version_bootargs; " \ + "run add_sd_bootargs; run add_version_bootargs; run shieldcmd; run modifyfdtcmd; " \ "bootz $kernel_addr - $fdt_addr; fi\0" \ "bootcmd=run sdboot\0" \ "ipaddr=192.168.1.1\0" \ @@ -83,7 +84,10 @@ "tftptimeoutcountmax=5\0" \ "bootpretryperiod=2000\0" \ "autoload=false\0" \ - "tftp_recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; setenv bootargs rdinit=/etc/preinit console=ttyO1,115200 debug; bootz $kernel_addr - $fdt_addr\0" \ + "shieldcmd=\0" \ + "fdtshieldcmd=\0" \ + "modifyfdtcmd=fdt addr $fdt_addr; run fdtshieldcmd;\0" \ + "tftp_recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; setenv bootargs rdinit=/etc/preinit console=$defaultconsole,115200 debug; run shieldcmd; run modifyfdtcmd; bootz $kernel_addr - $fdt_addr\0" \ "pxe_recovery=sleep 3 && dhcp && pxe get && pxe boot\0" \ "recovery=run pxe_recovery || setenv ipaddr $ipaddr; setenv serverip $serverip; run tftp_recovery\0" /* setenv ipaddr and serverip is necessary, because dhclient can destroy the IPs inernally */