diff options
Diffstat (limited to 'io-module/telit_radio.c')
-rw-r--r-- | io-module/telit_radio.c | 219 |
1 files changed, 219 insertions, 0 deletions
diff --git a/io-module/telit_radio.c b/io-module/telit_radio.c new file mode 100644 index 0000000..fbac4fa --- /dev/null +++ b/io-module/telit_radio.c @@ -0,0 +1,219 @@ + +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 = gpio_get_value(pwrmon_pin->pin.gpio); + 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 = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(3500); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + // wait for radio to power off + msleep(5000); + + // check that power is low + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value != 0) { + log_warning("radio is still on. performing radio reset."); + //Perform Hard Reset + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_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 = gpio_get_value(pwrmon_pin->pin.gpio); + 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 = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(5500); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(200); + + // check that power is high + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value == 0) { + log_warning("radio is still off. performing radio reset"); + //Perform Hard Reset + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_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 int radio_reset_telit(void) +{ + int ret; + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + + if (!rst_pin || !onoff_pin) { + return -ENODEV; + } + + // drive reset pin low for 500ms + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + // wait for 2 sec before toggling on/off pin + msleep(2000); + + // drive on/off pin low for 6 sec + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(6000); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + return ret; +} + +static ssize_t mts_attr_store_radio_reset_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) { + return -EINVAL; + } + + mutex_lock(&mts_io_mutex); + + err = radio_reset_telit(); + + mutex_unlock(&mts_io_mutex); + + if (err) { + return err; + } + + return count; +} + +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); |