summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--io-module/mts_io.c344
1 files 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
@@ -641,6 +641,14 @@ static struct gpio_pin gpio_pins_mtr2_0_0[] = {
.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",
.pin = AT91_PIN_PD21,
@@ -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");