diff options
Diffstat (limited to 'io-module/mtr2.c')
-rw-r--r-- | io-module/mtr2.c | 515 |
1 files changed, 515 insertions, 0 deletions
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 +}; |