summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Klug <john.klug@multitech.com>2021-08-10 17:41:33 -0500
committerJohn Klug <john.klug@multitech.com>2021-08-10 18:38:46 -0500
commitbc918398a517f618ac102cde2ade494924a85a0c (patch)
tree326f7cfa35c7fc20463076f06d180b4088392171
parentaa29d434b31002c0946036a4f3de14a7de4cfb27 (diff)
downloadmts-io-bc918398a517f618ac102cde2ade494924a85a0c.tar.gz
mts-io-bc918398a517f618ac102cde2ade494924a85a0c.tar.bz2
mts-io-bc918398a517f618ac102cde2ade494924a85a0c.zip
MTCAP3-0.0 mts-io version 4.6.04.6.0
-rw-r--r--configure.ac2
-rw-r--r--io-module/machine/mtcap3.c540
-rw-r--r--io-module/mts-io.c60
-rw-r--r--io-module/mts_io_module.h6
4 files changed, 592 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 2811759..fc176d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT([mts-io], [4.5.2])
+AC_INIT([mts-io], [4.6.0])
AC_CONFIG_SRCDIR([util/mts_util_lora2_reset.c])
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER([config.h])
diff --git a/io-module/machine/mtcap3.c b/io-module/machine/mtcap3.c
new file mode 100644
index 0000000..2304a28
--- /dev/null
+++ b/io-module/machine/mtcap3.c
@@ -0,0 +1,540 @@
+
+#define NXP_GPIO(BANK, IO) (((( BANK - 1 ) * 32) + IO))
+
+/* Used for both mtcap3 0.0 and 0.1 */
+static struct gpio_pin gpio_pins_mtcap3_0_0[] = {
+ {
+ .name = "ETH_RESET",
+ .pin = {
+ .gpio = NXP_GPIO(1, 4), // ETH_NRST - has ext PU
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "eth-reset",
+ },
+ },
+ {
+ .name = "RADIO_POWER_MONITOR",
+ .pin = {
+ .gpio = NXP_GPIO(4, 28), // CELL_STATUS
+ .flags = GPIOF_IN,
+ .label = "radio-power-monitor",
+ },
+ },
+ {
+ .name = "RADIO_RESET",
+ .pin = {
+ .gpio = NXP_GPIO(5, 4), // CELL_RESET - has ext PD - inverted through FET
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "radio-reset",
+ },
+ },
+ {
+ .name = "RADIO_ONOFF",
+ .pin = {
+ .gpio = NXP_GPIO(5, 8), // CELL_ONOFF - has ext PD - inverted through FET
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "radio-onoff",
+ },
+ },
+ {
+ .name = "RADIO_POWER",
+ .pin = {
+ .gpio = NXP_GPIO(5, 0), // CELL_PWR_EN - has ext PD
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "radio-power",
+ },
+ },
+ {
+ .name = "DEVICE_RESET",
+ .pin = {
+ .gpio = NXP_GPIO(2, 13), // SWITCH_IN - has EXT PU
+ .flags = GPIOF_IN,
+ .label = "reset",
+ },
+ .active_low = 1,
+ },
+ {
+ .name = "LORA_RESET",
+ .pin = {
+ .gpio = NXP_GPIO(1, 5), // LORA_RST
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "lora/reset",
+ },
+ .capability = CAPA_LORA,
+ },
+ {
+ .name = "LORA_LBT_RESET",
+ .pin = {
+ .gpio = NXP_GPIO(1, 27), // LORA_LBT_nRESET
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "lora/lbt-reset",
+ },
+ .capability = CAPA_LORA,
+ .active_low = 1,
+ },
+ /* LEDs */
+ {
+ .name = "STATUS_LED", // DEV_LED_GN
+ .pin = {
+ .gpio = NXP_GPIO(2, 15),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "led-status",
+ },
+ },
+ {
+ .name = "LED2", // LED2 is for LoRa status
+ .pin = {
+ .gpio = NXP_GPIO(3, 27),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-lora",
+ },
+ },
+ {
+ .name = "LED3", // LED3 is for Cellular status (Modem can directly enable it)
+ .pin = {
+ .gpio = NXP_GPIO(5, 5),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "led-cd",
+ },
+ // Procesor side is hooked up to drain; module on gate
+ .active_low = 1,
+ },
+ {
+ .name = "LED4", // LED4 is for power status
+ .pin = {
+ .gpio = NXP_GPIO(3, 28),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-extra",
+ },
+ },
+ {
+ .name = "LORA_VCORE", // LoRa Core Voltage - comes up and goes down before vio
+ .pin = {
+ .gpio = NXP_GPIO(2, 12),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "lora/vcore-enable",
+ },
+ },
+ {
+ .name = "LORA_VIO", // LoRa IO Voltage; goes up and comes down after vcore
+ .pin = {
+ .gpio = NXP_GPIO(2, 14),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "lora/vio-enable",
+ },
+ },
+ // NXP_GPIO(3, 28), LED_EXTRA on the Rev 0 schem., is always on power
+ { },
+};
+
+// Note on EG95 reset logic: this code was adapted from radio.c in
+// RadioSupervisoryChips/STM8L101-MTQ.
+
+// EG95 timings
+#define EG95_PWRKEY_KEEPOUT_WAIT_MS (60)
+#define EG95_PWRKEY_LOW_ON_WAIT_MS (540) // >= 500ms in datasheet
+#define EG95_PWRKEY_LOW_OFF_WAIT_MS (700) // >650ms in datasheet
+#define EG95_POWER_MON_ON_WAIT_S (30)
+#define EG95_POWER_MON_OFF_WAIT_S (35)
+#define EG95_POWER_KEEPOUT_WAIT_MS (60)
+#define EG95_RESET_N_WAIT_MS (300)
+
+/* radio control (power/reset) for mtcap3 */
+static int radio_off_mtcap3(void)
+{
+ int i = 0;
+ int value = 0;
+ struct gpio_pin *pwrmon_pin = gpio_pin_by_attr_name("radio-power-monitor");
+ struct gpio_pin *onoff_pin = gpio_pin_by_attr_name("radio-onoff");
+ struct gpio_pin *power_pin = gpio_pin_by_attr_name("radio-power");
+
+ if (!onoff_pin || !pwrmon_pin) {
+ return -ENODEV;
+ }
+
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+ if(value == 0) {
+ log_warning("cell radio is already off");
+ return 0;
+ }
+
+ /* The reference manual indicates that PWRKEY is equivalent to AT+QPOWD */
+
+ log_info("turning off cell radio");
+
+ // Toggle PWRKEY - logic is reversed to the module through the FET
+ gpio_set_value(onoff_pin->pin.gpio, 0);
+ msleep(EG95_PWRKEY_KEEPOUT_WAIT_MS);
+ gpio_set_value(onoff_pin->pin.gpio, 1);
+ msleep(EG95_PWRKEY_LOW_OFF_WAIT_MS);
+ gpio_set_value(onoff_pin->pin.gpio, 0);
+
+ // Wait for module to indicate status
+ for(i=0; i<=EG95_POWER_MON_OFF_WAIT_S; i++) {
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ if(!value) {
+ break;
+ }
+
+ msleep(1000);
+ }
+
+ // disable power to the radio; We want to do this generally for
+ // battery powered MTCAP based devices.
+ gpio_set_value(power_pin->pin.gpio, 0);
+ msleep(EG95_POWER_KEEPOUT_WAIT_MS);
+
+ if(value != 0) {
+ log_warning("cell radio was still on.");
+ } else {
+ log_info("cell radio has been turned off");
+ }
+
+ return 0;
+}
+
+static int radio_on_mtcap3(void)
+{
+ int i = 0;
+ int value = 0;
+ struct gpio_pin *pwrmon_pin = gpio_pin_by_attr_name("radio-power-monitor");
+ struct gpio_pin *onoff_pin = gpio_pin_by_attr_name("radio-onoff");
+ struct gpio_pin *power_pin = gpio_pin_by_attr_name("radio-power");
+
+ if (!onoff_pin || !pwrmon_pin || !power_pin) {
+ return -ENODEV;
+ }
+
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ if(value != 0) {
+ log_warning("cell radio is already on");
+ return 0;
+ }
+
+ log_info("turning on cell radio");
+
+ // Toggle PWRKEY - lgoic is reversed to the module through the FET
+ gpio_set_value(onoff_pin->pin.gpio, 0);
+ msleep(EG95_PWRKEY_KEEPOUT_WAIT_MS);
+
+ // Enable power to the radio
+ gpio_set_value(power_pin->pin.gpio, 1);
+ msleep(EG95_POWER_KEEPOUT_WAIT_MS);
+
+ gpio_set_value(onoff_pin->pin.gpio, 1);
+ msleep(EG95_PWRKEY_LOW_ON_WAIT_MS);
+
+ // Wait for module to inidcate status.
+ // The spec says >= 10s, but MTQ code does 30; will be on the order of secs
+ for(i=0; i<=EG95_POWER_MON_ON_WAIT_S; i++) {
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ if(value) {
+ break;
+ }
+
+ msleep(1000);
+ }
+
+ // Set pwrkey high (through the FET switch);
+ // MTQ code does this after waiting for radio-power-monitor assert
+ gpio_set_value(onoff_pin->pin.gpio, 0);
+
+ if(value == 0) {
+ log_warning("cell radio is still off.");
+ } else {
+ log_info("cell radio has been turned on");
+ }
+
+ return 0;
+}
+
+static ssize_t mts_attr_store_radio_power_mtcap3(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;
+ }
+
+ mutex_lock(&mts_io_mutex);
+ if (value == 0) {
+ err = radio_off_mtcap3();
+ } else if (value == 1) {
+ err = radio_on_mtcap3();
+ } else {
+ err = -EINVAL;
+ }
+ mutex_unlock(&mts_io_mutex);
+
+ if (err) {
+ return err;
+ }
+
+ return count;
+}
+
+// *_radio_enable_* is here for backward compatibility
+static ssize_t mts_attr_store_radio_enable_mtcap3(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ // Included for legacy compatibilty. The 'radio-power' object controls
+ // power to the module, rather than 'enable.' The radio is always
+ // enabled, and 'radio-power' mirrors the state of the regulator enable,
+ // alleviating confusion, as well as ensuring clean shut down which
+ // reduce module failures.
+ return count;
+}
+
+static ssize_t mts_attr_show_radio_enable_mtcap3(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%d\n", 1);
+}
+
+static ssize_t mts_attr_store_lora_power_mtcap3(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+ int err;
+ struct gpio_pin *vcore_pin = gpio_pin_by_attr_name("lora/vcore-enable");
+ struct gpio_pin *vio_pin = gpio_pin_by_attr_name("lora/vio-enable");
+
+ if ( !vcore_pin || !vio_pin) {
+ return -ENODEV;
+ }
+
+ if (sscanf(buf, "%i", &value) != 1) {
+ return -EINVAL;
+ }
+
+ mutex_lock(&mts_io_mutex);
+ if (value == 0) {
+ gpio_set_value(vio_pin->pin.gpio, 0);
+ msleep(20);
+ gpio_set_value(vcore_pin->pin.gpio, 0);
+ log_info("LoRa VCORE/VIO disabled");
+ } else if (value == 1) {
+ gpio_set_value(vcore_pin->pin.gpio, 1);
+ msleep(20);
+ gpio_set_value(vio_pin->pin.gpio, 1);
+ log_info("LoRa VCORE/VIO enabled");
+ } else {
+ err = -EINVAL;
+ }
+ mutex_unlock(&mts_io_mutex);
+
+ if (err) {
+ return err;
+ }
+
+ return count;
+}
+
+static ssize_t mts_attr_show_lora_power_mtcap3(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int value;
+ struct gpio_pin *vcore_pin = gpio_pin_by_attr_name("lora/vcore-enable");
+ struct gpio_pin *vio_pin = gpio_pin_by_attr_name("lora/vio-enable");
+
+ if ( !vcore_pin || !vio_pin) {
+ return -ENODEV;
+ }
+
+ value = gpio_get_value(vcore_pin->pin.gpio);
+ value += gpio_get_value(vio_pin->pin.gpio) * 2;
+
+ return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t mts_attr_store_radio_reset_mtcap3(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int i;
+ int value;
+ struct gpio_pin *pwrmon_pin = gpio_pin_by_attr_name("radio-power-monitor");
+ struct gpio_pin *reset_pin = gpio_pin_by_attr_name("radio-reset");
+
+ if ( !pwrmon_pin || !reset_pin) {
+ return -ENODEV;
+ }
+
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+ if (sscanf(buf, "%i", &value) != 1) {
+ return -EINVAL;
+ }
+
+ if (value != 0 && value != -1) {
+ return -EINVAL;
+ }
+
+ mutex_lock(&mts_io_mutex);
+
+ radio_off_mtcap3();
+ radio_on_mtcap3();
+
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ // Ensure that the module status indicates that it is up
+ if(!value) {
+ // Something has gone wrong
+
+ log_warning("cell radio not responding. Applying hard reset.");
+
+ // The manual advises against doing this as it is disorderly
+ // We do it here as a last resort.
+ gpio_set_value(reset_pin->pin.gpio, 1);
+ msleep(EG95_RESET_N_WAIT_MS);
+ gpio_set_value(reset_pin->pin.gpio, 0);
+
+ for(i=0; i<=EG95_POWER_MON_ON_WAIT_S; i++) {
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ if(value) {
+ break;
+ }
+
+ msleep(1000);
+ }
+
+ if(value == 0) {
+ log_warning("Unable to reset radio.");
+ } else {
+ log_info("cell radio has been reset");
+ }
+ }
+ else
+ {
+ log_info("cell radio has been reset");
+ }
+
+ mutex_unlock(&mts_io_mutex);
+
+ return count;
+}
+
+static ssize_t mts_attr_show_radio_power_mtcap3(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int value;
+ struct gpio_pin *pwrmon_pin = gpio_pin_by_attr_name("radio-power-monitor");
+
+ if ( !pwrmon_pin) {
+ return -ENODEV;
+ }
+
+ value = gpio_get_value(pwrmon_pin->pin.gpio);
+
+ return sprintf(buf, "%d\n", value);
+}
+
+static DEVICE_ATTR_MTS(dev_attr_radio_reset_mtcap3, "radio-reset",
+ mts_attr_show_gpio_pin, mts_attr_store_radio_reset_mtcap3);
+
+static DEVICE_ATTR_MTS(dev_attr_radio_power_mtcap3, "radio-power",
+ mts_attr_show_radio_power_mtcap3, mts_attr_store_radio_power_mtcap3);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_radio_power_monitor_mtcap3, "radio-power-monitor",
+ mts_attr_show_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_eth_reset_mtcap3, "eth-reset",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_led_lora_gpio_mtcap3, "led-lora",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_led_extra_gpio_mtcap3, "led-extra",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+
+static struct attribute *mtcap3_0_0_platform_attributes[] = {
+ &dev_attr_vendor_id.attr,
+ &dev_attr_product_id.attr,
+ &dev_attr_device_id.attr,
+ &dev_attr_uuid.attr,
+ &dev_attr_hw_version.attr,
+ &dev_attr_imei.attr,
+ &dev_attr_eth_mac.attr,
+ &dev_attr_has_radio.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_reset_monitor.attr,
+ &dev_attr_reset_monitor_intervals.attr,
+
+ &dev_attr_eth_reset_mtcap3.attr,
+ &dev_attr_led_status.attr,
+ &dev_attr_led_cd_gpio.attr,
+ &dev_attr_led_lora_gpio_mtcap3.attr,
+ &dev_attr_led_extra_gpio_mtcap3.attr,
+
+ /* Set to NULL if no radio -- should be 1st radio attribute */
+ &dev_attr_radio_reset_mtcap3.attr,
+ &dev_attr_radio_power_mtcap3.attr,
+ &dev_attr_radio_power_monitor_mtcap3.attr,
+
+ &dev_attr_radio_reset_backoffs.attr,
+ &dev_attr_radio_reset_backoff_index.attr,
+ &dev_attr_radio_reset_backoff_seconds.attr,
+
+ NULL,
+};
+
+static int
+is_radio_power_attr_mtcap3(struct attribute *attr)
+{
+ return (attr == &dev_attr_radio_power_mtcap3.attr);
+}
+
+static struct attribute_group mtcap3_0_0_platform_attribute_group = {
+ .attrs = mtcap3_0_0_platform_attributes
+};
+
+//
+// on-board LORA attributes are to be stored in the lora/ sub-directory
+//
+//
+static DEVICE_ATTR_MTS(dev_attr_lora_reset_mtcap3, "reset",
+ mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_lora_lbt_reset_mtcap3, "lbt-reset",
+ mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_lora_power_enable_mtcap3, "power-enable",
+ mts_attr_show_lora_power_mtcap3, mts_attr_store_lora_power_mtcap3);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_eui_mtcap3, "eui",
+ mts_attr_show_lora_product_info);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_product_id_mtcap3, "product-id",
+ mts_attr_show_lora_product_info);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_hw_version_mtcap3, "hw-version",
+ mts_attr_show_lora_product_info);
+
+static struct attribute *mtcap3_0_0_lora_attributes[] = {
+ &dev_attr_lora_eui_mtcap3.attr,
+ &dev_attr_lora_product_id_mtcap3.attr,
+ &dev_attr_lora_hw_version_mtcap3.attr,
+ &dev_attr_lora_reset_mtcap3.attr,
+ &dev_attr_lora_lbt_reset_mtcap3.attr,
+ &dev_attr_lora_power_enable_mtcap3.attr,
+ NULL,
+};
+
+static struct attribute_group mtcap3_0_0_lora_attribute_group = {
+ .attrs = mtcap3_0_0_lora_attributes
+};
+
+// here to maintain compatiblility
+static DEVICE_ATTR_MTS(dev_attr_radio_enable_mtcap3, "radio-enable",
+ mts_attr_show_radio_enable_mtcap3, mts_attr_store_radio_enable_mtcap3);
+
+static struct attribute *mtcap3_0_0_enable_radio_attribute[] = {
+ &dev_attr_radio_enable_mtcap3.attr,
+};
+
diff --git a/io-module/mts-io.c b/io-module/mts-io.c
index cb1c48e..e4290a6 100644
--- a/io-module/mts-io.c
+++ b/io-module/mts-io.c
@@ -85,7 +85,7 @@ static int mts_io_probe(struct platform_device *pdev)
{
return 0;
}
-
+
static int mts_io_remove(struct platform_device *pdev)
{
return 0;
@@ -672,13 +672,14 @@ static int get_radio_model_from_product_id(void) {
#include "machine/mths.c"
#include "machine/mtcpm.c"
#include "machine/mt100eocg.c"
+#include "machine/mtcap3.c"
/* include capabilities sub-directory support */
#include "mts_capab.c"
struct attribute **freelater = NULL; // Storage to free when driver is unloaded.
-static int
+static int
mts_id_eeprom_load(void)
{
int i, j = 0;
@@ -695,7 +696,7 @@ mts_id_eeprom_load(void)
int ret;
const struct firmware* fw = NULL;
- /* Attempt to load the mts-io driver */
+ /* Attempt to load the mts-io driver */
if((ret = request_firmware_direct(&fw, "0-0056/eeprom", &mts_io_platform_device->dev)) == 0) {
if(fw->size == sizeof(id_eeprom)) {
memcpy(&id_eeprom, fw->data, sizeof(id_eeprom));
@@ -704,13 +705,13 @@ mts_id_eeprom_load(void)
log_error("Invalid platform EEPROM length (%d)", fw->size);
return -EINVAL;
}
-
+
release_firmware(fw);
} else {
log_error("Unable to load EEPROM contents (%d)", ret);
return -ENODEV;
}
-
+
/* If we are an MTCPM-0.0, the base board sets the radio existance, and we always
* add the radio-reset, etc */
if (strncmp(id_eeprom.hw_version,HW_VERSION_MTCPM_0_0,sizeof HW_VERSION_MTCPM_0_0) != 0) {
@@ -722,7 +723,7 @@ mts_id_eeprom_load(void)
}
log_debug("mts_id_eeprom_load: noradio=%d",noradio);
}
-
+
if (((tmp=HW_VERSION_MTCAP_0_0),(mts_hw_version=MTCAP_0_0),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) ||
((tmp=HW_VERSION_MTCAP_0_1),(mts_hw_version=MTCAP_0_1),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) ||
((tmp=HW_VERSION_MTCAP_0_2),(mts_hw_version=MTCAP_0_2),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) ||
@@ -803,6 +804,37 @@ mts_id_eeprom_load(void)
attr_group_lora = &mtcap_0_0_lora_attribute_group;
}
log_info("detected board %s", tmp);
+ } else if ((tmp=HW_VERSION_MTCAP3_0_0),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) {
+ current_blength = attr_blength = sizeof mtcap3_0_0_platform_attributes;
+ current_blength -= sizeof(struct attribute *); /* Length without terminating NULL */
+
+ if(noradio) {
+ struct attribute **ap = mtcap3_0_0_platform_attribute_group.attrs;
+ while(1) {
+ if(ap[j] == NULL) {
+ log_info("Did not find radio reset attribute. Possible driver fault.");
+ break;
+ }
+ j++;
+ if (is_radio_power_attr_mtcap3(ap[j])) {
+ log_info("Pruning radio feature from mts-io",j);
+ ap[j] = NULL;
+ current_blength = j * sizeof (ap[j]); /* Size without NULL */
+ attr_blength += sizeof (ap[j]); /* Size of attr array with NULL */
+ break;
+ }
+ }
+ }
+
+ if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA)) {
+ attr_group_lora = &mtcap3_0_0_lora_attribute_group;
+ }
+
+ attr_group = &mtcap3_0_0_platform_attribute_group;
+ gpio_pins = gpio_pins_mtcap3_0_0;
+ set_buttons(default_buttons);
+ mts_hw_version = MTCAP3_0_0;
+ log_info("detected board %s", HW_VERSION_MTCAP3_0_0);
} else if (strncmp(id_eeprom.hw_version, HW_VERSION_MTRE, strlen(HW_VERSION_MTRE)) == 0) {
attr_group = &mtre_0_0_platform_attribute_group;
gpio_pins = gpio_pins_mtre_0_0;
@@ -955,7 +987,7 @@ mts_id_eeprom_load(void)
all_attrs[current_count] = (struct attribute *)NULL;
mtcdt_0_1_platform_attribute_group.attrs = all_attrs;
}
-
+
attr_group = &mtcdt_0_1_platform_attribute_group;
gpio_pins = gpio_pins_mtcdt_0_1;
if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA)) {
@@ -1056,7 +1088,7 @@ mts_id_eeprom_load(void)
gpio_pins = gpio_pins_mt100eocg_0_0;
mts_hw_version = MT100EOCG_0_0;
set_buttons(default_buttons);
- log_info("detected board %s", HW_VERSION_MT100EOCG_0_0);
+ log_info("detected board %s", HW_VERSION_MT100EOCG_0_0);
} else {
int i;
@@ -1188,7 +1220,7 @@ static int __init mts_io_init(void)
if (ret)
printk(KERN_ERR "mts-io: probe failed: %d\n", ret);
platform_driver_unregister(&mts_io_driver);
-
+
mts_io_platform_device = platform_device_alloc(PLATFORM_NAME, -1);
if (!mts_io_platform_device)
return -ENOMEM;
@@ -1211,7 +1243,7 @@ static int __init mts_io_init(void)
if (ret) {
printk(KERN_ERR "mts-io:mts-io-dout: probe failed: %d\n", ret);
}
- }
+ }
if (DEVICE_CAPA(id_eeprom.capa, CAPA_DIN)) {
ret = spi_register_driver(&mts_spi_din_driver);
if (ret) {
@@ -1250,10 +1282,10 @@ static int __init mts_io_init(void)
log_debug("could not request pin %s (%d) but it could have already been requested under a different pin name", pin->name, ret);
}
}
-
+
// Create CPU directory if approprate (only MTCDT3 for now)
ret = mts_cpu_dir_create(mts_hw_version);
-
+
// start general buttons processing
init_buttons();
@@ -1277,7 +1309,7 @@ static void __exit mts_io_exit(void)
{
if (DEVICE_CAPA(id_eeprom.capa, CAPA_DOUT)) {
spi_unregister_driver(&mts_spi_dout_driver);
- }
+ }
if (DEVICE_CAPA(id_eeprom.capa, CAPA_DIN)) {
spi_unregister_driver(&mts_spi_din_driver);
}
@@ -1292,7 +1324,7 @@ static void __exit mts_io_exit(void)
for (pin = gpio_pins; *pin->name; pin++)
if (pin->capability == 0 || DEVICE_CAPA(id_eeprom.capa,pin->capability))
gpio_free(pin->pin.gpio);
-
+
cleanup_buttons();
//cleanup supercap monitor worker if SUPERCAP CAPA is true
diff --git a/io-module/mts_io_module.h b/io-module/mts_io_module.h
index 44aeade..5655f29 100644
--- a/io-module/mts_io_module.h
+++ b/io-module/mts_io_module.h
@@ -5,7 +5,7 @@
* MTAC cards.
*/
-#define DRIVER_VERSION "v4.5.2"
+#define DRIVER_VERSION "v4.6.0"
#define DRIVER_AUTHOR "Multitech Systems"
#define DRIVER_DESC "MTS-IO Controller"
#define DRIVER_NAME "mts-io"
@@ -44,6 +44,9 @@
#define HW_VERSION_MTHS_0_0 "MTHS-0.0" // Never released
#define HW_VERSION_MTHS_0_1 "MTHS-0.1"
+// NXP i.MX Platforms */
+#define HW_VERSION_MTCAP3_0_0 "MTCAP3-0.0"
+
/* TI OMAP Platforms */
#define PRODUCT_ID_MTCPM "MTCPM"
@@ -75,6 +78,7 @@ enum {
MTHS_0_1,
MTCPM_0_0,
MTCPM_0_1,
+ MTCAP3_0_0,
};
/* Commented because it is not used. Сonflicts with <linux/leds.h> */