u-boot/board/nm/nrhw24/shield_comio.c

253 lines
5.6 KiB
C

#undef DEBUG
#include <common.h>
#include <asm/gpio.h>
#include <asm/arch/mux.h>
#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);
}