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