From 01fdcfb50a2ac5b65f81f274e8329c20f6d7737d Mon Sep 17 00:00:00 2001 From: Mike Fiore Date: Wed, 5 Feb 2014 12:22:10 -0600 Subject: add daughter card gpio pins to mtr2 pin layout implement functions to show and store daughter card din and dout lines added appropriate daughter card gpio attributes(LED's, output enable) to sysfs for MTDC-GPIOB --- io-module/mts_io.c | 344 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 335 insertions(+), 9 deletions(-) diff --git a/io-module/mts_io.c b/io-module/mts_io.c index a7a5d75..b2c5045 100644 --- a/io-module/mts_io.c +++ b/io-module/mts_io.c @@ -640,6 +640,14 @@ static struct gpio_pin gpio_pins_mtr2_0_0[] = { .output_value = 1, .use_pullup = 0, }, + { + .name = "NDC_EEPROM_WRITE_PROTECT", + .attr_name = "dc-eeprom-wp", + .pin = AT91_PIN_PC26, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + }, { .name = "BT_EN", .attr_name = "bt-enabled", @@ -688,6 +696,54 @@ static struct gpio_pin gpio_pins_mtr2_0_0[] = { .output_value = 0, .use_pullup = 0, }, + { + .name = "NDC_GPIO1", + .attr_name = "dc-gpio1", + .pin = AT91_PIN_PC0, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "NDC_GPIO2", + .attr_name = "dc-gpio2", + .pin = AT91_PIN_PC14, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "NDC_GPIO3", + .attr_name = "dc-gpio3", + .pin = AT91_PIN_PC29, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "NDC_GPIO4", + .attr_name = "dc-gpio4", + .pin = AT91_PIN_PC30, + .direction = GPIO_DIR_OUTPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "NDC_INTERRUPT1", + .attr_name = "dc-int1", + .pin = AT91_PIN_PC20, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, + { + .name = "NDC_INTERRUPT2", + .attr_name = "dc-int2", + .pin = AT91_PIN_PC21, + .direction = GPIO_DIR_INPUT, + .output_value = 0, + .use_pullup = 0, + }, { }, }; @@ -1168,6 +1224,24 @@ MODULE_PARM_DESC( "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_board_temp_dev; static unsigned int board_temp_max_speed_hz = 1 * 1000 * 1000; module_param(board_temp_max_speed_hz, uint, S_IRUGO); @@ -1576,12 +1650,37 @@ static int ADT7302_to_celsius(int value) return value; } +static const char *daughter_card_normalize_attribute_names(const char *name) { + switch (mts_dc_product_id) { + case MTDC_GPIOB_0_0: + if (! strcmp(name, "dc-led1")) { + return "dc-gpio1"; + } else if (! strcmp(name, "dc-led2")) { + return "dc-gpio2"; + } else if (! strcmp(name, "dc-oe")) { + return "dc-gpio3"; + } else { + log_error("cannot normalize attribute %s to standard daughter card GPIO pin names", name); + return "unavailable"; + } + + default: + log_error("daughter card %d not supported at this time", mts_dc_product_id); + return "unavailable"; + } +} + 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); + struct gpio_pin *pin; + if (strstr(attr->attr.name, "dc-")) { + pin = gpio_pin_by_attr_name(daughter_card_normalize_attribute_names(attr->attr.name)); + } else { + pin = gpio_pin_by_attr_name(attr->attr.name); + } if (!pin) { return -ENODEV; @@ -1609,7 +1708,12 @@ static ssize_t mts_attr_store_gpio_pin(struct device *dev, { int value; int err; - struct gpio_pin *pin = gpio_pin_by_attr_name(attr->attr.name); + struct gpio_pin *pin; + if (strstr(attr->attr.name, "dc-")) { + pin = gpio_pin_by_attr_name(daughter_card_normalize_attribute_names(attr->attr.name)); + } else { + pin = gpio_pin_by_attr_name(attr->attr.name); + } if (!pin) { return -ENODEV; @@ -2500,20 +2604,112 @@ static DEVICE_ATTR_RO_MTS(dev_attr_eth_mac, "mac-eth", static ssize_t mts_attr_show_dc_din(struct device *dev, struct device_attribute *attr, char *buf) { - /* TODO: actually write this function */ - return sprintf(buf, "%d\n", 0); + 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, "dc-din0")) { + bit = BIT(0); + } else if (!strcmp(attr->attr.name, "dc-din1")) { + bit = BIT(1); + } else if (!strcmp(attr->attr.name, "dc-din2")) { + bit = BIT(2); + } else if (!strcmp(attr->attr.name, "dc-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) { - /* TODO: actually write this function */ - return 0; + int value; + u8 bit; + + if (!spi_dc_dout_dev) { + log_error("dc dout device not present"); + return -ENODEV; + } + + if (!strcmp(attr->attr.name, "dc-dout0")) { + bit = BIT(0); + } else if (!strcmp(attr->attr.name, "dc-dout1")) { + bit = BIT(1); + } else if (!strcmp(attr->attr.name, "dc-dout2")) { + bit = BIT(2); + } else if (!strcmp(attr->attr.name, "dc-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) { - /* TODO: actually write this function */ - return sprintf(buf, "%d\n", 0); + int value; + u8 bit; + + if (!spi_dc_dout_dev) { + log_error("dc dout device not present"); + return -ENODEV; + } + + if (!strcmp(attr->attr.name, "dc-dout0")) { + bit = BIT(0); + } else if (!strcmp(attr->attr.name, "dc-dout1")) { + bit = BIT(1); + } else if (!strcmp(attr->attr.name, "dc-dout2")) { + bit = BIT(2); + } else if (!strcmp(attr->attr.name, "dc-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) @@ -2522,7 +2718,7 @@ static ssize_t mts_attr_show_dc_adc(struct device *dev, struct device_attribute return sprintf(buf, "%lu\n", (unsigned long) 0); } -/* daughter card gpio */ +/* MTDC-GPIOB */ static DEVICE_ATTR_RO_MTS(dev_attr_dc_din0, "dc-din0", mts_attr_show_dc_din); static DEVICE_ATTR_RO_MTS(dev_attr_dc_din1, "dc-din1", mts_attr_show_dc_din); static DEVICE_ATTR_RO_MTS(dev_attr_dc_din2, "dc-din2", mts_attr_show_dc_din); @@ -2534,6 +2730,9 @@ static DEVICE_ATTR_MTS(dev_attr_dc_dout3, "dc-dout3", mts_attr_show_dc_dout, mts static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc0, "dc-adc0", mts_attr_show_dc_adc); static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc1, "dc-adc1", mts_attr_show_dc_adc); static DEVICE_ATTR_RO_MTS(dev_attr_dc_adc2, "dc-adc2", mts_attr_show_dc_adc); +static DEVICE_ATTR_MTS(dev_attr_dc_led1, "dc-led1", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_MTS(dev_attr_dc_led2, "dc-led2", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); +static DEVICE_ATTR_MTS(dev_attr_dc_oe, "dc-oe", mts_attr_show_gpio_pin, mts_attr_store_gpio_pin); static struct attribute *mt100eocg_platform_attributes[] = { &dev_attr_vendor_id.attr, @@ -2636,6 +2835,11 @@ struct attribute *mtr2_platform_attributes[] = { 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, }; @@ -2654,6 +2858,10 @@ static struct attribute *mtr2_daughter_card_attributes[] = { &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, }; @@ -2929,6 +3137,95 @@ static struct spi_driver mts_spi_din_driver = { .remove = __devexit_p(mts_spi_din_remove), }; +static int __devinit 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 = __devexit_p(mts_spi_dc_dout_remove), +}; + +static int __devinit 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 = __devexit_p(mts_spi_dc_din_remove), +}; + static int __devinit mts_spi_board_temp_probe(struct spi_device *spi) { int tmp; @@ -3173,6 +3470,21 @@ static int __init mts_io_init(void) } else { log_info("successfully added GPIO daughter card attributes"); } + + log_info("registering daughter card dout driver"); + ret = spi_register_driver(&mts_spi_dc_dout_driver); + if (ret) { + log_error("failed to register dc dout driver"); + spi_unregister_driver(&mts_spi_dc_dout_driver); + goto error1; + } + log_info("registering daughter card din driver"); + ret = spi_register_driver(&mts_spi_dc_din_driver); + if (ret) { + log_error("failed to register dc din driver"); + spi_unregister_driver(&mts_spi_dc_din_driver); + goto error1; + } break; default: @@ -3338,6 +3650,18 @@ static void __exit mts_io_exit(void) if (has_spi_sout) spi_unregister_driver(&mts_spi_sout_driver); + if (has_daughter_card) { + switch (mts_dc_product_id) { + case MTDC_GPIOB_0_0: + spi_unregister_driver(&mts_spi_dc_dout_driver); + spi_unregister_driver(&mts_spi_dc_din_driver); + break; + + default: + break; + } + } + sysfs_remove_group(&mts_io_platform_device->dev.kobj, attr_group); sysfs_remove_link(&mts_io_platform_device->dev.parent->kobj, "mtcdp"); @@ -3359,3 +3683,5 @@ MODULE_ALIAS("mts-io-sout"); MODULE_ALIAS("mts-io-board-temp"); MODULE_ALIAS("mts-io-dout"); MODULE_ALIAS("mts-io-din"); +MODULE_ALIAS("mts-io-dc-dout"); +MODULE_ALIAS("mts-io-dc-din"); -- cgit v1.2.3