diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d9b48856ce..da8d38ec3e 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -391,20 +391,28 @@ config TARGET_AM335X_NETBIRD_V2 select DM_GPIO config TARGET_AM335X_NRHW20 - bool "Support am335x_nrhw20" - select CPU_V7 - select SUPPORT_SPL - select DM - select DM_SERIAL - select DM_GPIO + bool "Support am335x_nrhw20" + select CPU_V7 + select SUPPORT_SPL + select DM + select DM_SERIAL + select DM_GPIO config TARGET_AM335X_NRHW22 - bool "Support am335x_nrhw22" - select CPU_V7 - select SUPPORT_SPL - select DM - select DM_SERIAL - select DM_GPIO + bool "Support am335x_nrhw22" + select CPU_V7 + select SUPPORT_SPL + select DM + select DM_SERIAL + select DM_GPIO + +config TARGET_AM335X_NRHW24 + bool "Support am335x_nrhw24" + select CPU_V7 + select SUPPORT_SPL + select DM + select DM_SERIAL + select DM_GPIO config TARGET_AM335X_SL50 bool "Support am335x_sl50" @@ -906,6 +914,7 @@ source "board/nm/netbird/Kconfig" source "board/nm/netbird_v2/Kconfig" source "board/nm/nrhw20/Kconfig" source "board/nm/nrhw22/Kconfig" +source "board/nm/nrhw24/Kconfig" source "board/olimex/mx23_olinuxino/Kconfig" source "board/phytec/pcm051/Kconfig" source "board/phytec/pcm052/Kconfig" diff --git a/board/nm/common/da9063.h b/board/nm/common/da9063.h index decd99e07a..5a3851b0eb 100644 --- a/board/nm/common/da9063.h +++ b/board/nm/common/da9063.h @@ -17,14 +17,32 @@ #define PMIC_REG_STATUS_A 0x01 /* Status of ON_KEY, WAKE, COMP1V2, DVC */ #define PMIC_REG_FAULT_LOG 0x05 +#define PMIC_REG_CONTROL_D 0x11 /* Control register for blink/watchdog */ +#define PMIC_REG_GPIO14_15 0x1C /* Configuration of GPIO14/15 (mode, wake) */ #define PMIC_REG_GPIO_MODE0_7 0x1D /* Control register for GPIOs 0..7 */ #define PMIC_REG_GPIO_MODE8_15 0x1E /* Control register for GPIOs 8..15 */ -#define PMIC_REG_BBAT_CONT 0xC5 /* Control register for backup battery */ +#define PMIC_REG_BCORE1_CONT 0x21 /* Control register of BCORE1 */ +#define PMIC_REG_BCORE2_CONT 0x20 /* Control register of BCORE2 */ +#define PMIC_REG_BPERI_CONT 0x25 /* Control register of BPERI */ +#define PMIC_REG_BIO_CONT 0x24 /* Control register of BIO */ +#define PMIC_REG_BMEM_CONT 0x23 /* Control register of BMEM */ + +#define PMIC_REG_LDO3_CONT 0x28 /* Control register of LDO3 */ +#define PMIC_REG_LDO6_CONT 0x2B /* Control register of LDO6 */ +#define PMIC_REG_LDO7_CONT 0x2C /* Control register of LDO7 */ +#define PMIC_REG_LDO11_CONT 0x30 /* Control register of LDO11 */ + +#define PMIC_LDOx_EN_MASK 0x01 +#define PMIC_LDOx_CONF_MASK 0x80 + +#define PMIC_REG_ID_4_3 0x84 #define PMIC_REG_BUCK_ILIM_A 0x9A #define PMIC_REG_BUCK_ILIM_B 0x9B #define PMIC_REG_BUCK_ILIM_C 0x9C +#define PMIC_REG_BBAT_CONT 0xC5 /* Control register for backup battery */ + #define PMIC_REG_BCORE2_CONF 0x9D #define PMIC_REG_BCORE1_CONF 0x9E @@ -32,6 +50,15 @@ #define PMIC_REG_BMEM_CONF 0xA1 #define PMIC_REG_BPERI_CONF 0xA2 +#define PMIC_REG_CONFIG_E 0x10A +#define PMIC_REG_CONFIG_G 0x10C +#define PMIC_REG_CONFIG_L 0x111 + +#define PMIC_REG_TRIM_CLDR 0x120 /* Calendar Trim register, 2's complement, 1.9ppm per bit */ + +#define PMIC_REG_CONFIG_ID 0x184 /* OTP Config ID */ + + extern void da9063_init(int i2c_bus); extern int da9063_get_reg(int reg, u8* val); extern int da9063_set_reg(int reg, u8 val); diff --git a/board/nm/nrhw24/Kconfig b/board/nm/nrhw24/Kconfig new file mode 100644 index 0000000000..93a3d35d86 --- /dev/null +++ b/board/nm/nrhw24/Kconfig @@ -0,0 +1,26 @@ +if TARGET_AM335X_NRHW24 + +config SYS_BOARD + default "nrhw24" + +config SYS_VENDOR + default "nm" + +config SYS_SOC + default "am33xx" + +config SYS_CONFIG_NAME + default "am335x_nrhw24" + +config CONS_INDEX + int "UART used for console" + range 1 6 + default 2 + help + The AM335x SoC has a total of 6 UARTs (UART0 to UART5 as referenced + in documentation, etc) available to it. Depending on your specific + board you may want something other than UART0 as for example the IDK + uses UART3 so enter 4 here. + +endif + diff --git a/board/nm/nrhw24/Makefile b/board/nm/nrhw24/Makefile new file mode 100644 index 0000000000..c9e59635af --- /dev/null +++ b/board/nm/nrhw24/Makefile @@ -0,0 +1,13 @@ +# +# Makefile +# +# Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +# +# SPDX-License-Identifier: GPL-2.0+ +# + +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 ../common/da9063.o diff --git a/board/nm/nrhw24/board.c b/board/nm/nrhw24/board.c new file mode 100644 index 0000000000..c6c4e9f7e8 --- /dev/null +++ b/board/nm/nrhw24/board.c @@ -0,0 +1,1032 @@ +/* + * board.c + * + * Board functions for Netmodule NRHW 24, based on AM335x EVB + * + * Copyright (C) 2018 NetModule AG - http://www.netmodule.com/ + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../common/bdparser.h" +#include "../common/board_descriptor.h" +#include "../common/da9063.h" +#include "board.h" +#include "shield.h" +#include "shield_can.h" +#include "shield_comio.h" +#include "fileaccess.h" + +DECLARE_GLOBAL_DATA_PTR; + + +/* + * CPU GPIOs + * + * GPIO0_2: RST_GNSS~ + * GPIO0_5: EXTINT_GNSS + * GPIO0_6: TIMEPULSE_GNSS + * + * GPIO0_16: RST_PHY~ + * GPIO0_27: RST_SHIELD~ + * + * GPIO1_20: BT_EN + * GPIO1_21: GSM_PWR_EN + * GPIO1_25: RST_GSM + * GPIO1_26: WLAN_EN + * GPIO1_27: WLAN_IRQ + * + * GPIO3_17: SIM_SEL + */ + +#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) + +#define NETBIRD_GPIO_RST_ETH_N GPIO_TO_PIN(0, 16) + +#define NETBIRD_GPIO_RST_GNSS GPIO_TO_PIN(0, 2) + +#define NETBIRD_GPIO_RST_GSM GPIO_TO_PIN(1, 25) +#define NETBIRD_GPIO_PWR_GSM GPIO_TO_PIN(1, 21) +#define NETBIRD_GPIO_SIM_SEL GPIO_TO_PIN(3, 17) + +#define NETBIRD_GPIO_WLAN_EN GPIO_TO_PIN(1, 26) +#define NETBIRD_GPIO_BT_EN GPIO_TO_PIN(1, 20) + + + +/* + * PMIC GPIOs + * + * GPIO_7: EN_SUPPLY_GSM + * GPIO_8: EN_SUPPLY_WIFI + * GPIO_10: LED.LWR + * GPIO_11: LED.UPR + */ + +#define PMIC_GSM_SUPPLY_EN_IO 7 +#define PMIC_WIFI_SUPPLY_EN_IO 8 +#define PMIC_LED0 10 +#define PMIC_LED1 11 + +#define RESET_REASON_SHM_LOCATION (0x8e000000) + +#define DDR3_CLOCK_FREQUENCY (400) + +#if !defined(CONFIG_SPL_BUILD) +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; +#endif + +#define I2C_BD_EEPROM_BUS (2) +#define BD_EEPROM_ADDR (0x50) /* CPU BD EEPROM (8kByte) is at 50 (A0) */ +#define BD_ADDRESS (0x0000) /* Board descriptor at beginning of EEPROM */ +#define PD_ADDRESS (0x0200) /* Product descriptor */ +#define PARTITION_ADDRESS (0x0600) /* Partition Table */ + +#define SHIELD_COM_IO 0 +#define SHIELD_DUALCAN 1 + + +static BD_Context bdctx[3]; /* The descriptor contexts */ + + +static void init_leds(void) +{ +} + +// TODO: Only green color available +static void set_status_led(int on) +{ + da9063_set_gpio(PMIC_LED1, on); +} + +static void set_indicator_led(int on) +{ + da9063_set_gpio(PMIC_LED0, on); +} + + +static void init_i2c(void) +{ + i2c_set_bus_num(0); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + i2c_set_bus_num(2); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + i2c_set_bus_num(0); +} + +static int _bd_init(void) +{ + int old_bus; + + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(I2C_BD_EEPROM_BUS); + + if (bd_get_context(&bdctx[0], BD_EEPROM_ADDR, BD_ADDRESS) != 0) { + printf("%s() no valid bd found\n", __func__); + return -1; + } + + if (bd_get_context(&bdctx[1], BD_EEPROM_ADDR, PD_ADDRESS) != 0) { + printf("%s() no valid pd found (legacy support)\n", __func__); + return -1; + } + + if (bd_get_context(&bdctx[2], BD_EEPROM_ADDR, PARTITION_ADDRESS) != 0) { + printf("%s() no valid partition table found\n", __func__); + return -1; + } + + bd_register_context_list(bdctx, ARRAY_SIZE(bdctx)); + + i2c_set_bus_num(old_bus); + + return 0; +} + +static bool is_jtag_boot(uint32_t address) +{ + char* jtag_token = (char*)address; + if (strcmp(jtag_token, "JTAGBOOT") == 0) { + strcpy(jtag_token, "jtagboot"); + return true; + } + else { + return false; + } +} + +/* + * Read header information from EEPROM into global structure. + */ +static inline int __maybe_unused read_eeprom(void) +{ + return _bd_init(); +} + +/* Selects console for SPL. + * U-Boot console is defined by CONSOLE_INDEX variable + * defined using serial_set_console_index(int index) + */ +struct serial_device *default_serial_console(void) +{ + /* Mux Pins for selected UART properly. + Note: uart indexes start at 0 while + eserial indexes start at 1. */ + if ((spl_boot_device() == BOOT_DEVICE_UART) || + (spl_boot_device() == BOOT_DEVICE_JTAG)) { + enable_uart0_pin_mux(); + return &eserial1_device; + } else { + /* Use bluetooth uart, if no output shall be seen. */ + enable_uart5_pin_mux(); + return &eserial6_device; + } +} + +#ifndef CONFIG_SKIP_LOWLEVEL_INIT + +static const struct ddr_data ddr3_netbird_data = { + /* Ratios were optimized by DDR3 training software from TI */ + .datardsratio0 = 0x39, + .datawdsratio0 = 0x3f, + .datafwsratio0 = 0x98, + .datawrsratio0 = 0x7d, +}; + +static const struct cmd_control ddr3_netbird_cmd_ctrl_data = { + .cmd0csratio = MT41K256M16HA125E_RATIO, + .cmd0iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd1csratio = MT41K256M16HA125E_RATIO, + .cmd1iclkout = MT41K256M16HA125E_INVERT_CLKOUT, + + .cmd2csratio = MT41K256M16HA125E_RATIO, + .cmd2iclkout = MT41K256M16HA125E_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { + .sdram_config = MT41K256M16HA125E_EMIF_SDCFG, + .ref_ctrl = 0x61A, /* 32ms > 85°C */ + .sdram_tim1 = 0x0AAAE51B, + .sdram_tim2 = 0x246B7FDA, + .sdram_tim3 = 0x50FFE67F, + .zq_config = MT41K256M16HA125E_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = MT41K256M16HA125E_EMIF_READ_LATENCY, +}; + + +#define OSC (V_OSCK/1000000) + +struct dpll_params dpll_ddr_nrhw24 = { + DDR3_CLOCK_FREQUENCY, OSC-1, 1, -1, -1, -1, -1 +}; + +static void pmic_fix_config(void) +{ + /* TODO: Update later, currently no fixes are required */ +} + +static void pmic_ignition_gate_on(void) +{ + uint8_t val; + + /* Configure GPIO15 to permanent high, so that ignition sense signal is readable */ + + (void)da9063_set_reg(PMIC_REG_GPIO14_15, 0xCC); /* GPIO14/15 = Outputs open drain */ + + (void)da9063_get_reg(PMIC_REG_CONFIG_L, &val); /* Enable pull ups on GPIO14/15 */ + val |= 0xC0; + (void)da9063_set_reg(PMIC_REG_CONFIG_L, val); + + (void)da9063_get_reg(PMIC_REG_CONTROL_D, &val); /* No blinking, state selected by GPIOxx_MODE */ + val &= ~0xF8; + (void)da9063_set_reg(PMIC_REG_CONTROL_D, val); + + (void)da9063_get_reg(PMIC_REG_GPIO_MODE8_15, &val); /* Set to GPIO14,15 to high */ + val |= 0xC0; + (void)da9063_set_reg(PMIC_REG_GPIO_MODE8_15, val); +} + +static void init_pmic_spl(void) +{ + /* PMIC basic configuration */ + da9063_init(CONFIG_PMIC_I2C_BUS); + + /* Fix old configs (mainly prototype boards) */ + pmic_fix_config(); + + /* Enable +3V3_GNSS (LDO6) */ + (void)da9063_set_reg(PMIC_REG_LDO6_CONT, PMIC_LDOx_EN_MASK); + mdelay(2); + + pmic_ignition_gate_on(); + + /* Trim RTC to compensate +18ppm crystal deviation */ + // TODO: Check, caps have been changed + /* + (void)da9063_set_reg(PMIC_REG_TRIM_CLDR, (-18*10)/19); + */ + + /* Enable charging of RTC backup capacitor (1mA, 3.1V) */ + (void)da9063_set_reg(PMIC_REG_BBAT_CONT, 0xAF); +} + +void am33xx_spl_board_init(void) +{ + /* Set CPU speed to 600 MHz (fix) */ + dpll_mpu_opp100.m = MPUPLL_M_600; + + /* Set CORE Frequencies to OPP100 (600MHz) */ + do_setup_dpll(&dpll_core_regs, &dpll_core_opp100); + + /* Configure both I2C buses used in NRHW24 */ + init_i2c(); + + /* Setup PMIC */ + init_pmic_spl(); + + da9063_reset_reason_update(RESET_REASON_SHM_LOCATION); + + /* Set MPU Frequency to what we detected now that voltages are set */ + do_setup_dpll(&dpll_mpu_regs, &dpll_mpu_opp100); + + /* Debugger can place marker at end of SRAM to stop boot here */ + if (is_jtag_boot(CONFIG_JTAG_MARKER_SPL)) + { + puts("Detected JTAG boot, executing bkpt #0\n"); + + __asm__ __volatile__ ("bkpt #0"); + } +} + +const struct dpll_params *get_dpll_ddr_params(void) +{ + dpll_ddr_nrhw24.n = (get_osclk() / 1000000) - 1; + return &dpll_ddr_nrhw24; +} + +void set_uart_mux_conf(void) +{ + enable_uart0_pin_mux(); + enable_uart1_pin_mux(); +} + +void set_mux_conf_regs(void) +{ + enable_board_pin_mux(); +} + + +const struct ctrl_ioregs ioregs_netbird = { + .cm0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .cm2ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt0ioctl = MT41K256M16HA125E_IOCTRL_VALUE, + .dt1ioctl = MT41K256M16HA125E_IOCTRL_VALUE, +}; + + +void sdram_init(void) +{ + config_ddr(DDR3_CLOCK_FREQUENCY, &ioregs_netbird, + &ddr3_netbird_data, + &ddr3_netbird_cmd_ctrl_data, + &ddr3_emif_reg_data, 0); +} + +#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ + +#if !defined(CONFIG_SPL_BUILD) + +static void request_and_set_gpio(int gpio, const char *name, int value) +{ + int ret; + + ret = gpio_request(gpio, name); + if (ret < 0) { + printf("%s: Unable to request %s\n", __func__, name); + return; + } + + /* TODO: Set value here, remove later call gpio_set_value */ + ret = gpio_direction_output(gpio, 0); + if (ret < 0) { + printf("%s: Unable to set %s as output\n", __func__, name); + goto err_free_gpio; + } + + gpio_set_value(gpio, value); + + return; + +err_free_gpio: + gpio_free(gpio); +} + +#define REQUEST_AND_SET_GPIO(N) request_and_set_gpio(N, #N, 1); +#define REQUEST_AND_CLEAR_GPIO(N) request_and_set_gpio(N, #N, 0); + +#endif /* !defined(CONFIG_SPL_BUILD) */ + +#if !defined(CONFIG_SPL_BUILD) + +static void init_ethernet(void) +{ + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_RST_ETH_N); + /* Minimum Reset Pulse = 100us (SMSC8720) */ + mdelay(1); + gpio_set_value(NETBIRD_GPIO_RST_ETH_N, 1); + + // TODO: Check + /* Give clocks time to stabilize */ + mdelay(1); +} + +static void init_sim_mux(void) +{ + /* + * Switch pluggable micro sim to onboard modem (Mux = 1) + */ + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_SIM_SEL); +} + +static void init_gsm(void) +{ + /* + * Perform power up sequence for TOBY-L2 modem. + * + * TOBY-L2 series can be switched on in one of the following ways: + * - Rising edge on the VCC pin to a valid voltage for module supply, + * i.e. applying module supply + * - Low level on the PWR_ON pin, which is normally set high by an + * internal pull-up, for a valid time period when the applied VCC + * voltage is within the valid operating range (see section 4.2.8). + * - Low level on the RESET_N pin, which is normally set high by an + * internal pull-up, for a valid time period when the applied VCC + * voltage is within the valid operating range (see section 4.2.9). + * + * PWR_ON low time: 5 ms - Low time to switch-on the module + * RESET_N low time: 18..800 ms - Low time to switch-on the module + * 2.1..15 s - Low time to reset the module + * 16 s - Low time to switch-off the module + * + * References: + * - uBlox TOBY-L2 Datasheet UBX-13004573 - R24 + * 2.3.1 Module power-on + * 4.2.8 PWR_ON pin + * 4.2.9 RESET_N pin + * + * Functionality: + * - Leave GSM power enable as is (default at power up = off) + * - Set reset line inactive (note: inverter logic in HW present) + * - Leave button unpressed (note: inverter logic in HW present) + * - Modem shall be enabled by Linux system by enabling GSM power + * supply + */ + + puts("GSM: "); + + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_RST_GSM); /* Set reset inactive (active high) */ + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_PWR_GSM); /* Set power switch inactive/released (active high) */ + + puts("init\n"); +} + +static void init_gnss(void) +{ + /* + * Release GNSS reset line, so that module starts up early + */ + REQUEST_AND_SET_GPIO(NETBIRD_GPIO_RST_GNSS); +} + +static void init_wifi(void) +{ + /* Enable WiFi power supply */ + da9063_set_gpio(PMIC_WIFI_SUPPLY_EN_IO, 1); +} + +#endif /* !defined(CONFIG_SPL_BUILD) */ + + +/* + * Basic board specific setup. Pinmux has been handled already. + * Not called in SPL build. + */ +int board_init(void) +{ +#if defined(CONFIG_HW_WATCHDOG) + hw_watchdog_init(); +#endif + + gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; + + /* Configure both I2C buses used in NRHW24 */ + init_i2c(); + + da9063_init(CONFIG_PMIC_I2C_BUS); + + /* Let user know we're starting */ + init_leds(); + set_status_led(1); + set_indicator_led(0); + + printf("OSC: %lu MHz\n", get_osclk()/1000000); + + return 0; +} + +#if !defined(CONFIG_SPL_BUILD) + +extern int console_init_f(void); +extern void serial_set_console_index(int index); + +/* + * Set Linux console based on + * - Selection in /root/boot/consoledev + * - Available tty interfaces + * - ttyS1: standard console (default) + * - ttyS0: COM/IO shield (or used as console by kernel, + * when no other console available) + * - ttyNull0: Dummy device if no real UART is available + */ +void set_console(void) +{ + const char *defaultconsole = getenv("defaultconsole"); + char buf[20]; + int i; + + /* Set default console to ttyS1 if not yet defined in env */ + if (defaultconsole == 0) { + setenv("defaultconsole", "ttyS1"); + } + + /* If consoledev file is present, take the tty defined in it as console */ + if (read_file("/root/boot/consoledev",buf, sizeof(buf)) > 3) { + if (strstr(buf, "tty") == buf) { + buf[sizeof(buf)-1] = 0; + for (i=0; i 1) { + boot_partition = 0; + } + + /* mmcblk1p1 => root0, mmcblk1p2 => root1 so +1 */ + setenv_ulong("root_part", boot_partition + 1); +} + +static void get_hw_version(void) +{ + int hw_ver, hw_rev; + char hw_versions[16]; + char new_env[256]; /* current bootargs = 84 bytes */ + + bd_get_hw_version(&hw_ver, &hw_rev); + printf("HW24: V%d.%d\n", hw_ver, hw_rev); + + /* add hardware versions to environment */ + snprintf(hw_versions, sizeof(hw_versions), "CP=%d.%d", hw_ver, hw_rev); + snprintf(new_env, sizeof(new_env), "setenv bootargs $bootargs %s", hw_versions); + setenv("add_version_bootargs", new_env); +} + +static void get_pmic_version(void) +{ + uint8_t val = 0x00; + uint8_t ver, rev; + int rc; + + rc = da9063_get_reg(PMIC_REG_CONFIG_ID, &val); + if (!rc) { + ver = (val >> 4) & 0xF; + rev = (val >> 0) & 0xF; + } else { + ver = 0; + rev = 0; + } + + printf("PMIC: V%d.%d\n", ver, rev); +} + +static void check_fct(void) +{ + /* Check whether an I2C device (EEPROM) is present at address 0xA2/0x51 + * In this case we are connected to the factory test station. + * Clear the bootcmd, so that test system can easily connect. + */ + + int old_bus; + + old_bus = i2c_get_bus_num(); + i2c_set_bus_num(I2C_BD_EEPROM_BUS); + + /* If probe fails we are sure no eeprom is connected */ + if (i2c_probe(0x51) == 0) { + printf("Entering fct mode\n"); + setenv ("bootcmd", ""); + } + + i2c_set_bus_num(old_bus); +} + + +struct shield_command { + int shield_id; + const char *name; + const char *default_shieldcmd; + void (*init)(void); +}; + +static struct shield_command known_shield_commands[] = { + { + SHIELD_COM_IO, + "comio", + "shield comio mode rs232", + comio_shield_init + }, + { + SHIELD_DUALCAN, + "dualcan", + "shield dualcan termination off off", + can_shield_init + }, +}; + +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) { + debug("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; + } + + printf("Shield:%s\n", cmd->name); + + cmd->init(); + shieldcmd = cmd->default_shieldcmd; + + /* If a shield configuration is 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) { + debug("Shield command found in file, using it\n"); + shieldcmd = shieldcmd_linux; + } + + setenv("shieldcmd", shieldcmd); +} + +static void shield_init(void) +{ + shield_config(); +} + +static bool get_button_state(void) +{ + u8 state = 0x00; + + (void)da9063_get_reg(PMIC_REG_STATUS_A, &state); + + return (state & 0x01) == 0x01; +} + +static void blink_led(void) +{ + const int pulse_width = 400*1000; /* 400ms */ + + udelay(pulse_width); + set_indicator_led(1); + udelay(pulse_width); + set_indicator_led(0); +} + +static void check_reset_button(void) +{ + int counter = 0; + + /* Check how long button is pressed */ + do { + if (!get_button_state()) + break; + + udelay(100*1000); /* 100ms */ + counter += 100; + + if (counter == 2000) { + /* Indicate factory reset threshold */ + blink_led(); + } + else if (counter == 12000) { + /* Indicate recovery boot threshold */ + blink_led(); + blink_led(); + } + } while (counter < 12000); + + if (counter < 2000) { + /* Don't do anything for duration < 2s */ + } + else if (counter < 12000) + { + /* Do factory reset for duration between 2s and 12s */ + char new_bootargs[512]; + char *bootargs = getenv("bootargs"); + + if (bootargs == 0) bootargs=""; + + printf("Do factory reset during boot...\n"); + + strncpy(new_bootargs, bootargs, sizeof(new_bootargs)); + strncat(new_bootargs, " factory-reset", sizeof(new_bootargs)); + + setenv("bootargs", new_bootargs); + } + else + { + /* Boot into recovery for duration > 12s */ + + printf("Booting recovery image...\n"); + + /* Set consoledev to external port */ + setenv("defaultconsole", "ttyS1"); + + /* Set bootcmd to run recovery */ + setenv("bootcmd", "run recovery"); + } +} + +static void check_jtag_boot(void) +{ + if (is_jtag_boot(CONFIG_JTAG_MARKER_UBOOT)) { + char *bootcmd = getenv("bootcmd"); + setenv ("bootcmd", ""); + /* Save original bootcmd in "bc" to allow manual boot */ + setenv ("bc", bootcmd); + puts("Detected JTAG boot. Waiting on command line\n"); + } +} + +#endif /* !defined(CONFIG_SPL_BUILD) */ + + +int board_late_init(void) +{ +#if !defined(CONFIG_SPL_BUILD) + if (read_eeprom() < 0) + puts("Could not get board ID.\n"); + + get_hw_version(); + get_pmic_version(); + set_root_partition(); + set_devicetree_name(); + + /* Initialize pins */ + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_WLAN_EN); + REQUEST_AND_CLEAR_GPIO(NETBIRD_GPIO_BT_EN); + + init_ethernet(); + init_sim_mux(); + init_gsm(); + init_gnss(); + init_wifi(); + + + check_reset_button(); + + set_console(); + shield_init(); + + check_fct(); + check_jtag_boot(); +#endif + + return 0; +} + + +#ifndef CONFIG_DM_ETH + +#if (defined(CONFIG_DRIVER_TI_CPSW) && !defined(CONFIG_SPL_BUILD)) || \ + (defined(CONFIG_SPL_ETH_SUPPORT) && defined(CONFIG_SPL_BUILD)) +static void cpsw_control(int enabled) +{ + /* VTP can be added here */ + + return; +} + +static struct cpsw_slave_data cpsw_slaves[] = { + { + .slave_reg_ofs = 0x208, + .sliver_reg_ofs = 0xd80, + .phy_if = PHY_INTERFACE_MODE_RMII, + .phy_addr = 0 + } +}; + +static struct cpsw_platform_data cpsw_data = { + .mdio_base = CPSW_MDIO_BASE, + .cpsw_base = CPSW_BASE, + .mdio_div = 0xff, + .channels = 8, + .cpdma_reg_ofs = 0x800, + .slaves = 1, + .slave_data = cpsw_slaves, + .ale_reg_ofs = 0xd00, + .ale_entries = 1024, + .host_port_reg_ofs = 0x108, + .hw_stats_reg_ofs = 0x900, + .bd_ram_ofs = 0x2000, + .mac_control = (1 << 5), + .control = cpsw_control, + .host_port_num = 0, + .version = CPSW_CTRL_VERSION_2, +}; +#endif + +#if ((defined(CONFIG_SPL_ETH_SUPPORT) || defined(CONFIG_SPL_USBETH_SUPPORT)) &&\ + defined(CONFIG_SPL_BUILD)) || \ + ((defined(CONFIG_DRIVER_TI_CPSW) || \ + defined(CONFIG_USB_ETHER) && defined(CONFIG_MUSB_GADGET)) && \ + !defined(CONFIG_SPL_BUILD)) + +static void set_mac_address(int index, uchar mac[6]) +{ + /* Then take mac from bd */ + if (is_valid_ethaddr(mac)) { + eth_setenv_enetaddr_by_index("eth", index, mac); + } + else { + printf("Trying to set invalid MAC address"); + } +} + +/* TODO: Update doc */ +/* + * This function will: + * Read the eFuse for MAC addresses, and set ethaddr/eth1addr/usbnet_devaddr + * in the environment + * Perform fixups to the PHY present on certain boards. We only need this + * function in: + * - SPL with either CPSW or USB ethernet support + * - Full U-Boot, with either CPSW or USB ethernet + * Build in only these cases to avoid warnings about unused variables + * when we build an SPL that has neither option but full U-Boot will. + */ +int board_eth_init(bd_t *bis) +{ + int rv, n = 0; + uint8_t mac_addr0[6] = {02,00,00,00,00,01}; + __maybe_unused struct ti_am_eeprom *header; + +#if !defined(CONFIG_SPL_BUILD) +#ifdef CONFIG_DRIVER_TI_CPSW + + cpsw_data.mdio_div = 0x3E; + + bd_get_mac(0, mac_addr0, sizeof(mac_addr0)); + set_mac_address(0, mac_addr0); + + writel(RMII_MODE_ENABLE | RMII_CHIPCKL_ENABLE, &cdev->miisel); + + rv = cpsw_register(&cpsw_data); + if (rv < 0) + printf("Error %d registering CPSW switch\n", rv); + else + n += rv; +#endif +#endif + +#if defined(CONFIG_USB_ETHER) && \ + (!defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_USBETH_SUPPORT)) + if (is_valid_ethaddr(mac_addr0)) + eth_setenv_enetaddr("usbnet_devaddr", mac_addr0); + + rv = usb_eth_initialize(bis); + if (rv < 0) + printf("Error %d registering USB_ETHER\n", rv); + else + n += rv; +#endif + return n; +} +#endif + +#endif /* CONFIG_DM_ETH */ + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + return 0; +} +#endif + +#if defined(CONFIG_OF_BOARD_SETUP) + +static void ft_enable_node(void* blob, const char* name) +{ + int node_ofs = -1; + + node_ofs = fdt_path_offset(blob, name); + if (node_ofs >= 0) { + fdt_setprop_string(blob, node_ofs, "status", "okay"); + } +} + +static void ft_dio(void *blob, int shield_type) +{ + 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) +{ + switch (shield_type) { + /* Enable uart1 (ttyS0) always as kernel needs it as fallback + console, if (ttyS1) is not available as console. */ + + default: + /* TODO: Should use alias serial0 */ + ft_enable_node(blob, "/ocp/serial@44e09000"); + break; + } +} + +static void ft_dcan(void *blob, int shield_type) +{ + switch (shield_type) { + /* If Dual CAN shield is present enable dcan0, dcan1N1 */ + case SHIELD_DUALCAN: + /* TODO: Should use alias d_can0, d_can1 */ + ft_enable_node(blob, "/ocp/can@481cc000"); + ft_enable_node(blob, "/ocp/can@481d0000"); + break; + + default: + break; + } +} + +int ft_board_setup(void *blob, bd_t *bd) +{ + int shield_type = -1; + + shield_type = bd_get_shield(0); + + ft_dio(blob, shield_type); + ft_serial(blob, shield_type); + ft_dcan(blob, shield_type); + + return 0; +} + +#endif diff --git a/board/nm/nrhw24/board.h b/board/nm/nrhw24/board.h new file mode 100644 index 0000000000..62e3fe10a3 --- /dev/null +++ b/board/nm/nrhw24/board.h @@ -0,0 +1,35 @@ +/* + * board.h + * + * TI AM335x boards information header + * + * Copyright (C) 2011, Texas Instruments, Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _BOARD_H_ +#define _BOARD_H_ +/* + * We have three pin mux functions that must exist. We must be able to enable + * uart0, for initial output and i2c2 to read the main EEPROM. We then have a + * main pinmux function that can be overridden to enable all other pinmux that + * is required on the board. + */ +void enable_uart0_pin_mux(void); +void disable_uart0_pin_mux(void); +void enable_uart1_pin_mux(void); +void enable_uart3_pin_mux(void); +void enable_uart5_pin_mux(void); +/* +void enable_uart2_pin_mux(void); +void enable_uart3_pin_mux(void); +void enable_uart4_pin_mux(void); +void enable_uart5_pin_mux(void); +*/ +void enable_i2c0_pin_mux(void); +void enable_i2c2_pin_mux(void); +void enable_board_pin_mux(void); + +#define GPIO_TO_PIN(bank, gpio) (32 * (bank) + (gpio)) +#endif diff --git a/board/nm/nrhw24/fileaccess.c b/board/nm/nrhw24/fileaccess.c new file mode 100644 index 0000000000..f296704637 --- /dev/null +++ b/board/nm/nrhw24/fileaccess.c @@ -0,0 +1,40 @@ +#include +#include + +#define BLOCK_DEVICE "mmc" +#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 (fs_set_blk_dev(BLOCK_DEVICE, OVERLAY_PART, FS_TYPE_EXT) != 0) { + puts("Error, can not set blk device\n"); + return -1; + } + + /* Read at most file size bytes */ + if (fs_size(filename, &filesize)) { + return -1; + } + + if (filesize < size) + size = filesize; + + /* For very unclear reasons the block device needs to be set again after the call to fs_size() */ + if (fs_set_blk_dev(BLOCK_DEVICE, 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; +} diff --git a/board/nm/nrhw24/fileaccess.h b/board/nm/nrhw24/fileaccess.h new file mode 100644 index 0000000000..00bbaaea04 --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/mux.c b/board/nm/nrhw24/mux.c new file mode 100644 index 0000000000..098bab14d1 --- /dev/null +++ b/board/nm/nrhw24/mux.c @@ -0,0 +1,241 @@ +/* + * mux.c + * + * Copyright (C) 2018 NetModule AG - http://www.netmodule.com/ + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include "board.h" + +static struct module_pin_mux gpio_pin_mux[] = { + /* + * GPIO0_2: RST_GNSS~ + * GPIO0_5: EXTINT_GNSS + * GPIO0_6: TIMEPULSE_GNSS + * GPIO0_16: RST_PHY~ + * GPIO0_17: PMIC FAULT + * GPIO0_27: RST_SHIELD~ + * + * GPIO1_20: BT_EN + * GPIO1_21: GSM_PWR_EN + * GPIO1_25: RST_GSM + * GPIO1_26: WLAN_EN + * GPIO1_27: WLAN_IRQ + * + * GPIO3_17: SIM_SEL + */ + + /* Bank 0 */ + {OFFSET(spi0_sclk), (MODE(7) | PULLUDDIS)}, /* (A17) gpio0[2] */ /* RST_GNSS */ + {OFFSET(spi0_cs0), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* (A16) gpio0[5] */ /* EXTINT_GNSS */ + {OFFSET(spi0_cs1), (MODE(7) | PULLUDEN | PULLUP_EN | RXACTIVE)},/* (C15) gpio0[6] */ /* TIMEPULSE_GNSS */ + {OFFSET(ecap0_in_pwm0_out), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (C18) gpio0[7] */ /* IO_SHIELD */ + {OFFSET(mii1_txd3), (MODE(7) | PULLUDDIS)}, /* (J18) gpio0[16] */ /* RST_PHY~ */ + {OFFSET(gpmc_ad11), (MODE(7) | PULLUDDIS)}, /* (U12) gpio0[27] */ /* RST_SHIELD~ */ + + /* Bank 1 */ + {OFFSET(gpmc_a4), (MODE(7) | PULLUDDIS)}, /* (R14) gpio1[20] */ /* BT_EN */ + {OFFSET(gpmc_a5), (MODE(7) | PULLUDDIS)}, /* (V15) gpio1[21] */ /* GSM_PWR_EN */ + {OFFSET(gpmc_a9), (MODE(7) | PULLUDDIS)}, /* (U16) gpio1[25] */ /* RST_GSM */ + {OFFSET(gpmc_a10), (MODE(7) | PULLUDDIS)}, /* (T16) gpio1[26] */ /* WLAN_EN */ + {OFFSET(gpmc_a11), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (V17) gpio1[27] */ /* WLAN_IRQ */ + + /* TODO: What about all the unused GPMC pins ? */ + + /* Bank 2 */ +#if 0 + /* TODO: What is this meant for? */ + {OFFSET(lcd_data3), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (R4) gpio2[9] */ /* SYSBOOT_3 */ + {OFFSET(lcd_data4), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (T1) gpio2[10] */ /* SYSBOOT_4 */ + + /* TODO: Check other unued pins from sysboot block */ + /* Ensure PU/PD does not work against external signal */ + /* + * SYSBOOT 0,1,5,12,13 = Low + * SYSBOOT 2 = High + */ +#endif + + /* Bank 3 */ + {OFFSET(mcasp0_ahclkr), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, /* (C12) gpio3[17] */ /* SIM_SEL */ + {-1}, +}; + +/* I2C0 PMIC */ +static struct module_pin_mux i2c0_pin_mux[] = { + {OFFSET(i2c0_sda), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (C17) I2C0_SDA */ + {OFFSET(i2c0_scl), (MODE(0) | RXACTIVE | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (C16) I2C0_SCL */ + {-1}, +}; + +/* I2C2 System */ +static struct module_pin_mux i2c2_pin_mux[] = { + {OFFSET(uart1_rtsn), (MODE(3) | RXACTIVE | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (D17) I2C2_SCL */ + {OFFSET(uart1_ctsn), (MODE(3) | RXACTIVE | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (D18) I2C2_SDA */ + {-1}, +}; + +/* RMII1: Ethernet */ +static struct module_pin_mux rmii1_pin_mux[] = { + /* RMII */ + {OFFSET(mii1_crs), MODE(1) | PULLUDDIS | RXACTIVE}, /* (H17) rmii1_crs */ + {OFFSET(mii1_rxerr), MODE(7) | PULLUDEN | PULLDOWN_EN | RXACTIVE}, /* (J15) gpio */ + {OFFSET(mii1_rxd0), MODE(1) | PULLUDDIS | RXACTIVE}, /* (M16) rmii1_rxd0 */ + {OFFSET(mii1_rxd1), MODE(1) | PULLUDDIS | RXACTIVE}, /* (L15) rmii1_rxd1 */ + {OFFSET(mii1_txen), MODE(1) | PULLUDDIS}, /* (J16) rmii1_txen */ + {OFFSET(mii1_txd0), MODE(1) | PULLUDDIS}, /* (K17) rmii1_txd0 */ + {OFFSET(mii1_txd1), MODE(1) | PULLUDDIS}, /* (K16) rmii1_txd1 */ + {OFFSET(rmii1_refclk), MODE(0) | PULLUDDIS | RXACTIVE}, /* (H18) rmii1_refclk */ + + /* SMI */ + {OFFSET(mdio_clk), MODE(0) | PULLUDDIS}, /* (M18) mdio_clk */ + {OFFSET(mdio_data), MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE}, /* (M17) mdio_data */ + + /* 25MHz Clock Output */ + {OFFSET(xdma_event_intr0), MODE(3)}, /* (A15) clkout1 (25 MHz clk for Switch) */ + {-1}, +}; + +/* MMC0: WiFi */ +static struct module_pin_mux mmc0_sdio_pin_mux[] = { + {OFFSET(mmc0_clk), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_CLK */ + {OFFSET(mmc0_cmd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_CMD */ + {OFFSET(mmc0_dat0), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_DAT0 */ + {OFFSET(mmc0_dat1), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_DAT1 */ + {OFFSET(mmc0_dat2), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_DAT2 */ + {OFFSET(mmc0_dat3), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC0_DAT3 */ + {-1}, +}; + +/* MMC1: eMMC */ +static struct module_pin_mux mmc1_emmc_pin_mux[] = { + {OFFSET(gpmc_csn1), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_CLK */ + {OFFSET(gpmc_csn2), (MODE(2) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_CMD */ + {OFFSET(gpmc_ad0), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT0 */ + {OFFSET(gpmc_ad1), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT1 */ + {OFFSET(gpmc_ad2), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT2 */ + {OFFSET(gpmc_ad3), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT3 */ + {OFFSET(gpmc_ad4), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT4 */ + {OFFSET(gpmc_ad5), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT5 */ + {OFFSET(gpmc_ad6), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT6 */ + {OFFSET(gpmc_ad7), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* MMC1_DAT7 */ + {-1}, +}; + +/* USB_DRVBUS not used -> configure as GPIO */ +static struct module_pin_mux usb_pin_mux[] = { + {OFFSET(usb0_drvvbus), (MODE(7) | PULLUDDIS)}, /* (F16) USB0_DRVVBUS */ + {OFFSET(usb1_drvvbus), (MODE(7) | PULLUDDIS)}, /* (F15) USB1_DRVVBUS */ + {-1}, +}; + +/* UART0: RS232/RS485 shield mode */ +static struct module_pin_mux uart0_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (E15) UART0_RXD */ + {OFFSET(uart0_txd), (MODE(0) | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (E16) UART0_TXD */ + {-1}, +}; + +/* UART0: Shield I/F (UART, CAN) */ +/* Leave UART0 unconfigured because we want to configure it as needed by Linux (can/spi/uart/etc) */ +/* Mode 7 = GPIO */ +static struct module_pin_mux uart0_disabled_pin_mux[] = { + {OFFSET(uart0_rxd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E15) GPIO1_10 */ + {OFFSET(uart0_txd), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E16) GPIO1_11 */ + {OFFSET(uart0_ctsn), (MODE(7) | PULLUDDIS | RXACTIVE)}, /* (E18) GPIO1_8 */ + {OFFSET(uart0_rtsn), (MODE(7) | PULLUDEN | PULLUP_EN)}, /* (E17) GPIO1_9 */ + {-1}, +}; + +/* UART1: User (Debug/Console) */ +static struct module_pin_mux uart1_pin_mux[] = { + {OFFSET(uart1_rxd), (MODE(0) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (D16) uart1_rxd */ + {OFFSET(uart1_txd), (MODE(0) | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (D15) uart1_txd */ + {-1}, +}; + +/* UART3: GNSS */ +static struct module_pin_mux uart3_pin_mux[] = { + {OFFSET(mii1_rxd3), (MODE(1) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (L17) UART3_RXD */ + {OFFSET(mii1_rxd2), (MODE(1) | PULLUDEN | PULLUP_EN | SLEWCTRL)}, /* (L16) UART3_TXD */ + {-1}, +}; + +/* UART5: Highspeed UART for Bluetooth (no SLEWCTRL) */ +static struct module_pin_mux uart5_pin_mux[] = { + {OFFSET(lcd_data9), (MODE(4) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (U2) UART5_RXD */ + {OFFSET(lcd_data8), (MODE(4) | PULLUDEN | PULLUP_EN)}, /* (U1) UART5_TXD */ + {OFFSET(lcd_data14), (MODE(6) | PULLUDEN | PULLUP_EN | RXACTIVE)}, /* (V4) uart5_ctsn */ + {OFFSET(lcd_data15), (MODE(6) | PULLUDEN | PULLUP_EN)}, /* (T5) uart5_rtsn */ + {-1}, +}; + +static struct module_pin_mux unused_pin_mux[] = { + /* SYSBOOT6, 7, 10, 11: Not used pulldown active, receiver disabled */ + {OFFSET(lcd_data6), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, + {OFFSET(lcd_data7), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, + {OFFSET(lcd_data10), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, + {OFFSET(lcd_data11), (MODE(7) | PULLUDEN | PULLDOWN_EN)}, + + /* TODO: GPMCA1..3, A6..8 */ + + {-1}, +}; + + +void enable_board_pin_mux(void) +{ + configure_module_pin_mux(gpio_pin_mux); + + configure_module_pin_mux(rmii1_pin_mux); + configure_module_pin_mux(mmc0_sdio_pin_mux); + configure_module_pin_mux(mmc1_emmc_pin_mux); + configure_module_pin_mux(usb_pin_mux); + + configure_module_pin_mux(i2c0_pin_mux); + configure_module_pin_mux(i2c2_pin_mux); + + configure_module_pin_mux(uart3_pin_mux); + configure_module_pin_mux(uart5_pin_mux); + + configure_module_pin_mux(unused_pin_mux); +} + +void enable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_pin_mux); +} + +void disable_uart0_pin_mux(void) +{ + configure_module_pin_mux(uart0_disabled_pin_mux); +} + +void enable_uart1_pin_mux(void) +{ + configure_module_pin_mux(uart1_pin_mux); +} + +void enable_uart3_pin_mux(void) +{ + configure_module_pin_mux(uart3_pin_mux); +} + +void enable_uart5_pin_mux(void) +{ + configure_module_pin_mux(uart5_pin_mux); +} diff --git a/board/nm/nrhw24/shield.c b/board/nm/nrhw24/shield.c new file mode 100644 index 0000000000..97f1394a9d --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/shield.h b/board/nm/nrhw24/shield.h new file mode 100644 index 0000000000..2ab27a0941 --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/shield_can.c b/board/nm/nrhw24/shield_can.c new file mode 100644 index 0000000000..36fa0a66a7 --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/shield_can.h b/board/nm/nrhw24/shield_can.h new file mode 100644 index 0000000000..21684cd4f7 --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/shield_comio.c b/board/nm/nrhw24/shield_comio.c new file mode 100644 index 0000000000..f43e992349 --- /dev/null +++ b/board/nm/nrhw24/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/nrhw24/shield_comio.h b/board/nm/nrhw24/shield_comio.h new file mode 100644 index 0000000000..2b2602e917 --- /dev/null +++ b/board/nm/nrhw24/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/board/nm/nrhw24/u-boot.lds b/board/nm/nrhw24/u-boot.lds new file mode 100644 index 0000000000..a41565b648 --- /dev/null +++ b/board/nm/nrhw24/u-boot.lds @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2004-2008 Texas Instruments + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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; either version 2 of + * the License, or (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.__image_copy_start) + *(.vectors) + CPUDIR/start.o (.text*) + board/nm/nrhw24/built-in.o (.text*) + *(.text*) + } + + . = ALIGN(4); + .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) } + + . = ALIGN(4); + .data : { + *(.data*) + } + + . = ALIGN(4); + + . = .; + + . = ALIGN(4); + .u_boot_list : { + KEEP(*(SORT(.u_boot_list*))); + } + + . = ALIGN(4); + + .__efi_runtime_start : { + *(.__efi_runtime_start) + } + + .efi_runtime : { + *(efi_runtime_text) + *(efi_runtime_data) + } + + .__efi_runtime_stop : { + *(.__efi_runtime_stop) + } + + .efi_runtime_rel_start : + { + *(.__efi_runtime_rel_start) + } + + .efi_runtime_rel : { + *(.relefi_runtime_text) + *(.relefi_runtime_data) + } + + .efi_runtime_rel_stop : + { + *(.__efi_runtime_rel_stop) + } + + . = ALIGN(4); + + .image_copy_end : + { + *(.__image_copy_end) + } + + .rel_dyn_start : + { + *(.__rel_dyn_start) + } + + .rel.dyn : { + *(.rel*) + } + + .rel_dyn_end : + { + *(.__rel_dyn_end) + } + + .hash : { *(.hash*) } + + .end : + { + *(.__end) + } + + _image_binary_end = .; + + /* + * Deprecated: this MMU section is used by pxa at present but + * should not be used by new boards/CPUs. + */ + . = ALIGN(4096); + .mmutable : { + *(.mmutable) + } + +/* + * Compiler-generated __bss_start and __bss_end, see arch/arm/lib/bss.c + * __bss_base and __bss_limit are for linker only (overlay ordering) + */ + + .bss_start __rel_dyn_start (OVERLAY) : { + KEEP(*(.__bss_start)); + __bss_base = .; + } + + .bss __bss_base (OVERLAY) : { + *(.bss*) + . = ALIGN(4); + __bss_limit = .; + } + + .bss_end __bss_limit (OVERLAY) : { + KEEP(*(.__bss_end)); + } + + .dynsym _image_binary_end : { *(.dynsym) } + .dynbss : { *(.dynbss) } + .dynstr : { *(.dynstr*) } + .dynamic : { *(.dynamic*) } + .gnu.hash : { *(.gnu.hash) } + .plt : { *(.plt*) } + .interp : { *(.interp*) } + .gnu : { *(.gnu*) } + .ARM.exidx : { *(.ARM.exidx*) } +} diff --git a/configs/am335x_nrhw24_defconfig b/configs/am335x_nrhw24_defconfig new file mode 100644 index 0000000000..a886c4823f --- /dev/null +++ b/configs/am335x_nrhw24_defconfig @@ -0,0 +1,49 @@ +CONFIG_ARM=y +CONFIG_TARGET_AM335X_NRHW24=y +CONFIG_SPL_STACK_R_ADDR=0x82000000 +CONFIG_SPL=y +CONFIG_SPL_STACK_R=y +CONFIG_FIT=y +CONFIG_SYS_EXTRA_OPTIONS="EMMC_BOOT" +CONFIG_HUSH_PARSER=y +CONFIG_AUTOBOOT_KEYED=y +CONFIG_AUTOBOOT_PROMPT="Press s to abort autoboot in %d seconds\n" +CONFIG_AUTOBOOT_STOP_STR="s" +CONFIG_CMD_BOOTZ=y +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_ASKENV=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_I2C=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_DHCP=y +CONFIG_CMD_MII=y +CONFIG_CMD_PING=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_DFU_TFTP=y +CONFIG_SYS_NS16550=y +CONFIG_USB=y +CONFIG_USB_MUSB_HOST=y +CONFIG_USB_MUSB_GADGET=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_G_DNL_MANUFACTURER="Texas Instruments" +CONFIG_G_DNL_VENDOR_NUM=0x0451 +CONFIG_G_DNL_PRODUCT_NUM=0xd022 +CONFIG_OF_LIBFDT=y +# CONFIG_BOOTP_PXE_CLIENTARCH is not set +# CONFIG_CMD_PXE is not set +# CONFIG_CMD_BOOTEFI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_ELF is not set +# CONFIG_FPGA is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_PMIC is not set +# CONFIG_EFI_LOADER is not set +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set diff --git a/include/configs/am335x_nrhw24.h b/include/configs/am335x_nrhw24.h new file mode 100755 index 0000000000..8759f44189 --- /dev/null +++ b/include/configs/am335x_nrhw24.h @@ -0,0 +1,250 @@ +/* + * am335x_nrhw24.h + * + * Copyright (C) 2018 NetModule AG - http://www.netmodule.com/ + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * 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. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __CONFIG_AM335X_NRHW24_H +#define __CONFIG_AM335X_NRHW24_H + +#include + +#undef CONFIG_SPL_AM33XX_ENABLE_RTC32K_OSC + +#undef CONFIG_HW_WATCHDOG +#undef CONFIG_OMPAP_WATCHDOG +#undef CONFIG_SPL_WATCHDOG_SUPPORT + +#ifndef CONFIG_SPL_BUILD +# define CONFIG_TIMESTAMP +# define CONFIG_LZO +#endif + +#define CONFIG_SYS_BOOTM_LEN (16 << 20) + +#define MACH_TYPE_TIAM335EVM 3589 /* Until the next sync */ +#define CONFIG_MACH_TYPE MACH_TYPE_TIAM335EVM +#define CONFIG_BOARD_LATE_INIT + +#define CONFIG_PRE_CONSOLE_BUFFER 1 +#define CONFIG_PRE_CON_BUF_ADDR 0x80000000 +#define CONFIG_PRE_CON_BUF_SZ 64*1024 + +/* Clock Defines */ +#define V_OSCK 0 /* 0 means detect from sysboot1 config */ +#define V_SCLK (V_OSCK) + +#include + +#define CONFIG_ARP_TIMEOUT 200 +#undef CONFIG_NET_RETRY_COUNT +#define CONFIG_NET_RETRY_COUNT 5 +#define CONFIG_BOOTP_MAY_FAIL + +#ifndef CONFIG_SPL_BUILD +#define KERNEL_ADDR "0x80000000" +#define LOAD_ADDR "0x83000000" +#define FDT_ADDR "0x82000000" +#define PXE_ADDR "0x82800000" +#define FDT_HIGH_ADDR "0x9f000000" +#define INIT_RD_ADDR "0x88000000" + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "kernel_image=kernel.bin\0" \ + "fdt_image=openwrt-nrhw24-nb801.dtb\0"\ + "modeboot=sdboot\0" \ + "fdt_addr=" FDT_ADDR "\0" \ + "kernel_addr=" KERNEL_ADDR "\0" \ + "load_addr=" LOAD_ADDR "\0" \ + "root_part=1\0" /* Default root partition, overwritten in board file */ \ + "defaultconsole=ttyS1\0" /* Default output console */ \ + "add_sd_bootargs=setenv bootargs $bootargs root=/dev/${mmc_dev}p$root_part rootfstype=ext4 " \ + "console=$defaultconsole,115200 rootwait loglevel=4 ti_cpsw.rx_packet_max=1526\0" \ + "add_version_bootargs=setenv bootargs $bootargs\0" \ + "fdt_skip_update=yes\0" \ + "ethprime=cpsw\0" \ + "sdbringup=echo Try bringup boot && ext4load mmc 1:$root_part $kernel_addr /boot/zImage && " \ + "ext4load mmc 1:$root_part $fdt_addr /boot/$fdt_image && setenv bootargs $bootargs rw;\0" \ + "sdprod=ext4load mmc 1:$root_part $kernel_addr /boot/$kernel_image && " \ + "ext4load mmc 1:$root_part $fdt_addr /boot/$fdt_image && setenv bootargs $bootargs ro;\0" \ + "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; " \ + /* For v4.19 kernel $mmc_dev should be "mmcblk1" (read from DT), for v3.18 kernel: "mmcblk0". */ \ + "fdt addr $fdt_addr;if fdt get value mmc_dev /nm_env nm,mmc-dev;then;else setenv mmc_dev mmcblk0;fi;" \ + "run add_sd_bootargs; run add_version_bootargs; run shieldcmd; " \ + "bootz $kernel_addr - $fdt_addr; fi\0" \ + "bootcmd=run sdboot\0" \ + "ipaddr=192.168.1.1\0" \ + "serverip=192.168.1.254\0" \ + "pxefile_addr_r=" PXE_ADDR "\0" \ + "fdt_addr_r=" FDT_ADDR "\0" \ + "fdt_high=" FDT_HIGH_ADDR "\0" \ + "kernel_addr_r=" KERNEL_ADDR "\0" \ + "ramdisk_addr_r=" LOAD_ADDR "\0" \ + "initrd_high=" INIT_RD_ADDR "\0" \ + "bootpretryperiod=1000\0" \ + "tftptimeout=2000\0" \ + "tftptimeoutcountmax=5\0" \ + "bootpretryperiod=2000\0" \ + "autoload=false\0" \ + "shieldcmd=\0" \ + "tftp_recovery=tftpboot $kernel_addr recovery-image; tftpboot $fdt_addr recovery-dtb; " \ + "setenv bootargs rdinit=/etc/preinit console=$defaultconsole,115200 " \ + "debug ti_cpsw.rx_packet_max=1526; run shieldcmd; " \ + "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 */ +#endif + +/* UART Configuration */ +#define CONFIG_SYS_NS16550_COM1 0x44e09000 /* UART0: XModem Boot, Shield */ +#define CONFIG_SYS_NS16550_COM2 0x48022000 /* UART1: Debug UART (Internal) */ +#define CONFIG_SYS_NS16550_COM3 0x48024000 /* Unused */ +#define CONFIG_SYS_NS16550_COM4 0x481A6000 /* GNSS */ +#define CONFIG_SYS_NS16550_COM5 0x481A8000 /* Unused */ +#define CONFIG_SYS_NS16550_COM6 0x481AA000 /* Bluetooth */ + +#define CONFIG_I2C +#define CONFIG_I2C_MULTI_BUS + +#define CONFIG_CMD_EEPROM +#define CONFIG_SYS_I2C_EEPROM_ADDR 0x50 /* Main EEPROM */ +#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 2 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS 4 +#define CONFIG_SYS_EEPROM_PAGE_WRITE_DELAY_MS 50 /* TODO: Can this be reduced to 20ms */ + +/* Put Environment in eMMC */ +#define CONFIG_ENV_OFFSET (512 * 128) /* @ 512*256 SPL starts */ +#define CONFIG_ENV_SIZE (4 * 1024) +#define CONFIG_ENV_IS_IN_MMC +#define CONFIG_SYS_MMC_ENV_DEV 1 + +#if 0 +#define CONFIG_SYS_MMC_ENV_PART 2 +#define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) +#define CONFIG_SYS_REDUNDAND_ENVIRONMENT +#endif + + +#undef CONFIG_SPL_ENV_SUPPORT +#undef CONFIG_SPL_NAND_SUPPORT +#undef CONFIG_SPL_ONENAND_SUPPORT + +/* We need to disable SPI to not confuse the eeprom env driver */ +#undef CONFIG_SPI +#undef CONFIG_SPI_BOOT +#undef CONFIG_SPL_OS_BOOT + +#define CONFIG_SPL_POWER_SUPPORT /* TODO: Check */ +#define CONFIG_SPL_YMODEM_SUPPORT + +#define CONFIG_SPL_LDSCRIPT "$(CPUDIR)/am33xx/u-boot-spl.lds" + +#define CONFIG_SUPPORT_EMMC_BOOT + +/* + * USB configuration. We enable MUSB support, both for host and for + * gadget. We set USB0 as peripheral and USB1 as host, based on the + * board schematic and physical port wired to each. Then for host we + * add mass storage support and for gadget we add both RNDIS ethernet + * and DFU. + */ +#define CONFIG_USB_MUSB_DSPS +#define CONFIG_ARCH_MISC_INIT +#define CONFIG_USB_MUSB_PIO_ONLY +#define CONFIG_USB_MUSB_DISABLE_BULK_COMBINE_SPLIT +#define CONFIG_AM335X_USB0 +#define CONFIG_AM335X_USB0_MODE MUSB_HOST + +/* Fastboot */ +#define CONFIG_USB_FUNCTION_FASTBOOT +#define CONFIG_CMD_FASTBOOT +#define CONFIG_ANDROID_BOOT_IMAGE +#define CONFIG_FASTBOOT_BUF_ADDR CONFIG_SYS_LOAD_ADDR +#define CONFIG_FASTBOOT_BUF_SIZE 0x07000000 +/* TODO: Check */ + +/* To support eMMC booting */ +#define CONFIG_STORAGE_EMMC +#define CONFIG_FASTBOOT_FLASH_MMC_DEV 1 + +#ifdef CONFIG_USB_MUSB_HOST +#define CONFIG_USB_STORAGE +#endif + +#ifdef CONFIG_USB_MUSB_GADGET +/* Removing USB gadget and can be enabled adter adding support usb DM */ +#ifndef CONFIG_DM_ETH +#define CONFIG_USB_ETHER +#define CONFIG_USB_ETH_RNDIS +#define CONFIG_USBNET_HOST_ADDR "de:ad:be:af:00:00" +#endif /* CONFIG_DM_ETH */ +#endif /* CONFIG_USB_MUSB_GADGET */ + + +/* + * Disable MMC DM for SPL build and can be re-enabled after adding + * DM support in SPL + */ +#ifdef CONFIG_SPL_BUILD +#undef CONFIG_DM_MMC +#undef CONFIG_TIMER +#endif + +#if defined(CONFIG_SPL_BUILD) +/* Remove other SPL modes. */ +#undef CONFIG_SPL_NAND_SUPPORT +#define CONFIG_ENV_IS_NOWHERE +#undef CONFIG_PARTITION_UUIDS +#undef CONFIG_EFI_PARTITION +#endif + +/* Network. */ +#define CONFIG_PHY_GIGE +#define CONFIG_PHYLIB +#define CONFIG_PHY_SMSC + +#ifdef CONFIG_DRIVER_TI_CPSW +#define CONFIG_CLOCK_SYNTHESIZER +#define CLK_SYNTHESIZER_I2C_ADDR 0x65 +#endif + +#define CONFIG_SYS_MEMTEST_START 0x80000000 +#define CONFIG_SYS_MEMTEST_END 0x87900000 + +#define CONFIG_NM_LOGIN +#define CONFIG_CRYPT + +#if 0 +#define CONFIG_POWER +#define CONFIG_POWER_I2C +#define CONFIG_POWER_DA9063 /* TODO: Provide driver */ +#endif + +#define CONFIG_CMD_PXE + +#define CONFIG_OF_BOARD_SETUP + +#define CONFIG_JTAG_MARKER_SPL 0x402FFF00 +#define CONFIG_JTAG_MARKER_UBOOT 0x807FFF00 + +/* SPL command is not needed */ +#undef CONFIG_CMD_SPL + +/* Never enable ISO it is broken and can lead to a crash */ +#undef CONFIG_ISO_PARTITION + +#endif /* ! __CONFIG_AM335X_NRHW24_H */