From c3ae43430ccf0cf92a4fa2d4bcf0024b53dbac7a Mon Sep 17 00:00:00 2001
From: Mykyta Dorokhin <mykyta.dorokhin@globallogic.com>
Date: Wed, 2 Nov 2016 17:04:34 +0200
Subject: feat: expose on-board lora attributes oveer lora/ subdirectory

---
 io-module/mtcap.c    | 163 +++++++++++++++------------------------------------
 io-module/mts_io.c   |  57 +++++++++++++-----
 io-module/mts_lora.c | 114 +++++++++++++++++++++++++++++++++++
 3 files changed, 205 insertions(+), 129 deletions(-)
 create mode 100644 io-module/mts_lora.c

(limited to 'io-module')

diff --git a/io-module/mtcap.c b/io-module/mtcap.c
index e651406..d86c5a6 100644
--- a/io-module/mtcap.c
+++ b/io-module/mtcap.c
@@ -45,24 +45,27 @@ static struct gpio_pin gpio_pins_mtcap_0_0[] = {
 		.pin = {
 			.gpio = AT91_PIN_PA8, // LORA_RST
 			.flags = GPIOF_OUT_INIT_LOW,
-			.label = "lora-reset",
+			.label = "lora/reset",
 		},
+		.capability = CAPA_LORA,
 	},
 	{  // gpio 1 for LORA 1.5 ref design
 		.name = "LORA_CDONE",
 		.pin = {
 			.gpio = AT91_PIN_PA6,
 			.flags = GPIOF_IN,
-			.label = "lora-cdone",
+			.label = "lora/cdone",
 		},
+		.capability = CAPA_LORA,
 	},
 	{  // gpio 2 for LORA 1.5 ref design
 		.name = "LORA_CRESET",
 		.pin = {
 			.gpio = AT91_PIN_PA29,
 			.flags = GPIOF_OUT_INIT_HIGH,
-			.label = "lora-creset",
-		}
+			.label = "lora/creset",
+		},
+		.capability = CAPA_LORA,
 	},
 
 
@@ -357,123 +360,20 @@ static ssize_t mts_attr_show_radio_power_mtcap(struct device *dev,
 	return sprintf(buf, "%d\n", value);
 }
 
-static int lora_reset_mtcap(void)
-{
-	struct gpio_pin *rst_pin = gpio_pin_by_attr_name("lora-reset");
-
-	if (!rst_pin) {
-		return -ENODEV;
-	}
-
-	/*
-	 * drive the reset pin low, set pin high for 100ns, drive pin low
-	 */
-	gpio_set_value(rst_pin->pin.gpio, 0);
-
-	gpio_set_value(rst_pin->pin.gpio, 1);
-
-	msleep(1);
-
-	gpio_set_value(rst_pin->pin.gpio, 0);
-
-	msleep(100);
-
-	return 0;
-}
-
-static ssize_t mts_attr_store_lora_reset_mtcap(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;
-	}
-
-	log_info("performing lora reset");
-
-	mutex_lock(&mts_io_mutex);
-
-	err = lora_reset_mtcap();
-
-	mutex_unlock(&mts_io_mutex);
-
-	if (err) {
-		return err;
-	}
-
-	return count;
-}
-
-static int eth_reset_mtcap(void)
-{
-	struct gpio_pin *rst_pin = gpio_pin_by_attr_name("eth-reset");
-
-	if (!rst_pin) {
-		return -ENODEV;
-	}
-
-	/*
-	 * DS00002275A (09-15-16) KSZ8091MNX/RNB DATA SHEET:
-	 * 		For warm reset, the reset (RST#) pin should be asserted low for a minimum of 500 μs.
-	 */
-	gpio_set_value(rst_pin->pin.gpio, 0);
-
-	msleep(2);
-
-	gpio_set_value(rst_pin->pin.gpio, 1);
-
-	msleep(1);
-
-	return 0;
-}
-
-static ssize_t mts_attr_store_eth_reset_mtcap(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;
-	}
-
-	log_info("performing eth reset");
-
-	mutex_lock(&mts_io_mutex);
-
-	err = eth_reset_mtcap();
-
-	mutex_unlock(&mts_io_mutex);
-
-	if (err) {
-		return err;
-	}
-
-	return count;
-}
-
 static DEVICE_ATTR_MTS(dev_attr_radio_reset_mtcap, "radio-reset",
-	mts_attr_show_gpio_pin, mts_attr_store_radio_reset_mtcap);
+		mts_attr_show_gpio_pin, mts_attr_store_radio_reset_mtcap);
 
 static DEVICE_ATTR_MTS(dev_attr_radio_power_mtcap, "radio-power",
 		mts_attr_show_radio_power_mtcap, mts_attr_store_radio_power_mtcap);
 
-static DEVICE_ATTR_MTS(dev_attr_lora_reset_mtcap, "lora-reset",
-		mts_attr_show_gpio_pin, mts_attr_store_lora_reset_mtcap);
-
 static DEVICE_ATTR_MTS(dev_attr_eth_reset_mtcap, "eth-reset",
-		mts_attr_show_gpio_pin, mts_attr_store_eth_reset_mtcap);
+		mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
 
 static DEVICE_ATTR_MTS(dev_attr_led_lora_gpio_mtcap, "led-lora",
-	mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
+		mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
 
 static DEVICE_ATTR_MTS(dev_attr_led_wifi_gpio_mtcap, "led-wifi",
-	mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
-
-static DEVICE_ATTR_RO_MTS(dev_attr_lora_eui, "lora-eui",
-	mts_attr_show_product_info);
+		mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);
 
 static struct attribute *mtcap_0_0_platform_attributes[] = {
 		&dev_attr_vendor_id.attr,
@@ -489,8 +389,6 @@ static struct attribute *mtcap_0_0_platform_attributes[] = {
 
 		&dev_attr_eth_reset_mtcap.attr,
 
-		&dev_attr_lora_reset_mtcap.attr,
-
 		&dev_attr_radio_power_mtcap.attr,
 		&dev_attr_radio_reset_mtcap.attr,
 
@@ -503,11 +401,46 @@ static struct attribute *mtcap_0_0_platform_attributes[] = {
 		&dev_attr_led_lora_gpio_mtcap.attr,
 		&dev_attr_led_wifi_gpio_mtcap.attr,
 
-		&dev_attr_lora_eui.attr,
-
 		NULL,
 };
 
 static struct attribute_group mtcap_0_0_platform_attribute_group = {
 	.attrs = mtcap_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_mtcap, "reset",
+		mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_cdone_mtcap, "cdone",
+		mts_attr_show_lora_gpio_pin);
+
+static DEVICE_ATTR_MTS(dev_attr_lora_creset_mtcap, "creset",
+		mts_attr_show_lora_gpio_pin, mts_attr_store_lora_gpio_pin);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_eui_mtcap, "eui",
+		mts_attr_show_lora_product_info);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_product_id_mtcap, "product-id",
+		mts_attr_show_lora_product_info);
+
+static DEVICE_ATTR_RO_MTS(dev_attr_lora_hw_version_mtcap, "hw-version",
+		mts_attr_show_lora_product_info);
+
+static struct attribute *mtcap_0_0_lora_attributes[] = {
+		&dev_attr_lora_eui_mtcap.attr,
+		&dev_attr_lora_product_id_mtcap.attr,
+		&dev_attr_lora_hw_version_mtcap.attr,
+		&dev_attr_lora_reset_mtcap.attr,
+		&dev_attr_lora_cdone_mtcap.attr,
+		&dev_attr_lora_creset_mtcap.attr,
+		NULL,
+};
+
+static struct attribute_group mtcap_0_0_lora_attribute_group = {
+	.attrs = mtcap_0_0_lora_attributes
+};
diff --git a/io-module/mts_io.c b/io-module/mts_io.c
index 547f099..f1f8cb6 100644
--- a/io-module/mts_io.c
+++ b/io-module/mts_io.c
@@ -47,7 +47,7 @@
 
 #include "mts_io.h"
 
-#define DRIVER_VERSION	"v1.5.0"
+#define DRIVER_VERSION	"v1.5.1"
 #define DRIVER_AUTHOR	"James Maki <jmaki@multitech.com>"
 #define DRIVER_DESC	"MTS-IO Controller"
 #define DRIVER_NAME	"mts-io"
@@ -77,6 +77,7 @@ static struct mts_id_eeprom_layout id_eeprom;
 static uint8_t mts_hw_version;
 static struct platform_device *mts_io_platform_device;
 static struct attribute_group *attr_group;
+static struct attribute_group *attr_group_lora; // on-board lora peripheral to be stored in the lora/ sub-directory
 static struct gpio_pin *gpio_pins;
 
 static DEFINE_MUTEX(mts_io_mutex);
@@ -633,10 +634,14 @@ static DEVICE_ATTR_RO_MTS(dev_attr_imei, "imei",
 static DEVICE_ATTR_RO_MTS(dev_attr_eth_mac, "mac-eth",
 	mts_attr_show_product_info);
 
+/* include on-board lora peripheral */
+#include "mts_lora.c"
+
 /* include per-device pins and attributes */
 #include "mtcdt.c"
 #include "mtcap.c"
 
+
 #if NUM_AP > 0
 
 /* accessory card EEPROMs */
@@ -765,6 +770,25 @@ static void init_accessory_ports(void) {}
 static void teardown_accessory_ports(void) {}
 #endif
 
+static void init_ports(void)
+{
+	if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) && attr_group_lora) {
+		mts_load_lora_port();
+	}
+
+	init_accessory_ports();
+}
+
+static void teardown_ports(void)
+{
+	if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) && attr_group_lora) {
+		mts_teardown_lora_port();
+	}
+
+	teardown_accessory_ports();
+}
+
+
 struct attribute *freelater = NULL; // Storage to free when driver is unloaded.
 
 static int mts_id_eeprom_load()
@@ -789,6 +813,9 @@ static int mts_id_eeprom_load()
 	} else if (strncmp(id_eeprom.hw_version, HW_VERSION_MTCAP_0_0, strlen(HW_VERSION_MTCAP_0_0)) == 0)  {
 		attr_group = &mtcap_0_0_platform_attribute_group;
 		gpio_pins = gpio_pins_mtcap_0_0;
+		if (DEVICE_CAPA(id_eeprom.capa, CAPA_LORA)) {
+			attr_group_lora = &mtcap_0_0_lora_attribute_group;
+		}
 		mts_hw_version = MTCAP_0_0;
 		log_info("detected board %s", HW_VERSION_MTCAP_0_0);
 	}
@@ -851,6 +878,7 @@ static int mts_id_eeprom_load()
 	log_info("capa-bluetooth: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_BLUETOOTH) ? "yes" : "no");
 	log_info("capa-wifi-bluetooth: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_WIFI_BT) ? "yes" : "no");
 	log_info("capa-gnss: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_GNSS) ? "yes" : "no");
+	log_info("capa-lora: %s", DEVICE_CAPA(id_eeprom.capa, CAPA_LORA) ? "yes" : "no");
 
 	if (DEVICE_CAPA(id_eeprom.capa, CAPA_BLUETOOTH)) {
 		log_info("mac-bluetooth: %02X:%02X:%02X:%02X:%02X:%02X",
@@ -877,17 +905,18 @@ static int mts_id_eeprom_load()
 	}
 	log_info("uuid: %s", (char*)buf);
 
-	if (mts_hw_version == MTCAP_0_0) {
-		log_info("lora-eui: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
-			id_eeprom.lora_eui[0],
-			id_eeprom.lora_eui[1],
-			id_eeprom.lora_eui[2],
-			id_eeprom.lora_eui[3],
-			id_eeprom.lora_eui[4],
-			id_eeprom.lora_eui[5],
-			id_eeprom.lora_eui[6],
-			id_eeprom.lora_eui[7]);
-	}
+	log_info("lora-eui: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X",
+		id_eeprom.lora_eui[0],
+		id_eeprom.lora_eui[1],
+		id_eeprom.lora_eui[2],
+		id_eeprom.lora_eui[3],
+		id_eeprom.lora_eui[4],
+		id_eeprom.lora_eui[5],
+		id_eeprom.lora_eui[6],
+		id_eeprom.lora_eui[7]);
+
+	log_info("lora-product-id: %.32s",  id_eeprom.lora_product_id);
+	log_info("lora-hw-version: %.32s", id_eeprom.lora_hw_version);
 
 	return 0;
 }
@@ -899,7 +928,7 @@ static void cleanup(void)
 		platform_device_unregister(mts_io_platform_device);
 	}
 
-	teardown_accessory_ports();
+	teardown_ports();
 	if(freelater) {
 		kfree(freelater);
 		freelater = NULL;
@@ -933,7 +962,7 @@ static int __init mts_io_init(void)
 		return ret;
 	}
 
-	init_accessory_ports();
+	init_ports();
 
 	ret = sysfs_create_group(&mts_io_platform_device->dev.kobj, attr_group);
 	if (ret) {
diff --git a/io-module/mts_lora.c b/io-module/mts_lora.c
new file mode 100644
index 0000000..7b7e204
--- /dev/null
+++ b/io-module/mts_lora.c
@@ -0,0 +1,114 @@
+static struct kobject *mts_lora_kobject;
+
+static void mts_load_lora_port(void)
+{
+	// create lora/ subdir
+	mts_lora_kobject = kobject_create_and_add("lora", &mts_io_platform_device->dev.kobj);
+
+	if (sysfs_create_group(mts_lora_kobject, attr_group_lora)) {
+		log_error("failed to create lora attributes");
+	}
+}
+
+static void	mts_teardown_lora_port(void)
+{
+	// clean up "lora/" kobject if it exists
+	if (mts_lora_kobject) {
+		kobject_put(mts_lora_kobject);
+	}
+}
+
+static ssize_t mts_attr_show_lora_product_info(struct kobject *kobj,
+			struct kobj_attribute *attr, char *buf)
+{
+	ssize_t value;
+
+	char label[32];
+	snprintf(label, sizeof label, "%s/%s", kobj->name, attr->attr.name);
+
+	if (strcmp(label, "lora/eui") == 0) {
+			value = sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
+				id_eeprom.lora_eui[0],
+				id_eeprom.lora_eui[1],
+				id_eeprom.lora_eui[2],
+				id_eeprom.lora_eui[3],
+				id_eeprom.lora_eui[4],
+				id_eeprom.lora_eui[5],
+				id_eeprom.lora_eui[6],
+				id_eeprom.lora_eui[7]);
+	}
+	else if (strcmp(label, "lora/product-id") == 0) {
+		value = sprintf(buf, "%.32s\n", id_eeprom.lora_product_id);
+	}
+	else if (strcmp(label, "lora/hw-version") == 0) {
+		value = sprintf(buf, "%.32s\n", id_eeprom.lora_hw_version);
+	}
+	else {
+		log_error("attribute '%s' not found", label);
+		value = -1;
+	}
+	return value;
+}
+
+static ssize_t mts_attr_show_lora_gpio_pin(struct kobject *kobj,
+			struct kobj_attribute *attr,
+			char *buf)
+{
+	int value;
+	struct gpio_pin *pin;
+
+	char pin_label[32];
+	snprintf(pin_label, sizeof pin_label, "%s/%s", kobj->name, attr->attr.name); // ex. lora/reset
+
+	pin = gpio_pin_by_attr_name(pin_label);
+	if (!pin) {
+		return -ENODEV;
+	}
+
+	mutex_lock(&mts_io_mutex);
+
+	value = gpio_get_value(pin->pin.gpio);
+
+	mutex_unlock(&mts_io_mutex);
+
+	if (value < 0) {
+		return value;
+	}
+
+	if (pin->active_low) {
+		value = !value;
+	}
+
+	return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t mts_attr_store_lora_gpio_pin(struct kobject *kobj,
+		struct kobj_attribute *attr, const char *buf, size_t count)
+{
+	int value;
+	struct gpio_pin *pin;
+	char pin_label[32];
+
+	snprintf(pin_label, sizeof pin_label, "%s/%s", kobj->name, attr->attr.name); // ex. lora/reset
+
+	pin = gpio_pin_by_attr_name(pin_label);
+	if (!pin) {
+		return -ENODEV;
+	}
+
+	if (sscanf(buf, "%i", &value) != 1) {
+		return -EINVAL;
+	}
+
+	if (pin->active_low) {
+		value = !value;
+	}
+
+	mutex_lock(&mts_io_mutex);
+
+	gpio_set_value(pin->pin.gpio, value);
+
+	mutex_unlock(&mts_io_mutex);
+
+	return count;
+}
-- 
cgit v1.2.3