diff options
author | Jesse Gilles <jgilles@multitech.com> | 2014-05-16 16:43:44 -0500 |
---|---|---|
committer | Jesse Gilles <jgilles@multitech.com> | 2014-05-16 16:43:44 -0500 |
commit | 9cf9a09c665ecfb6425a08e424b01c8cacbdb660 (patch) | |
tree | 4ca4e88e9e53076086610846e863c505e0d48674 /io-module | |
parent | fb0cddc68ee95d61cd2af4889b18bf3d6ddd01d2 (diff) | |
download | mts-io-9cf9a09c665ecfb6425a08e424b01c8cacbdb660.tar.gz mts-io-9cf9a09c665ecfb6425a08e424b01c8cacbdb660.tar.bz2 mts-io-9cf9a09c665ecfb6425a08e424b01c8cacbdb660.zip |
Major changes to split sources up
* moved common peripheral i/o functions to separate source files
* moved device-specific setup to separate source files
* removed LED blink functionality (unused)
* mtcdp, mt100eocg are not supported, but code is included for possible future use
Diffstat (limited to 'io-module')
-rw-r--r-- | io-module/adc.c | 87 | ||||
-rw-r--r-- | io-module/gpio.c | 83 | ||||
-rw-r--r-- | io-module/mt100eocg.c | 221 | ||||
-rw-r--r-- | io-module/mtcdp.c | 310 | ||||
-rw-r--r-- | io-module/mtr.c | 468 | ||||
-rw-r--r-- | io-module/mtr2.c | 515 | ||||
-rw-r--r-- | io-module/mts_io.c | 3140 | ||||
-rw-r--r-- | io-module/mts_io.h | 19 | ||||
-rw-r--r-- | io-module/spi.c | 767 | ||||
-rw-r--r-- | io-module/telit_radio.c | 219 |
10 files changed, 2773 insertions, 3056 deletions
diff --git a/io-module/adc.c b/io-module/adc.c new file mode 100644 index 0000000..bcb3598 --- /dev/null +++ b/io-module/adc.c @@ -0,0 +1,87 @@ + +#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); diff --git a/io-module/gpio.c b/io-module/gpio.c new file mode 100644 index 0000000..72c55f6 --- /dev/null +++ b/io-module/gpio.c @@ -0,0 +1,83 @@ + +struct gpio_pin *gpio_pin_by_name(const char *name) { + struct gpio_pin *pin; + + for (pin = gpio_pins; *pin->name; pin++) { + if (!strcmp(pin->name, name)) { + return pin; + } + } + + log_error("pin named %s not found", name); + + return NULL; +} + +struct gpio_pin *gpio_pin_by_attr_name(const char *name) { + struct gpio_pin *pin; + + for (pin = gpio_pins; *pin->name; pin++) { + if (!strcmp(pin->pin.label, name)) { + return pin; + } + } + + log_error("pin with attr name %s not found", name); + + return NULL; +} + +static ssize_t mts_attr_show_gpio_pin(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int value; + struct gpio_pin *pin = gpio_pin_by_attr_name(attr->attr.name); + + 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_gpio_pin(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int value; + struct gpio_pin *pin = gpio_pin_by_attr_name(attr->attr.name); + + 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; +} diff --git a/io-module/mt100eocg.c b/io-module/mt100eocg.c new file mode 100644 index 0000000..8d2338d --- /dev/null +++ b/io-module/mt100eocg.c @@ -0,0 +1,221 @@ + +static struct gpio_pin gpio_pins_mt100eocg_0_0[] = { + { + .name = "ENIO", + .pin = AT91_PIN_PC15, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "ETH0_ENABLED", + .attr_name = "eth0-enabled", + .pin = AT91_PIN_PB31, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "RADIO_RESET", + .attr_name = "radio-reset", + .pin = AT91_PIN_PB30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "DEVICE_RESET", + .attr_name = "reset", + .pin = AT91_PIN_PA22, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "LED3", + .attr_name = "led3", + .pin = AT91_PIN_PC9, +#if LED_LS_CONTROLLABLE + .direction = GPIO_DIR_OUTPUT, +#else + .direction = GPIO_DIR_INPUT, +#endif + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "LED2", + .attr_name = "led2", + .pin = AT91_PIN_PA30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "RSERSRC", + .attr_name = "rsersrc", + .pin = AT91_PIN_PC7, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "TXD1", + .pin = AT91_PIN_PB17, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "DTR1", + .attr_name = "extserial-dtr", + .pin = AT91_PIN_PB18, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "DCD1", + .attr_name = "extserial-dcd", + .pin = AT91_PIN_PB3, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "GPIO11", + .attr_name = "gpio11", + .pin = AT91_PIN_PB19, + .direction = GPIO_DIR_OD, + .output_value = 1, + .use_pullup = 1, + }, + { + .name = "GPIO12", + .attr_name = "gpio12", + .pin = AT91_PIN_PB20, + .direction = GPIO_DIR_OD, + .output_value = 1, + .use_pullup = 1, + }, + { + .name = "ADC0", + .pin = AT91_PIN_PC0, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC1", + .pin = AT91_PIN_PC1, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC2", + .pin = AT91_PIN_PC2, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC3", + .pin = AT91_PIN_PC3, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { }, +}; + +/* mt100eocg specific attributes */ +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_extserial_dtr.attr, + &dev_attr_extserial_dcd_gpio.attr, + &dev_attr_rsersrc.attr, + &dev_attr_radio_reset.attr, + &dev_attr_eth0_enabled.attr, + &dev_attr_gpio11.attr, + &dev_attr_gpio12.attr, + + &dev_attr_gpo1.attr, + &dev_attr_gpo2.attr, + &dev_attr_gpo3.attr, + &dev_attr_gpo4.attr, + &dev_attr_led1.attr, + &dev_attr_led2.attr, + &dev_attr_led3.attr, + &dev_attr_led4.attr, + &dev_attr_led5.attr, + &dev_attr_led6.attr, + + &dev_attr_gpi5.attr, + &dev_attr_gpi6.attr, + &dev_attr_gpi7.attr, + &dev_attr_gpi8.attr, + &dev_attr_gpi9.attr, + &dev_attr_gpi10.attr, + + &dev_attr_board_temperature.attr, + + &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/mtcdp.c b/io-module/mtcdp.c new file mode 100644 index 0000000..31551b0 --- /dev/null +++ b/io-module/mtcdp.c @@ -0,0 +1,310 @@ + +#define USBH2_PS_CONTROLLABLE 0 + +static struct gpio_pin gpio_pins_mtcdp_0_0[] = { + { + .name = "ENIO", + .pin = AT91_PIN_PC15, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "ETH0_ENABLED", + .attr_name = "eth0-enabled", + .pin = AT91_PIN_PB31, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "RADIO_RESET", + .attr_name = "radio-reset", + .pin = AT91_PIN_PB30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "DEVICE_RESET", + .attr_name = "reset", + .pin = AT91_PIN_PA22, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "LS_LED", + .attr_name = "led-ls", + .pin = AT91_PIN_PC9, +#if LED_LS_CONTROLLABLE + .direction = GPIO_DIR_OUTPUT, +#else + .direction = GPIO_DIR_INPUT, +#endif + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .attr_name = "led-status", + .pin = AT91_PIN_PA30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "STATUS_LED", + .attr_name = "led-sdk-a", + .pin = AT91_PIN_PA30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, +#endif + { + .name = "RSERSRC", + .attr_name = "rsersrc", + .pin = AT91_PIN_PC7, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "DTR1", + .attr_name = "extserial-dtr", + .pin = AT91_PIN_PC10, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { }, +}; + +static struct gpio_pin gpio_pins_mtcdp_1_0[] = { + { + .name = "ENIO", + .pin = AT91_PIN_PC15, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "ETH0_ENABLED", + .attr_name = "eth0-enabled", + .pin = AT91_PIN_PB31, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "RADIO_RESET", + .attr_name = "radio-reset", + .pin = AT91_PIN_PB30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "DEVICE_RESET", + .attr_name = "reset", + .pin = AT91_PIN_PA22, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "LS_LED", + .attr_name = "led-ls", + .pin = AT91_PIN_PC9, +#if LED_LS_CONTROLLABLE + .direction = GPIO_DIR_OUTPUT, +#else + .direction = GPIO_DIR_INPUT, +#endif + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .attr_name = "led-status", + .pin = AT91_PIN_PA30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "STATUS_LED", + .attr_name = "led-sdk-a", + .pin = AT91_PIN_PA30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "RSERSRC", + .attr_name = "rsersrc", + .pin = AT91_PIN_PC7, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "TXD1", + .pin = AT91_PIN_PB17, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "DTR1", + .attr_name = "extserial-dtr", + .pin = AT91_PIN_PB18, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, + { + .name = "USBH2_PS_OC", + .attr_name = "usbh2-ps-oc", + .pin = AT91_PIN_PB19, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, +#if USBH2_PS_CONTROLLABLE + { + .name = "USBH2_PS_ENABLED", + .attr_name = "usbh2-ps-enabled", + .pin = AT91_PIN_PB20, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + .active_low = 1, + }, +#endif + { + .name = "NDC_RESET", + .attr_name = "ndc-reset", + .pin = AT91_PIN_PB21, + .direction = GPIO_DIR_OUTPUT, + .output_value = 1, + .use_pullup = 0, + }, + { + .name = "ADC0", + .pin = AT91_PIN_PC0, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC1", + .pin = AT91_PIN_PC1, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC2", + .pin = AT91_PIN_PC2, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "ADC3", + .pin = AT91_PIN_PC3, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { }, +}; + +/* mtcdp specific attributes */ +static DEVICE_ATTR_MTS(dev_attr_led_sdk_a, "led-sdk-a", + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_RO_MTS(dev_attr_usbh2_ps_oc, "usbh2-ps-oc", + mts_attr_show_gpio_pin); + +#if USBH2_PS_CONTROLLABLE +static DEVICE_ATTR_MTS(dev_attr_usbh2_ps_enabled, "usbh2-ps-enabled", + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +#endif + +static struct attribute *mtcdp_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_reset.attr, + &dev_attr_reset_monitor.attr, + &dev_attr_radio_reset.attr, + &dev_attr_ndc_reset.attr, + &dev_attr_eth0_enabled.attr, + &dev_attr_extserial_dtr.attr, + &dev_attr_led_ls.attr, + &dev_attr_led_status.attr, + &dev_attr_led_sdk_a.attr, + &dev_attr_usbh2_ps_oc.attr, +#if USBH2_PS_CONTROLLABLE + &dev_attr_usbh2_ps_enabled.attr, +#endif + + &dev_attr_extserial_dcd.attr, + &dev_attr_extserial_ri.attr, + &dev_attr_extserial_dsr.attr, + &dev_attr_led_cd.attr, + &dev_attr_led_sdk_b.attr, + &dev_attr_led_sig1.attr, + &dev_attr_led_sdk_c.attr, + &dev_attr_led_sig2.attr, + &dev_attr_led_sdk_d.attr, + &dev_attr_led_sig3.attr, + &dev_attr_led_sdk_e.attr, + &dev_attr_led_dtr.attr, + &dev_attr_led_sdk_f.attr, + + &dev_attr_dout0.attr, + &dev_attr_dout1.attr, + &dev_attr_dout2.attr, + &dev_attr_dout3.attr, + &dev_attr_dout4.attr, + &dev_attr_dout5.attr, + &dev_attr_dout6.attr, + &dev_attr_dout7.attr, + + &dev_attr_din0.attr, + &dev_attr_din1.attr, + &dev_attr_din2.attr, + &dev_attr_din3.attr, + &dev_attr_din4.attr, + &dev_attr_din5.attr, + &dev_attr_din6.attr, + &dev_attr_din7.attr, + + &dev_attr_board_temperature.attr, + + &dev_attr_adc0.attr, + &dev_attr_adc1.attr, + &dev_attr_adc2.attr, + &dev_attr_adc3.attr, + + NULL, +}; + +static struct attribute_group mtcdp_platform_attribute_group = { + .attrs = mtcdp_platform_attributes +}; diff --git a/io-module/mtr.c b/io-module/mtr.c new file mode 100644 index 0000000..cef1560 --- /dev/null +++ b/io-module/mtr.c @@ -0,0 +1,468 @@ + +static struct gpio_pin gpio_pins_mtr_0_0[] = { + { + .name = "NETH_RST", + .pin = { + .gpio = AT91_PIN_PC6, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "eth0-enabled", + }, + }, + { + .name = "PWRMON", + .pin = { + .gpio = AT91_PIN_PA23, + .flags = GPIOF_IN, + .label = "radio-power", + }, + }, + { + .name = "3G_RST", + .pin = { + .gpio = AT91_PIN_PA22, + .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, + .label = "radio-reset", + }, + }, + { + .name = "3G_ONOFF", + .pin = { + .gpio = AT91_PIN_PA21, + .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, + .label = "radio-enabled", + }, + }, + { + .name = "DEVICE_RESET", + .pin = { + .gpio = AT91_PIN_PC4, + .flags = GPIOF_IN, + .label = "reset", + }, + .active_low = 1, + }, + { + .name = "LS_LED", + .pin = { + .gpio = AT91_PIN_PC16, +#if LED_LS_CONTROLLABLE + .flags = GPIOF_OUT_INIT_HIGH, +#else + .flags = GPIOF_IN, +#endif + .label = "led-ls", + }, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .pin = { + .gpio = AT91_PIN_PC21, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led-status", + }, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .pin = { + .gpio = AT91_PIN_PC21, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led-a", + }, + .active_low = 1, + }, + { + .name = "LED3", + .pin = { + .gpio = AT91_PIN_PC15, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-wifi", + }, + .active_low = 1, + }, + { + .name = "LED3", + .pin = { + .gpio = AT91_PIN_PC15, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-b", + }, + .active_low = 1, + }, + { + .name = "LED4", + .pin = { + .gpio = AT91_PIN_PC20, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-cd", + }, + .active_low = 1, + }, + { + .name = "LED4", + .pin = { + .gpio = AT91_PIN_PC20, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-c", + }, + .active_low = 1, + }, + { + .name = "LED6", + .pin = { + .gpio = AT91_PIN_PC19, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig1", + }, + .active_low = 1, + }, + { + .name = "LED6", + .pin = { + .gpio = AT91_PIN_PC19, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-d", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PC18, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig2", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PC18, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-e", + }, + .active_low = 1, + }, + { + .name = "LED8", + .pin = { + .gpio = AT91_PIN_PC17, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig3", + }, + .active_low = 1, + }, + { + .name = "LED8", + .pin = { + .gpio = AT91_PIN_PC17, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-f", + }, + .active_low = 1, + }, + { + .name = "RI_B", + .pin = { + .gpio = AT91_PIN_PC25, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-ri", + }, + .active_low = 1, + }, + { + .name = "DTR_B", + .pin = { + .gpio = AT91_PIN_PC26, + .flags = GPIOF_IN, + .label = "extserial-dtr", + }, + .active_low = 1, + }, + { + .name = "DSR_B", + .pin = { + .gpio = AT91_PIN_PC27, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dsr", + }, + .active_low = 1, + }, + { + .name = "DCD_B", + .pin = { + .gpio = AT91_PIN_PC28, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dcd", + }, + .active_low = 1, + }, + { + .name = "BT_EN", + .pin = { + .gpio = AT91_PIN_PA28, + .flags = GPIOF_OUT_INIT_LOW, + .label = "bt-enabled", + }, + }, + { + .name = "WLAN_EN", + .pin = { + .gpio = AT91_PIN_PA27, + .flags = GPIOF_OUT_INIT_LOW, + .label = "wlan-enabled", + }, + }, + { }, +}; + +static struct gpio_pin gpio_pins_mtr_0_1[] = { + { + .name = "NETH_RST", + .pin = { + .gpio = AT91_PIN_PC6, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "eth0-enabled", + }, + }, + { + .name = "PWRMON", + .pin = { + .gpio = AT91_PIN_PA23, + .flags = GPIOF_IN, + .label = "radio-power", + }, + }, + { + .name = "3G_RST", + .pin = { + .gpio = AT91_PIN_PA22, + .flags = GPIOF_OUT_INIT_HIGH | GPIOF_PULLUP, + .label = "radio-reset", + }, + }, + { + .name = "3G_ONOFF", + .pin = { + .gpio = AT91_PIN_PA21, + .flags = GPIOF_OUT_INIT_HIGH | GPIOF_PULLUP, + .label = "radio-enabled", + }, + }, + { + .name = "DEVICE_RESET", + .pin = { + .gpio = AT91_PIN_PC4, + .flags = GPIOF_IN, + .label = "reset", + }, + .active_low = 1, + }, + { + .name = "LS_LED", + .pin = { + .gpio = AT91_PIN_PC16, +#if LED_LS_CONTROLLABLE + .flags = GPIOF_OUT_INIT_HIGH, +#else + .flags = GPIOF_IN, +#endif + .label = "led-ls", + }, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .pin = { + .gpio = AT91_PIN_PC21, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led-status", + }, + .active_low = 1, + }, + { + .name = "LED3", + .pin = { + .gpio = AT91_PIN_PC15, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-wifi", + }, + .active_low = 1, + }, + { + .name = "LED3", + .pin = { + .gpio = AT91_PIN_PC15, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-b", + }, + .active_low = 1, + }, + { + .name = "LED4", + .pin = { + .gpio = AT91_PIN_PC20, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-cd", + }, + .active_low = 1, + }, + { + .name = "LED4", + .pin = { + .gpio = AT91_PIN_PC20, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-c", + }, + .active_low = 1, + }, + { + .name = "LED6", + .pin = { + .gpio = AT91_PIN_PC19, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig1", + }, + .active_low = 1, + }, + { + .name = "LED6", + .pin = { + .gpio = AT91_PIN_PC19, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-d", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PC18, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig2", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PC18, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-e", + }, + .active_low = 1, + }, + { + .name = "LED8", + .pin = { + .gpio = AT91_PIN_PC17, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig3", + }, + .active_low = 1, + }, + { + .name = "LED8", + .pin = { + .gpio = AT91_PIN_PC17, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-f", + }, + .active_low = 1, + }, + { + .name = "RI_B", + .pin = { + .gpio = AT91_PIN_PC25, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-ri", + }, + .active_low = 1, + }, + { + .name = "DTR_B", + .pin = { + .gpio = AT91_PIN_PC26, + .flags = GPIOF_IN, + .label = "extserial-dtr", + }, + .active_low = 1, + }, + { + .name = "DSR_B", + .pin = { + .gpio = AT91_PIN_PC27, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dsr", + }, + .active_low = 1, + }, + { + .name = "DCD_B", + .pin = { + .gpio = AT91_PIN_PC28, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dcd", + }, + .active_low = 1, + }, + { + .name = "BT_EN", + .pin = { + .gpio = AT91_PIN_PA28, + .flags = GPIOF_OUT_INIT_LOW, + .label = "bt-enabled", + }, + }, + { + .name = "WLAN_EN", + .pin = { + .gpio = AT91_PIN_PA27, + .flags = GPIOF_OUT_INIT_LOW, + .label = "wlan-enabled", + }, + }, + { }, +}; + +static struct attribute *mtr_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_wifi_mac.attr, + &dev_attr_reset.attr, + &dev_attr_reset_monitor.attr, + &dev_attr_radio_power_telit.attr, + &dev_attr_radio_reset_telit.attr, + &dev_attr_extserial_ri_gpio.attr, + &dev_attr_extserial_dtr.attr, + &dev_attr_extserial_dsr_gpio.attr, + &dev_attr_extserial_dcd_gpio.attr, + &dev_attr_eth0_enabled.attr, + &dev_attr_bt_enabled.attr, + &dev_attr_wlan_enabled.attr, + + &dev_attr_led_status.attr, + &dev_attr_led_sig1_gpio.attr, + &dev_attr_led_sig2_gpio.attr, + &dev_attr_led_sig3_gpio.attr, + &dev_attr_led_cd_gpio.attr, + &dev_attr_led_wifi_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_led_e_gpio.attr, + &dev_attr_led_f_gpio.attr, + + NULL, +}; + +static struct attribute_group mtr_platform_attribute_group = { + .attrs = mtr_platform_attributes +}; diff --git a/io-module/mtr2.c b/io-module/mtr2.c new file mode 100644 index 0000000..2efc85d --- /dev/null +++ b/io-module/mtr2.c @@ -0,0 +1,515 @@ + +static struct gpio_pin gpio_pins_mtr2_0_0[] = { + { + .name = "NETH_RST", + .pin = { + .gpio = AT91_PIN_PC6, + .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, + .label = "eth-switch-enabled", + }, + }, + { + .name = "RADIO_RESET", + .pin = { + .gpio = AT91_PIN_PC5, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "radio-reset", + }, + }, + { + .name = "RADIO_RESET", + .pin = { + .gpio = AT91_PIN_PC5, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "radio-power", + }, + }, + { + .name = "DEVICE_RESET", + .pin = { + .gpio = AT91_PIN_PC4, + .flags = GPIOF_IN, + .label = "reset", + }, + .active_low = 1, + }, + { + .name = "LS_LED", + .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", + .pin = { + .gpio = AT91_PIN_PA24, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led-status", + }, + .active_low = 1, + }, + { + .name = "STATUS_LED", + .pin = { + .gpio = AT91_PIN_PA24, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led-a", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PA25, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-cd", + }, + .active_low = 1, + }, + { + .name = "LED7", + .pin = { + .gpio = AT91_PIN_PA25, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-c", + }, + .active_low = 1, + }, + { + .name = "LED10", + .pin = { + .gpio = AT91_PIN_PA26, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig1", + }, + .active_low = 1, + }, + { + .name = "LED10", + .pin = { + .gpio = AT91_PIN_PA26, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-d", + }, + .active_low = 1, + }, + { + .name = "LED11", + .pin = { + .gpio = AT91_PIN_PA27, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig2", + }, + .active_low = 1, + }, + { + .name = "LED11", + .pin = { + .gpio = AT91_PIN_PA27, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-e", + }, + .active_low = 1, + }, + { + .name = "LED12", + .pin = { + .gpio = AT91_PIN_PA28, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-sig3", + }, + .active_low = 1, + }, + { + .name = "LED12", + .pin = { + .gpio = AT91_PIN_PA28, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-f", + }, + .active_low = 1, + }, + { + .name = "LED13", + .pin = { + .gpio = AT91_PIN_PA29, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-wifi", + }, + .active_low = 1, + }, + { + .name = "LED13", + .pin = { + .gpio = AT91_PIN_PA29, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "led-b", + }, + .active_low = 1, + }, + { + .name = "UART3_DTR", + .pin = { + .gpio = AT91_PIN_PC12, + .flags = GPIOF_IN, + .label = "extserial-dtr", + }, + .active_low = 1, + }, + { + .name = "UART3_DSR", + .pin = { + .gpio = AT91_PIN_PC11, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dsr", + }, + .active_low = 1, + }, + { + .name = "UART3_DCD", + .pin = { + .gpio = AT91_PIN_PC10, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-dcd", + }, + .active_low = 1, + }, + { + .name = "UART3_RI", + .pin = { + .gpio = AT91_PIN_PC13, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "extserial-ri", + }, + .active_low = 1, + }, + { + .name = "NDC_RESET", + .pin = { + .gpio = AT91_PIN_PC3, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "ndc-reset", + }, + }, + { + .name = "NDC_EEPROM_WRITE_PROTECT", + .pin = { + .gpio = AT91_PIN_PC26, + .flags = GPIOF_OUT_INIT_LOW, + .label = "ndc-eeprom-wp", + }, + }, + { + .name = "BT_EN", + .pin = { + .gpio = AT91_PIN_PD21, + .flags = GPIOF_OUT_INIT_LOW, + .label = "bt-enabled", + }, + }, + { + .name = "WLAN_EN", + .pin = { + .gpio = AT91_PIN_PC1, + .flags = GPIOF_OUT_INIT_LOW, + .label = "wlan-enabled", + }, + }, + { + .name = "SERIAL_MODE0", + .pin = { + .gpio = AT91_PIN_PC23, + .flags = GPIOF_OUT_INIT_LOW, + .label = "serial-mode", + }, + }, + { + .name = "SERIAL_MODE1", + .pin = { + .gpio = AT91_PIN_PC24, + .flags = GPIOF_OUT_INIT_LOW, + .label = "serial-mode", + }, + }, + { + .name = "SERIAL_MODE2", + .pin = { + .gpio = AT91_PIN_PC25, + .flags = GPIOF_OUT_INIT_LOW, + .label = "serial-mode", + }, + }, + { + .name = "RS4XX_TERM_RES", + .pin = { + .gpio = AT91_PIN_PC26, + .flags = GPIOF_OUT_INIT_LOW, + .label = "rs4xx-term-res", + }, + }, + { + .name = "NDC_GPIO1", + .pin = { + .gpio = AT91_PIN_PC0, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dc-gpio1", + }, + }, + { + .name = "NDC_GPIO2", + .pin = { + .gpio = AT91_PIN_PC14, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dc-gpio2", + }, + }, + { + .name = "NDC_GPIO3", + .pin = { + .gpio = AT91_PIN_PC29, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dc-gpio3", + }, + }, + { + .name = "NDC_GPIO4", + .pin = { + .gpio = AT91_PIN_PC30, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dc-gpio4", + }, + }, + { + .name = "NDC_INTERRUPT1", + .pin = { + .gpio = AT91_PIN_PC20, + .flags = GPIOF_IN, + .label = "dc-int1", + }, + }, + { + .name = "NDC_INTERRUPT2", + .pin = { + .gpio = AT91_PIN_PC21, + .flags = GPIOF_IN, + .label = "dc-int2", + }, + }, + { }, +}; + +/* MTOCGD2 specific functions */ +static ssize_t mts_attr_show_serial_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int ret; + int smode0; + int smode1; + int smode2; + + struct gpio_pin *pin_smode0 = gpio_pin_by_name("SERIAL_MODE0"); + struct gpio_pin *pin_smode1 = gpio_pin_by_name("SERIAL_MODE1"); + struct gpio_pin *pin_smode2 = gpio_pin_by_name("SERIAL_MODE2"); + + if (!pin_smode0 || !pin_smode1 || !pin_smode2) + return -ENODEV; + + mutex_lock(&mts_io_mutex); + + smode0 = gpio_get_value(pin_smode0->pin.gpio); + smode1 = gpio_get_value(pin_smode1->pin.gpio); + smode2 = gpio_get_value(pin_smode2->pin.gpio); + + if (smode2 == 0 && smode1 == 0 && smode0 == 1) + ret = sprintf(buf, "rs232\n"); + else if (smode2 == 0 && smode1 == 1 && smode0 == 0) + ret = sprintf(buf, "rs485\n"); + else if (smode2 == 1 && smode1 == 0 && smode0 == 0) + ret = sprintf(buf, "rs422\n"); + else if (smode2 == 0 && smode1 == 0 && smode0 == 0) + ret = sprintf(buf, "loopback\n"); + else + ret = sprintf(buf, "error\n"); + + mutex_unlock(&mts_io_mutex); + + return ret; +} + +static ssize_t mts_attr_store_serial_mode(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int smode0; + int smode1; + int smode2; + struct gpio_pin *pin_smode0 = gpio_pin_by_name("SERIAL_MODE0"); + struct gpio_pin *pin_smode1 = gpio_pin_by_name("SERIAL_MODE1"); + struct gpio_pin *pin_smode2 = gpio_pin_by_name("SERIAL_MODE2"); + + if (!pin_smode0 || !pin_smode1 || !pin_smode2) + return -ENODEV; + + if (!strcasecmp(buf, "rs232")) { + smode2 = 0; + smode1 = 0; + smode0 = 1; + } + else if (!strcasecmp(buf, "rs485")) { + smode2 = 0; + smode1 = 1; + smode0 = 0; + } + else if (!strcasecmp(buf, "rs422")) { + smode2 = 1; + smode1 = 0; + smode0 = 0; + } + else if (!strcasecmp(buf, "loopback")) { + smode2 = 0; + smode1 = 0; + smode0 = 0; + } + else { + return -EINVAL; + } + + mutex_lock(&mts_io_mutex); + + gpio_set_value(pin_smode2->pin.gpio, smode2); + gpio_set_value(pin_smode1->pin.gpio, smode1); + gpio_set_value(pin_smode0->pin.gpio, smode0); + + mutex_unlock(&mts_io_mutex); + + return count; +} + +/* MTOCGD2 specific attributes */ +static DEVICE_ATTR_MTS(dev_attr_serial_mode, "serial-mode", + mts_attr_show_serial_mode, mts_attr_store_serial_mode); +static DEVICE_ATTR_MTS(dev_attr_eth_switch_enabled, "eth-switch-enabled", + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_MTS(dev_attr_rs4xx_term_res, "rs4xx-term-res", + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); + +static struct attribute *mtr2_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_wifi_mac.attr, + &dev_attr_reset.attr, + &dev_attr_reset_monitor.attr, + &dev_attr_radio_power.attr, + &dev_attr_radio_reset.attr, + &dev_attr_ndc_reset.attr, + &dev_attr_extserial_dtr.attr, + &dev_attr_extserial_dsr_gpio.attr, + &dev_attr_extserial_ri_gpio.attr, + &dev_attr_extserial_dcd_gpio.attr, + &dev_attr_eth_switch_enabled.attr, + &dev_attr_bt_enabled.attr, + &dev_attr_wlan_enabled.attr, + + &dev_attr_serial_mode.attr, + &dev_attr_rs4xx_term_res.attr, + + &dev_attr_led_status.attr, + &dev_attr_led_wifi_gpio.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_led_e_gpio.attr, + &dev_attr_led_f_gpio.attr, + + &dev_attr_board_temperature.attr, + + /* extra space for the daughter card attributes */ + NULL, // index 34 + NULL, // index 35 + NULL, // index 36 + NULL, // index 37 + NULL, // index 38 + NULL, // index 39 + NULL, // index 40 + NULL, // index 41 + NULL, // index 42 + NULL, // index 43 + NULL, // index 44 + NULL, // index 45 + NULL, // index 46 + NULL, // index 47 + NULL, // index 48 + NULL, // index 49 + NULL, // index 50 + NULL, // index 51 + NULL, +}; + +static struct attribute *mtr2_daughter_card_attributes[] = { + &dev_attr_dc_din0.attr, + &dev_attr_dc_din1.attr, + &dev_attr_dc_din2.attr, + &dev_attr_dc_din3.attr, + + &dev_attr_dc_dout0.attr, + &dev_attr_dc_dout1.attr, + &dev_attr_dc_dout2.attr, + &dev_attr_dc_dout3.attr, + + &dev_attr_dc_adc0.attr, + &dev_attr_dc_adc1.attr, + &dev_attr_dc_adc2.attr, + + &dev_attr_dc_led1.attr, + &dev_attr_dc_led2.attr, + &dev_attr_dc_oe.attr, + + NULL, +}; + +static bool mtr2_add_daughter_card_attributes(void) +{ + size_t platform_attrs_size = sizeof(mtr2_platform_attributes) / sizeof(struct attribute *); + size_t daughter_card_attrs_size = sizeof(mtr2_daughter_card_attributes) / sizeof(struct attribute *); + size_t platform_attrs_index; + size_t daughter_card_attrs_index; + size_t copy_length = daughter_card_attrs_size - 1; /* don't need to copy the NULL at the end */ + + for (platform_attrs_index = 0; platform_attrs_index < platform_attrs_size; platform_attrs_index++) { + if (! mtr2_platform_attributes[platform_attrs_index]) { + break; + } + } + + if (platform_attrs_size < platform_attrs_index + daughter_card_attrs_size) { + log_error("not enough room for MTR2 daughter card attributes!"); + return false; + } + + for (daughter_card_attrs_index = 0; daughter_card_attrs_index < copy_length; daughter_card_attrs_index++, platform_attrs_index++) { + mtr2_platform_attributes[platform_attrs_index] = mtr2_daughter_card_attributes[daughter_card_attrs_index]; + } + + return true; +} + +static struct attribute_group mtr2_platform_attribute_group = { + .attrs = mtr2_platform_attributes +}; diff --git a/io-module/mts_io.c b/io-module/mts_io.c index 79351fa..1f641d9 100644 --- a/io-module/mts_io.c +++ b/io-module/mts_io.c @@ -1,7 +1,7 @@ /* * MTS-IO Controller * - * Copyright (C) 2013 by Multi-Tech Systems + * Copyright (C) 2014 by Multi-Tech Systems * * Authors: James Maki <jmaki@multitech.com> * Jesse Gilles <jgilles@multitech.com> @@ -44,46 +44,14 @@ #include "mts_io.h" -#define DRIVER_VERSION "v0.8.2" +#define DRIVER_VERSION "v0.9.1" #define DRIVER_AUTHOR "James Maki <jmaki@multitech.com>" #define DRIVER_DESC "MTS-IO Controller" #define DRIVER_NAME "mts-io" #define PLATFORM_NAME "mts-io" -#define DEBUG 0 - -#define __log(level, name, format, args...) \ - printk(level "[" name "] " DRIVER_NAME ":%s:%d: " format "\n" , \ - __func__ , __LINE__ , ## args) - -#define log_emerg(format, args...) __log(KERN_EMERG, "EMERG", format , ## args) -#define log_alert(format, args...) __log(KERN_ALERT, "ALERT", format , ## args) -#define log_crit(format, args...) __log(KERN_CRIT, "CRIT", format , ## args) -#define log_error(format, args...) __log(KERN_ERR, "ERROR", format , ## args) -#define log_warning(format, args...) __log(KERN_WARNING, "WARNING", format , ## args) -#define log_notice(format, args...) __log(KERN_NOTICE, "NOTICE", format , ## args) -#define log_info(format, args...) __log(KERN_INFO, "INFO", format , ## args) -#if DEBUG -# define log_debug(format, args...) __log(KERN_DEBUG, "DEBUG", format , ## args) -#else -# define log_debug(format, args...) do {} while (0) -#endif - -#define LED_STATUS_CONTROLLABLE_MTCDP 0 #define LED_LS_CONTROLLABLE 0 -#define USBH2_PS_CONTROLLABLE 0 - -static int led_mode_status = LED_OFF; - -#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) #define AT91SAM9X5_BASE_ADC 0xf804c000 @@ -109,1253 +77,44 @@ static uint8_t has_spi_din; static uint8_t has_spi_dout; static uint8_t has_spi_temp; +static struct platform_device *mts_io_platform_device; static struct attribute_group *attr_group; - static struct gpio_pin *gpio_pins; -/* -static struct gpio_pin gpio_pins_mtcdp_0_0[] = { - { - .name = "ENIO", - .pin = AT91_PIN_PC15, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "ETH0_ENABLED", - .attr_name = "eth0-enabled", - .pin = AT91_PIN_PB31, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "RADIO_RESET", - .attr_name = "radio-reset", - .pin = AT91_PIN_PB30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "DEVICE_RESET", - .attr_name = "reset", - .pin = AT91_PIN_PA22, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "LS_LED", - .attr_name = "led-ls", - .pin = AT91_PIN_PC9, -#if LED_LS_CONTROLLABLE - .direction = GPIO_DIR_OUTPUT, -#else - .direction = GPIO_DIR_INPUT, -#endif - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, -#if LED_STATUS_CONTROLLABLE_MTCDP - { - .name = "STATUS_LED", - .attr_name = "led-status", - .pin = AT91_PIN_PA30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, -#endif - { - .name = "RSERSRC", - .attr_name = "rsersrc", - .pin = AT91_PIN_PC7, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "DTR1", - .attr_name = "extserial-dtr", - .pin = AT91_PIN_PC10, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { }, -}; - -static struct gpio_pin gpio_pins_mtcdp_1_0[] = { - { - .name = "ENIO", - .pin = AT91_PIN_PC15, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "ETH0_ENABLED", - .attr_name = "eth0-enabled", - .pin = AT91_PIN_PB31, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "RADIO_RESET", - .attr_name = "radio-reset", - .pin = AT91_PIN_PB30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "DEVICE_RESET", - .attr_name = "reset", - .pin = AT91_PIN_PA22, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "LS_LED", - .attr_name = "led-ls", - .pin = AT91_PIN_PC9, -#if LED_LS_CONTROLLABLE - .direction = GPIO_DIR_OUTPUT, -#else - .direction = GPIO_DIR_INPUT, -#endif - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, -#if LED_STATUS_CONTROLLABLE_MTCDP - { - .name = "STATUS_LED", - .attr_name = "led-status", - .pin = AT91_PIN_PA30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, -#endif - { - .name = "RSERSRC", - .attr_name = "rsersrc", - .pin = AT91_PIN_PC7, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "TXD1", - .pin = AT91_PIN_PB17, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "DTR1", - .attr_name = "extserial-dtr", - .pin = AT91_PIN_PB18, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "USBH2_PS_OC", - .attr_name = "usbh2-ps-oc", - .pin = AT91_PIN_PB19, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, -#if USBH2_PS_CONTROLLABLE - { - .name = "USBH2_PS_ENABLED", - .attr_name = "usbh2-ps-enabled", - .pin = AT91_PIN_PB20, - .direction = GPIO_DIR_OUTPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, -#endif - { - .name = "NDC_RESET", - .attr_name = "ndc-reset", - .pin = AT91_PIN_PB21, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "ADC0", - .pin = AT91_PIN_PC0, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC1", - .pin = AT91_PIN_PC1, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC2", - .pin = AT91_PIN_PC2, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC3", - .pin = AT91_PIN_PC3, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { }, -}; - -static struct gpio_pin gpio_pins_mt100eocg_0_0[] = { - { - .name = "ENIO", - .pin = AT91_PIN_PC15, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "ETH0_ENABLED", - .attr_name = "eth0-enabled", - .pin = AT91_PIN_PB31, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "RADIO_RESET", - .attr_name = "radio-reset", - .pin = AT91_PIN_PB30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - }, - { - .name = "DEVICE_RESET", - .attr_name = "reset", - .pin = AT91_PIN_PA22, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "LED3", - .attr_name = "led3", - .pin = AT91_PIN_PC9, -#if LED_LS_CONTROLLABLE - .direction = GPIO_DIR_OUTPUT, -#else - .direction = GPIO_DIR_INPUT, -#endif - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "LED2", - .attr_name = "led2", - .pin = AT91_PIN_PA30, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "RSERSRC", - .attr_name = "rsersrc", - .pin = AT91_PIN_PC7, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "TXD1", - .pin = AT91_PIN_PB17, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "DTR1", - .attr_name = "extserial-dtr", - .pin = AT91_PIN_PB18, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "DCD1", - .attr_name = "extserial-dcd", - .pin = AT91_PIN_PB3, - .direction = GPIO_DIR_OUTPUT, - .output_value = 1, - .use_pullup = 0, - .active_low = 1, - }, - { - .name = "GPIO11", - .attr_name = "gpio11", - .pin = AT91_PIN_PB19, - .direction = GPIO_DIR_OD, - .output_value = 1, - .use_pullup = 1, - }, - { - .name = "GPIO12", - .attr_name = "gpio12", - .pin = AT91_PIN_PB20, - .direction = GPIO_DIR_OD, - .output_value = 1, - .use_pullup = 1, - }, - { - .name = "ADC0", - .pin = AT91_PIN_PC0, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC1", - .pin = AT91_PIN_PC1, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC2", - .pin = AT91_PIN_PC2, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { - .name = "ADC3", - .pin = AT91_PIN_PC3, - .direction = GPIO_DIR_INPUT, - .output_value = 0, - .use_pullup = 0, - }, - { }, -}; -*/ - -static struct gpio_pin gpio_pins_mtr2_0_0[] = { - { - .name = "NETH_RST", - .pin = { - .gpio = AT91_PIN_PC6, - .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, - .label = "eth-switch-enabled", - }, - }, - { - .name = "RADIO_RESET", - .pin = { - .gpio = AT91_PIN_PC5, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "radio-reset", - }, - }, - { - .name = "RADIO_RESET", - .pin = { - .gpio = AT91_PIN_PC5, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "radio-power", - }, - }, - { - .name = "DEVICE_RESET", - .pin = { - .gpio = AT91_PIN_PC4, - .flags = GPIOF_IN, - .label = "reset", - }, - .active_low = 1, - }, - { - .name = "LS_LED", - .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", - .pin = { - .gpio = AT91_PIN_PA24, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led-status", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PA25, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-cd", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PA25, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-c", - }, - .active_low = 1, - }, - { - .name = "LED10", - .pin = { - .gpio = AT91_PIN_PA26, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig1", - }, - .active_low = 1, - }, - { - .name = "LED10", - .pin = { - .gpio = AT91_PIN_PA26, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-d", - }, - .active_low = 1, - }, - { - .name = "LED11", - .pin = { - .gpio = AT91_PIN_PA27, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig2", - }, - .active_low = 1, - }, - { - .name = "LED11", - .pin = { - .gpio = AT91_PIN_PA27, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-e", - }, - .active_low = 1, - }, - { - .name = "LED12", - .pin = { - .gpio = AT91_PIN_PA28, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig3", - }, - .active_low = 1, - }, - { - .name = "LED12", - .pin = { - .gpio = AT91_PIN_PA28, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-f", - }, - .active_low = 1, - }, - { - .name = "LED13", - .pin = { - .gpio = AT91_PIN_PA29, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-wifi", - }, - .active_low = 1, - }, - { - .name = "LED13", - .pin = { - .gpio = AT91_PIN_PA29, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-b", - }, - .active_low = 1, - }, - { - .name = "UART3_DTR", - .pin = { - .gpio = AT91_PIN_PC12, - .flags = GPIOF_IN, - .label = "extserial-dtr", - }, - .active_low = 1, - }, - { - .name = "UART3_DSR", - .pin = { - .gpio = AT91_PIN_PC11, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dsr", - }, - .active_low = 1, - }, - { - .name = "UART3_DCD", - .pin = { - .gpio = AT91_PIN_PC10, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dcd", - }, - .active_low = 1, - }, - { - .name = "UART3_RI", - .pin = { - .gpio = AT91_PIN_PC13, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-ri", - }, - .active_low = 1, - }, - { - .name = "NDC_RESET", - .pin = { - .gpio = AT91_PIN_PC3, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "ndc-reset", - }, - }, - { - .name = "NDC_EEPROM_WRITE_PROTECT", - .pin = { - .gpio = AT91_PIN_PC26, - .flags = GPIOF_OUT_INIT_LOW, - .label = "ndc-eeprom-wp", - }, - }, - { - .name = "BT_EN", - .pin = { - .gpio = AT91_PIN_PD21, - .flags = GPIOF_OUT_INIT_LOW, - .label = "bt-enabled", - }, - }, - { - .name = "WLAN_EN", - .pin = { - .gpio = AT91_PIN_PC1, - .flags = GPIOF_OUT_INIT_LOW, - .label = "wlan-enabled", - }, - }, - { - .name = "SERIAL_MODE0", - .pin = { - .gpio = AT91_PIN_PC23, - .flags = GPIOF_OUT_INIT_LOW, - .label = "serial-mode", - }, - }, - { - .name = "SERIAL_MODE1", - .pin = { - .gpio = AT91_PIN_PC24, - .flags = GPIOF_OUT_INIT_LOW, - .label = "serial-mode", - }, - }, - { - .name = "SERIAL_MODE2", - .pin = { - .gpio = AT91_PIN_PC25, - .flags = GPIOF_OUT_INIT_LOW, - .label = "serial-mode", - }, - }, - { - .name = "RS4XX_TERM_RES", - .pin = { - .gpio = AT91_PIN_PC26, - .flags = GPIOF_OUT_INIT_LOW, - .label = "rs4xx-term-res", - }, - }, - { - .name = "NDC_GPIO1", - .pin = { - .gpio = AT91_PIN_PC0, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dc-gpio1", - }, - }, - { - .name = "NDC_GPIO2", - .pin = { - .gpio = AT91_PIN_PC14, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dc-gpio2", - }, - }, - { - .name = "NDC_GPIO3", - .pin = { - .gpio = AT91_PIN_PC29, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dc-gpio3", - }, - }, - { - .name = "NDC_GPIO4", - .pin = { - .gpio = AT91_PIN_PC30, - .flags = GPIOF_OUT_INIT_LOW, - .label = "dc-gpio4", - }, - }, - { - .name = "NDC_INTERRUPT1", - .pin = { - .gpio = AT91_PIN_PC20, - .flags = GPIOF_IN, - .label = "dc-int1", - }, - }, - { - .name = "NDC_INTERRUPT2", - .pin = { - .gpio = AT91_PIN_PC21, - .flags = GPIOF_IN, - .label = "dc-int2", - }, - }, - { }, -}; - -static struct gpio_pin gpio_pins_mtr_0_0[] = { - { - .name = "NETH_RST", - .pin = { - .gpio = AT91_PIN_PC6, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "eth0-enabled", - }, - }, - { - .name = "PWRMON", - .pin = { - .gpio = AT91_PIN_PA23, - .flags = GPIOF_IN, - .label = "radio-power", - }, - }, - { - .name = "3G_RST", - .pin = { - .gpio = AT91_PIN_PA22, - .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, - .label = "radio-reset", - }, - }, - { - .name = "3G_ONOFF", - .pin = { - .gpio = AT91_PIN_PA21, - .flags = GPIOF_OPEN_DRAIN | GPIOF_INIT_HIGH, - .label = "radio-enabled", - }, - }, - { - .name = "DEVICE_RESET", - .pin = { - .gpio = AT91_PIN_PC4, - .flags = GPIOF_IN, - .label = "reset", - }, - .active_low = 1, - }, - { - .name = "LS_LED", - .pin = { - .gpio = AT91_PIN_PC16, -#if LED_LS_CONTROLLABLE - .flags = GPIOF_OUT_INIT_HIGH, -#else - .flags = GPIOF_IN, -#endif - .label = "led-ls", - }, - .active_low = 1, - }, - { - .name = "STATUS_LED", - .pin = { - .gpio = AT91_PIN_PC21, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led-status", - }, - .active_low = 1, - }, - { - .name = "LED3", - .pin = { - .gpio = AT91_PIN_PC15, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-wifi", - }, - .active_low = 1, - }, - { - .name = "LED3", - .pin = { - .gpio = AT91_PIN_PC15, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-b", - }, - .active_low = 1, - }, - { - .name = "LED4", - .pin = { - .gpio = AT91_PIN_PC20, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-cd", - }, - .active_low = 1, - }, - { - .name = "LED4", - .pin = { - .gpio = AT91_PIN_PC20, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-c", - }, - .active_low = 1, - }, - { - .name = "LED6", - .pin = { - .gpio = AT91_PIN_PC19, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig1", - }, - .active_low = 1, - }, - { - .name = "LED6", - .pin = { - .gpio = AT91_PIN_PC19, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-d", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PC18, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig2", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PC18, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-e", - }, - .active_low = 1, - }, - { - .name = "LED8", - .pin = { - .gpio = AT91_PIN_PC17, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig3", - }, - .active_low = 1, - }, - { - .name = "LED8", - .pin = { - .gpio = AT91_PIN_PC17, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-f", - }, - .active_low = 1, - }, - { - .name = "RI_B", - .pin = { - .gpio = AT91_PIN_PC25, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-ri", - }, - .active_low = 1, - }, - { - .name = "DTR_B", - .pin = { - .gpio = AT91_PIN_PC26, - .flags = GPIOF_IN, - .label = "extserial-dtr", - }, - .active_low = 1, - }, - { - .name = "DSR_B", - .pin = { - .gpio = AT91_PIN_PC27, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dsr", - }, - .active_low = 1, - }, - { - .name = "DCD_B", - .pin = { - .gpio = AT91_PIN_PC28, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dcd", - }, - .active_low = 1, - }, - { - .name = "BT_EN", - .pin = { - .gpio = AT91_PIN_PA28, - .flags = GPIOF_OUT_INIT_LOW, - .label = "bt-enabled", - }, - }, - { - .name = "WLAN_EN", - .pin = { - .gpio = AT91_PIN_PA27, - .flags = GPIOF_OUT_INIT_LOW, - .label = "wlan-enabled", - }, - }, - { }, -}; - -static struct gpio_pin gpio_pins_mtr_0_1[] = { - { - .name = "NETH_RST", - .pin = { - .gpio = AT91_PIN_PC6, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "eth0-enabled", - }, - }, - { - .name = "PWRMON", - .pin = { - .gpio = AT91_PIN_PA23, - .flags = GPIOF_IN, - .label = "radio-power", - }, - }, - { - .name = "3G_RST", - .pin = { - .gpio = AT91_PIN_PA22, - .flags = GPIOF_OUT_INIT_HIGH | GPIOF_PULLUP, - .label = "radio-reset", - }, - }, - { - .name = "3G_ONOFF", - .pin = { - .gpio = AT91_PIN_PA21, - .flags = GPIOF_OUT_INIT_HIGH | GPIOF_PULLUP, - .label = "radio-enabled", - }, - }, - { - .name = "DEVICE_RESET", - .pin = { - .gpio = AT91_PIN_PC4, - .flags = GPIOF_IN, - .label = "reset", - }, - .active_low = 1, - }, - { - .name = "LS_LED", - .pin = { - .gpio = AT91_PIN_PC16, -#if LED_LS_CONTROLLABLE - .flags = GPIOF_OUT_INIT_HIGH, -#else - .flags = GPIOF_IN, -#endif - .label = "led-ls", - }, - .active_low = 1, - }, - { - .name = "STATUS_LED", - .pin = { - .gpio = AT91_PIN_PC21, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led-status", - }, - .active_low = 1, - }, - { - .name = "LED3", - .pin = { - .gpio = AT91_PIN_PC15, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-wifi", - }, - .active_low = 1, - }, - { - .name = "LED3", - .pin = { - .gpio = AT91_PIN_PC15, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-b", - }, - .active_low = 1, - }, - { - .name = "LED4", - .pin = { - .gpio = AT91_PIN_PC20, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-cd", - }, - .active_low = 1, - }, - { - .name = "LED4", - .pin = { - .gpio = AT91_PIN_PC20, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-c", - }, - .active_low = 1, - }, - { - .name = "LED6", - .pin = { - .gpio = AT91_PIN_PC19, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig1", - }, - .active_low = 1, - }, - { - .name = "LED6", - .pin = { - .gpio = AT91_PIN_PC19, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-d", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PC18, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig2", - }, - .active_low = 1, - }, - { - .name = "LED7", - .pin = { - .gpio = AT91_PIN_PC18, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-e", - }, - .active_low = 1, - }, - { - .name = "LED8", - .pin = { - .gpio = AT91_PIN_PC17, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-sig3", - }, - .active_low = 1, - }, - { - .name = "LED8", - .pin = { - .gpio = AT91_PIN_PC17, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "led-f", - }, - .active_low = 1, - }, - { - .name = "RI_B", - .pin = { - .gpio = AT91_PIN_PC25, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-ri", - }, - .active_low = 1, - }, - { - .name = "DTR_B", - .pin = { - .gpio = AT91_PIN_PC26, - .flags = GPIOF_IN, - .label = "extserial-dtr", - }, - .active_low = 1, - }, - { - .name = "DSR_B", - .pin = { - .gpio = AT91_PIN_PC27, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dsr", - }, - .active_low = 1, - }, - { - .name = "DCD_B", - .pin = { - .gpio = AT91_PIN_PC28, - .flags = GPIOF_OUT_INIT_HIGH, - .label = "extserial-dcd", - }, - .active_low = 1, - }, - { - .name = "BT_EN", - .pin = { - .gpio = AT91_PIN_PA28, - .flags = GPIOF_OUT_INIT_LOW, - .label = "bt-enabled", - }, - }, - { - .name = "WLAN_EN", - .pin = { - .gpio = AT91_PIN_PA27, - .flags = GPIOF_OUT_INIT_LOW, - .label = "wlan-enabled", - }, - }, - { }, -}; - -struct gpio_pin *gpio_pin_by_name(const char *name) { - struct gpio_pin *pin; - - for (pin = gpio_pins; *pin->name; pin++) { - if (!strcmp(pin->name, name)) { - return pin; - } - } - - log_error("pin named %s not found", name); - - return NULL; -} - -struct gpio_pin *gpio_pin_by_attr_name(const char *name) { - struct gpio_pin *pin; - - for (pin = gpio_pins; *pin->name; pin++) { - if (!strcmp(pin->pin.label, name)) { - return pin; - } - } - - log_error("pin with attr name %s not found", name); - - return NULL; -} - - -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_dc_dout_dev; -static u8 spi_dc_dout_value; -static DEFINE_MUTEX(spi_dc_dout_mutex); -static unsigned int dc_dout_max_speed_hz = 1 * 1000 * 1000; -module_param(dc_dout_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - dc_dout_max_speed_hz, - "Maximum clock rate to be used with this device (default: 1 MHz)" -); - -static struct spi_device *spi_dc_din_dev; -static unsigned int dc_din_max_speed_hz = 1 * 1000 * 1000; -module_param(dc_din_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - dc_din_max_speed_hz, - "Maximum clock rate to be used with this device (default: 1 MHz)" -); - -static struct spi_device *spi_dc_adc_dev; -static unsigned int dc_adc_max_speed_hz = 20 * 1000 * 1000; -module_param(dc_adc_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - dc_adc_max_speed_hz, - "Maximum clock rate to be used with this device (default: 20 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)" -); - -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); +static DEFINE_MUTEX(mts_io_mutex); - kfree(tx); +/* generic GPIO support */ +#include "gpio.c" - return tmp; -} +/* AT91 built-in ADC */ +#include "adc.c" -static inline int spi_readn(struct spi_device *spi, u8 *buf, size_t len) -{ - int tmp; - u8 *rx; +/* SPI-based stuff */ +#include "spi.c" - rx = kmalloc(len, GFP_KERNEL); - if (!rx) { - return -ENOMEM; - } +/* accessory card support */ +#include "mtdc_gpiob.c" - tmp = spi_read(spi, rx, len); - memcpy(buf, rx, len); - - kfree(rx); - - return tmp; -} +/* telit radio reset handling */ +#include "telit_radio.c" -#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) - -#define BLINK_PER_SEC 8 -#define BLINK_INTERVAL (HZ / BLINK_PER_SEC) -#define RESET_HOLD_COUNT (BLINK_PER_SEC * 3) -#define RESET_LONG_HOLD_COUNT (BLINK_PER_SEC * 30) +/* reset button handling */ +#define RESET_CHECK_PER_SEC 8 +#define RESET_INTERVAL (HZ / RESET_CHECK_PER_SEC) +#define RESET_HOLD_COUNT (RESET_CHECK_PER_SEC * 3) +#define RESET_LONG_HOLD_COUNT (RESET_CHECK_PER_SEC * 30) static pid_t reset_pid = -1; static pid_t reset_count = 0; static int reset_short_signal = SIGUSR1; static int reset_long_signal = SIGUSR2; static int reset_extra_long_signal = SIGHUP; -static DEFINE_MUTEX(mts_io_mutex); -static void blink_callback(struct work_struct *ignored); +static void reset_callback(struct work_struct *ignored); -static DECLARE_DELAYED_WORK(blink_work, blink_callback); +static DECLARE_DELAYED_WORK(reset_work, reset_callback); -static void blink_callback(struct work_struct *ignored) +static void reset_callback(struct work_struct *ignored) { struct gpio_pin *pin; int reset_pressed = 0; @@ -1394,205 +153,66 @@ static void blink_callback(struct work_struct *ignored) reset_count = 0; } - if (led_mode_status == LED_FLASHING) { - pin = gpio_pin_by_name("STATUS_LED"); - if (pin) { - gpio_set_value(pin->pin.gpio, !gpio_get_value(pin->pin.gpio)); - } - } - mutex_unlock(&mts_io_mutex); - schedule_delayed_work(&blink_work, BLINK_INTERVAL); + schedule_delayed_work(&reset_work, RESET_INTERVAL); } -static int radio_off_telit(void) +static ssize_t mts_attr_show_reset_monitor(struct device *dev, + struct device_attribute *attr, + char *buf) { - int value, ret; - struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); - struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); - struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); - - if (!onoff_pin || !pwrmon_pin || !rst_pin) { - return -ENODEV; - } - - value = gpio_get_value(pwrmon_pin->pin.gpio); - if(value == 0) { - log_error("radio is already off"); - return -EINVAL; - } - - // drive on/off pin low for at least 3 sec - log_info("shutting down radio"); - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(3500); - - // set on/off pin high - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - // wait for radio to power off - msleep(5000); + int ret; - // check that power is low - value = gpio_get_value(pwrmon_pin->pin.gpio); - if(value != 0) { - log_warning("radio is still on. performing radio reset."); - //Perform Hard Reset - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } + mutex_lock(&mts_io_mutex); - msleep(500); + ret = sprintf(buf, "%d %d %d %d\n", reset_pid, reset_short_signal, reset_long_signal, reset_extra_long_signal); - // set pin high - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - } else { - log_info("radio has been shut down"); - } + mutex_unlock(&mts_io_mutex); return ret; } -static int radio_on_telit(void) +static ssize_t mts_attr_store_reset_monitor(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) { - int value, ret; - struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); - struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); - struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); - - if (!onoff_pin || !pwrmon_pin || !rst_pin) { - return -ENODEV; - } + pid_t pid; + int short_signal; + int long_signal; + int extra_long_signal; + int result = sscanf(buf, "%i %i %i %i", &pid, &short_signal, &long_signal, &extra_long_signal); - value = gpio_get_value(pwrmon_pin->pin.gpio); - if(value != 0) { - log_error("radio is already on"); + if (result < 3 || result > 4) { return -EINVAL; } - // drive on/off pin low for at least 5 sec - log_info("turning on radio"); - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(5500); - - // set on/off pin high - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(200); - - // check that power is high - value = gpio_get_value(pwrmon_pin->pin.gpio); - if(value == 0) { - log_warning("radio is still off. performing radio reset"); - //Perform Hard Reset - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(500); - - // set pin high - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - } else { - log_info("radio has been turned on"); - } - - return ret; -} + if(result == 3) { + mutex_lock(&mts_io_mutex); -static ssize_t mts_attr_store_radio_power_telit(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int value; - int err; + reset_pid = pid; + reset_short_signal = short_signal; + reset_long_signal = long_signal; - if (sscanf(buf, "%i", &value) != 1) { - return -EINVAL; - } - if (value == 0) { - mutex_lock(&mts_io_mutex); - err = radio_off_telit(); mutex_unlock(&mts_io_mutex); } else { mutex_lock(&mts_io_mutex); - err = radio_on_telit(); - mutex_unlock(&mts_io_mutex); - } - if (err) { - return err; + reset_pid = pid; + reset_short_signal = short_signal; + reset_long_signal = long_signal; + reset_extra_long_signal = extra_long_signal; + + mutex_unlock(&mts_io_mutex); } return count; } -static int radio_reset_telit(void) -{ - int ret; - struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); - struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); - - if (!rst_pin || !onoff_pin) { - return -ENODEV; - } - - // drive reset pin low for 500ms - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(500); - - // set pin high - ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - // wait for 2 sec before toggling on/off pin - msleep(2000); - - // drive on/off pin low for 6 sec - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - msleep(6000); - - // set on/off pin high - ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); - if (ret) { - return ret; - } - - return ret; -} +static DEVICE_ATTR_MTS(dev_attr_reset_monitor, "reset-monitor", + mts_attr_show_reset_monitor, mts_attr_store_reset_monitor); +static DEVICE_ATTR_RO_MTS(dev_attr_reset, "reset", mts_attr_show_gpio_pin); +/* generic peripheral reset functions */ static int radio_reset(void) { struct gpio_pin *pin = gpio_pin_by_name("RADIO_RESET"); @@ -1610,89 +230,6 @@ static int radio_reset(void) return 0; } -static int ndc_reset(void) -{ - struct gpio_pin *pin = gpio_pin_by_name("NDC_RESET"); - - if (!pin) { - return -ENODEV; - } - - gpio_set_value(pin->pin.gpio, 0); - - mdelay(1); - - gpio_set_value(pin->pin.gpio, 1); - - return 0; -} - -static int ADT7302_to_celsius(int value) -{ - if (value & 0x2000) { - value = value - 16384; - } - - value = value / 32 + 1 * ((value % 32) >= 16); - - return value; -} - -static ssize_t mts_attr_show_gpio_pin(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int value; - struct gpio_pin *pin = gpio_pin_by_attr_name(attr->attr.name); - - 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_gpio_pin(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int value; - struct gpio_pin *pin = gpio_pin_by_attr_name(attr->attr.name); - - 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; -} - static ssize_t mts_attr_store_radio_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1719,38 +256,23 @@ static ssize_t mts_attr_store_radio_reset(struct device *dev, return count; } -static ssize_t mts_attr_store_radio_reset_telit(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static int ndc_reset(void) { - int value; - int err; + struct gpio_pin *pin = gpio_pin_by_name("NDC_RESET"); - if (sscanf(buf, "%i", &value) != 1) { - return -EINVAL; - } - if (value != 0) { - return -EINVAL; + if (!pin) { + return -ENODEV; } - mutex_lock(&mts_io_mutex); - - err = radio_reset_telit(); + gpio_set_value(pin->pin.gpio, 0); - mutex_unlock(&mts_io_mutex); + mdelay(1); - if (err) { - return err; - } + gpio_set_value(pin->pin.gpio, 1); - return count; + return 0; } -static DEVICE_ATTR_MTS(dev_attr_radio_power, "radio-power", - mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - -static DEVICE_ATTR_MTS(dev_attr_radio_reset, "radio-reset", - mts_attr_show_gpio_pin, mts_attr_store_radio_reset); - static ssize_t mts_attr_store_ndc_reset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1776,397 +298,35 @@ static ssize_t mts_attr_store_ndc_reset(struct device *dev, return count; } + +static DEVICE_ATTR_MTS(dev_attr_radio_reset, "radio-reset", + mts_attr_show_gpio_pin, mts_attr_store_radio_reset); static DEVICE_ATTR_MTS(dev_attr_ndc_reset, "ndc-reset", mts_attr_show_gpio_pin, mts_attr_store_ndc_reset); +/* shared gpio attributes */ +static DEVICE_ATTR_MTS(dev_attr_radio_power, "radio-power", + 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_bt_enabled, "bt-enabled", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - static DEVICE_ATTR_MTS(dev_attr_wlan_enabled, "wlan-enabled", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - -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 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 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 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 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 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_extserial_dtr, "extserial-dtr", mts_attr_show_gpio_pin); - static DEVICE_ATTR_MTS(dev_attr_extserial_dsr_gpio, "extserial-dsr", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - static DEVICE_ATTR_MTS(dev_attr_extserial_ri_gpio, "extserial-ri", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_MTS(dev_attr_extserial_dcd_gpio, "extserial-dcd", + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); -static ssize_t mts_attr_show_led_status(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%d\n", led_mode_status); -} - -static ssize_t mts_attr_store_led_status(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int value; - int ret; - struct gpio_pin *pin = gpio_pin_by_name("STATUS_LED"); - - if (!pin) { - return -ENODEV; - } - - if (sscanf(buf, "%i", &value) != 1) { - return -EINVAL; - } - - mutex_lock(&mts_io_mutex); - - switch (value) { - case LED_OFF: - led_mode_status = LED_OFF; - gpio_set_value(pin->pin.gpio, 1); - - break; - - case LED_ON: - led_mode_status = LED_ON; - gpio_set_value(pin->pin.gpio, 0); - - break; - - case LED_FLASHING: - led_mode_status = LED_FLASHING; - gpio_set_value(pin->pin.gpio, 0); - - break; - - default: - ret = -EINVAL; - } - - mutex_unlock(&mts_io_mutex); - - return count; -} - +/* shared gpio-based LEDs */ static DEVICE_ATTR_MTS(dev_attr_led_status, "led-status", - mts_attr_show_led_status, mts_attr_store_led_status); + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); static DEVICE_ATTR_MTS(dev_attr_led_a_gpio, "led-a", - mts_attr_show_led_status, mts_attr_store_led_status); - -#if LED_STATUS_CONTROLLABLE_MTCDP -static DEVICE_ATTR_MTS(dev_attr_led_sdk_a, "led-sdk-a", - mts_attr_show_led_status, mts_attr_store_led_status); -#endif + mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); #if LED_LS_CONTROLLABLE static DEVICE_ATTR_MTS(dev_attr_led_ls, "led-ls", @@ -2200,288 +360,8 @@ static DEVICE_ATTR_MTS(dev_attr_led_e_gpio, "led-e", static DEVICE_ATTR_MTS(dev_attr_led_f_gpio, "led-f", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); -static DEVICE_ATTR_RO_MTS(dev_attr_reset, "reset", mts_attr_show_gpio_pin); - -static DEVICE_ATTR_MTS(dev_attr_rs4xx_term_res, "rs4xx-term-res", - mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - -static ssize_t mts_attr_show_reset_monitor(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - - mutex_lock(&mts_io_mutex); - - ret = sprintf(buf, "%d %d %d %d\n", reset_pid, reset_short_signal, reset_long_signal, reset_extra_long_signal); - - mutex_unlock(&mts_io_mutex); - - return ret; -} - -static ssize_t mts_attr_store_reset_monitor(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - pid_t pid; - int short_signal; - int long_signal; - int extra_long_signal; - int result = sscanf(buf, "%i %i %i %i", &pid, &short_signal, &long_signal, &extra_long_signal); - - if (result < 3 || result > 4) { - return -EINVAL; - } - - if(result == 3) { - mutex_lock(&mts_io_mutex); - - reset_pid = pid; - reset_short_signal = short_signal; - reset_long_signal = long_signal; - - mutex_unlock(&mts_io_mutex); - } else { - mutex_lock(&mts_io_mutex); - - reset_pid = pid; - reset_short_signal = short_signal; - reset_long_signal = long_signal; - reset_extra_long_signal = extra_long_signal; - - mutex_unlock(&mts_io_mutex); - } - - return count; -} - -static DEVICE_ATTR_MTS(dev_attr_reset_monitor, "reset-monitor", - mts_attr_show_reset_monitor, mts_attr_store_reset_monitor); - -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)); -} - -static DEVICE_ATTR_RO_MTS(dev_attr_board_temperature, "board-temperature", - mts_attr_show_board_temperature); - -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 DEVICE_ATTR_RO_MTS(dev_attr_usbh2_ps_oc, "usbh2-ps-oc", - mts_attr_show_gpio_pin); - -#if USBH2_PS_CONTROLLABLE -static DEVICE_ATTR_MTS(dev_attr_usbh2_ps_enabled, "usbh2-ps-enabled", - mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); -#endif - -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_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); - -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 DEVICE_ATTR_MTS(dev_attr_extserial_dcd_gpio, "extserial-dcd", - mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - -static ssize_t mts_attr_show_serial_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - int smode0; - int smode1; - int smode2; - - struct gpio_pin *pin_smode0 = gpio_pin_by_name("SERIAL_MODE0"); - struct gpio_pin *pin_smode1 = gpio_pin_by_name("SERIAL_MODE1"); - struct gpio_pin *pin_smode2 = gpio_pin_by_name("SERIAL_MODE2"); - - if (!pin_smode0 || !pin_smode1 || !pin_smode2) - return -ENODEV; - - mutex_lock(&mts_io_mutex); - - smode0 = gpio_get_value(pin_smode0->pin.gpio); - smode1 = gpio_get_value(pin_smode1->pin.gpio); - smode2 = gpio_get_value(pin_smode2->pin.gpio); - - if (smode2 == 0 && smode1 == 0 && smode0 == 1) - ret = sprintf(buf, "rs232\n"); - else if (smode2 == 0 && smode1 == 1 && smode0 == 0) - ret = sprintf(buf, "rs485\n"); - else if (smode2 == 1 && smode1 == 0 && smode0 == 0) - ret = sprintf(buf, "rs422\n"); - else if (smode2 == 0 && smode1 == 0 && smode0 == 0) - ret = sprintf(buf, "loopback\n"); - else - ret = sprintf(buf, "error\n"); - - mutex_unlock(&mts_io_mutex); - - return ret; -} - -static ssize_t mts_attr_store_serial_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int smode0; - int smode1; - int smode2; - struct gpio_pin *pin_smode0 = gpio_pin_by_name("SERIAL_MODE0"); - struct gpio_pin *pin_smode1 = gpio_pin_by_name("SERIAL_MODE1"); - struct gpio_pin *pin_smode2 = gpio_pin_by_name("SERIAL_MODE2"); - - if (!pin_smode0 || !pin_smode1 || !pin_smode2) - return -ENODEV; - - if (!strcasecmp(buf, "rs232")) { - smode2 = 0; - smode1 = 0; - smode0 = 1; - } - else if (!strcasecmp(buf, "rs485")) { - smode2 = 0; - smode1 = 1; - smode0 = 0; - } - else if (!strcasecmp(buf, "rs422")) { - smode2 = 1; - smode1 = 0; - smode0 = 0; - } - else if (!strcasecmp(buf, "loopback")) { - smode2 = 0; - smode1 = 0; - smode0 = 0; - } - else { - return -EINVAL; - } - - mutex_lock(&mts_io_mutex); - - gpio_set_value(pin_smode2->pin.gpio, smode2); - gpio_set_value(pin_smode1->pin.gpio, smode1); - gpio_set_value(pin_smode0->pin.gpio, smode0); - - mutex_unlock(&mts_io_mutex); - - return count; -} +/* eeprom info */ static ssize_t mts_attr_show_product_info(struct device *dev, struct device_attribute *attr, char *buf) @@ -2522,882 +402,29 @@ static ssize_t mts_attr_show_product_info(struct device *dev, return value; } -static DEVICE_ATTR_MTS(dev_attr_serial_mode, "serial-mode", - mts_attr_show_serial_mode, mts_attr_store_serial_mode); - -static DEVICE_ATTR_MTS(dev_attr_eth_switch_enabled, "eth-switch-enabled", - mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); - -static DEVICE_ATTR_MTS(dev_attr_radio_power_telit, "radio-power", - mts_attr_show_gpio_pin, mts_attr_store_radio_power_telit); - -static DEVICE_ATTR_MTS(dev_attr_radio_reset_telit, "radio-reset", - mts_attr_show_gpio_pin, mts_attr_store_radio_reset_telit); - static DEVICE_ATTR_RO_MTS(dev_attr_vendor_id, "vendor-id", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_product_id, "product-id", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_device_id, "device-id", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_hw_version, "hw-version", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_imei, "imei", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_wifi_mac, "mac-wifi", mts_attr_show_product_info); - static DEVICE_ATTR_RO_MTS(dev_attr_eth_mac, "mac-eth", mts_attr_show_product_info); -struct gpio_pin *dc_gpio_pin_by_attr_name(const char *name) { - struct gpio_pin *pin; - char *pin_attr_name; - - if (!strcmp(name, "led1")) { - pin_attr_name = "dc-gpio1"; - } else if (!strcmp(name, "led2")) { - pin_attr_name = "dc-gpio2"; - } else if (!strcmp(name, "dout-enable")) { - pin_attr_name = "dc-gpio3"; - } else { - log_error("daughter card attribute %s not available", name); - return NULL; - } - - for (pin = gpio_pins; *pin->name; pin++) { - if (!strcmp(pin->pin.label, pin_attr_name)) { - return pin; - } - } - - log_error("pin with attr name %s not found", name); - - return NULL; -} - - -static ssize_t mts_attr_show_dc_gpio_pin(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int value; - struct gpio_pin *pin = dc_gpio_pin_by_attr_name(attr->attr.name); - - if (!pin) { - return -ENODEV; - } +/* include per-device pins and attributes */ +#include "mtr2.c" +#include "mtr.c" - 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_dc_gpio_pin(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int value; - struct gpio_pin *pin = dc_gpio_pin_by_attr_name(attr->attr.name); - - 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; -} - -static ssize_t mts_attr_show_dc_din(struct device *dev, struct device_attribute *attr, char *buf) -{ - int tmp; - u8 bit; - u8 byte; - - if (!spi_dc_din_dev) { - log_error("dc din device not present"); - return -ENODEV; - } - - if (!strcmp(attr->attr.name, "din0")) { - bit = BIT(0); - } else if (!strcmp(attr->attr.name, "din1")) { - bit = BIT(1); - } else if (!strcmp(attr->attr.name, "din2")) { - bit = BIT(2); - } else if (!strcmp(attr->attr.name, "din3")) { - bit = BIT(3); - } else { - log_error("dc din attr does not exist"); - return -ENOENT; - } - - tmp = spi_readn(spi_dc_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_store_dc_dout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - int value; - u8 bit; - - if (!spi_dc_dout_dev) { - log_error("dc dout device not present"); - return -ENODEV; - } - - if (!strcmp(attr->attr.name, "dout0")) { - bit = BIT(0); - } else if (!strcmp(attr->attr.name, "dout1")) { - bit = BIT(1); - } else if (!strcmp(attr->attr.name, "dout2")) { - bit = BIT(2); - } else if (!strcmp(attr->attr.name, "dout3")) { - bit = BIT(3); - } else { - log_error("dc dout attr does not exist"); - return -ENOENT; - } - - if (sscanf(buf, "%i", &value) != 1) { - log_error("dc dout attr invalid argument"); - return -EINVAL; - } - - mutex_lock(&spi_dc_dout_mutex); - - if (value) { - spi_dc_dout_value &= ~bit; - } else { - spi_dc_dout_value |= bit; - } - - spi_writen(spi_dc_dout_dev, &spi_dc_dout_value, 1); - - mutex_unlock(&spi_dc_dout_mutex); - - return count; -} - -static ssize_t mts_attr_show_dc_dout(struct device *dev, struct device_attribute *attr, char *buf) -{ - int value; - u8 bit; - - if (!spi_dc_dout_dev) { - log_error("dc dout device not present"); - return -ENODEV; - } - - if (!strcmp(attr->attr.name, "dout0")) { - bit = BIT(0); - } else if (!strcmp(attr->attr.name, "dout1")) { - bit = BIT(1); - } else if (!strcmp(attr->attr.name, "dout2")) { - bit = BIT(2); - } else if (!strcmp(attr->attr.name, "dout3")) { - bit = BIT(3); - } else { - log_error("dc dout attr does not exist"); - return -ENOENT; - } - - mutex_lock(&spi_dc_dout_mutex); - - value = spi_dc_dout_value & bit ? 0 : 1; - - mutex_unlock(&spi_dc_dout_mutex); - - return sprintf(buf, "%d\n", value); -} - -static ssize_t mts_attr_show_dc_adc(struct device *dev, struct device_attribute *attr, char *buf) -{ - int tmp; - int tx_data; - int rx_data; - int channel; - int channel_mask = 0x0180; /* 0b 0000 0001 1000 0000 */ - int manual_mode = 0x1840; /* 0b 0001 1000 0100 0000 */ - uint8_t tx[2]; - uint8_t rx[2]; - - if (!spi_dc_adc_dev) { - log_error("dc adc device not present"); - return -ENODEV; - } - - memset(tx, 0, sizeof(tx)); - memset(rx, 0, sizeof(rx)); - - if (!strcmp(attr->attr.name, "adc0")) { - channel = 0; - } else if (!strcmp(attr->attr.name, "adc1")) { - channel = 1; - } else if (! strcmp(attr->attr.name, "adc2")) { - channel = 2; - } else { - log_error("dc adc attr does not exist"); - return -ENOENT; - } - - /* 1st transfer to set up (5V reference, channel to read from) */ - tx_data = manual_mode | ((channel << 7) & channel_mask); - tx[0] = tx_data >> 8; - tx[1] = tx_data & 0xFF; - tmp = spi_writen(spi_dc_adc_dev, tx, 2); - if (tmp) { - log_error("spi_write failed %d", tmp); - return tmp; - } - - /* 2nd transfer to clock chip for ADC conversion - * this can be a throw-away read or an empty write, - * the ADC just needs the clock running so it can convert */ - tx[0] = 0; - tx[1] = 0; - tmp = spi_writen(spi_dc_adc_dev, tx, 2); - if (tmp) { - log_error("2nd spi_write failed %d", tmp); - return tmp; - } - - /* 3rd transfer to read data */ - tmp = spi_readn(spi_dc_adc_dev, rx, 2); - if (tmp) { - log_error("spi_read failed %d", tmp); - return tmp; - } - rx_data = ((rx[0] & 0x0F) << 8) | (rx[1] & 0xFF); - - return sprintf(buf, "%lu\n", (unsigned long) rx_data); -} - -/* MTDC-GPIOB */ -static DEVICE_ATTR_RO_MTS(dev_attr_dc_din0, "din0", mts_attr_show_dc_din); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_din1, "din1", mts_attr_show_dc_din); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_din2, "din2", mts_attr_show_dc_din); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_din3, "din3", mts_attr_show_dc_din); -static DEVICE_ATTR_MTS(dev_attr_dc_dout0, "dout0", mts_attr_show_dc_dout, mts_attr_store_dc_dout); -static DEVICE_ATTR_MTS(dev_attr_dc_dout1, "dout1", mts_attr_show_dc_dout, mts_attr_store_dc_dout); -static DEVICE_ATTR_MTS(dev_attr_dc_dout2, "dout2", mts_attr_show_dc_dout, mts_attr_store_dc_dout); -static DEVICE_ATTR_MTS(dev_attr_dc_dout3, "dout3", mts_attr_show_dc_dout, mts_attr_store_dc_dout); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc0, "adc0", mts_attr_show_dc_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc1, "adc1", mts_attr_show_dc_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc2, "adc2", mts_attr_show_dc_adc); -static DEVICE_ATTR_MTS(dev_attr_dc_led1, "led1", mts_attr_show_dc_gpio_pin, mts_attr_store_dc_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_dc_led2, "led2", mts_attr_show_dc_gpio_pin, mts_attr_store_dc_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_dc_oe, "dout-enable", mts_attr_show_dc_gpio_pin, mts_attr_store_dc_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_extserial_dtr.attr, - &dev_attr_extserial_dcd_gpio.attr, - &dev_attr_rsersrc.attr, - &dev_attr_radio_reset.attr, - &dev_attr_eth0_enabled.attr, - &dev_attr_gpio11.attr, - &dev_attr_gpio12.attr, - - &dev_attr_gpo1.attr, - &dev_attr_gpo2.attr, - &dev_attr_gpo3.attr, - &dev_attr_gpo4.attr, - &dev_attr_led1.attr, - &dev_attr_led2.attr, - &dev_attr_led3.attr, - &dev_attr_led4.attr, - &dev_attr_led5.attr, - &dev_attr_led6.attr, - - &dev_attr_gpi5.attr, - &dev_attr_gpi6.attr, - &dev_attr_gpi7.attr, - &dev_attr_gpi8.attr, - &dev_attr_gpi9.attr, - &dev_attr_gpi10.attr, - - &dev_attr_board_temperature.attr, - - &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 -}; - -struct attribute *mtr2_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_wifi_mac.attr, - &dev_attr_reset.attr, - &dev_attr_reset_monitor.attr, - &dev_attr_radio_power.attr, - &dev_attr_radio_reset.attr, - &dev_attr_ndc_reset.attr, - &dev_attr_extserial_dtr.attr, - &dev_attr_extserial_dsr_gpio.attr, - &dev_attr_extserial_ri_gpio.attr, - &dev_attr_extserial_dcd_gpio.attr, - &dev_attr_eth_switch_enabled.attr, - &dev_attr_bt_enabled.attr, - &dev_attr_wlan_enabled.attr, - - &dev_attr_serial_mode.attr, - &dev_attr_rs4xx_term_res.attr, - - &dev_attr_led_status.attr, - &dev_attr_led_wifi_gpio.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_led_e_gpio.attr, - &dev_attr_led_f_gpio.attr, - - &dev_attr_board_temperature.attr, - - /* extra space for the daughter card attributes */ - NULL, // index 34 - NULL, // index 35 - NULL, // index 36 - NULL, // index 37 - NULL, // index 38 - NULL, // index 39 - NULL, // index 40 - NULL, // index 41 - NULL, // index 42 - NULL, // index 43 - NULL, // index 44 - NULL, // index 45 - NULL, // index 46 - NULL, // index 47 - NULL, // index 48 - NULL, // index 49 - NULL, // index 50 - NULL, // index 51 - NULL, -}; - -static struct attribute *mtr2_daughter_card_attributes[] = { - &dev_attr_dc_din0.attr, - &dev_attr_dc_din1.attr, - &dev_attr_dc_din2.attr, - &dev_attr_dc_din3.attr, - - &dev_attr_dc_dout0.attr, - &dev_attr_dc_dout1.attr, - &dev_attr_dc_dout2.attr, - &dev_attr_dc_dout3.attr, - - &dev_attr_dc_adc0.attr, - &dev_attr_dc_adc1.attr, - &dev_attr_dc_adc2.attr, - - &dev_attr_dc_led1.attr, - &dev_attr_dc_led2.attr, - &dev_attr_dc_oe.attr, - - NULL, -}; - -static struct attribute_group mtr2_platform_attribute_group = { - .attrs = mtr2_platform_attributes -}; - -bool mtr2_add_daughter_card_attributes(void) -{ - size_t platform_attrs_size = sizeof(mtr2_platform_attributes) / sizeof(struct attribute *); - size_t daughter_card_attrs_size = sizeof(mtr2_daughter_card_attributes) / sizeof(struct attribute *); - size_t platform_attrs_index; - size_t daughter_card_attrs_index; - size_t copy_length = daughter_card_attrs_size - 1; /* don't need to copy the NULL at the end */ - - for (platform_attrs_index = 0; platform_attrs_index < platform_attrs_size; platform_attrs_index++) { - if (! mtr2_platform_attributes[platform_attrs_index]) { - break; - } - } - - if (platform_attrs_size < platform_attrs_index + daughter_card_attrs_size) { - log_error("not enough room for MTR2 daughter card attributes!"); - return false; - } - - for (daughter_card_attrs_index = 0; daughter_card_attrs_index < copy_length; daughter_card_attrs_index++, platform_attrs_index++) { - mtr2_platform_attributes[platform_attrs_index] = mtr2_daughter_card_attributes[daughter_card_attrs_index]; - } - - return true; -} - -static struct attribute *mtcdp_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_reset.attr, - &dev_attr_reset_monitor.attr, - &dev_attr_radio_reset.attr, - &dev_attr_ndc_reset.attr, - &dev_attr_eth0_enabled.attr, - &dev_attr_extserial_dtr.attr, - &dev_attr_led_ls.attr, -#if LED_STATUS_CONTROLLABLE_MTCDP - &dev_attr_led_status.attr, - &dev_attr_led_sdk_a.attr, -#endif - &dev_attr_usbh2_ps_oc.attr, -#if USBH2_PS_CONTROLLABLE - &dev_attr_usbh2_ps_enabled.attr, -#endif - - &dev_attr_extserial_dcd.attr, - &dev_attr_extserial_ri.attr, - &dev_attr_extserial_dsr.attr, - &dev_attr_led_cd.attr, - &dev_attr_led_sdk_b.attr, - &dev_attr_led_sig1.attr, - &dev_attr_led_sdk_c.attr, - &dev_attr_led_sig2.attr, - &dev_attr_led_sdk_d.attr, - &dev_attr_led_sig3.attr, - &dev_attr_led_sdk_e.attr, - &dev_attr_led_dtr.attr, - &dev_attr_led_sdk_f.attr, - - &dev_attr_dout0.attr, - &dev_attr_dout1.attr, - &dev_attr_dout2.attr, - &dev_attr_dout3.attr, - &dev_attr_dout4.attr, - &dev_attr_dout5.attr, - &dev_attr_dout6.attr, - &dev_attr_dout7.attr, - - &dev_attr_din0.attr, - &dev_attr_din1.attr, - &dev_attr_din2.attr, - &dev_attr_din3.attr, - &dev_attr_din4.attr, - &dev_attr_din5.attr, - &dev_attr_din6.attr, - &dev_attr_din7.attr, - - &dev_attr_board_temperature.attr, - - &dev_attr_adc0.attr, - &dev_attr_adc1.attr, - &dev_attr_adc2.attr, - &dev_attr_adc3.attr, - - NULL, -}; - -static struct attribute_group mtcdp_platform_attribute_group = { - .attrs = mtcdp_platform_attributes -}; - -static struct attribute *mtr_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_wifi_mac.attr, - &dev_attr_reset.attr, - &dev_attr_reset_monitor.attr, - &dev_attr_radio_power_telit.attr, - &dev_attr_radio_reset_telit.attr, - &dev_attr_extserial_ri_gpio.attr, - &dev_attr_extserial_dtr.attr, - &dev_attr_extserial_dsr_gpio.attr, - &dev_attr_extserial_dcd_gpio.attr, - &dev_attr_eth0_enabled.attr, - &dev_attr_bt_enabled.attr, - &dev_attr_wlan_enabled.attr, - - &dev_attr_led_status.attr, - &dev_attr_led_sig1_gpio.attr, - &dev_attr_led_sig2_gpio.attr, - &dev_attr_led_sig3_gpio.attr, - &dev_attr_led_cd_gpio.attr, - &dev_attr_led_wifi_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_led_e_gpio.attr, - &dev_attr_led_f_gpio.attr, - - NULL, -}; - -static struct attribute_group mtr_platform_attribute_group = { - .attrs = mtr_platform_attributes -}; - -static struct platform_device *mts_io_platform_device; - -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; - - if (!DEVICE_CAPA(id_eeprom.capa, CAPA_DOUT)) { - log_debug("digital outputs not available"); - return -ENODEV; - } - - 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; - - if (!DEVICE_CAPA(id_eeprom.capa, CAPA_DIN)) { - log_debug("digital inputs not available"); - return -ENODEV; - } - - 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_dc_dout_probe(struct spi_device *spi) -{ - int tmp; - - if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { - log_error("daughter card digital outputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = dc_dout_max_speed_hz; - spi->mode = 0; - - log_debug("dc_dout_max_speed_hz: %d", dc_dout_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup dc dout failed"); - return tmp; - } - - spi_dc_dout_value = 0x00; - spi_writen(spi, &spi_dc_dout_value, 1); - - spi_dc_dout_dev = spi; - - return 0; -} - -static int mts_spi_dc_dout_remove(struct spi_device *spi) -{ - spi_dc_dout_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_dc_dout_driver = { - .driver = { - .name = "mts-io-dc-dout", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_dc_dout_probe, - .remove = mts_spi_dc_dout_remove, -}; - -static int mts_spi_dc_din_probe(struct spi_device *spi) -{ - int tmp; - - if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { - log_error("daughter card digital inputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = dc_din_max_speed_hz; - spi->mode = SPI_CPOL; - - log_debug("dc_din_max_speed_hz: %d", dc_din_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup daughter card din failed"); - return tmp; - } - - spi_dc_din_dev = spi; - - return 0; -} - -static int mts_spi_dc_din_remove(struct spi_device *spi) -{ - spi_dc_din_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_dc_din_driver = { - .driver = { - .name = "mts-io-dc-din", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_dc_din_probe, - .remove = mts_spi_dc_din_remove, -}; - -static int mts_spi_dc_adc_probe(struct spi_device *spi) -{ - int tmp; - - if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { - log_error("daughter card analog to digital not available"); - return -ENODEV; - } - - spi->max_speed_hz = dc_adc_max_speed_hz; - spi->mode = 0; - - log_debug("dc_adc_max_speed_hz: %d", dc_adc_max_speed_hz); - log_debug("dc_adc_mode: %d", spi->mode); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup daughter card adc failed"); - return tmp; - } - - spi_dc_adc_dev = spi; - - return 0; -} - -static int mts_spi_dc_adc_remove(struct spi_device *spi) -{ - spi_dc_adc_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_dc_adc_driver = { - .driver = { - .name = "mts-io-dc-adc", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_dc_adc_probe, - .remove = mts_spi_dc_adc_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, -}; +/* currently not supported +#include "mtcdp.c" +#include "mt100eocg.c" +*/ static int mts_dc_eeprom_load(void) { @@ -3688,6 +715,7 @@ static int __init mts_io_init(void) } } + /* ADC Setup */ #ifdef CONFIG_SOC_AT91SAM9X5 adc_base = ioremap(AT91SAM9X5_BASE_ADC, SZ_16K); #else @@ -3724,9 +752,9 @@ static int __init mts_io_init(void) } } - // No blink_callback for MT100EOCG + // No reset_callback for MT100EOCG if ( mts_product_id != MT100EOCG_0_0 ) { - blink_callback(NULL); + reset_callback(NULL); } return 0; @@ -3766,7 +794,7 @@ error1: static void __exit mts_io_exit(void) { if ( mts_product_id != MT100EOCG_0_0 ) { - cancel_delayed_work_sync(&blink_work); + cancel_delayed_work_sync(&reset_work); } iounmap(adc_base); diff --git a/io-module/mts_io.h b/io-module/mts_io.h index ad82b2a..0842f25 100644 --- a/io-module/mts_io.h +++ b/io-module/mts_io.h @@ -4,6 +4,25 @@ #include "mts_eeprom.h" #include <linux/gpio.h> +#define DEBUG 0 + +#define __log(level, name, format, args...) \ + printk(level "[" name "] " DRIVER_NAME ":%s:%d: " format "\n" , \ + __func__ , __LINE__ , ## args) + +#define log_emerg(format, args...) __log(KERN_EMERG, "EMERG", format , ## args) +#define log_alert(format, args...) __log(KERN_ALERT, "ALERT", format , ## args) +#define log_crit(format, args...) __log(KERN_CRIT, "CRIT", format , ## args) +#define log_error(format, args...) __log(KERN_ERR, "ERROR", format , ## args) +#define log_warning(format, args...) __log(KERN_WARNING, "WARNING", format , ## args) +#define log_notice(format, args...) __log(KERN_NOTICE, "NOTICE", format , ## args) +#define log_info(format, args...) __log(KERN_INFO, "INFO", format , ## args) +#if DEBUG +# define log_debug(format, args...) __log(KERN_DEBUG, "DEBUG", format , ## args) +#else +# define log_debug(format, args...) do {} while (0) +#endif + #define MTS_ATTR_MODE_RW S_IWUSR | S_IRUGO #define MTS_ATTR_MODE_RO S_IRUGO diff --git a/io-module/spi.c b/io-module/spi.c new file mode 100644 index 0000000..2da3f05 --- /dev/null +++ b/io-module/spi.c @@ -0,0 +1,767 @@ +/* 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_dc_dout_dev; +static u8 spi_dc_dout_value; +static DEFINE_MUTEX(spi_dc_dout_mutex); +static unsigned int dc_dout_max_speed_hz = 1 * 1000 * 1000; +module_param(dc_dout_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + dc_dout_max_speed_hz, + "Maximum clock rate to be used with this device (default: 1 MHz)" +); + +static struct spi_device *spi_dc_din_dev; +static unsigned int dc_din_max_speed_hz = 1 * 1000 * 1000; +module_param(dc_din_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + dc_din_max_speed_hz, + "Maximum clock rate to be used with this device (default: 1 MHz)" +); + +static struct spi_device *spi_dc_adc_dev; +static unsigned int dc_adc_max_speed_hz = 20 * 1000 * 1000; +module_param(dc_adc_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + dc_adc_max_speed_hz, + "Maximum clock rate to be used with this device (default: 20 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; + + if (!DEVICE_CAPA(id_eeprom.capa, CAPA_DOUT)) { + log_debug("digital outputs not available"); + return -ENODEV; + } + + 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; + + if (!DEVICE_CAPA(id_eeprom.capa, CAPA_DIN)) { + log_debug("digital inputs not available"); + return -ENODEV; + } + + 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_dc_dout_probe(struct spi_device *spi) +{ + int tmp; + + if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { + log_error("daughter card digital outputs not available"); + return -ENODEV; + } + + spi->max_speed_hz = dc_dout_max_speed_hz; + spi->mode = 0; + + log_debug("dc_dout_max_speed_hz: %d", dc_dout_max_speed_hz); + + tmp = spi_setup(spi); + if (tmp < 0) { + log_error("spi_setup dc dout failed"); + return tmp; + } + + spi_dc_dout_value = 0x00; + spi_writen(spi, &spi_dc_dout_value, 1); + + spi_dc_dout_dev = spi; + + return 0; +} + +static int mts_spi_dc_dout_remove(struct spi_device *spi) +{ + spi_dc_dout_dev = NULL; + + return 0; +} + +static struct spi_driver mts_spi_dc_dout_driver = { + .driver = { + .name = "mts-io-dc-dout", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = mts_spi_dc_dout_probe, + .remove = mts_spi_dc_dout_remove, +}; + +static int mts_spi_dc_din_probe(struct spi_device *spi) +{ + int tmp; + + if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { + log_error("daughter card digital inputs not available"); + return -ENODEV; + } + + spi->max_speed_hz = dc_din_max_speed_hz; + spi->mode = SPI_CPOL; + + log_debug("dc_din_max_speed_hz: %d", dc_din_max_speed_hz); + + tmp = spi_setup(spi); + if (tmp < 0) { + log_error("spi_setup daughter card din failed"); + return tmp; + } + + spi_dc_din_dev = spi; + + return 0; +} + +static int mts_spi_dc_din_remove(struct spi_device *spi) +{ + spi_dc_din_dev = NULL; + + return 0; +} + +static struct spi_driver mts_spi_dc_din_driver = { + .driver = { + .name = "mts-io-dc-din", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = mts_spi_dc_din_probe, + .remove = mts_spi_dc_din_remove, +}; + +static int mts_spi_dc_adc_probe(struct spi_device *spi) +{ + int tmp; + + if (! has_daughter_card || mts_dc_product_id != MTDC_GPIOB_0_0) { + log_error("daughter card analog to digital not available"); + return -ENODEV; + } + + spi->max_speed_hz = dc_adc_max_speed_hz; + spi->mode = 0; + + log_debug("dc_adc_max_speed_hz: %d", dc_adc_max_speed_hz); + log_debug("dc_adc_mode: %d", spi->mode); + + tmp = spi_setup(spi); + if (tmp < 0) { + log_error("spi_setup daughter card adc failed"); + return tmp; + } + + spi_dc_adc_dev = spi; + + return 0; +} + +static int mts_spi_dc_adc_remove(struct spi_device *spi) +{ + spi_dc_adc_dev = NULL; + + return 0; +} + +static struct spi_driver mts_spi_dc_adc_driver = { + .driver = { + .name = "mts-io-dc-adc", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = mts_spi_dc_adc_probe, + .remove = mts_spi_dc_adc_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, +}; diff --git a/io-module/telit_radio.c b/io-module/telit_radio.c new file mode 100644 index 0000000..fbac4fa --- /dev/null +++ b/io-module/telit_radio.c @@ -0,0 +1,219 @@ + +static int radio_off_telit(void) +{ + int value, ret; + struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + + if (!onoff_pin || !pwrmon_pin || !rst_pin) { + return -ENODEV; + } + + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value == 0) { + log_error("radio is already off"); + return -EINVAL; + } + + // drive on/off pin low for at least 3 sec + log_info("shutting down radio"); + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(3500); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + // wait for radio to power off + msleep(5000); + + // check that power is low + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value != 0) { + log_warning("radio is still on. performing radio reset."); + //Perform Hard Reset + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + } else { + log_info("radio has been shut down"); + } + + return ret; +} + +static int radio_on_telit(void) +{ + int value, ret; + struct gpio_pin *pwrmon_pin = gpio_pin_by_name("PWRMON"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + + if (!onoff_pin || !pwrmon_pin || !rst_pin) { + return -ENODEV; + } + + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value != 0) { + log_error("radio is already on"); + return -EINVAL; + } + + // drive on/off pin low for at least 5 sec + log_info("turning on radio"); + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(5500); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(200); + + // check that power is high + value = gpio_get_value(pwrmon_pin->pin.gpio); + if(value == 0) { + log_warning("radio is still off. performing radio reset"); + //Perform Hard Reset + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + } else { + log_info("radio has been turned on"); + } + + return ret; +} + +static ssize_t mts_attr_store_radio_power_telit(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; + } + if (value == 0) { + mutex_lock(&mts_io_mutex); + err = radio_off_telit(); + mutex_unlock(&mts_io_mutex); + } else { + mutex_lock(&mts_io_mutex); + err = radio_on_telit(); + mutex_unlock(&mts_io_mutex); + } + + if (err) { + return err; + } + + return count; +} + +static int radio_reset_telit(void) +{ + int ret; + struct gpio_pin *rst_pin = gpio_pin_by_name("3G_RST"); + struct gpio_pin *onoff_pin = gpio_pin_by_name("3G_ONOFF"); + + if (!rst_pin || !onoff_pin) { + return -ENODEV; + } + + // drive reset pin low for 500ms + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 0, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(500); + + // set pin high + ret = gpio_direction_output_pullup(rst_pin->pin.gpio, 1, rst_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + // wait for 2 sec before toggling on/off pin + msleep(2000); + + // drive on/off pin low for 6 sec + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 0, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + msleep(6000); + + // set on/off pin high + ret = gpio_direction_output_pullup(onoff_pin->pin.gpio, 1, onoff_pin->pin.flags & GPIOF_PULLUP); + if (ret) { + return ret; + } + + return ret; +} + +static ssize_t mts_attr_store_radio_reset_telit(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; + } + if (value != 0) { + return -EINVAL; + } + + mutex_lock(&mts_io_mutex); + + err = radio_reset_telit(); + + mutex_unlock(&mts_io_mutex); + + if (err) { + return err; + } + + return count; +} + +static DEVICE_ATTR_MTS(dev_attr_radio_power_telit, "radio-power", + mts_attr_show_gpio_pin, mts_attr_store_radio_power_telit); + +static DEVICE_ATTR_MTS(dev_attr_radio_reset_telit, "radio-reset", + mts_attr_show_gpio_pin, mts_attr_store_radio_reset_telit); |