diff options
Diffstat (limited to 'io-module/mts_io.c')
-rw-r--r-- | io-module/mts_io.c | 312 |
1 files changed, 299 insertions, 13 deletions
diff --git a/io-module/mts_io.c b/io-module/mts_io.c index 16e0a34..ad85d0d 100644 --- a/io-module/mts_io.c +++ b/io-module/mts_io.c @@ -652,7 +652,7 @@ static struct gpio_pin gpio_pins_mtr2_0_0[] = { .attr_name = "serial_mode", .pin = AT91_PIN_PC23, .direction = GPIO_DIR_OUTPUT, - .output_value = 1, + .output_value = 0, .use_pullup = 0, }, { @@ -692,6 +692,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .use_pullup = 0, }, { + .name = "PWRMON", + .attr_name = "radio-power", + .pin = AT91_PIN_PA23, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 0, + }, + { .name = "3G_RST", .attr_name = "radio-reset", .pin = AT91_PIN_PA22, @@ -748,6 +757,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .active_low = 1, }, { + .name = "LED3", + .attr_name = "led-b", + .pin = AT91_PIN_PC15, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { .name = "LED4", .attr_name = "led-cd", .pin = AT91_PIN_PC20, @@ -757,6 +775,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .active_low = 1, }, { + .name = "LED4", + .attr_name = "led-c", + .pin = AT91_PIN_PC20, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { .name = "LED6", .attr_name = "led-sig1", .pin = AT91_PIN_PC19, @@ -766,6 +793,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .active_low = 1, }, { + .name = "LED6", + .attr_name = "led-d", + .pin = AT91_PIN_PC19, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { .name = "LED7", .attr_name = "led-sig2", .pin = AT91_PIN_PC18, @@ -775,6 +811,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .active_low = 1, }, { + .name = "LED7", + .attr_name = "led-e", + .pin = AT91_PIN_PC18, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { .name = "LED8", .attr_name = "led-sig3", .pin = AT91_PIN_PC17, @@ -784,6 +829,15 @@ static struct gpio_pin gpio_pins_mtr_0_0[] = { .active_low = 1, }, { + .name = "LED8", + .attr_name = "led-f", + .pin = AT91_PIN_PC17, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { .name = "RI_B", .attr_name = "extserial-ri", .pin = AT91_PIN_PC25, @@ -848,6 +902,15 @@ static struct gpio_pin gpio_pins_mtr_0_1[] = { .use_pullup = 0, }, { + .name = "PWRMON", + .attr_name = "radio-power", + .pin = AT91_PIN_PA23, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 0, + }, + { .name = "3G_RST", .attr_name = "radio-reset", .pin = AT91_PIN_PA22, @@ -1172,11 +1235,13 @@ struct clk *adc_clk; #define BLINK_PER_SEC 8 #define BLINK_INTERVAL (HZ / BLINK_PER_SEC) #define RESET_HOLD_COUNT (BLINK_PER_SEC * 3) +#define RESET_LONG_HOLD_COUNT (BLINK_PER_SEC * 30) static pid_t reset_pid = -1; static pid_t reset_count = 0; static int reset_short_signal = SIGUSR1; static int reset_long_signal = SIGUSR2; +static int reset_extra_long_signal = SIGHUP; static DEFINE_MUTEX(mts_io_mutex); static void blink_callback(struct work_struct *ignored); @@ -1203,14 +1268,20 @@ static void blink_callback(struct work_struct *ignored) if (vpid) { if (reset_pressed) { reset_count++; - } else if (reset_count > 0 && reset_count < RESET_HOLD_COUNT) { - kill_pid(vpid, reset_short_signal, 1); - reset_count = 0; + } else { + //Reset button has not been pressed + if (reset_count > 0 && reset_count < RESET_HOLD_COUNT) { + kill_pid(vpid, reset_short_signal, 1); + reset_count = 0; + } else if (reset_count >= RESET_HOLD_COUNT && reset_count < RESET_LONG_HOLD_COUNT) { + reset_count = 0; + kill_pid(vpid, reset_long_signal, 1); + } } - if (reset_count >= RESET_HOLD_COUNT) { + if (reset_count >= RESET_LONG_HOLD_COUNT) { reset_count = 0; - kill_pid(vpid, reset_long_signal, 1); + kill_pid(vpid, reset_extra_long_signal, 1); } } else { reset_count = 0; @@ -1228,6 +1299,177 @@ static void blink_callback(struct work_struct *ignored) schedule_delayed_work(&blink_work, BLINK_INTERVAL); } +static int radio_off_telit(void) +{ + int value, ret; + struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + + if (!onoff_pin || !pwrmon_pin || !rst_pin) { + return -ENODEV; + } + + value = at91_get_gpio_value(pwrmon_pin->pin); + if(value == 0) { + log_error("radio is already off"); + return -EINVAL; + } + + // drive on/off pin low for at least 3 sec + log_info("shutting down radio"); + ret = at91_set_gpio_output_with_pullup(onoff_pin->pin, 0, onoff_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(3500); + + // set on/off pin high + ret = at91_set_gpio_output_with_pullup(onoff_pin->pin, 1, onoff_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(200); + + // check that power is low + value = at91_get_gpio_value(pwrmon_pin->pin); + if(value != 0) { + log_warning("radio is still on. performing radio reset."); + //Perform Hard Reset + ret = at91_set_gpio_output_with_pullup(rst_pin->pin, 0, rst_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = at91_set_gpio_output_with_pullup(rst_pin->pin, 1, rst_pin->use_pullup); + if (ret) { + return ret; + } + } else { + log_info("radio has been shut down"); + } + + return ret; +} + +static int radio_on_telit(void) +{ + int value, ret; + struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + + if (!onoff_pin || !pwrmon_pin || !rst_pin) { + return -ENODEV; + } + + value = at91_get_gpio_value(pwrmon_pin->pin); + if(value != 0) { + log_error("radio is already on"); + return -EINVAL; + } + + // drive on/off pin low for at least 5 sec + log_info("turning on radio"); + ret = at91_set_gpio_output_with_pullup(onoff_pin->pin, 0, onoff_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(5500); + + // set on/off pin high + ret = at91_set_gpio_output_with_pullup(onoff_pin->pin, 1, onoff_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(200); + + // check that power is high + value = at91_get_gpio_value(pwrmon_pin->pin); + if(value == 0) { + log_warning("radio is still off. performing radio reset"); + //Perform Hard Reset + ret = at91_set_gpio_output_with_pullup(rst_pin->pin, 0, rst_pin->use_pullup); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = at91_set_gpio_output_with_pullup(rst_pin->pin, 1, rst_pin->use_pullup); + if (ret) { + return ret; + } + } else { + log_info("radio has been turned on"); + } + + return ret; +} + +static ssize_t mts_attr_store_radio_power_telit(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int value; + int err; + + if (sscanf(buf, "%i", &value) != 1) { + return -EINVAL; + } + if (value == 0) { + mutex_lock(&mts_io_mutex); + err = radio_off_telit(); + mutex_unlock(&mts_io_mutex); + } else { + mutex_lock(&mts_io_mutex); + err = radio_on_telit(); + mutex_unlock(&mts_io_mutex); + } + + if (err) { + return err; + } + + return count; +} + +static ssize_t mts_attr_store_radio_power(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int value; + int ret; + + struct gpio_pin *pin = gpio_pin_by_name("RADIO_RESET"); + + if (!pin) { + return -ENODEV; + } + + if (sscanf(buf, "%i", &value) != 1) { + return -EINVAL; + } + + if (value == 0) { + mutex_lock(&mts_io_mutex); + ret = at91_set_gpio_value(pin->pin, 0); + mutex_unlock(&mts_io_mutex); + } else { + mutex_lock(&mts_io_mutex); + ret = at91_set_gpio_value(pin->pin, 1); + mutex_unlock(&mts_io_mutex); + } + + return ret; +} + static int radio_reset_telit(void) { int ret; @@ -1437,6 +1679,9 @@ static ssize_t mts_attr_store_radio_reset_telit(struct device *dev, return count; } +static DEVICE_ATTR_MTS(dev_attr_radio_power, "radio-power", + mts_attr_show_gpio_pin, mts_attr_store_radio_power); + static DEVICE_ATTR_MTS(dev_attr_radio_reset, "radio-reset", mts_attr_show_gpio_pin, mts_attr_store_radio_reset); @@ -1902,7 +2147,7 @@ static ssize_t mts_attr_show_reset_monitor(struct device *dev, mutex_lock(&mts_io_mutex); - ret = sprintf(buf, "%d %d %d\n", reset_pid, reset_short_signal, reset_long_signal); + ret = sprintf(buf, "%d %d %d %d\n", reset_pid, reset_short_signal, reset_long_signal, reset_extra_long_signal); mutex_unlock(&mts_io_mutex); @@ -1915,18 +2160,31 @@ static ssize_t mts_attr_store_reset_monitor(struct device *dev, pid_t pid; int short_signal; int long_signal; + int extra_long_signal; + int result = sscanf(buf, "%i %i %i %i", &pid, &short_signal, &long_signal, &extra_long_signal); - if (sscanf(buf, "%i %i %i", &pid, &short_signal, &long_signal) != 3) { + if (result < 3 || result > 4) { return -EINVAL; } - mutex_lock(&mts_io_mutex); + if(result == 3) { + mutex_lock(&mts_io_mutex); - reset_pid = pid; - reset_short_signal = short_signal; - reset_long_signal = long_signal; + reset_pid = pid; + reset_short_signal = short_signal; + reset_long_signal = long_signal; - mutex_unlock(&mts_io_mutex); + mutex_unlock(&mts_io_mutex); + } else { + mutex_lock(&mts_io_mutex); + + reset_pid = pid; + reset_short_signal = short_signal; + reset_long_signal = long_signal; + reset_extra_long_signal = extra_long_signal; + + mutex_unlock(&mts_io_mutex); + } return count; } @@ -2100,6 +2358,8 @@ static ssize_t mts_attr_show_serial_mode(struct device *dev, ret = sprintf(buf, "rs485\n"); else if (smode2 == 1 && smode1 == 0 && smode0 == 0) ret = sprintf(buf, "rs422\n"); + else if (smode2 == 0 && smode1 == 0 && smode0 == 0) + ret = sprintf(buf, "loopback\n"); else ret = sprintf(buf, "error\n"); @@ -2136,6 +2396,11 @@ static ssize_t mts_attr_store_serial_mode(struct device *dev, smode1 = 0; smode0 = 0; } + else if (!strcasecmp(buf, "loopback")) { + smode2 = 0; + smode1 = 0; + smode0 = 0; + } else { return -EINVAL; } @@ -2197,6 +2462,9 @@ static DEVICE_ATTR_MTS(dev_attr_serial_mode, "serial-mode", static DEVICE_ATTR_MTS(dev_attr_eth_switch_enabled, "eth-switch-enabled", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_MTS(dev_attr_radio_power_telit, "radio-power", + mts_attr_show_gpio_pin, mts_attr_store_radio_power_telit); + static DEVICE_ATTR_MTS(dev_attr_radio_reset_telit, "radio-reset", mts_attr_show_gpio_pin, mts_attr_store_radio_reset_telit); @@ -2278,6 +2546,7 @@ static struct attribute *mtr2_platform_attributes[] = { &dev_attr_wifi_mac.attr, &dev_attr_reset.attr, &dev_attr_reset_monitor.attr, + &dev_attr_radio_power.attr, &dev_attr_radio_reset.attr, &dev_attr_ndc_reset.attr, &dev_attr_extserial_dtr.attr, @@ -2393,6 +2662,7 @@ static struct attribute *mtr_platform_attributes[] = { &dev_attr_wifi_mac.attr, &dev_attr_reset.attr, &dev_attr_reset_monitor.attr, + &dev_attr_radio_power_telit.attr, &dev_attr_radio_reset_telit.attr, &dev_attr_extserial_ri_gpio.attr, &dev_attr_extserial_dtr.attr, @@ -2409,6 +2679,13 @@ static struct attribute *mtr_platform_attributes[] = { &dev_attr_led_cd_gpio.attr, &dev_attr_led_wifi_gpio.attr, + &dev_attr_led_a_gpio.attr, + &dev_attr_led_b_gpio.attr, + &dev_attr_led_c_gpio.attr, + &dev_attr_led_d_gpio.attr, + &dev_attr_led_e_gpio.attr, + &dev_attr_led_f_gpio.attr, + NULL, }; @@ -2656,6 +2933,15 @@ static int mts_id_eeprom_load(void) has_spi_dout = 0; has_spi_temp = 1; log_info("detected board %s", HW_VERSION_MTOCGD3_0_0); + } else if (strncmp(id_eeprom.hw_version, HW_VERSION_MTOCGD_0_0, strlen(HW_VERSION_MTOCGD_0_0)) == 0) { + attr_group = &mtr_platform_attribute_group; + gpio_pins = gpio_pins_mtr_0_0; + mts_product_id = MTOCGD_0_0; + has_spi_sout = 0; + has_spi_din = 0; + has_spi_dout = 0; + has_spi_temp = 0; + log_info("detected board %s", HW_VERSION_MTOCGD_0_0); } else { attr_group = &mtcdp_platform_attribute_group; gpio_pins = gpio_pins_mtcdp_1_0; |