diff options
-rw-r--r-- | io-module/mts_io.c | 197 |
1 files changed, 197 insertions, 0 deletions
diff --git a/io-module/mts_io.c b/io-module/mts_io.c index ba9996f..211dbc4 100644 --- a/io-module/mts_io.c +++ b/io-module/mts_io.c @@ -636,6 +636,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, @@ -837,6 +846,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, @@ -1217,6 +1235,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; @@ -1426,6 +1615,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); @@ -2186,6 +2378,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); @@ -2267,6 +2462,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_extserial_dtr.attr, &dev_attr_extserial_dsr_gpio.attr, @@ -2381,6 +2577,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, |