summaryrefslogtreecommitdiff
path: root/io-module/telit_radio.c
diff options
context:
space:
mode:
Diffstat (limited to 'io-module/telit_radio.c')
-rw-r--r--io-module/telit_radio.c219
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);