summaryrefslogtreecommitdiff
path: root/io-module
diff options
context:
space:
mode:
authorJohn Klug <john.klug@multitech.com>2020-02-25 13:06:26 -0600
committerJohn Klug <john.klug@multitech.com>2020-10-16 10:17:20 -0500
commitaa3be1b385cc26566745207d7862fa9067dcdf3c (patch)
treec6388d5254ce76a3286147ac81ba318919beb873 /io-module
parent2cf96aed8c6c90855cc43b10716aafdabdd51966 (diff)
downloadmts-io-aa3be1b385cc26566745207d7862fa9067dcdf3c.tar.gz
mts-io-aa3be1b385cc26566745207d7862fa9067dcdf3c.tar.bz2
mts-io-aa3be1b385cc26566745207d7862fa9067dcdf3c.zip
Support mtcpm CPU board4.3.0a
Diffstat (limited to 'io-module')
-rw-r--r--io-module/adc.c126
-rw-r--r--io-module/machine/mtcap.c (renamed from io-module/mtcap.c)0
-rw-r--r--io-module/machine/mtcdt.c (renamed from io-module/mtcdt.c)10
-rw-r--r--io-module/machine/mtcpm.c297
-rw-r--r--io-module/machine/mths.c (renamed from io-module/mths.c)8
-rw-r--r--io-module/machine/mtr.c (renamed from io-module/mtr.c)13
-rw-r--r--io-module/mt100eocg.c252
-rw-r--r--io-module/mts-io.c142
-rw-r--r--io-module/mts_capab.c35
-rw-r--r--io-module/mts_io.h1
-rw-r--r--io-module/mts_io_module.h11
-rw-r--r--io-module/spi.c597
12 files changed, 428 insertions, 1064 deletions
diff --git a/io-module/adc.c b/io-module/adc.c
deleted file mode 100644
index 3d5f3d0..0000000
--- a/io-module/adc.c
+++ /dev/null
@@ -1,126 +0,0 @@
-#define AT91SAM9X5_BASE_ADC 0xf804c000
-#define AT91SAM9260_BASE_ADC 0xfffe0000
-
-#define ADC_SHTIME_DEFAULT 0x05
-#define ADC_STARTUP_DEFAULT 0x04
-#define ADC_PRESCALE_DEFAULT 0x3F
-#define ADC_MODE_DEFAULT \
- ((ADC_SHTIME_DEFAULT & 0x0F) << 24) | \
- ((ADC_STARTUP_DEFAULT & 0x1F) << 16) | \
- ((ADC_PRESCALE_DEFAULT & 0x3F) << 8)
-
-#define ADC_CR_OFFSET 0x00
-#define ADC_MR_OFFSET 0x04
-#define ADC_CHER_OFFSET 0x10
-#define ADC_CHDR_OFFSET 0x14
-#define ADC_CHSR_OFFSET 0x18
-#define ADC_SR_OFFSET 0x1C
-#define ADC_LDCR_OFFSET 0x20
-#define ADC_IER_OFFSET 0x14
-#define ADC_IDR_OFFSET 0x28
-#define ADC_IMR_OFFSET 0x2C
-#define ADC_CDR0_OFFSET 0x30
-#define ADC_CDR1_OFFSET 0x34
-#define ADC_CDR2_OFFSET 0x38
-#define ADC_CDR3_OFFSET 0x3C
-
-void __iomem *adc_base;
-struct clk *adc_clk;
-
-#define ADC_CONVERT_RESET(base) writel(0x01, (base) + ADC_CR_OFFSET)
-#define ADC_CONVERT_START(base) writel(0x02, (base) + ADC_CR_OFFSET)
-
-static ssize_t mts_attr_show_adc(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int offset;
- u32 value;
- u32 chan_mask;
-
- if (!DEVICE_CAPA(id_eeprom.capa, CAPA_ADC)) {
- log_debug("ADC not available");
- return -ENODEV;
- }
-
- if (!strcmp(attr->attr.name, "adc0")) {
- offset = ADC_CDR0_OFFSET;
- chan_mask = 0x01;
- } else if (!strcmp(attr->attr.name, "adc1")) {
- offset = ADC_CDR1_OFFSET;
- chan_mask = 0x02;
- } else if (!strcmp(attr->attr.name, "adc2")) {
- offset = ADC_CDR2_OFFSET;
- chan_mask = 0x04;
- } else if (!strcmp(attr->attr.name, "adc3")) {
- offset = ADC_CDR3_OFFSET;
- chan_mask = 0x08;
- } else {
- log_notice("adc attr does not exist");
- return -ENOENT;
- }
-
- mutex_lock(&mts_io_mutex);
-
- // disable all channels and enable the one we want
- writel(0x0F, adc_base + ADC_CHDR_OFFSET);
- writel(chan_mask, adc_base + ADC_CHER_OFFSET);
-
- ADC_CONVERT_START(adc_base);
-
- // wait for conversion to complete (EOC bit set)
- value = 0;
- while (value != chan_mask) {
- value = readl(adc_base + ADC_SR_OFFSET) & chan_mask;
- log_debug("ADC_SR EOC [%X]", value);
- }
-
- // read result
- value = readl(adc_base + offset);
-
- mutex_unlock(&mts_io_mutex);
-
- return sprintf(buf, "%lu\n", (unsigned long) value);
-}
-
-static DEVICE_ATTR_RO_MTS(dev_attr_adc0, "adc0", mts_attr_show_adc);
-static DEVICE_ATTR_RO_MTS(dev_attr_adc1, "adc1", mts_attr_show_adc);
-static DEVICE_ATTR_RO_MTS(dev_attr_adc2, "adc2", mts_attr_show_adc);
-static DEVICE_ATTR_RO_MTS(dev_attr_adc3, "adc3", mts_attr_show_adc);
-
-static int mts_io_board_adc_probe(struct platform_device *pdev)
-{
- int err;
- adc_clk = clk_get(&pdev->dev, "adc_clk");
- if (adc_clk) {
- err = clk_prepare_enable(adc_clk);
- if (err) {
- log_error("clock failed to prepare+enable: %d\n", err);
- return err;
- }
- #ifdef CONFIG_SOC_AT91SAM9X5
- adc_base = ioremap(AT91SAM9X5_BASE_ADC, SZ_16K);
- #else
- adc_base = ioremap(AT91SAM9260_BASE_ADC, SZ_16K);
- #endif
- if (!adc_base) {
- log_error("ioremap failed.\n");
- return -ENOMEM;
- }
- ADC_CONVERT_RESET(adc_base);
- writel(ADC_MODE_DEFAULT, adc_base + ADC_MR_OFFSET);
- writel(0x000F0F0F, adc_base + ADC_IDR_OFFSET);
- writel(0x0F, adc_base + ADC_CHDR_OFFSET);
- }
- return 0;
-}
-
-static int mts_io_board_adc_remove(struct platform_device *pdev)
-{
- if (adc_clk) {
- int ret;
- clk_disable_unprepare(adc_clk);
- }
- return 0;
-}
-
diff --git a/io-module/mtcap.c b/io-module/machine/mtcap.c
index bd08d5a..bd08d5a 100644
--- a/io-module/mtcap.c
+++ b/io-module/machine/mtcap.c
diff --git a/io-module/mtcdt.c b/io-module/machine/mtcdt.c
index 69f87f7..575dd1e 100644
--- a/io-module/mtcdt.c
+++ b/io-module/machine/mtcdt.c
@@ -302,7 +302,7 @@ static struct gpio_pin gpio_pins_mtcdt_0_1[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PD15,
- .flags = GPIOF_OUT_INIT_LOW, /* Keep GPS quiet during boot */
+ .flags = GPIOF_OUT_INIT_LOW, /* Keep GPS quiet during boot for EXAR */
.label = "gnss-reset",
},
.capability = CAPA_GPS,
@@ -370,8 +370,10 @@ static DEVICE_ATTR_MTS(dev_attr_eth_reset, "eth-reset",
mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
static DEVICE_ATTR_MTS(dev_attr_gnss_int, "gnss-int",
mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-
+static DEVICE_ATTR_RO_MTS(dev_attr_wifi_mac, "mac-wifi",
+ mts_attr_show_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_bluetooth_mac, "mac-bluetooth",
+ mts_attr_show_product_info);
static struct attribute *mtcdt_platform_attributes[] = {
&dev_attr_vendor_id.attr,
@@ -454,6 +456,8 @@ static struct attribute *mtcdt_0_1_wifi_bt_attributes[] = {
&dev_attr_wifi_bt_reset.attr,
&dev_attr_wifi_bt_lpmode.attr,
&dev_attr_wifi_bt_int.attr,
+ &dev_attr_bluetooth_mac.attr,
+ &dev_attr_wifi_mac.attr,
};
static struct attribute *mtcdt_0_1_gnss_attributes[] = {
diff --git a/io-module/machine/mtcpm.c b/io-module/machine/mtcpm.c
new file mode 100644
index 0000000..8167218
--- /dev/null
+++ b/io-module/machine/mtcpm.c
@@ -0,0 +1,297 @@
+#include "mts_io.h"
+
+#define OMAP_GPIO(BANK, GPIO) ((BANK*32)+GPIO)
+/*
+ * Within a struct gpio_pin, there is only one
+ * occurrence of each pin, so there is only one
+ * pin label set for each gpio pin.
+ */
+static struct gpio_pin gpio_pins_mtcpm[] = {
+ {
+ .name = "RADIO_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(5,9), /* 5_9 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "radio-reset",
+ },
+ },
+#if 0
+ /* This goes through the PMIC for now */
+ {
+ .name = "RADIO_POWER",
+ .pin = {
+ .gpio = 0,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "radio-power",
+ },
+ },
+#endif
+ {
+ .name = "DEVICE_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(1,29),
+ .flags = GPIOF_IN,
+ .label = "reset",
+ },
+ .active_low = 1,
+ },
+ {
+ .name = "WIFI_BT_INT",
+ .pin = {
+ .gpio = OMAP_GPIO(4,12), /* 4_12 */
+ .flags = GPIOF_IN,
+ .label = "wifi-bt-int",
+ },
+ .capability = CAPA_BLUETOOTH,
+ },
+ {
+ .name = "WIFI_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(4,11), /* 4_11 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "wlan-enabled",
+ },
+ .capability = CAPA_WIFI,
+ .active_low = 0,
+ },
+ {
+ .name = "BT_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(4,10), /* 4_10 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "bt-enabled",
+ },
+ .capability = CAPA_BLUETOOTH,
+ .active_low = 0,
+ },
+ {
+ .name = "USBHUB_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(3, 15),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "usbhub-reset",
+ },
+ .active_low = 0,
+ },
+ {
+ .name = "ETH_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(4,7), /* 4_7 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "eth-reset",
+ },
+ .active_low = 0,
+ },
+ {
+ .name = "GNSS_INT",
+ .pin = {
+ .gpio = OMAP_GPIO(5,12), /* 5_12 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "gnss-int",
+ },
+ .capability = CAPA_GPS,
+ },
+ {
+ .name = "GNSS_RESET",
+ .pin = {
+ .gpio = OMAP_GPIO(5,10), /* 5_10 */
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "gnss-reset",
+ },
+ .capability = CAPA_GPS,
+ .active_low = 0,
+ },
+#if 0
+ /* Link status comes directly from the MTQ out to the baseboard */
+ {
+ .name = "LS_LED",
+ .pin = {
+ .gpio = 0,
+ .flags = GPIOF_IN,
+ .label = "led-ls",
+ },
+ .active_low = 1,
+ },
+#endif
+ {
+ .name = "STATUS_LED",
+ .pin = {
+ .gpio = OMAP_GPIO(0, 20),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-status",
+ },
+ },
+ {
+ .name = "CD",
+ .pin = {
+ .gpio = OMAP_GPIO(0, 21),
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "led-cd",
+ },
+ },
+ {
+ .name = "LED1",
+ .pin = {
+ .gpio = OMAP_GPIO(4, 26),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-sig1",
+ },
+ },
+ {
+ .name = "LED2",
+ .pin = {
+ .gpio = OMAP_GPIO(4, 27),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-sig2",
+ },
+ },
+ {
+ .name = "LED3",
+ .pin = {
+ .gpio = OMAP_GPIO(4, 28),
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "led-sig3",
+ },
+ },
+ { },
+};
+
+static DEVICE_ATTR_MTS(dev_attr_wifi_reset_mtcpm, "wlan-enabled",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_bt_reset_mtcpm, "bt-enabled",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_RO_MTS(dev_attr_wifi_bt_int_mtcpm, "wifi-bt-int",
+ mts_attr_show_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_gnss_reset_mtcpm, "gnss-reset",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_usbhub_reset_mtcpm, "usbhub-reset",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_eth_reset_mtcpm, "eth-reset",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_gnss_int_mtcpm, "gnss-int",
+ mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_lora_reset_mtcpm, "reset",
+ mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_cdone_mtcpm, "cdone",
+ mts_attr_show_lora_gpio_pin);
+static DEVICE_ATTR_MTS(dev_attr_lora_creset_mtcpm, "creset",
+ mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_eui_mtcpm, "eui",
+ mts_attr_show_lora_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_product_id_mtcpm, "product-id",
+ mts_attr_show_lora_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_hw_version_mtcpm, "hw-version",
+ mts_attr_show_lora_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_wifi_mac_mtcpm, "mac-wifi",
+ mts_attr_show_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_bluetooth_mac_mtcpm, "mac-bluetooth",
+ mts_attr_show_product_info);
+
+static struct attribute *mtcpm_platform_attributes[] = {
+ &dev_attr_imei.attr,
+ &dev_attr_eth_mac.attr,
+ &dev_attr_reset.attr,
+ &dev_attr_reset_monitor.attr,
+ &dev_attr_reset_monitor_intervals.attr,
+
+ &dev_attr_led_status.attr,
+ &dev_attr_led_cd_gpio.attr,
+ &dev_attr_led_sig1_gpio.attr,
+ &dev_attr_led_sig2_gpio.attr,
+ &dev_attr_led_sig3_gpio.attr,
+
+ &dev_attr_usbhub_reset.attr,
+ &dev_attr_eth_reset.attr,
+
+ // radio feature is last to be able to
+ // easily remove radio.
+ // is_radio_power_attr_mtcdt() searches
+ // for this for truncation.
+ &dev_attr_radio_power.attr, /* Must be first radio attribute */
+ &dev_attr_radio_reset.attr,
+
+ &dev_attr_radio_reset_backoffs.attr,
+ &dev_attr_radio_reset_backoff_index.attr,
+ &dev_attr_radio_reset_backoff_seconds.attr,
+
+ &dev_attr_wifi_reset_mtcpm.attr,
+ &dev_attr_bt_reset_mtcpm.attr,
+ &dev_attr_wifi_bt_int_mtcpm.attr,
+
+ &dev_attr_gnss_reset_mtcpm.attr,
+ &dev_attr_gnss_int_mtcpm.attr,
+ &dev_attr_wifi_mac_mtcpm.attr,
+ &dev_attr_bluetooth_mac_mtcpm.attr,
+ NULL,
+};
+
+
+
+static struct attribute_group mtcpm_platform_attribute_group = {
+ .attrs = mtcpm_platform_attributes
+};
+
+static int
+is_radio_power_attr_mtcpm(struct attribute *attr)
+{
+ return (attr == &dev_attr_radio_power.attr);
+}
+
+static struct attribute *mtcpm_lora_attributes[] = {
+ &dev_attr_lora_eui_mtcpm.attr,
+ &dev_attr_lora_product_id_mtcpm.attr,
+ &dev_attr_lora_hw_version_mtcpm.attr,
+ &dev_attr_lora_reset_mtcpm.attr,
+ &dev_attr_lora_cdone_mtcpm.attr,
+ &dev_attr_lora_creset_mtcpm.attr,
+ NULL,
+};
+
+static struct attribute_group mtcpm_lora_attribute_group = {
+ .attrs = mtcpm_lora_attributes
+};
+
+static struct attribute *mtcpm_cpu_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,
+ NULL,
+};
+
+
+static struct attribute_group mtcpm_cpu_attribute_group = {
+ .attrs = mtcpm_cpu_attributes
+};
+
+static struct kobject *mts_cpu_kobject = NULL;
+
+static int mts_cpu_dir_create(uint8_t hw_version)
+{
+ if (hw_version != MTCPM_0_0)
+ return 0;
+
+ mts_cpu_kobject = kobject_create_and_add("cpu", &mts_io_platform_device->dev.kobj);
+ if (!mts_cpu_kobject) {
+ log_error("kobject_create_and_add for cpu directory failed");
+ return -ENOMEM;
+ }
+
+ if (sysfs_create_group(mts_cpu_kobject, &mtcpm_cpu_attribute_group)) {
+ log_error("sysfs_create_group failed to create cpu group");
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static void mts_cpu_dir_delete(void)
+{
+ if (mts_cpu_kobject) {
+ kobject_put(mts_cpu_kobject);
+ mts_cpu_kobject = NULL;
+ }
+}
+
diff --git a/io-module/mths.c b/io-module/machine/mths.c
index a51380c..c19598d 100644
--- a/io-module/mths.c
+++ b/io-module/machine/mths.c
@@ -230,7 +230,7 @@ static struct gpio_pin gpio_pins_mths_0_0[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PC6,
- .flags = GPIOF_OUT_INIT_HIGH,
+ .flags = GPIOF_OUT_INIT_LOW,
.label = "gnss-reset",
}
},
@@ -461,7 +461,7 @@ static struct gpio_pin gpio_pins_mths_0_1[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PC6,
- .flags = GPIOF_OUT_INIT_HIGH,
+ .flags = GPIOF_OUT_INIT_LOW,
.label = "gnss-reset",
}
},
@@ -795,6 +795,9 @@ static DEVICE_ATTR_MTS(dev_attr_led_f_gpio_mths, "led-f",
static DEVICE_ATTR_RO_MTS(dev_attr_wifi_mac_mths, "mac-wifi",
mts_attr_show_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_bluetooth_mac_mths, "mac-bluetooth",
+ mts_attr_show_product_info);
+
static DEVICE_ATTR_MTS(dev_attr_wifi_bt_lpwkup_mths, "wifi-bt-lpwkup",
mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
@@ -829,6 +832,7 @@ static struct attribute *mths_0_0_platform_attributes[] = {
&dev_attr_hw_version.attr,
&dev_attr_imei.attr,
&dev_attr_wifi_mac_mths.attr,
+ &dev_attr_bluetooth_mac_mths.attr,
&dev_attr_has_radio.attr,
&dev_attr_reset.attr,
diff --git a/io-module/mtr.c b/io-module/machine/mtr.c
index e47beae..8664984 100644
--- a/io-module/mtr.c
+++ b/io-module/machine/mtr.c
@@ -885,7 +885,7 @@ static struct gpio_pin gpio_pins_mtrv1_0_1[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PD15,
- .flags = GPIOF_OUT_INIT_HIGH,
+ .flags = GPIOF_OUT_INIT_LOW,
.label = "gnss-reset",
}
},
@@ -1158,7 +1158,7 @@ static struct gpio_pin gpio_pins_mtrv1_0_2[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PD15,
- .flags = GPIOF_OUT_INIT_HIGH,
+ .flags = GPIOF_OUT_INIT_LOW,
.label = "gnss-reset",
}
},
@@ -1412,7 +1412,7 @@ static struct gpio_pin gpio_pins_mtrv1_0_3[] = {
.name = "GNSS_RESET",
.pin = {
.gpio = AT91_PIN_PD15,
- .flags = GPIOF_OUT_INIT_HIGH,
+ .flags = GPIOF_OUT_INIT_LOW,
.label = "gnss-reset",
}
},
@@ -1740,6 +1740,9 @@ static DEVICE_ATTR_MTS(dev_attr_extserial_dcd_gpio_mtr, "extserial-dcd",
static DEVICE_ATTR_RO_MTS(dev_attr_wifi_mac_mtr, "mac-wifi",
mts_attr_show_product_info);
+static DEVICE_ATTR_RO_MTS(dev_attr_bluetooth_mac_mtr, "mac-bluetooth",
+ mts_attr_show_product_info);
+
static DEVICE_ATTR_MTS(dev_attr_wifi_bt_lpwkup_mtr, "wifi-bt-lpwkup",
mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
@@ -1778,6 +1781,7 @@ static struct attribute *mtr_platform_attributes[] = {
&dev_attr_eth_mac.attr,
&dev_attr_has_radio.attr,
&dev_attr_wifi_mac_mtr.attr,
+ &dev_attr_bluetooth_mac_mtr.attr,
&dev_attr_reset.attr,
&dev_attr_reset_monitor.attr,
&dev_attr_reset_monitor_intervals.attr,
@@ -1831,6 +1835,7 @@ static struct attribute *mtrv1_0_1_platform_attributes[] = {
&dev_attr_eth_mac.attr,
&dev_attr_has_radio.attr,
&dev_attr_wifi_mac_mtr.attr,
+ &dev_attr_bluetooth_mac_mtr.attr,
&dev_attr_reset.attr,
&dev_attr_reset_monitor.attr,
@@ -1887,6 +1892,7 @@ static struct attribute *mtrv1_0_2_platform_attributes[] = {
&dev_attr_eth_mac.attr,
&dev_attr_has_radio.attr,
&dev_attr_wifi_mac_mtr.attr,
+ &dev_attr_bluetooth_mac_mtr.attr,
&dev_attr_reset.attr,
&dev_attr_reset_monitor.attr,
@@ -1946,6 +1952,7 @@ static struct attribute *mtrv1_0_3_platform_attributes[] = {
&dev_attr_eth_mac.attr,
&dev_attr_has_radio.attr,
&dev_attr_wifi_mac_mtr.attr,
+ &dev_attr_bluetooth_mac_mtr.attr,
&dev_attr_reset.attr,
&dev_attr_reset_monitor.attr,
diff --git a/io-module/mt100eocg.c b/io-module/mt100eocg.c
deleted file mode 100644
index 749b85a..0000000
--- a/io-module/mt100eocg.c
+++ /dev/null
@@ -1,252 +0,0 @@
-#include "at91gpio.h"
-/* Used for both MT100EOCG 0.0 */
-static struct gpio_pin gpio_pins_mt100eocg_0_0[] = {
- {
- .name = "ADC0",
- .pin = {
- .label = "adc0",
- .gpio = AT91_PIN_PC0,
- .flags = GPIOF_IN,
- },
- },
- {
- .name = "ADC1",
- .pin = {
- .label = "adc1",
- .gpio = AT91_PIN_PC1,
- .flags = GPIOF_IN,
- },
- },
- {
- .name = "ADC2",
- .pin = {
- .label = "adc2",
- .gpio = AT91_PIN_PC2,
- .flags = GPIOF_IN,
- },
- },
- {
- .name = "ADC3",
- .pin = {
- .label = "adc3",
- .gpio = AT91_PIN_PC3,
- .flags = GPIOF_IN,
- },
- },
- {
- .name = "DTR1",
- .pin = {
- .label = "extserial-dtr",
- .gpio = AT91_PIN_PB18,
- .flags = GPIOF_IN,
- },
- .active_low = 1,
- },
- {
- .name = "DCD1",
- .pin = {
- .label = "extserial-dcd",
- .gpio = AT91_PIN_PB3,
- .flags = GPIOF_OUT_INIT_HIGH,
- },
- .active_low = 1,
- },
- {
- .name = "ETH0_ENABLED",
- .pin = {
- .label = "eth0-enabled",
- .gpio = AT91_PIN_PB31,
- .flags = GPIOF_OUT_INIT_HIGH,
- },
- },
- {
- .name = "ENIO",
- .pin = {
- .label = "enio",
- .gpio = AT91_PIN_PC15,
- .flags = GPIOF_OUT_INIT_LOW,
- },
- },
- {
- .name = "DEVICE_RESET",
- .pin = {
- .label = "reset",
- .gpio = AT91_PIN_PA22,
- .flags = GPIOF_IN,
- },
- .active_low = 1,
- },
- {
- .name = "RSERSRC",
- .pin = {
- .label = "rsersrc",
- .gpio = AT91_PIN_PC7,
- .flags = GPIOF_OUT_INIT_HIGH,
- },
- .active_low = 1,
- },
- {
- .name = "RADIO_RESET",
- .pin = {
- .label = "radio-reset",
- .gpio = AT91_PIN_PB30,
- .flags = GPIOF_OUT_INIT_HIGH,
- },
- },
- {
- .name = "GPIO11",
- .pin = {
- .label = "gpio11",
- .gpio = AT91_PIN_PB19,
- .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH,
- },
- },
- {
- .name = "GPIO12",
- .pin = {
- .label = "gpio12",
- .gpio = AT91_PIN_PB20,
- .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH,
- },
- },
- {
- .name = "LED2",
- .pin = {
- .label = "led2",
- .gpio = AT91_PIN_PA30,
- .flags = GPIOF_OUT_INIT_HIGH,
- },
- .active_low = 1,
- },
- {
- .name = "LED3",
- .pin = {
- .label = "led3",
- .gpio = AT91_PIN_PC9,
-#if LED_LS_CONTROLLABLE
- .flags = GPIOF_OUT_INIT_HIGH,
-#else
- .flags = GPIOF_IN,
-#endif
- },
- .active_low = 1,
- },
- /*
- {
- .name = "TXD1",
- .pin = {
- .gpio = AT91_PIN_PB17,
- .flags = GPIOF_IN,
- },
- },*/
- { },
-};
-
-/* mt100eocg specific attributes */
-static DEVICE_ATTR_RO_MTS(dev_attr_extserial_dtr, "extserial-dtr",
- mts_attr_show_gpio_pin);
-
-static DEVICE_ATTR_MTS(dev_attr_extserial_dcd_gpio, "extserial-dcd",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static DEVICE_ATTR_MTS(dev_attr_eth0_enabled, "eth0-enabled",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static DEVICE_ATTR_MTS(dev_attr_enio, "enio",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static DEVICE_ATTR_MTS(dev_attr_gpo1, "gpo1",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_gpo2, "gpo2",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_gpo3, "gpo3",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_gpo4, "gpo4",
- mts_attr_show_dout, mts_attr_store_dout);
-
-
-static DEVICE_ATTR_MTS(dev_attr_led1, "led1",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_led2, "led2",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-#if LED_LS_CONTROLLABLE
-static DEVICE_ATTR_MTS(dev_attr_led3, "led3",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-#else
-static DEVICE_ATTR_RO_MTS(dev_attr_led3, "led3", mts_attr_show_gpio_pin);
-#endif
-
-static DEVICE_ATTR_MTS(dev_attr_led4, "led4",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_led5, "led5",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_led6, "led6",
- mts_attr_show_dout, mts_attr_store_dout);
-
-static DEVICE_ATTR_MTS(dev_attr_gpio11, "gpio11",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-static DEVICE_ATTR_MTS(dev_attr_gpio12, "gpio12",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static DEVICE_ATTR_MTS(dev_attr_rsersrc, "rsersrc",
- mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static struct attribute *mt100eocg_platform_attributes[] = {
- &dev_attr_vendor_id.attr,
- &dev_attr_product_id.attr,
- &dev_attr_device_id.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_extserial_dtr.attr,
- &dev_attr_extserial_dcd_gpio.attr,
- &dev_attr_rsersrc.attr, // AT91_PIN_PC7
- &dev_attr_radio_reset.attr, // AT91_PIN_PB30
- &dev_attr_eth0_enabled.attr,
- &dev_attr_gpio11.attr, // AT91_PIN_PB19
- &dev_attr_gpio12.attr, // AT91_PIN_PB20
- &dev_attr_enio.attr,
-// SPI
- &dev_attr_gpo1.attr,
- &dev_attr_gpo2.attr,
- &dev_attr_gpo3.attr,
- &dev_attr_gpo4.attr,
-//
-// SPI
- &dev_attr_led1.attr,
-//
- &dev_attr_led2.attr, // AT91_PIN_PA30
- &dev_attr_led3.attr, // AT91_PIN_PC9
-// SPI
- &dev_attr_led4.attr,
- &dev_attr_led5.attr,
- &dev_attr_led6.attr,
-//
-// SPI
- &dev_attr_gpi5.attr,
- &dev_attr_gpi6.attr,
- &dev_attr_gpi7.attr,
- &dev_attr_gpi8.attr,
- &dev_attr_gpi9.attr,
- &dev_attr_gpi10.attr,
-//
-// SPI
- &dev_attr_board_temperature.attr,
-//
-// adc
- &dev_attr_adc0.attr,
- &dev_attr_adc1.attr,
- &dev_attr_adc2.attr,
- &dev_attr_adc3.attr,
-
- NULL,
-};
-
-static struct attribute_group mt100eocg_platform_attribute_group = {
- .attrs = mt100eocg_platform_attributes
-};
diff --git a/io-module/mts-io.c b/io-module/mts-io.c
index d6bd4f2..f224777 100644
--- a/io-module/mts-io.c
+++ b/io-module/mts-io.c
@@ -20,7 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
-#include <linux/clk.h>
+
#include <linux/delay.h>
#include <linux/ioctl.h>
#include <linux/input.h>
@@ -71,11 +71,6 @@ static const struct of_device_id mts_io_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, mts_io_dt_ids);
-/* on-board EEPROM */
-static struct mts_id_eeprom_layout id_eeprom;
-
-#include "adc.c"
-
/*
* We must call platform_set_drvdata, or else the
* devres_head for the driver has junk in it, and
@@ -88,11 +83,7 @@ static struct mts_id_eeprom_layout id_eeprom;
*/
static int mts_io_probe(struct platform_device *pdev)
{
- int ret = 0;
- if (!DEVICE_CAPA(id_eeprom.capa, CAPA_ADC)) {
- ret = mts_io_board_adc_probe(pdev);
- }
- return ret;
+ return 0;
}
static int mts_io_remove(struct platform_device *pdev)
@@ -113,6 +104,8 @@ static struct platform_driver mts_io_driver = {
};
+/* on-board EEPROM */
+static struct mts_id_eeprom_layout id_eeprom;
static uint8_t mts_hw_version;
struct platform_device *mts_io_platform_device;
EXPORT_SYMBOL(mts_io_platform_device);
@@ -135,8 +128,6 @@ static time_t time_now_secs(void);
/* generic GPIO support */
#include "gpio.c"
-#include "spi.c"
-
/* generic Button support */
//#include "buttons.c"
@@ -165,8 +156,8 @@ bool sent_extra_long = false;
* by a numeric, we have no modem.
* All other cases, we have a modem.
*/
-static int
-has_radio(const char *product_id, size_t len)
+int
+mts_has_radio(const char *product_id, size_t len)
{
char *p;
if (!product_id || ! *product_id)
@@ -203,6 +194,7 @@ has_radio(const char *product_id, size_t len)
log_debug("Undefined product-id - has modem");
return 1; /* Product id invalid or empty, so instantiate a radio anyway */
}
+EXPORT_SYMBOL(mts_has_radio);
/* active-low socket modem reset */
static ssize_t mts_attr_store_radio_reset(struct device *dev,
@@ -528,7 +520,7 @@ static ssize_t mts_attr_show_product_info(struct device *dev,
value = sprintf(buf, "%.32s\n", id_eeprom.product_id);
} else if (strcmp(attr->attr.name, "has-radio") == 0) {
value = sprintf(buf, "%1d\n",
- has_radio(id_eeprom.product_id,sizeof id_eeprom.product_id));
+ mts_has_radio(id_eeprom.product_id,sizeof id_eeprom.product_id));
} else if (strcmp(attr->attr.name, "device-id") == 0) {
value = sprintf(buf, "%.32s\n", id_eeprom.device_id);
} else if (strcmp(attr->attr.name, "uuid") == 0) {
@@ -558,7 +550,15 @@ static ssize_t mts_attr_show_product_info(struct device *dev,
id_eeprom.mac_wifi[3],
id_eeprom.mac_wifi[4],
id_eeprom.mac_wifi[5]);
- } else if (strcmp(attr->attr.name, "mac-eth") == 0) {
+ } else if (strcmp(attr->attr.name, "mac-bluetooth") == 0) {
+ value = sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
+ id_eeprom.mac_bluetooth[0],
+ id_eeprom.mac_bluetooth[1],
+ id_eeprom.mac_bluetooth[2],
+ id_eeprom.mac_bluetooth[3],
+ id_eeprom.mac_bluetooth[4],
+ id_eeprom.mac_bluetooth[5]);
+ } else if (strcmp(attr->attr.name, "mac-eth") == 0) {
value = sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X\n",
id_eeprom.mac_addr[0],
id_eeprom.mac_addr[1],
@@ -617,11 +617,12 @@ static int get_radio_model_from_product_id(void) {
#include "mts_lora.c"
/* include per-device pins and attributes */
-#include "mtcdt.c"
-#include "mtcap.c"
-#include "mtr.c"
-#include "mths.c"
-#include "mt100eocg.c"
+#include "machine/mtcdt.c"
+#include "machine/mtcap.c"
+#include "machine/mtr.c"
+#include "machine/mths.c"
+#include "machine/mtcpm.c"
+
/* include capabilities sub-directory support */
#include "mts_capab.c"
@@ -649,15 +650,20 @@ mts_id_eeprom_load(void)
log_info("Platform EEPROM contents loaded");
} else {
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;
}
- noradio = ! has_radio(id_eeprom.product_id,sizeof id_eeprom.product_id);
- log_debug("mts_id_eeprom: noradio=%d",noradio);
+ // If we are an MTCPM, the base board sets the radio existance.
+ if (strncmp(id_eeprom.hw_version,HW_VERSION_MTCPM_DASH,sizeof HW_VERSION_MTCPM_DASH) != 0) {
+ noradio = ! mts_has_radio(id_eeprom.product_id,sizeof id_eeprom.product_id);
+ log_debug("mts_id_eeprom: noradio=%d",noradio);
+ }
if (((tmp=HW_VERSION_MTCAP_0_0),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) ||
((tmp=HW_VERSION_MTCAP_0_1),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) ||
@@ -784,7 +790,7 @@ mts_id_eeprom_load(void)
attr_group = &mtcdt_0_1_platform_attribute_group;
gpio_pins = gpio_pins_mtcdt_0_1;
- set_buttons(default_buttons);
+ set_buttons(default_buttons);
log_info("detected board %s", tmp);
} else if ((tmp=HW_VERSION_MTCDTIPHP_0_0),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) {
current_blength = attr_blength = sizeof mtcdt_0_1_platform_attributes;
@@ -831,15 +837,9 @@ mts_id_eeprom_load(void)
if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA)) {
attr_group_lora = &mtcdtiphp_0_0_lora_attribute_group;
}
- set_buttons(default_buttons);
+ set_buttons(default_buttons);
log_info("detected board %s", tmp);
- } else if (strncmp(id_eeprom.product_id, PRODUCT_ID_MT100EOCG, strlen(PRODUCT_ID_MT100EOCG)) == 0) {
- attr_group = &mt100eocg_platform_attribute_group;
- 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);
- } else {
+ } else if ((tmp=HW_VERSION_MTCDT_0_0),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) {
if(noradio) {
struct attribute **ap = mtcdt_platform_attribute_group.attrs;
while(1) {
@@ -859,9 +859,35 @@ mts_id_eeprom_load(void)
attr_group = &mtcdt_platform_attribute_group;
gpio_pins = gpio_pins_mtcdt_0_0;
mts_hw_version = MTCDT_0_0;
+ set_buttons(default_buttons);
+ log_info("detected board %s", tmp);
+
+ } else if (strncmp(id_eeprom.hw_version, HW_VERSION_MTCPM_0_0, strlen(HW_VERSION_MTCPM_0_0)) == 0) {
+ attr_group = &mtcpm_platform_attribute_group;
+ gpio_pins = gpio_pins_mtcpm;
set_buttons(default_buttons);
- log_info("detected board %s", HW_VERSION_MTCDT_0_0);
- }
+ mts_hw_version = MTCPM_0_0;
+ log_info("detected board %s", HW_VERSION_MTCPM_0_0);
+ } else {
+ int i;
+
+ for(i=0;i<sizeof id_eeprom.hw_version;i++) {
+ if(! id_eeprom.hw_version[i])
+ /* Found NULL so done */
+ break;
+ if(! isprint(id_eeprom.hw_version[i]))
+ break;
+ }
+ log_alert("Unsupported EEPROM settings or device");
+
+ if(i)
+ log_alert("Found unsupported EEPROM HW_VERSION: %.*s",i,id_eeprom.hw_version);
+ log_alert("Check log for HW_VERSION dump");
+
+ print_hex_dump_bytes("HW_VERSION: ", DUMP_PREFIX_OFFSET, id_eeprom.hw_version, sizeof id_eeprom.hw_version);
+
+ return -ENODEV;
+ }
log_info("sizeof: %lu", (unsigned long) sizeof(struct mts_id_eeprom_layout));
log_info("vendor-id: %.32s", id_eeprom.vendor_id);
@@ -883,8 +909,10 @@ mts_id_eeprom_load(void)
log_info("capa-adc: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_ADC) ? "yes" : "no");
log_info("capa-wifi: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_WIFI) ? "yes" : "no");
log_info("capa-bluetooth: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_BLUETOOTH) ? "yes" : "no");
- log_info("capa-lora: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) ? "yes" : "no");
- log_info("capa-battery: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_BATTERY) ? "yes" : "no");
+ if (!(mts_hw_version != HW_VERSION_MTCPM_0_0)) /* Moved to mtcdt3b driver in MTCDT3 baseboard hardware */
+ log_info("capa-lora: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) ? "yes" : "no");
+ log_info("capa-battery: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_BATTERY) ? "yes" : "no");
+
if (DEVICE_CAPA(id_eeprom.capa, CAPA_BLUETOOTH)) {
log_info("mac-bluetooth: %02X:%02X:%02X:%02X:%02X:%02X",
@@ -941,6 +969,7 @@ static void cleanup(void)
}
mts_capab_dir_delete();
+ mts_cpu_dir_delete();
}
static int __init mts_io_init(void)
@@ -964,46 +993,27 @@ static int __init mts_io_init(void)
platform_driver_unregister(&mts_io_driver);
mts_io_platform_device = platform_device_alloc(PLATFORM_NAME, -1);
- if (!mts_io_platform_device) {
- cleanup();
+ if (!mts_io_platform_device)
return -ENOMEM;
- }
/* request_firmware() requires a device, so call after device allocated */
ret = mts_id_eeprom_load();
if (ret) {
- cleanup();
+ kfree(mts_io_platform_device);
return ret;
}
ret = platform_device_add(mts_io_platform_device);
if (ret) {
- cleanup();
+ kfree(mts_io_platform_device);
return ret;
}
- if (DEVICE_CAPA(id_eeprom.capa, CAPA_DOUT)) {
- ret = spi_register_driver(&mts_spi_dout_driver);
- 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) {
- printk(KERN_ERR "mts-io:mts-io-din: probe failed: %d\n", ret);
- }
- }
- ret = spi_register_driver(&mts_spi_board_temp_driver);
- if (ret) {
- printk(KERN_ERR "mts-io:mts-io-board-temp: probe failed: %d\n", ret);
- }
-
if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) && attr_group_lora) {
mts_load_lora_port();
}
- ret = mts_capab_dir_create();
+ ret = mts_capab_dir_create(mts_hw_version);
if (ret) {
cleanup();
return ret;
@@ -1022,6 +1032,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();
@@ -1038,14 +1052,6 @@ static int __init mts_io_init(void)
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);
- }
- spi_unregister_driver(&mts_spi_board_temp_driver);
-
struct gpio_pin *pin;
/* delete radio_reset_timer */
del_timer(&radio_reset_timer);
diff --git a/io-module/mts_capab.c b/io-module/mts_capab.c
index 17c505a..38e8442 100644
--- a/io-module/mts_capab.c
+++ b/io-module/mts_capab.c
@@ -68,21 +68,34 @@ static struct attribute_group mts_capa_attr_group = {
};
static struct kobject *mts_capa_kobject = NULL;
+EXPORT_SYMBOL(mts_capa_kobject);
-static int mts_capab_dir_create(void)
+static int mts_capab_dir_create(uint8_t hw_version)
{
- mts_capa_kobject = kobject_create_and_add("capability", &mts_io_platform_device->dev.kobj);
- if (!mts_capa_kobject) {
- log_error("kobject_create_and_add for capability directory failed");
- return -ENOMEM;
- }
+ int i,j;
+
+ if (hw_version == MTCPM_0_0) {
+ for (i=0; mts_capa_attributes[i]; i++) {
+ /* Remove capa_lora for MTCPM mts-io driver */
+ if (mts_capa_attributes[i] == &capa_attr_lora.attr) {
+ for(j=i; mts_capa_attributes[j]; j++)
+ mts_capa_attributes[j] = mts_capa_attributes[j+1];
+ break;
+ }
+ }
+ }
+ mts_capa_kobject = kobject_create_and_add("capability", &mts_io_platform_device->dev.kobj);
+ if (!mts_capa_kobject) {
+ log_error("kobject_create_and_add for capability directory failed");
+ return -ENOMEM;
+ }
- if (sysfs_create_group(mts_capa_kobject, &mts_capa_attr_group)) {
- log_error("sysfs_create_group failed to create capability group");
- return -ENOMEM;
- }
+ if (sysfs_create_group(mts_capa_kobject, &mts_capa_attr_group)) {
+ log_error("sysfs_create_group failed to create capability group");
+ return -ENOMEM;
+ }
- return 0;
+ return 0;
}
static void mts_capab_dir_delete(void)
diff --git a/io-module/mts_io.h b/io-module/mts_io.h
index 5e83879..12647fb 100644
--- a/io-module/mts_io.h
+++ b/io-module/mts_io.h
@@ -49,6 +49,7 @@ struct gpio_pin {
uint8_t capability;
};
+extern int mts_has_radio(const char *product_id, size_t len);
#endif /* __MTS_IO_H */
diff --git a/io-module/mts_io_module.h b/io-module/mts_io_module.h
index 0e1b1d5..4fcd3a7 100644
--- a/io-module/mts_io_module.h
+++ b/io-module/mts_io_module.h
@@ -5,13 +5,13 @@
* MTAC cards.
*/
-#define DRIVER_VERSION "v4.1.4a"
+#define DRIVER_VERSION "v4.3.0a"
#define DRIVER_AUTHOR "Multitech Systems"
#define DRIVER_DESC "MTS-IO Controller"
#define DRIVER_NAME "mts-io"
#define DEBUG 0
-
+/* Atmel AT91 Platforms */
#define PRODUCT_ID_MTCDP_E1_DK "MTCDP-E1-DK"
#define PRODUCT_ID_MT100EOCG "MT100EOCG"
#define PRODUCT_ID_MTR "MTR"
@@ -41,6 +41,12 @@
#define HW_VERSION_MTHS_0_0 "MTHS-0.0"
#define HW_VERSION_MTHS_0_1 "MTHS-0.1"
+/* TI OMAP Platforms */
+#define PRODUCT_ID_MTCPM "MTCPM"
+
+#define HW_VERSION_MTCPM_DASH "MTCPM-"
+#define HW_VERSION_MTCPM_0_0 "MTCPM-0.0"
+
enum {
MTCDP_E1_DK_0_0,
MTCDP_E1_DK_1_0,
@@ -58,6 +64,7 @@ enum {
MTCAP_0_1,
MTHS_0_0,
MTHS_0_1,
+ MTCPM_0_0,
};
enum {
diff --git a/io-module/spi.c b/io-module/spi.c
deleted file mode 100644
index 1244cfc..0000000
--- a/io-module/spi.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/* SPI devices, functions, and attributes */
-
-static int ADT7302_to_celsius(int value)
-{
- if (value & 0x2000) {
- value = value - 16384;
- }
-
- value = value / 32 + 1 * ((value % 32) >= 16);
-
- return value;
-}
-
-/* SPI Devices */
-static struct spi_device *spi_sout_dev;
-static u8 spi_sout_value;
-static DEFINE_MUTEX(spi_sout_mutex);
-static unsigned int sout_max_speed_hz = 1 * 1000 * 1000;
-module_param(sout_max_speed_hz, uint, S_IRUGO);
-MODULE_PARM_DESC(
- sout_max_speed_hz,
- "Maximum clock rate to be used with this device (default: 1 MHz)"
-);
-
-static struct spi_device *spi_dout_dev;
-static u8 spi_dout_value;
-static DEFINE_MUTEX(spi_dout_mutex);
-static unsigned int dout_max_speed_hz = 1 * 1000 * 1000;
-module_param(dout_max_speed_hz, uint, S_IRUGO);
-MODULE_PARM_DESC(
- dout_max_speed_hz,
- "Maximum clock rate to be used with this device (default: 1 MHz)"
-);
-
-static struct spi_device *spi_din_dev;
-static unsigned int din_max_speed_hz = 1 * 1000 * 1000;
-module_param(din_max_speed_hz, uint, S_IRUGO);
-MODULE_PARM_DESC(
- din_max_speed_hz,
- "Maximum clock rate to be used with this device (default: 1 MHz)"
-);
-
-static struct spi_device *spi_board_temp_dev;
-static unsigned int board_temp_max_speed_hz = 1 * 1000 * 1000;
-module_param(board_temp_max_speed_hz, uint, S_IRUGO);
-MODULE_PARM_DESC(
- board_temp_max_speed_hz,
- "Maximum clock rate to be used with this device (default: 1 MHz)"
-);
-
-/* Generic SPI functions */
-static inline int spi_writen(struct spi_device *spi, const u8 *buf, size_t len)
-{
- int tmp;
- u8 *tx;
-
- tx = kmalloc(len, GFP_KERNEL);
- if (!tx) {
- return -ENOMEM;
- }
-
- memcpy(tx, buf, len);
- tmp = spi_write(spi, tx, len);
-
- kfree(tx);
-
- return tmp;
-}
-
-static inline int spi_readn(struct spi_device *spi, u8 *buf, size_t len)
-{
- int tmp;
- u8 *rx;
-
- rx = kmalloc(len, GFP_KERNEL);
- if (!rx) {
- return -ENOMEM;
- }
-
- tmp = spi_read(spi, rx, len);
- memcpy(buf, rx, len);
-
- kfree(rx);
-
- return tmp;
-}
-
-/* ----------------------------------------------------------------------------
- *
- * SPI-based attribute show/store functions
- *
- * ----------------------------------------------------------------------------
-*/
-
-#define SOUT_LED_CD_BIT BIT(0)
-#define SOUT_EXTSERIAL_RI_BIT BIT(1)
-#define SOUT_EXTSERIAL_DSR_BIT BIT(2)
-#define SOUT_LED_DTR BIT(3)
-#define SOUT_LED_SIG1_BIT BIT(4)
-#define SOUT_LED_SIG2_BIT BIT(5)
-#define SOUT_LED_SIG3_BIT BIT(6)
-#define SOUT_EXTSERIAL_DCD_BIT BIT(7)
-
-static ssize_t mts_attr_store_sout(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int value;
- u8 bit;
-
- if (!spi_sout_dev) {
- log_notice("sout device not present");
- return -ENODEV;
- }
-
- if (!strcmp(attr->attr.name, "extserial-ri")) {
- bit = SOUT_EXTSERIAL_RI_BIT;
- } else if (!strcmp(attr->attr.name, "extserial-dsr")) {
- bit = SOUT_EXTSERIAL_DSR_BIT;
- } else if (!strcmp(attr->attr.name, "extserial-dcd")) {
- bit = SOUT_EXTSERIAL_DCD_BIT;
- } else if (!strcmp(attr->attr.name, "led-cd") ||
- !strcmp(attr->attr.name, "led-sdk-b")) {
- bit = SOUT_LED_CD_BIT;
- } else if (!strcmp(attr->attr.name, "led-dtr") ||
- !strcmp(attr->attr.name, "led-sdk-f")) {
- bit = SOUT_LED_DTR;
- } else if (!strcmp(attr->attr.name, "led-sig1") ||
- !strcmp(attr->attr.name, "led-sdk-c")) {
- bit = SOUT_LED_SIG1_BIT;
- } else if (!strcmp(attr->attr.name, "led-sig2") ||
- !strcmp(attr->attr.name, "led-sdk-d")) {
- bit = SOUT_LED_SIG2_BIT;
- } else if (!strcmp(attr->attr.name, "led-sig3") ||
- !strcmp(attr->attr.name, "led-sdk-e")) {
- bit = SOUT_LED_SIG3_BIT;
- } else {
- log_notice("sout attr does not exist");
- return -ENOENT;
- }
-
- if (sscanf(buf, "%i", &value) != 1) {
- log_notice("sout attr invalid argument");
- return -EINVAL;
- }
-
- mutex_lock(&spi_sout_mutex);
-
- if (value) {
- spi_sout_value &= ~bit;
- } else {
- spi_sout_value |= bit;
- }
- spi_writen(spi_sout_dev, &spi_sout_value, 1);
-
- mutex_unlock(&spi_sout_mutex);
-
- return count;
-}
-
-static ssize_t mts_attr_show_sout(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int value;
- u8 bit;
-
- if (!spi_sout_dev) {
- log_error("sout device not present");
- return -ENODEV;
- }
-
- if (!strcmp(attr->attr.name, "extserial-ri")) {
- bit = SOUT_EXTSERIAL_RI_BIT;
- } else if (!strcmp(attr->attr.name, "extserial-dsr")) {
- bit = SOUT_EXTSERIAL_DSR_BIT;
- } else if (!strcmp(attr->attr.name, "extserial-dcd")) {
- bit = SOUT_EXTSERIAL_DCD_BIT;
- } else if (!strcmp(attr->attr.name, "led-cd") ||
- !strcmp(attr->attr.name, "led-sdk-b")) {
- bit = SOUT_LED_CD_BIT;
- } else if (!strcmp(attr->attr.name, "led-dtr") ||
- !strcmp(attr->attr.name, "led-sdk-f")) {
- bit = SOUT_LED_DTR;
- } else if (!strcmp(attr->attr.name, "led-sig1") ||
- !strcmp(attr->attr.name, "led-sdk-c")) {
- bit = SOUT_LED_SIG1_BIT;
- } else if (!strcmp(attr->attr.name, "led-sig2") ||
- !strcmp(attr->attr.name, "led-sdk-d")) {
- bit = SOUT_LED_SIG2_BIT;
- } else if (!strcmp(attr->attr.name, "led-sig3") ||
- !strcmp(attr->attr.name, "led-sdk-e")) {
- bit = SOUT_LED_SIG3_BIT;
- } else {
- log_notice("sout attr does not exist");
- return -ENOENT;
- }
-
- mutex_lock(&spi_sout_mutex);
-
- value = spi_sout_value & bit ? 0 : 1;
-
- mutex_unlock(&spi_sout_mutex);
-
- return sprintf(buf, "%d\n", value);
-}
-
-static ssize_t mts_attr_store_dout(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int value;
- u8 bit;
-
- if (!spi_dout_dev) {
- log_notice("dout device not present");
- return -ENODEV;
- }
-
- if ((!strcmp(attr->attr.name, "dout0")) || (!strcmp(attr->attr.name, "gpo1"))) {
- bit = BIT(0);
- } else if ((!strcmp(attr->attr.name, "dout1")) || (!strcmp(attr->attr.name, "gpo2"))) {
- bit = BIT(1);
- } else if ((!strcmp(attr->attr.name, "dout2")) || (!strcmp(attr->attr.name, "gpo3"))) {
- bit = BIT(2);
- } else if ((!strcmp(attr->attr.name, "dout3")) || (!strcmp(attr->attr.name, "gpo4"))) {
- bit = BIT(3);
- } else if ((!strcmp(attr->attr.name, "dout4")) || (!strcmp(attr->attr.name, "led1"))) {
- bit = BIT(4);
- } else if ((!strcmp(attr->attr.name, "dout5")) || (!strcmp(attr->attr.name, "led4"))) {
- bit = BIT(5);
- } else if ((!strcmp(attr->attr.name, "dout6")) || (!strcmp(attr->attr.name, "led5"))) {
- bit = BIT(6);
- } else if ((!strcmp(attr->attr.name, "dout7")) || (!strcmp(attr->attr.name, "led6"))) {
- bit = BIT(7);
- } else {
- log_notice("dout attr does not exist");
- return -ENOENT;
- }
-
- if (sscanf(buf, "%i", &value) != 1) {
- log_notice("dout attr invalid argument");
- return -EINVAL;
- }
-
- mutex_lock(&spi_dout_mutex);
-
- if (value) {
- spi_dout_value &= ~bit;
- } else {
- spi_dout_value |= bit;
- }
-
- spi_writen(spi_dout_dev, &spi_dout_value, 1);
-
- mutex_unlock(&spi_dout_mutex);
-
- return count;
-}
-
-static ssize_t mts_attr_show_dout(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int value;
- u8 bit;
-
- if (!spi_dout_dev) {
- log_error("dout device not present");
- return -ENODEV;
- }
-
- if ((!strcmp(attr->attr.name, "dout0")) || (!strcmp(attr->attr.name, "gpo1"))) {
- bit = BIT(0);
- } else if ((!strcmp(attr->attr.name, "dout1")) || (!strcmp(attr->attr.name, "gpo2"))) {
- bit = BIT(1);
- } else if ((!strcmp(attr->attr.name, "dout2")) || (!strcmp(attr->attr.name, "gpo3"))) {
- bit = BIT(2);
- } else if ((!strcmp(attr->attr.name, "dout3")) || (!strcmp(attr->attr.name, "gpo4"))) {
- bit = BIT(3);
- } else if ((!strcmp(attr->attr.name, "dout4")) || (!strcmp(attr->attr.name, "led1"))) {
- bit = BIT(4);
- } else if ((!strcmp(attr->attr.name, "dout5")) || (!strcmp(attr->attr.name, "led4"))) {
- bit = BIT(5);
- } else if ((!strcmp(attr->attr.name, "dout6")) || (!strcmp(attr->attr.name, "led5"))) {
- bit = BIT(6);
- } else if ((!strcmp(attr->attr.name, "dout7")) || (!strcmp(attr->attr.name, "led6"))) {
- bit = BIT(7);
- } else {
- log_notice("dout attr does not exist");
- return -ENOENT;
- }
-
- mutex_lock(&spi_dout_mutex);
-
- value = spi_dout_value & bit ? 0 : 1;
-
- mutex_unlock(&spi_dout_mutex);
-
- return sprintf(buf, "%d\n", value);
-}
-
-static ssize_t mts_attr_show_din(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int tmp;
- u8 bit;
- u8 byte;
-
- if (!spi_din_dev) {
- log_error("din device not present");
- return -ENODEV;
- }
-
- if ((!strcmp(attr->attr.name, "din0")) || (!strcmp(attr->attr.name, "gpi5"))) {
- bit = BIT(0);
- } else if ((!strcmp(attr->attr.name, "din1")) || (!strcmp(attr->attr.name, "gpi6"))) {
- bit = BIT(1);
- } else if ((!strcmp(attr->attr.name, "din2")) || (!strcmp(attr->attr.name, "gpi7"))) {
- bit = BIT(2);
- } else if ((!strcmp(attr->attr.name, "din3")) || (!strcmp(attr->attr.name, "gpi8"))) {
- bit = BIT(3);
- } else if ((!strcmp(attr->attr.name, "din4")) || (!strcmp(attr->attr.name, "gpi9"))) {
- bit = BIT(4);
- } else if ((!strcmp(attr->attr.name, "din5")) || (!strcmp(attr->attr.name, "gpi10"))) {
- bit = BIT(5);
- } else if (!strcmp(attr->attr.name, "din6")) {
- bit = BIT(6);
- } else if (!strcmp(attr->attr.name, "din7")) {
- bit = BIT(7);
- } else {
- log_notice("din attr does not exist");
- return -ENOENT;
- }
-
- tmp = spi_readn(spi_din_dev, &byte, 1);
- if (tmp) {
- log_error("spi_read failed %d", tmp);
- return tmp;
- }
-
- tmp = byte & bit ? 1 : 0;
-
- return sprintf(buf, "%d\n", tmp);
-}
-
-static ssize_t mts_attr_show_board_temperature(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int tmp;
- u16 temp_raw;
-
- if (!spi_board_temp_dev) {
- log_notice("spi_board_temp device not present");
- return -ENODEV;
- }
-
- tmp = spi_readn(spi_board_temp_dev, (u8 *) buf, 2);
- if (tmp) {
- log_error("spi_readn failed %d", tmp);
- return tmp;
- }
- temp_raw = ((u8 *) buf)[0] << 8 | ((u8 *) buf)[1];
-
- log_debug("temp: 0x%04X", temp_raw);
-
- return sprintf(buf, "%d\n", ADT7302_to_celsius(temp_raw));
-}
-
-/* ----------------------------------------------------------------------------
- *
- * SPI-based attributes
- *
- * ----------------------------------------------------------------------------
-*/
-
-static DEVICE_ATTR_RO_MTS(dev_attr_board_temperature, "board-temperature",
- mts_attr_show_board_temperature);
-
-static DEVICE_ATTR_MTS(dev_attr_extserial_dcd, "extserial-dcd",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_extserial_ri, "extserial-ri",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_extserial_dsr, "extserial-dsr",
- mts_attr_show_sout, mts_attr_store_sout);
-
-static DEVICE_ATTR_MTS(dev_attr_led_cd, "led-cd",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sdk_b, "led-sdk-b",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sig1, "led-sig1",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sdk_c, "led-sdk-c",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sig2, "led-sig2",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sdk_d, "led-sdk-d",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sig3, "led-sig3",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sdk_e, "led-sdk-e",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_dtr, "led-dtr",
- mts_attr_show_sout, mts_attr_store_sout);
-static DEVICE_ATTR_MTS(dev_attr_led_sdk_f, "led-sdk-f",
- mts_attr_show_sout, mts_attr_store_sout);
-
-static DEVICE_ATTR_MTS(dev_attr_dout0, "dout0",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout1, "dout1",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout2, "dout2",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout3, "dout3",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout4, "dout4",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout5, "dout5",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout6, "dout6",
- mts_attr_show_dout, mts_attr_store_dout);
-static DEVICE_ATTR_MTS(dev_attr_dout7, "dout7",
- mts_attr_show_dout, mts_attr_store_dout);
-
-static DEVICE_ATTR_RO_MTS(dev_attr_din0, "din0", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din1, "din1", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din2, "din2", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din3, "din3", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din4, "din4", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din5, "din5", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din6, "din6", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_din7, "din7", mts_attr_show_din);
-
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi5, "gpi5", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi6, "gpi6", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi7, "gpi7", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi8, "gpi8", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi9, "gpi9", mts_attr_show_din);
-static DEVICE_ATTR_RO_MTS(dev_attr_gpi10, "gpi10", mts_attr_show_din);
-
-/* SPI driver setup */
-static int mts_spi_sout_probe(struct spi_device *spi)
-{
- int tmp;
-
- spi->max_speed_hz = sout_max_speed_hz;
- spi->mode = 0;
-
- log_debug("sout_max_speed_hz: %d", sout_max_speed_hz);
-
- tmp = spi_setup(spi);
- if (tmp < 0) {
- log_error("spi_setup sout failed");
- return tmp;
- }
-
- spi_sout_value = 0xFF;
- spi_writen(spi, &spi_sout_value, 1);
-
- spi_sout_dev = spi;
-
- return 0;
-}
-
-static int mts_spi_sout_remove(struct spi_device *spi)
-{
- spi_sout_dev = NULL;
-
- return 0;
-}
-
-static struct spi_driver mts_spi_sout_driver = {
- .driver = {
- .name = "mts-io-sout",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = mts_spi_sout_probe,
- .remove = mts_spi_sout_remove,
-};
-
-static int mts_spi_dout_probe(struct spi_device *spi)
-{
- int tmp;
-
- spi->max_speed_hz = dout_max_speed_hz;
- spi->mode = 0;
-
- log_debug("dout_max_speed_hz: %d", dout_max_speed_hz);
-
- tmp = spi_setup(spi);
- if (tmp < 0) {
- log_error("spi_setup dout failed");
- return tmp;
- }
-
- spi_dout_value = 0x00;
- spi_writen(spi, &spi_dout_value, 1);
-
- spi_dout_dev = spi;
-
- return 0;
-}
-
-static int mts_spi_dout_remove(struct spi_device *spi)
-{
- spi_dout_dev = NULL;
-
- return 0;
-}
-
-static struct spi_driver mts_spi_dout_driver = {
- .driver = {
- .name = "mts-io-dout",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = mts_spi_dout_probe,
- .remove = mts_spi_dout_remove,
-};
-
-static int mts_spi_din_probe(struct spi_device *spi)
-{
- int tmp;
- spi->max_speed_hz = din_max_speed_hz;
- spi->mode = SPI_CPOL;
-
- log_debug("din_max_speed_hz: %d", din_max_speed_hz);
-
- tmp = spi_setup(spi);
- if (tmp < 0) {
- log_error("spi_setup din failed");
- return tmp;
- }
-
- spi_din_dev = spi;
-
- return 0;
-}
-
-static int mts_spi_din_remove(struct spi_device *spi)
-{
- spi_din_dev = NULL;
-
- return 0;
-}
-
-static struct spi_driver mts_spi_din_driver = {
- .driver = {
- .name = "mts-io-din",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = mts_spi_din_probe,
- .remove = mts_spi_din_remove,
-};
-
-static int mts_spi_board_temp_probe(struct spi_device *spi)
-{
- int tmp;
-
- spi->max_speed_hz = board_temp_max_speed_hz;
- spi->mode = SPI_CPOL | SPI_CPHA;
-
- log_debug("board_temp_max_speed_hz: %d", board_temp_max_speed_hz);
-
- tmp = spi_setup(spi);
- if (tmp < 0) {
- log_error("spi_setup board-temp failed");
- return tmp;
- }
-
- spi_board_temp_dev = spi;
-
- return 0;
-}
-
-static int mts_spi_board_temp_remove(struct spi_device *spi)
-{
- spi_board_temp_dev = NULL;
-
- return 0;
-}
-
-static struct spi_driver mts_spi_board_temp_driver = {
- .driver = {
- .name = "mts-io-board-temp",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = mts_spi_board_temp_probe,
- .remove = mts_spi_board_temp_remove,
-};