From bc918398a517f618ac102cde2ade494924a85a0c Mon Sep 17 00:00:00 2001 From: John Klug Date: Tue, 10 Aug 2021 17:41:33 -0500 Subject: MTCAP3-0.0 mts-io version 4.6.0 --- configure.ac | 2 +- io-module/machine/mtcap3.c | 540 +++++++++++++++++++++++++++++++++++++++++++++ io-module/mts-io.c | 60 +++-- io-module/mts_io_module.h | 6 +- 4 files changed, 592 insertions(+), 16 deletions(-) create mode 100644 io-module/machine/mtcap3.c 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 */ -- cgit v1.2.3