diff options
| -rw-r--r-- | io-module/at91gpio.h | 36 | ||||
| -rw-r--r-- | io-module/buttons.h | 1 | ||||
| -rw-r--r-- | io-module/gpio.c | 16 | ||||
| -rw-r--r-- | io-module/machine/mtcdt.c | 290 | ||||
| -rw-r--r-- | io-module/mts-io.c | 66 | ||||
| -rw-r--r-- | io-module/mts_io.h | 1 | ||||
| -rw-r--r-- | io-module/mts_io_module.h | 6 | ||||
| -rw-r--r-- | io-module/radio_udev_discovery.c | 1 | ||||
| -rw-r--r-- | io-module/version.h | 9 | 
9 files changed, 418 insertions, 8 deletions
| diff --git a/io-module/at91gpio.h b/io-module/at91gpio.h index c2f8a77..f9b527d 100644 --- a/io-module/at91gpio.h +++ b/io-module/at91gpio.h @@ -179,4 +179,40 @@  #define	AT91_PIN_PE30	(0x80 + 30)  #define	AT91_PIN_PE31	(0x80 + 31) +/* MTCDT-0.2 I2C I/O Port expanders + * ARCH_NR_GPIOS is set to 512 in + * gpio.h if it is not set in + * the kernel configuration with + * CONFIG_ARCH_NR_GPIO.  If that number + * ever chnages, the BASE integer will + * change as well.  512 - 8 = 504 */ +#define PCA9557_0_BASE  504  // i2c address 0x18 +#define PCA9557_0_IO0	(PCA9557_0_BASE + 0) +#define PCA9557_0_IO1	(PCA9557_0_BASE + 1) +#define PCA9557_0_IO2	(PCA9557_0_BASE + 2) +#define PCA9557_0_IO3	(PCA9557_0_BASE + 3) +#define PCA9557_0_IO4	(PCA9557_0_BASE + 4) +#define PCA9557_0_IO5	(PCA9557_0_BASE + 5) +#define PCA9557_0_IO6	(PCA9557_0_BASE + 6) +#define PCA9557_0_IO7	(PCA9557_0_BASE + 7) + +/* This value depends on order of discovery. + * This controller has a higher address on + * the I2C bus and the pins are assigned + * in the order of discovery from highest + * to lowest pin numbers. + * + * GPIO numbers can be verified by + * examining /sys/kernel/debug/gpio. + */ +#define PCA9557_1_BASE  496  // i2c address 0x19 +#define PCA9557_1_IO0	(PCA9557_1_BASE + 0) +#define PCA9557_1_IO1	(PCA9557_1_BASE + 1) +#define PCA9557_1_IO2	(PCA9557_1_BASE + 2) +#define PCA9557_1_IO3	(PCA9557_1_BASE + 3) +#define PCA9557_1_IO4	(PCA9557_1_BASE + 4) +#define PCA9557_1_IO5	(PCA9557_1_BASE + 5) +#define PCA9557_1_IO6	(PCA9557_1_BASE + 6) +#define PCA9557_1_IO7	(PCA9557_1_BASE + 7) +  #endif diff --git a/io-module/buttons.h b/io-module/buttons.h index ef80f34..d7ce8bd 100644 --- a/io-module/buttons.h +++ b/io-module/buttons.h @@ -34,6 +34,7 @@  #include "mts_io_module.h"  #include "mts_io.h" +#include "version.h"  #define BUTTON_CHECK_PER_SEC        8  #define BUTTON_INTERVAL             (HZ / BUTTON_CHECK_PER_SEC) diff --git a/io-module/gpio.c b/io-module/gpio.c index 0b45300..e754ed6 100644 --- a/io-module/gpio.c +++ b/io-module/gpio.c @@ -44,6 +44,14 @@ struct gpio_pin *gpio_pin_by_attr_name(const char *name) {  	return NULL;  } +/* Any gpio that could potentially get routed over an i2c bus + * as opposed to a memory write to a register must call + * "cansleep" versions of gpio functions.  The purpose of the + * function is to remind kernel driver writers that any GPIO + * routed over i2c (or spi) cannot be accessed in an interrupt + * handler. Interrupt handlers should use the GPIO pins + * that are memory mapped. gpio_get_value and gpio_set_value + * cannot be used with the PCA 9557 or a dump will result. */  ssize_t mts_attr_show_gpio_pin(struct device *dev,  			struct device_attribute *attr,  			char *buf) @@ -57,7 +65,7 @@ ssize_t mts_attr_show_gpio_pin(struct device *dev,  	mutex_lock(&mts_io_mutex); -	value = gpio_get_value(pin->pin.gpio); +	value = gpio_get_value_cansleep(pin->pin.gpio);  	mutex_unlock(&mts_io_mutex); @@ -92,7 +100,7 @@ static ssize_t mts_attr_store_gpio_pin(struct device *dev,  	mutex_lock(&mts_io_mutex); -	gpio_set_value(pin->pin.gpio, value); +	gpio_set_value_cansleep(pin->pin.gpio, value);  	mutex_unlock(&mts_io_mutex); @@ -105,11 +113,11 @@ static int reset_gpio_pin(struct gpio_pin *pin, unsigned int delay_ms, unsigned  		return -ENODEV;  	} -	gpio_set_value(pin->pin.gpio, value); +	gpio_set_value_cansleep(pin->pin.gpio, value);  	mdelay(delay_ms); -	gpio_set_value(pin->pin.gpio, !value); +	gpio_set_value_cansleep(pin->pin.gpio, !value);  	return 0;  } diff --git a/io-module/machine/mtcdt.c b/io-module/machine/mtcdt.c index b753a9e..f8b5f0b 100644 --- a/io-module/machine/mtcdt.c +++ b/io-module/machine/mtcdt.c @@ -351,6 +351,235 @@ static struct gpio_pin gpio_pins_mtcdt_0_1[] = {  	{ },  }; +// MTCDT-0.2, Schematic Rev L dated 8 Nov 2021. +static struct gpio_pin gpio_pins_mtcdt_0_2[] = { +	{ +		.name = "RADIO_RESET", +		.pin = { +			.gpio = AT91_PIN_PC3, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "radio-reset", +		}, +	}, +	{ +		.name = "RADIO_RESET", +		.pin = { +			.gpio = AT91_PIN_PC3, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "radio-power", +		}, +	}, +	{ +		.name = "RADIO_STATUS", +		.pin = { +			.gpio = PCA9557_0_IO2, +			.flags = GPIOF_IN, +			.label = "radio-status", +		}, +	}, +	{ +		.name = "DEVICE_RESET", +		.pin = { +			.gpio = AT91_PIN_PC2, +			.flags = GPIOF_IN, +			.label = "reset", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LS_LED", /* LED7 */ +		.pin = { +			.gpio = AT91_PIN_PA14, +#if LED_LS_CONTROLLABLE +			.flags = GPIOF_OUT_INIT_HIGH, +#else +			.flags = GPIOF_IN, +#endif +			.label = "led-ls", +		}, +		.active_low = 1, +	}, +	{ +		.name = "STATUS_LED", /* LED2 */ +		.pin = { +			.gpio = AT91_PIN_PA24, +			.flags = GPIOF_OUT_INIT_LOW, +			.label = "led-status", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED5", +		.pin = { +			.gpio = PCA9557_1_IO0, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-cd", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED5", +		.pin = { +			.gpio = PCA9557_1_IO0, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-a", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED1", +		.pin = { +			.gpio = PCA9557_1_IO1, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-sig1", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED1", +		.pin = { +			.gpio = PCA9557_1_IO1, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-b", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED4", +		.pin = { +			.gpio = PCA9557_1_IO2, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-sig2", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED4", +		.pin = { +			.gpio = PCA9557_1_IO2, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-c", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED3", +		.pin = { +			.gpio = PCA9557_0_IO0, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-sig3", +		}, +		.active_low = 1, +	}, +	{ +		.name = "LED3", +		.pin = { +			.gpio = PCA9557_0_IO0, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "led-d", +		}, +		.active_low = 1, +	}, +	{ +		.name = "ETH_RESET", +		.pin = { +				.gpio = AT91_PIN_PC4, +				.flags = GPIOF_OUT_INIT_HIGH, +				.label = "eth-reset", +		} +	}, +	{ +		.name = "WIFI_BT_ULPWKUP", +		.pin = { +			.gpio = AT91_PIN_PA0, +			.flags = GPIOF_IN, +			.label = "wifi-bt-ulpwkup", +		}, +		.capability = CAPA_WIFI, +	}, +	{ +		.name = "WIFI_BT_LPWKUP", +		.pin = { +			.gpio = PCA9557_0_IO1, +			.flags = GPIOF_IN, +			.label = "wifi-bt-lpwkup", +		}, +		.capability = CAPA_WIFI, +	}, +	{ +		.name = "WIFI_BT_INT", +		.pin = { +			.gpio = AT91_PIN_PB11, +			.flags = GPIOF_IN, +			.label = "wifi-bt-int", +		}, +		.capability = CAPA_WIFI, +	}, +	{ +		.name = "WIFI_BT_RESET", +		.pin = { +			.gpio = AT91_PIN_PD14, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "wifi-bt-reset", +		}, +		.capability = CAPA_WIFI, +	}, +	{ +		.name = "GNSS_RESET", +		.pin = { +			.gpio = AT91_PIN_PD15, +			.flags = GPIOF_OUT_INIT_LOW, /* Keep GPS quiet during boot for EXAR */ +			.label = "gnss-reset", +		}, +		.capability = CAPA_GPS, +	}, +	{ +		.name = "SECURE_RESET", +		.pin = { +			.gpio = AT91_PIN_PD16, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "secure-reset", +		} +	}, +	{ +		.name = "MTQ_RESET", +		.pin = { +			.gpio = AT91_PIN_PD17, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "mtq-reset", +		} +	}, +	{ +		.name = "USBHUB_RESET", +		.pin = { +			.gpio = AT91_PIN_PD18, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "usbhub-reset", +		} +	}, +	{ +		.name = "GNSS_INT", +		.pin = { +			.gpio = AT91_PIN_PD19, +			.flags = GPIOF_OUT_INIT_HIGH, +			.label = "gnss-int", +		}, +		.capability = CAPA_GPS, +	}, +	{ +		.name = "WIFI_BT_LPMODE", +		.pin = { +			.gpio = AT91_PIN_PD20, +			.flags = GPIOF_IN, +			.label = "wifi-bt-lpmode", +		}, +		.capability = CAPA_WIFI, +	}, +	{ }, +}; + + +  static DEVICE_ATTR_MTS(dev_attr_wifi_bt_lpwkup, "wifi-bt-lpwkup",  	mts_attr_show_gpio_pin, mts_attr_store_gpio_pin);  static DEVICE_ATTR_MTS(dev_attr_wifi_bt_ulpwkup, "wifi-bt-ulpwkup", @@ -373,6 +602,8 @@ 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 DEVICE_ATTR_RO_MTS(dev_attr_radio_status, "radio-status", +	mts_attr_show_gpio_pin);  static struct attribute *mtcdt_platform_attributes[] = {  	&dev_attr_vendor_id.attr, @@ -456,6 +687,47 @@ static struct attribute *mtcdt_0_1_platform_attributes[] = {  	NULL,  }; +static struct attribute *mtcdt_0_2_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_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_led_a_gpio.attr, +	&dev_attr_led_b_gpio.attr, +	&dev_attr_led_c_gpio.attr, +	&dev_attr_led_d_gpio.attr, + +	&dev_attr_usbhub_reset.attr, +	&dev_attr_eth_reset.attr, +         +    &dev_attr_radio_power.attr,  /* Must be first radio attribute */ +	&dev_attr_radio_reset.attr, +	&dev_attr_radio_status.attr, + +	&dev_attr_radio_reset_backoffs.attr, +	&dev_attr_radio_reset_backoff_index.attr, +	&dev_attr_radio_reset_backoff_seconds.attr, + +	// UDEV notification of radio discovery +	&dev_attr_radio_udev_discovery.attr, +	&dev_attr_radio_reset_monitor.attr, +	NULL, +}; +  static struct attribute *mtcdt_0_1_wifi_bt_attributes[] = {  		&dev_attr_wifi_bt_lpwkup.attr,  		&dev_attr_wifi_bt_ulpwkup.attr, @@ -466,11 +738,25 @@ static struct attribute *mtcdt_0_1_wifi_bt_attributes[] = {                  &dev_attr_wifi_mac.attr,  }; +static struct attribute *mtcdt_0_2_wifi_bt_attributes[] = { +		&dev_attr_wifi_bt_lpwkup.attr, +		&dev_attr_wifi_bt_ulpwkup.attr, +		&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[] = {  		&dev_attr_gnss_reset.attr,  		&dev_attr_gnss_int.attr,  }; +static struct attribute *mtcdt_0_2_gnss_attributes[] = { +		&dev_attr_gnss_reset.attr, +		&dev_attr_gnss_int.attr, +};  static struct attribute_group mtcdt_platform_attribute_group = {  	.attrs = mtcdt_platform_attributes @@ -480,6 +766,10 @@ static struct attribute_group mtcdt_0_1_platform_attribute_group = {  }; +static struct attribute_group mtcdt_0_2_platform_attribute_group = { +	.attrs = mtcdt_0_2_platform_attributes +}; +  static int   is_radio_power_attr_mtcdt(struct attribute *attr)  { diff --git a/io-module/mts-io.c b/io-module/mts-io.c index ed0cb49..8b1fbec 100644 --- a/io-module/mts-io.c +++ b/io-module/mts-io.c @@ -46,6 +46,7 @@  #include "at91gpio.h"  #include "mts_io_module.h" +#include "version.h"  #include "mts_io.h"  #include "buttons.h"  #include "mts_supercap.h" @@ -80,6 +81,13 @@ MODULE_DEVICE_TABLE(of, mts_io_dt_ids);  /* on-board EEPROM */  static struct mts_id_eeprom_layout id_eeprom; +// Allow other modules to query the hardware version +const char *mts_get_hw_version(void) +{ +    return id_eeprom.hw_version; +} +EXPORT_SYMBOL(mts_get_hw_version); +  #include "adc.c"  static int mts_io_probe(struct platform_device *pdev) @@ -544,6 +552,9 @@ static DEVICE_ATTR_MTS(dev_attr_led_d_gpio, "led-d",  static DEVICE_ATTR_MTS(dev_attr_led_e_gpio, "led-e",  	mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); + + +  /* eeprom info */  static ssize_t mts_attr_show_product_info(struct device *dev,  			struct device_attribute *attr, @@ -962,6 +973,61 @@ mts_id_eeprom_load(void)  		gpio_pins = gpio_pins_mtcdt_0_1;  		set_buttons(default_buttons);                  log_info("detected board %s", tmp); +        } else if ((tmp=HW_VERSION_MTCDT_0_2),(mts_hw_version=MTCDT_0_2),strncmp(id_eeprom.hw_version, tmp, strlen(tmp)) == 0) { +                need_append = 0; +                current_blength = attr_blength = sizeof  mtcdt_0_2_platform_attributes; +                current_blength -= sizeof(struct attribute *);  /* Length without terminating NULL */ + +                /* See if we have no radio, and if so, prune out the stuff that follows */ +                if(noradio) { +                    struct attribute **ap = mtcdt_0_2_platform_attribute_group.attrs; +                    while(1) { +                        if(ap[j] == NULL) { +                            log_info("Did not find radio power attribute.  Possible driver fault."); +                            break; +                        } +                        j++; +                        if (is_radio_power_attr_mtcdt(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_WIFI)) { +			attr_blength += sizeof mtcdt_0_2_wifi_bt_attributes; +                        need_append = 1; +		} +		if(DEVICE_CAPA(id_eeprom.capa, CAPA_GPS)) { +			attr_blength += sizeof mtcdt_0_2_gnss_attributes; +                        need_append = 1; +		} +		if (need_append) { +			freelater = all_attrs = kmalloc(attr_blength,GFP_KERNEL); +			current_count = current_blength/(sizeof (struct attribute *)); +			memcpy(all_attrs,mtcdt_0_2_platform_attributes,current_blength); +			if(DEVICE_CAPA(id_eeprom.capa, CAPA_WIFI)) { +				log_info("Adding WiFi/BT to mts-io driver"); +				memcpy(all_attrs + current_count,mtcdt_0_2_wifi_bt_attributes,sizeof mtcdt_0_2_wifi_bt_attributes); +				current_count += sizeof mtcdt_0_2_wifi_bt_attributes / (sizeof  (struct attribute *)); +			} +			if(DEVICE_CAPA(id_eeprom.capa, CAPA_GPS)) { +				log_info("Adding GPS to mts-io driver"); +				attr_blength += sizeof mtcdt_0_2_gnss_attributes; +				memcpy(all_attrs + current_count,mtcdt_0_2_gnss_attributes,sizeof mtcdt_0_2_gnss_attributes); +				current_count += sizeof mtcdt_0_2_gnss_attributes / (sizeof  (struct attribute *)); +			} +			all_attrs[current_count] = (struct attribute *)NULL; +			mtcdt_0_2_platform_attribute_group.attrs = all_attrs; +		} + +		attr_group = &mtcdt_0_2_platform_attribute_group; +		gpio_pins = gpio_pins_mtcdt_0_2; +		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) {                  need_append = 0;                  current_blength = attr_blength = sizeof  mtcdt_0_1_platform_attributes; diff --git a/io-module/mts_io.h b/io-module/mts_io.h index 2c4b7b6..4f46804 100644 --- a/io-module/mts_io.h +++ b/io-module/mts_io.h @@ -50,6 +50,7 @@ struct gpio_pin {  };  extern int mts_has_radio(const char *product_id, size_t len); +extern const char *mts_get_hw_version(void);  #endif /* __MTS_IO_H */ diff --git a/io-module/mts_io_module.h b/io-module/mts_io_module.h index eca15a3..4eb0ff0 100644 --- a/io-module/mts_io_module.h +++ b/io-module/mts_io_module.h @@ -5,10 +5,6 @@   * MTAC cards.   */ -#define DRIVER_VERSION  "v4.7.2" -#define DRIVER_AUTHOR   "Multitech Systems" -#define DRIVER_DESC "MTS-IO Controller" -#define DRIVER_NAME "mts-io"  #define DEBUG		0  /* Atmel AT91 Platforms */ @@ -36,6 +32,7 @@  #define HW_VERSION_MTRE				"MTRE-0.0"  #define HW_VERSION_MTCDT_0_0			"MTCDT-0.0"  // No GPS or WiFi Capability  #define HW_VERSION_MTCDT_0_1			"MTCDT-0.1"  // Conduit refresh with GPS and WiFi possible +#define HW_VERSION_MTCDT_0_2			"MTCDT-0.2"  // Atmel Serial and PCA9557  #define HW_VERSION_MTCDTIP_0_0			"MTCDTIP-0.0"  #define HW_VERSION_MTCDTIPHP_0_0		"MTCDTIPHP-0.0" // Also known as LoRa 2.1  #define HW_VERSION_MTCAP_0_0			"MTCAP-0.0" @@ -81,6 +78,7 @@ enum {  	MTCPM_0_0,  	MTCPM_0_1,      MTCAP3_0_0, +	MTCDT_0_2,  };  /* Commented because it is not used. Сonflicts with <linux/leds.h> */ diff --git a/io-module/radio_udev_discovery.c b/io-module/radio_udev_discovery.c index 3a557ca..6e322b1 100644 --- a/io-module/radio_udev_discovery.c +++ b/io-module/radio_udev_discovery.c @@ -7,6 +7,7 @@  #include <linux/signalfd.h>  #endif  #include "mts_io_module.h" +#include "version.h"  #include "radio_udev_discovery.h"  /* diff --git a/io-module/version.h b/io-module/version.h new file mode 100644 index 0000000..fff0a7a --- /dev/null +++ b/io-module/version.h @@ -0,0 +1,9 @@ +#ifndef __VERSION_H +#define __VERSION_H + +#define DRIVER_VERSION  "v4.8.0" +#define DRIVER_AUTHOR   "Multitech Systems" +#define DRIVER_DESC "MTS-IO Controller" +#define DRIVER_NAME "mts-io" + +#endif | 
