diff options
author | Mike Fiore <mfiore@multitech.com> | 2014-09-23 10:35:11 -0500 |
---|---|---|
committer | Mike Fiore <mfiore@multitech.com> | 2014-09-23 10:35:11 -0500 |
commit | a21c24fa2486e4d4a3b25d0dcbf873ae62fdbcec (patch) | |
tree | 6d78da220c6235cd33408acbd22adf9b4038bbc1 /io-module | |
parent | 24c012065ca7a764e1e51a9cfc4422d649cd2851 (diff) | |
download | mts-io-a21c24fa2486e4d4a3b25d0dcbf873ae62fdbcec.tar.gz mts-io-a21c24fa2486e4d4a3b25d0dcbf873ae62fdbcec.tar.bz2 mts-io-a21c24fa2486e4d4a3b25d0dcbf873ae62fdbcec.zip |
mts-io: clean up accessory card support
use custom kernel config option MTS_NUM_ACCESSORY_PORTS to find out how many slots exist
(mostly) dynamically handle any number of accessory cards
streamline code to make it easier to add accessory cards in the future
Diffstat (limited to 'io-module')
-rw-r--r-- | io-module/Makefile | 1 | ||||
-rw-r--r-- | io-module/mtac.c | 22 | ||||
-rw-r--r-- | io-module/mtac_gpiob.c | 552 | ||||
-rw-r--r-- | io-module/mtac_mfser.c | 106 | ||||
-rw-r--r-- | io-module/mtr2d2.c | 7 | ||||
-rw-r--r-- | io-module/mts_io.c | 376 | ||||
-rw-r--r-- | io-module/mts_io.h | 20 | ||||
-rw-r--r-- | io-module/spi.c | 295 |
8 files changed, 532 insertions, 847 deletions
diff --git a/io-module/Makefile b/io-module/Makefile index f95a55e..5d036f4 100644 --- a/io-module/Makefile +++ b/io-module/Makefile @@ -1,5 +1,4 @@ obj-m := mts_io.o -CFLAGS_mts_io.o := ${DAUGHTER_CARD} clean: rm -f *.ko *.o diff --git a/io-module/mtac.c b/io-module/mtac.c new file mode 100644 index 0000000..b9a2520 --- /dev/null +++ b/io-module/mtac.c @@ -0,0 +1,22 @@ +static struct kobj_attribute* create_attribute(const char* _name, umode_t _mode) { + char* attr_name; + struct kobj_attribute* _attr; + + _attr = kzalloc(sizeof(struct kobj_attribute), GFP_KERNEL); + if (! _attr) { + log_error("kzalloc of attribute %s failed", _name); + return NULL; + } + + sysfs_attr_init(_attr); + attr_name = kstrdup(_name, GFP_KERNEL); + if (! attr_name) { + log_error("GFP_KERNEL dup failed for attribute [%s]", _name); + return NULL; + } + + _attr->attr.name = attr_name; + _attr->attr.mode = _mode; + + return _attr; +} diff --git a/io-module/mtac_gpiob.c b/io-module/mtac_gpiob.c index 5a592b7..728634d 100644 --- a/io-module/mtac_gpiob.c +++ b/io-module/mtac_gpiob.c @@ -1,22 +1,130 @@ +struct spi_device *gpiob_spi[NUM_AP][3]; +struct spi_driver gpiob_spi_drivers[NUM_AP][3]; + +static u8 spi_ap_dout_value; +static DEFINE_MUTEX(spi_ap_dout_mutex); +static unsigned int ap_dout_max_speed_hz = 1 * 1000 * 1000; +module_param(ap_dout_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + ap_dout_max_speed_hz, + "Maximum clock rate to be used with this device (default: 1 MHz)" +); + +static unsigned int ap_din_max_speed_hz = 1 * 1000 * 1000; +module_param(ap_din_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + ap_din_max_speed_hz, + "Maximum clock rate to be used with this device (default: 1 MHz)" +); + +static unsigned int ap_adc_max_speed_hz = 20 * 1000 * 1000; +module_param(ap_adc_max_speed_hz, uint, S_IRUGO); +MODULE_PARM_DESC( + ap_adc_max_speed_hz, + "Maximum clock rate to be used with this device (default: 20 MHz)" +); + +static bool gpiob_get_dev_info_from_modalias(const char* modalias, int* port, char* buf) { + sscanf(modalias, "mts-io-ap%d-%s", port, buf); + + return true; +} + +static int mts_spi_ap_probe(struct spi_device *spi) +{ + int tmp; + int port; + int port_index; + char buf[16]; + enum spi_devices dev; + + gpiob_get_dev_info_from_modalias(spi->modalias, &port, buf); + port_index = port - 1; + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); + return -ENODEV; + } + + if (strstr(buf, "dout")) { + dev = dout; + spi->max_speed_hz = ap_dout_max_speed_hz; + spi->mode = 0; + } else if (strstr(buf, "din")) { + dev = din; + spi->max_speed_hz = ap_din_max_speed_hz; + spi->mode = SPI_CPOL; + } else if (strstr(buf, "adc")) { + dev = adc; + spi->max_speed_hz = ap_adc_max_speed_hz; + spi->mode = 0; + } else { + log_error("unknown gpiob spi device type [%s]", buf); + return -ENODEV; + } + + gpiob_spi[port_index][dev] = spi; + + tmp = spi_setup(gpiob_spi[port_index][dev]); + if (tmp < 0) { + log_error("spi_setup ap %d %s failed", port, buf); + return tmp; + } + + if (dev == dout) { + spi_ap_dout_value = 0x00; + spi_writen(gpiob_spi[port_index][dev], &spi_ap_dout_value, 1); + } + + return 0; +} + +static int mts_spi_ap_remove(struct spi_device *spi) +{ + int port; + int port_index; + char buf[16]; + + gpiob_get_dev_info_from_modalias(spi->modalias, &port, buf); + port_index = port - 1; + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); + return -ENODEV; + } + + if (strstr(buf, "dout")) { + gpiob_spi[port_index][dout] = NULL; + } else if (strstr(buf, "din")) { + gpiob_spi[port_index][din] = NULL; + } else if (strstr(buf, "adc")) { + gpiob_spi[port_index][adc] = NULL; + } else { + log_error("unknown gpiob spi device type [%s]", buf); + return -ENODEV; + } + + return 0; +} + +// Is there a way to make this dynamic as well? struct gpio_pin *ap_gpio_pin_by_attr_name(const char *name) { struct gpio_pin *pin; char *pin_attr_name; - if (!strcmp(name, "ap1-led1")) { + if (!strcmp(name, "ap-led1:1")) { pin_attr_name = "ap1-gpio3"; - } else if (!strcmp(name, "ap1-led2")) { + } else if (!strcmp(name, "ap-led2:1")) { pin_attr_name = "ap1-gpio4"; - } else if (!strcmp(name, "ap1-dout-enable")) { + } else if (!strcmp(name, "ap-dout-enable:1")) { pin_attr_name = "ap1-gpio1"; - } else if (!strcmp(name, "ap1-reset")) { + } else if (!strcmp(name, "ap-reset:1")) { pin_attr_name = "ap1-reset"; - } else if (!strcmp(name, "ap2-led1")) { + } else if (!strcmp(name, "ap-led1:2")) { pin_attr_name = "ap2-gpio3"; - } else if (!strcmp(name, "ap2-led2")) { + } else if (!strcmp(name, "ap-led2:2")) { pin_attr_name = "ap2-gpio4"; - } else if (!strcmp(name, "ap2-dout-enable")) { + } else if (!strcmp(name, "ap-dout-enable:2")) { pin_attr_name = "ap2-gpio1"; - } else if (!strcmp(name, "ap2-reset")) { + } else if (!strcmp(name, "ap-reset:2")) { pin_attr_name = "ap2-reset"; } else { log_error("accessory card attribute %s not available", name); @@ -35,8 +143,8 @@ struct gpio_pin *ap_gpio_pin_by_attr_name(const char *name) { } -static ssize_t mts_attr_show_ap_gpio_pin(struct device *dev, - struct device_attribute *attr, +static ssize_t mts_attr_show_ap_gpio_pin(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int value; @@ -63,8 +171,8 @@ static ssize_t mts_attr_show_ap_gpio_pin(struct device *dev, return sprintf(buf, "%d\n", value); } -static ssize_t mts_attr_store_ap_gpio_pin(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_ap_gpio_pin(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int value; struct gpio_pin *pin = ap_gpio_pin_by_attr_name(attr->attr.name); @@ -90,46 +198,29 @@ static ssize_t mts_attr_store_ap_gpio_pin(struct device *dev, return count; } -static ssize_t mts_attr_show_ap_din(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t mts_attr_show_ap_din(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int tmp; + int channel; + int port; + int port_index; u8 bit; u8 byte; - struct spi_device* spi_dev; - if (strstr(attr->attr.name, ":0")) { - if (!spi_ap1_din_dev) { - log_error("accessory card 1 din device not present"); - return -ENODEV; - } - - spi_dev = spi_ap1_din_dev; - } else if (strstr(attr->attr.name, ":1")) { - if (!spi_ap2_din_dev) { - log_error("accessory card 2 din device not present"); - return -ENODEV; - } - - spi_dev = spi_ap2_din_dev; - } else { - log_error("unknown din device %s", attr->attr.name); - return -ENODEV; + sscanf(attr->attr.name, "din%d:%d", &channel, &port); + port_index = port - 1; + if (channel < 0 || channel > 3) { + log_error("channel [%d] is invalid", channel); + return -ENOENT; } - - if (strstr(attr->attr.name, "din0")) { - bit = BIT(0); - } else if (strstr(attr->attr.name, "din1")) { - bit = BIT(1); - } else if (strstr(attr->attr.name, "din2")) { - bit = BIT(2); - } else if (strstr(attr->attr.name, "din3")) { - bit = BIT(3); - } else { - log_error("accessory card din attr does not exist"); + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); return -ENOENT; } - tmp = spi_readn(spi_dev, &byte, 1); + bit = BIT(channel); + + tmp = spi_readn(gpiob_spi[port_index][din], &byte, 1); if (tmp) { log_error("spi_read failed %d", tmp); return tmp; @@ -140,46 +231,29 @@ static ssize_t mts_attr_show_ap_din(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", tmp); } -static ssize_t mts_attr_store_ap_dout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_ap_dout(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) { int value; + int channel; + int port; + int port_index; u8 bit; - struct spi_device* spi_dev; - - if (strstr(attr->attr.name, ":0")) { - if (!spi_ap1_dout_dev) { - log_error("accessory card 1 dout device not present"); - return -ENODEV; - } - spi_dev = spi_ap1_dout_dev; - } else if (strstr(attr->attr.name, ":1")) { - if (!spi_ap2_dout_dev) { - log_error("accessory card 2 dout device not present"); - return -ENODEV; - } - - spi_dev = spi_ap2_dout_dev; - } else { - log_error("unknown dout device %s", attr->attr.name); - return -ENODEV; + sscanf(attr->attr.name, "dout%d:%d", &channel, &port); + port_index = port - 1; + if (channel < 0 || channel > 3) { + log_error("channel [%d] is invalid", channel); + return -ENOENT; } - - if (strstr(attr->attr.name, "dout0")) { - bit = BIT(0); - } else if (strstr(attr->attr.name, "dout1")) { - bit = BIT(1); - } else if (strstr(attr->attr.name, "dout2")) { - bit = BIT(2); - } else if (strstr(attr->attr.name, "dout3")) { - bit = BIT(3); - } else { - log_error("accessory card dout attr does not exist"); + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); return -ENOENT; } + bit = BIT(channel); + if (sscanf(buf, "%i", &value) != 1) { - log_error("accessory card dout attr invalid argument"); + log_error("accessory card dout attr invalid argument [%d]", value); return -EINVAL; } @@ -191,51 +265,32 @@ static ssize_t mts_attr_store_ap_dout(struct device *dev, struct device_attribut spi_ap_dout_value |= bit; } - spi_writen(spi_dev, &spi_ap_dout_value, 1); + spi_writen(gpiob_spi[port_index][dout], &spi_ap_dout_value, 1); mutex_unlock(&spi_ap_dout_mutex); return count; } -static ssize_t mts_attr_show_ap_dout(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t mts_attr_show_ap_dout(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int value; + int channel; + int port; u8 bit; - struct spi_device* spi_dev; - if (strstr(attr->attr.name, ":0")) { - if (!spi_ap1_dout_dev) { - log_error("accessory card 1 dout device not present"); - return -ENODEV; - } - - spi_dev = spi_ap1_dout_dev; - } else if (strstr(attr->attr.name, ":1")) { - if (!spi_ap2_dout_dev) { - log_error("accessory card 2 dout device not present"); - return -ENODEV; - } - - spi_dev = spi_ap2_dout_dev; - } else { - log_error("unknown dout device %s", attr->attr.name); - return -ENODEV; + sscanf(attr->attr.name, "dout%d:%d", &channel, &port); + if (channel < 0 || channel > 3) { + log_error("channel [%d] is invalid", channel); + return -ENOENT; } - - if (strstr(attr->attr.name, "dout0")) { - bit = BIT(0); - } else if (strstr(attr->attr.name, "dout1")) { - bit = BIT(1); - } else if (strstr(attr->attr.name, "dout2")) { - bit = BIT(2); - } else if (strstr(attr->attr.name, "dout3")) { - bit = BIT(3); - } else { - log_error("accessory card dout attr does not exist"); + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); return -ENOENT; } + bit = BIT(channel); + mutex_lock(&spi_ap_dout_mutex); value = spi_ap_dout_value & bit ? 0 : 1; @@ -245,48 +300,30 @@ static ssize_t mts_attr_show_ap_dout(struct device *dev, struct device_attribute return sprintf(buf, "%d\n", value); } -static ssize_t mts_attr_show_ap_adc(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t mts_attr_show_ap_adc(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { int tmp; int tx_data; int rx_data; int channel; + int port; + int port_index; 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]; - struct spi_device* spi_dev; memset(tx, 0, sizeof(tx)); memset(rx, 0, sizeof(rx)); - if (strstr(attr->attr.name, ":0")) { - if (!spi_ap1_adc_dev) { - log_error("accessory card 1 adc device not present"); - return -ENODEV; - } - - spi_dev = spi_ap1_adc_dev; - } else if (strstr(attr->attr.name, ":1")) { - if (!spi_ap2_adc_dev) { - log_error("accessory card 2 adc device not present"); - return -ENODEV; - } - - spi_dev = spi_ap2_adc_dev; - } else { - log_error("unknown adc device %s", attr->attr.name); - return -ENODEV; + sscanf(attr->attr.name, "adc%d:%d", &channel, &port); + port_index = port - 1; + if (channel < 0 || channel > 2) { + log_error("channel [%d] is invalid", channel); + return -ENOENT; } - - if (strstr(attr->attr.name, "adc0")) { - channel = 0; - } else if (strstr(attr->attr.name, "adc1")) { - channel = 1; - } else if (strstr(attr->attr.name, "adc2")) { - channel = 2; - } else { - log_error("accessory card adc attr does not exist"); + if (port < 1 || port > NUM_AP) { + log_error("port [%d] is invalid", port); return -ENOENT; } @@ -294,7 +331,7 @@ static ssize_t mts_attr_show_ap_adc(struct device *dev, struct device_attribute tx_data = manual_mode | ((channel << 7) & channel_mask); tx[0] = tx_data >> 8; tx[1] = tx_data & 0xFF; - tmp = spi_writen(spi_dev, tx, 2); + tmp = spi_writen(gpiob_spi[port_index][adc], tx, 2); if (tmp) { log_error("spi_write failed %d", tmp); return tmp; @@ -305,14 +342,14 @@ static ssize_t mts_attr_show_ap_adc(struct device *dev, struct device_attribute * the ADC just needs the clock running so it can convert */ tx[0] = 0; tx[1] = 0; - tmp = spi_writen(spi_dev, tx, 2); + tmp = spi_writen(gpiob_spi[port_index][adc], tx, 2); if (tmp) { log_error("2nd spi_write failed %d", tmp); return tmp; } /* 3rd transfer to read data */ - tmp = spi_readn(spi_dev, rx, 2); + tmp = spi_readn(gpiob_spi[port_index][adc], rx, 2); if (tmp) { log_error("spi_read failed %d", tmp); return tmp; @@ -322,88 +359,165 @@ static ssize_t mts_attr_show_ap_adc(struct device *dev, struct device_attribute return sprintf(buf, "%lu\n", (unsigned long) rx_data); } -/* accessory port 1 gpiob attributes */ -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_din0, "din0:0", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_din1, "din1:0", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_din2, "din2:0", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_din3, "din3:0", mts_attr_show_ap_din); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_dout0, "dout0:0", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_dout1, "dout1:0", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_dout2, "dout2:0", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_dout3, "dout3:0", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_adc0, "adc0:0", mts_attr_show_ap_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_adc1, "adc1:0", mts_attr_show_ap_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_ap1_gpio_adc2, "adc2:0", mts_attr_show_ap_adc); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_led1, "ap1-led1", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_led2, "ap1-led2", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap1_gpio_oe, "ap1-dout-enable", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap1_reset, "ap1-reset", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); - -static int ap1_gpio_attributes_size = 15; // not including NULL at end - -static struct attribute *ap1_gpio_attributes[] = { - &dev_attr_ap1_reset.attr, - - &dev_attr_ap1_gpio_oe.attr, // gpio1 - &dev_attr_ap1_gpio_led1.attr, // gpio3 - &dev_attr_ap1_gpio_led2.attr, // gpio4 - - &dev_attr_ap1_gpio_din0.attr, - &dev_attr_ap1_gpio_din1.attr, - &dev_attr_ap1_gpio_din2.attr, - &dev_attr_ap1_gpio_din3.attr, - - &dev_attr_ap1_gpio_dout0.attr, - &dev_attr_ap1_gpio_dout1.attr, - &dev_attr_ap1_gpio_dout2.attr, - &dev_attr_ap1_gpio_dout3.attr, - - &dev_attr_ap1_gpio_adc0.attr, - &dev_attr_ap1_gpio_adc1.attr, - &dev_attr_ap1_gpio_adc2.attr, - - NULL, -}; +static bool gpiob_spi_driver_setup(struct spi_driver *driver, const char *driver_name) { + char* name = kstrdup(driver_name, GFP_KERNEL); + if (! name) { + log_error("GFP_KERNEL dup failed for driver [%s]", driver_name); + return false; + } + driver->driver.name = name; + driver->driver.bus = &spi_bus_type; + driver->driver.owner = THIS_MODULE; + driver->probe = mts_spi_ap_probe; + driver->remove = mts_spi_ap_remove; + + return true; +} + +// 4 digital inputs +// 4 digital outputs +// 3 analog to digital +// 2 LEDs +// 1 digital out enable +// 1 reset +static int ap_gpiob_attrs_size = 15; + +static bool gpiob_setup(enum ap port) { + int i; + int port_index = port - 1; + struct kobj_attribute *attr; + char buf[32]; + + log_info("loading GPIOB accessory card in port %d", port); + + if (device_attrs_size + ap_gpiob_attrs_size >= device_attrs_max_size) { + log_error("can't load GPIOB accessory card in port %d - not enough room for attributes", port); + return false; + } + + // add digital inputs + for (i = 0; i < 4; i++) { + sprintf(buf, "din%d:%d", i, port); + attr = create_attribute(buf, MTS_ATTR_MODE_RO); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_din; + device_attrs[device_attrs_size++] = &attr->attr; + } + + // add digital outputs + for (i = 0; i < 4; i++) { + sprintf(buf, "dout%d:%d", i, port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_dout; + attr->store = mts_attr_store_ap_dout; + device_attrs[device_attrs_size++] = &attr->attr; + } + + // add analog to digital + for (i = 0; i < 3; i++) { + sprintf(buf, "adc%d:%d", i, port); + attr = create_attribute(buf, MTS_ATTR_MODE_RO); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_adc; + device_attrs[device_attrs_size++] = &attr->attr; + } + + // add LEDs + for (i = 1; i <= 2; i++) { + sprintf(buf, "ap-led%d:%d", i, port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_gpio_pin; + attr->store = mts_attr_store_ap_gpio_pin; + device_attrs[device_attrs_size++] = &attr->attr; + } + + // misc attributes + sprintf(buf, "ap-dout-enable:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_gpio_pin; + attr->store = mts_attr_store_ap_gpio_pin; + device_attrs[device_attrs_size++] = &attr->attr; + + sprintf(buf, "ap-reset:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_gpio_pin; + attr->store = mts_attr_store_ap_gpio_pin; + device_attrs[device_attrs_size++] = &attr->attr; + + // setup and register drivers + log_debug("registering accessory card %d dout driver", port); + sprintf(buf, "mts-io-ap%d-dout", port); + if (! gpiob_spi_driver_setup(&gpiob_spi_drivers[port_index][dout], buf)) { + log_error("failed to set up spi driver [%s]", buf); + return false; + } + if (spi_register_driver(&gpiob_spi_drivers[port_index][dout])) { + log_error("failed to register accessory card %d dout driver", port); + spi_unregister_driver(&gpiob_spi_drivers[port_index][dout]); + return false; + } + + log_debug("registering accessory card %d din driver", port); + sprintf(buf, "mts-io-ap%d-din", port); + if (! gpiob_spi_driver_setup(&gpiob_spi_drivers[port_index][din], buf)) { + log_error("failed to set up spi driver [%s]", buf); + return false; + } + if (spi_register_driver(&gpiob_spi_drivers[port_index][din])) { + log_error("failed to register accessory card %d din driver", port); + spi_unregister_driver(&gpiob_spi_drivers[port_index][din]); + return false; + } + + log_debug("registering accessory card %d adc driver", port); + sprintf(buf, "mts-io-ap%d-adc", port); + if (! gpiob_spi_driver_setup(&gpiob_spi_drivers[port_index][adc], buf)) { + log_error("failed to set up spi driver [%s]", buf); + return false; + } + if (spi_register_driver(&gpiob_spi_drivers[port_index][adc])) { + log_error("failed to register accessory card %d adc driver", port); + spi_unregister_driver(&gpiob_spi_drivers[port_index][adc]); + return false; + } + return true; +} + +static bool gpiob_teardown(enum ap port) { + int port_index = port - 1; + + // do we need to clean up allocated memory here as well? + log_info("unloading GPIOB accessory card in port %d", port); + spi_unregister_driver(&gpiob_spi_drivers[port_index][dout]); + spi_unregister_driver(&gpiob_spi_drivers[port_index][din]); + spi_unregister_driver(&gpiob_spi_drivers[port_index][adc]); + return true; +} -/* accessory port 2 gpiob attributes */ -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_din0, "din0:1", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_din1, "din1:1", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_din2, "din2:1", mts_attr_show_ap_din); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_din3, "din3:1", mts_attr_show_ap_din); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_dout0, "dout0:1", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_dout1, "dout1:1", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_dout2, "dout2:1", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_dout3, "dout3:1", mts_attr_show_ap_dout, mts_attr_store_ap_dout); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_adc0, "adc0:1", mts_attr_show_ap_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_adc1, "adc1:1", mts_attr_show_ap_adc); -static DEVICE_ATTR_RO_MTS(dev_attr_ap2_gpio_adc2, "adc2:1", mts_attr_show_ap_adc); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_led1, "ap2-led1", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_led2, "ap2-led2", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap2_gpio_oe, "ap2-dout-enable", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); -static DEVICE_ATTR_MTS(dev_attr_ap2_reset, "ap2-reset", mts_attr_show_ap_gpio_pin, mts_attr_store_ap_gpio_pin); - -static int ap2_gpio_attributes_size = 15; // not including NULL at end - -static struct attribute *ap2_gpio_attributes[] = { - &dev_attr_ap2_reset.attr, - - &dev_attr_ap2_gpio_oe.attr, // gpio1 - &dev_attr_ap2_gpio_led1.attr, // gpio3 - &dev_attr_ap2_gpio_led2.attr, // gpio4 - - &dev_attr_ap2_gpio_din0.attr, - &dev_attr_ap2_gpio_din1.attr, - &dev_attr_ap2_gpio_din2.attr, - &dev_attr_ap2_gpio_din3.attr, - - &dev_attr_ap2_gpio_dout0.attr, - &dev_attr_ap2_gpio_dout1.attr, - &dev_attr_ap2_gpio_dout2.attr, - &dev_attr_ap2_gpio_dout3.attr, - - &dev_attr_ap2_gpio_adc0.attr, - &dev_attr_ap2_gpio_adc1.attr, - &dev_attr_ap2_gpio_adc2.attr, - - NULL, +static struct ap_info gpiob_info = { + .product_id = MTAC_GPIOB_0_0, + .setup = &gpiob_setup, + .teardown = &gpiob_teardown }; diff --git a/io-module/mtac_mfser.c b/io-module/mtac_mfser.c index 14eddd1..5871bfe 100644 --- a/io-module/mtac_mfser.c +++ b/io-module/mtac_mfser.c @@ -2,13 +2,13 @@ struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { struct gpio_pin *pin; char *pin_attr_name; - if (!strcmp(name, "rs4xx-term-res:0")) { + if (!strcmp(name, "rs4xx-term-res:1")) { pin_attr_name = "ap1-gpio3"; - } else if (!strcmp(name, "rts-override:0")) { + } else if (!strcmp(name, "rts-override:1")) { pin_attr_name = "ap1-gpio4"; - } else if (!strcmp(name, "rs4xx-term-res:1")) { + } else if (!strcmp(name, "rs4xx-term-res:2")) { pin_attr_name = "ap2-gpio3"; - } else if (!strcmp(name, "rts-override:1")) { + } else if (!strcmp(name, "rts-override:2")) { pin_attr_name = "ap2-gpio4"; } else { log_error("accessory card attribute %s not available", name); @@ -27,8 +27,8 @@ struct gpio_pin *ap_mfser_pin_by_attr_name(const char *name) { } -static ssize_t mts_attr_show_ap_mfser_pin(struct device *dev, - struct device_attribute *attr, +static ssize_t mts_attr_show_ap_mfser_pin(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int value; @@ -55,8 +55,8 @@ static ssize_t mts_attr_show_ap_mfser_pin(struct device *dev, return sprintf(buf, "%d\n", value); } -static ssize_t mts_attr_store_ap_mfser_pin(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_ap_mfser_pin(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int value; struct gpio_pin *pin = ap_mfser_pin_by_attr_name(attr->attr.name); @@ -82,8 +82,8 @@ static ssize_t mts_attr_store_ap_mfser_pin(struct device *dev, return count; } -static ssize_t mts_attr_show_mfser_mode(struct device *dev, - struct device_attribute *attr, +static ssize_t mts_attr_show_mfser_mode(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int ret; @@ -93,11 +93,11 @@ static ssize_t mts_attr_show_mfser_mode(struct device *dev, struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":0")) { + if (strstr(attr->attr.name, ":1")) { pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); } - else if (strstr(attr->attr.name, ":1")) { + else if (strstr(attr->attr.name, ":2")) { pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); } @@ -130,19 +130,19 @@ static ssize_t mts_attr_show_mfser_mode(struct device *dev, return ret; } -static ssize_t mts_attr_store_mfser_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mts_attr_store_mfser_mode(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) { int modesel0; int modesel1; struct gpio_pin *pin_modesel0; struct gpio_pin *pin_modesel1; - if (strstr(attr->attr.name, ":0")) { + if (strstr(attr->attr.name, ":1")) { pin_modesel0 = gpio_pin_by_name("AP1_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP1_GPIO2"); } - else if (strstr(attr->attr.name, ":1")) { + else if (strstr(attr->attr.name, ":2")) { pin_modesel0 = gpio_pin_by_name("AP2_GPIO1"); pin_modesel1 = gpio_pin_by_name("AP2_GPIO2"); } @@ -184,32 +184,62 @@ static ssize_t mts_attr_store_mfser_mode(struct device *dev, return count; } -/* accessory port 1 serial attributes */ -static DEVICE_ATTR_MTS(dev_attr_ap1_serial_mode, "serial-mode:0", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); -static DEVICE_ATTR_MTS(dev_attr_ap1_rs4xx_term_res, "rs4xx-term-res:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); -static DEVICE_ATTR_MTS(dev_attr_ap1_rts_override, "rts-override:0", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); +// 1 serial mode +// 1 rs4xx term resistor +// 1 rts override +static int ap_mfser_attrs_size = 3; -static int ap1_mfser_attributes_size = 3; // not including NULL at end +static bool mfser_setup(enum ap port) { + struct kobj_attribute *attr; + char buf[32]; -static struct attribute *ap1_mfser_attributes[] = { - &dev_attr_ap1_serial_mode.attr, - &dev_attr_ap1_rs4xx_term_res.attr, // gpio3 - &dev_attr_ap1_rts_override.attr, // gpio4 - NULL, -}; + log_info("loading MFSER accessory card in port %d", port); -/* accessory port 2 serial attributes */ -static DEVICE_ATTR_MTS(dev_attr_ap2_serial_mode, "serial-mode:1", mts_attr_show_mfser_mode, mts_attr_store_mfser_mode); -static DEVICE_ATTR_MTS(dev_attr_ap2_rs4xx_term_res, "rs4xx-term-res:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); -static DEVICE_ATTR_MTS(dev_attr_ap2_rts_override, "rts-override:1", mts_attr_show_ap_mfser_pin, mts_attr_store_ap_mfser_pin); + if (device_attrs_size + ap_mfser_attrs_size >= device_attrs_max_size) { + log_error("can't load MFSER accessory card in port %d - not enough room for attributes", port); + return false; + } -static int ap2_mfser_attributes_size = 3; // not including NULL at end + sprintf(buf, "serial-mode:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_mfser_mode; + attr->store = mts_attr_store_mfser_mode; + device_attrs[device_attrs_size++] = &attr->attr; -static struct attribute *ap2_mfser_attributes[] = { - &dev_attr_ap2_serial_mode.attr, - &dev_attr_ap2_rs4xx_term_res.attr, // gpio3 - &dev_attr_ap2_rts_override.attr, // gpio4 - NULL, -}; + sprintf(buf, "rs4xx-term-res:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_mfser_pin; + attr->store = mts_attr_store_ap_mfser_pin; + device_attrs[device_attrs_size++] = &attr->attr; + sprintf(buf, "rts-override:%d", port); + attr = create_attribute(buf, MTS_ATTR_MODE_RW); + if (! attr) { + log_error("failed to create attribute[%s]", buf); + return false; + } + attr->show = mts_attr_show_ap_mfser_pin; + attr->store = mts_attr_store_ap_mfser_pin; + device_attrs[device_attrs_size++] = &attr->attr; + + return true; +} +static bool mfser_teardown(enum ap port) { + log_info("unloading MFSER accessory card in port %d", port); + return true; +} + +static struct ap_info mfser_info = { + .product_id = MTAC_MFSER_0_0, + .setup = &mfser_setup, + .teardown = &mfser_teardown +}; diff --git a/io-module/mtr2d2.c b/io-module/mtr2d2.c index 0926952..24a99f3 100644 --- a/io-module/mtr2d2.c +++ b/io-module/mtr2d2.c @@ -1,4 +1,3 @@ - static struct gpio_pin gpio_pins_mtr2d2_0_0[] = { { .name = "RADIO_RESET", @@ -266,7 +265,8 @@ static struct gpio_pin gpio_pins_mtr2d2_0_0[] = { { }, }; -static int mtr2d2_platform_attributes_size = 64; // not including NULL at end +static int mtr2d2_platform_attributes_max_size = 64; // including NULL at end +static int mtr2d2_platform_attributes_size = 21; static struct attribute *mtr2d2_platform_attributes[] = { &dev_attr_vendor_id.attr, @@ -295,6 +295,8 @@ static struct attribute *mtr2d2_platform_attributes[] = { &dev_attr_board_temperature.attr, /* extra space for the accessory card attributes */ + NULL, // index 21 + NULL, // index 22 NULL, // index 23 NULL, // index 24 NULL, // index 25 @@ -336,7 +338,6 @@ static struct attribute *mtr2d2_platform_attributes[] = { NULL, // index 61 NULL, // index 62 NULL, // index 63 - NULL, // index 64 NULL, }; diff --git a/io-module/mts_io.c b/io-module/mts_io.c index 9adfd12..936d0d2 100644 --- a/io-module/mts_io.c +++ b/io-module/mts_io.c @@ -59,24 +59,33 @@ extern uint8_t mts_id_eeprom[512]; static struct mts_id_eeprom_layout id_eeprom; -/* accessory card EEPROMs */ -#ifdef MTOCGD2 -extern uint8_t mts_ap1_eeprom[512]; -extern uint8_t mts_ap2_eeprom[512]; +// NUM_AP should be defined from the board code +// it should be set to the value of CONFIG_MTS_NUM_ACCESSORY_PORTS +// arch/arm/mach-at91/board-dt-sam9.c +// if it is 0 or undefined, there is no accessory card support on this HW +#ifdef CONFIG_MTS_NUM_ACCESSORY_PORTS + +#ifndef NUM_AP +#define NUM_AP CONFIG_MTS_NUM_ACCESSORY_PORTS +#endif + #else -uint8_t mts_ap1_eeprom[512] = {}; -uint8_t mts_ap2_eeprom[512] = {}; +#define NUM_AP 0 #endif -static struct mts_ap_eeprom_layout ap1_eeprom; -static struct mts_ap_eeprom_layout ap2_eeprom; -bool accessory_card_capable = false; -bool have_accessory_card_slot_1 = false; -bool have_accessory_card_slot_2 = false; +#if NUM_AP > 0 +/* accessory card EEPROMs */ +extern uint8_t mts_ap_eeprom[NUM_AP][512]; +static struct mts_ap_eeprom_layout ap_eeprom[NUM_AP]; +#endif + +static struct ap_info* port_info[NUM_AP]; + +static struct attribute **device_attrs; +static size_t device_attrs_size; +static size_t device_attrs_max_size; static uint8_t mts_product_id; -static uint8_t mts_ap1_product_id; -static uint8_t mts_ap2_product_id; static uint8_t has_spi_sout; static uint8_t has_spi_din; static uint8_t has_spi_dout; @@ -98,6 +107,7 @@ static DEFINE_MUTEX(mts_io_mutex); #include "spi.c" /* accessory card support */ +#include "mtac.c" #include "mtac_gpiob.c" #include "mtac_mfser.c" @@ -415,131 +425,57 @@ static DEVICE_ATTR_RO_MTS(dev_attr_eth_mac, "mac-eth", #include "mt100eocg.c" */ -static bool add_accessory_card_attributes(int slot) -{ - size_t device_attrs_size; - size_t card_attrs_size; - size_t attrs_index; - size_t i; - - struct attribute **device_attrs; - struct attribute **card_attrs; - - switch (mts_product_id) { - case MTR2D2_0_0: - device_attrs_size = mtr2d2_platform_attributes_size; - device_attrs = mtr2d2_platform_attributes; - break; - default: - log_error("accessory cards aren't supported for platform %s", id_eeprom.hw_version); - return false; - } +static bool load_port(int port) { + int port_index = port - 1; + memcpy(&ap_eeprom[port_index], mts_ap_eeprom[port_index], sizeof(mts_ap_eeprom[port_index])); - if (slot == 1) { - switch (mts_ap1_product_id) { - case MTAC_GPIOB_0_0: - card_attrs_size = ap1_gpio_attributes_size; - card_attrs = ap1_gpio_attributes; - break; - case MTAC_MFSER_0_0: - card_attrs_size = ap1_mfser_attributes_size; - card_attrs = ap1_mfser_attributes; - break; - default: - log_error("accessory card %s isn't supported", ap1_eeprom.hw_version); - return false; - } - } else if (slot == 2) { - switch (mts_ap2_product_id) { - case MTAC_GPIOB_0_0: - card_attrs_size = ap2_gpio_attributes_size; - card_attrs = ap2_gpio_attributes; - break; - case MTAC_MFSER_0_0: - card_attrs_size = ap2_mfser_attributes_size; - card_attrs = ap2_mfser_attributes; - break; - default: - log_error("accessory card %s isn't supported", ap2_eeprom.hw_version); - return false; - } + if (mts_ap_eeprom[port_index][0] == 0xFF) { + log_error("uninitialized eeprom on accessory card %d", port); + } else if (mts_ap_eeprom[port_index][0] == 0x00) { + log_info("no accessory card inserted in port %d", port); } else { - log_error("%d is an invalid slot value", slot); - return false; - } - - for (attrs_index = 0; attrs_index < device_attrs_size; attrs_index++) { - if (! device_attrs[attrs_index]) { - break; + if (strstr(ap_eeprom[port_index].product_id, PRODUCT_ID_MTAC_GPIOB)) { + port_info[port_index] = &gpiob_info; + } else if (strstr(ap_eeprom[port_index].product_id, PRODUCT_ID_MTAC_MFSER)) { + port_info[port_index] = &mfser_info; + } else { + log_error("unknown accessory card [%s] in port %d", ap_eeprom[port_index].product_id, port); + return false; } - } - if (device_attrs_size < attrs_index + card_attrs_size) { - log_error("not enough room for accessory card attributes!"); - return false; - } + log_info("accessory card %d vendor-id: %.32s", port, ap_eeprom[port_index].vendor_id); + log_info("accessory card %d product-id: %.32s", port, ap_eeprom[port_index].product_id); + log_info("accessory card %d device-id: %.32s", port, ap_eeprom[port_index].device_id); + log_info("accessory card %d hw-version: %.32s", port, ap_eeprom[port_index].hw_version); + if (strncmp(ap_eeprom[port_index].product_id, PRODUCT_ID_MTAC_ETH, strlen(PRODUCT_ID_MTAC_ETH)) == 0) { + log_info("accessory card %d mac-addr: %02X:%02X:%02X:%02X:%02X:%02X", + port, + ap_eeprom[port_index].mac_addr[0], + ap_eeprom[port_index].mac_addr[1], + ap_eeprom[port_index].mac_addr[2], + ap_eeprom[port_index].mac_addr[3], + ap_eeprom[port_index].mac_addr[4], + ap_eeprom[port_index].mac_addr[5]); + } - for (i = 0; i < card_attrs_size; i++) { - device_attrs[attrs_index + i] = card_attrs[i]; + if (! port_info[port_index]->setup(port)) { + log_error("accessory port %d setup failed", port); + port_info[port_index]->teardown(port); + return false; + } } return true; } -static bool mts_ap_eeprom_load(void) +static void init_accessory_ports(void) { - // Accessory Card Slot 1 - memcpy(&ap1_eeprom, mts_ap1_eeprom, sizeof(mts_ap1_eeprom)); - - if (mts_ap1_eeprom[0] == 0xFF) { - log_error("uninitialized eeprom on accessory card 1"); - } else if (mts_ap1_eeprom[0] == 0x00) { - log_info("no accessory card inserted in slot 1"); - } else { - have_accessory_card_slot_1 = true; - - log_info("accessory card 1 vendor-id: %.32s", ap1_eeprom.vendor_id); - log_info("accessory card 1 product-id: %.32s", ap1_eeprom.product_id); - log_info("accessory card 1 device-id: %.32s", ap1_eeprom.device_id); - log_info("accessory card 1 hw-version: %.32s", ap1_eeprom.hw_version); - if (strncmp(ap1_eeprom.product_id, PRODUCT_ID_MTAC_ETH, strlen(PRODUCT_ID_MTAC_ETH)) == 0) { - log_info("accessory card 1 mac-addr: %02X:%02X:%02X:%02X:%02X:%02X", - ap1_eeprom.mac_addr[0], - ap1_eeprom.mac_addr[1], - ap1_eeprom.mac_addr[2], - ap1_eeprom.mac_addr[3], - ap1_eeprom.mac_addr[4], - ap1_eeprom.mac_addr[5]); - } - } - - // Accessory Card Slot 2 - memcpy(&ap2_eeprom, mts_ap2_eeprom, sizeof(mts_ap2_eeprom)); - - if (mts_ap2_eeprom[0] == 0xFF) { - log_error("uninitialized eeprom on accessory card 2"); - } else if (mts_ap2_eeprom[0] == 0x00) { - log_info("no accessory card inserted in slot 2"); - } else { - have_accessory_card_slot_2 = true; - - log_info("accessory card 2 vendor-id: %.32s", ap2_eeprom.vendor_id); - log_info("accessory card 2 product-id: %.32s", ap2_eeprom.product_id); - log_info("accessory card 2 device-id: %.32s", ap2_eeprom.device_id); - log_info("accessory card 2 hw-version: %.32s", ap2_eeprom.hw_version); - if (strncmp(ap2_eeprom.product_id, PRODUCT_ID_MTAC_ETH, strlen(PRODUCT_ID_MTAC_ETH)) == 0) { - log_info("accessory card 2 mac-addr: %02X:%02X:%02X:%02X:%02X:%02X", - ap2_eeprom.mac_addr[0], - ap2_eeprom.mac_addr[1], - ap2_eeprom.mac_addr[2], - ap2_eeprom.mac_addr[3], - ap2_eeprom.mac_addr[4], - ap2_eeprom.mac_addr[5]); + int i; + for (i = 1; i <= NUM_AP; i++) { + if (! load_port(i)) { + log_error("failed to load accessory card in port %d", i); } } - - // if either slot has a valid card, return true - return (have_accessory_card_slot_1 || have_accessory_card_slot_2); } static int mts_id_eeprom_load(void) @@ -581,7 +517,6 @@ static int mts_id_eeprom_load(void) attr_group = &mtr2_platform_attribute_group; gpio_pins = gpio_pins_mtr2_0_0; mts_product_id = MTR2_0_0; - accessory_card_capable = true; has_spi_sout = 0; has_spi_din = 0; has_spi_dout = 0; @@ -611,7 +546,6 @@ static int mts_id_eeprom_load(void) attr_group = &mtr2_platform_attribute_group; gpio_pins = gpio_pins_mtr2_0_0; mts_product_id = MTOCGD2_0_0; - accessory_card_capable = true; has_spi_sout = 0; has_spi_din = 0; has_spi_dout = 0; @@ -637,10 +571,15 @@ static int mts_id_eeprom_load(void) has_spi_temp = 0; log_info("detected board %s", HW_VERSION_MTOCGD_0_1); } else if (strncmp(id_eeprom.hw_version, HW_VERSION_MTR2D2_0_0, strlen(HW_VERSION_MTR2D2_0_0)) == 0) { + // need to put any accessory card attributes into this list so they show up in sysfs + // the port_info->setup callback does this + device_attrs = mtr2d2_platform_attributes; + device_attrs_size = mtr2d2_platform_attributes_size; + device_attrs_max_size = mtr2d2_platform_attributes_max_size; + attr_group = &mtr2d2_platform_attribute_group; gpio_pins = gpio_pins_mtr2d2_0_0; mts_product_id = MTR2D2_0_0; - accessory_card_capable = true; has_spi_sout = 0; has_spi_din = 0; has_spi_dout = 0; @@ -706,6 +645,7 @@ static int __init mts_io_init(void) int ret; size_t device_attributes_size; size_t card_attributes_size; + int i; log_info("init: " DRIVER_VERSION); @@ -714,118 +654,11 @@ static int __init mts_io_init(void) goto error1; } - if (accessory_card_capable) { - mts_ap1_product_id = MTAC_NONE; - mts_ap2_product_id = MTAC_NONE; - if (mts_ap_eeprom_load()) { - // handle both slots, but do slot 1 first - // probably need special handling if both cards are the same type - if (have_accessory_card_slot_1) { - // more elegant way to handle this? - if (strstr(ap1_eeprom.product_id, PRODUCT_ID_MTAC_GPIOB)) { - mts_ap1_product_id = MTAC_GPIOB_0_0; - } - else if (strstr(ap1_eeprom.product_id, PRODUCT_ID_MTAC_MFSER)) { - mts_ap1_product_id = MTAC_MFSER_0_0; - } - - switch(mts_ap1_product_id) { - case MTAC_GPIOB_0_0: - log_info("loading GPIO accessory card in slot 1"); - if (! add_accessory_card_attributes(1)) { - log_error("failed to load GPIO accessory card in slot 1"); - } else { - log_info("successfully loaded GPIO accessory card in slot 1"); - } - log_debug("registering accessory card 1 dout driver"); - ret = spi_register_driver(&mts_spi_ap1_dout_driver); - if (ret) { - log_error("failed to register accessory card 1 dout driver"); - spi_unregister_driver(&mts_spi_ap1_dout_driver); - goto error1; - } - log_debug("registering accessory card 1 din driver"); - ret = spi_register_driver(&mts_spi_ap1_din_driver); - if (ret) { - log_error("failed to register accessory card 1 din driver"); - spi_unregister_driver(&mts_spi_ap1_din_driver); - goto error1; - } - log_debug("registering accessory card 1 adc driver"); - ret = spi_register_driver(&mts_spi_ap1_adc_driver); - if (ret) { - log_error("failed to register accessory card 1 adc driver"); - spi_unregister_driver(&mts_spi_ap1_adc_driver); - goto error1; - } - break; - case MTAC_MFSER_0_0: - log_info("loading MFSER accessory card in slot 1"); - if (! add_accessory_card_attributes(1)) { - log_error("failed to load MFSER accessory card in slot 1"); - } else { - log_info("successfully loaded MFSER accessory card in slot 1"); - } - break; - - default: - log_error("accessory card %s unsupported", ap1_eeprom.product_id); - } - } - - if (have_accessory_card_slot_2) { - // more elegant way to handle this? - if (strstr(ap2_eeprom.product_id, PRODUCT_ID_MTAC_GPIOB)) { - mts_ap2_product_id = MTAC_GPIOB_0_0; - } - else if (strstr(ap2_eeprom.product_id, PRODUCT_ID_MTAC_MFSER)) { - mts_ap2_product_id = MTAC_MFSER_0_0; - } - - switch(mts_ap2_product_id) { - case MTAC_GPIOB_0_0: - log_info("loading GPIO accessory card in slot 2"); - if (! add_accessory_card_attributes(2)) { - log_error("failed to load GPIO accessory card in slot 2"); - } else { - log_info("successfully loaded GPIO accessory card in slot 2"); - } - log_debug("registering accessory card 2 dout driver"); - ret = spi_register_driver(&mts_spi_ap2_dout_driver); - if (ret) { - log_error("failed to register accessory card 2 dout driver"); - spi_unregister_driver(&mts_spi_ap2_dout_driver); - goto error1; - } - log_debug("registering accessory card 2 din driver"); - ret = spi_register_driver(&mts_spi_ap2_din_driver); - if (ret) { - log_error("failed to register accessory card 2 din driver"); - spi_unregister_driver(&mts_spi_ap2_din_driver); - goto error1; - } - log_debug("registering accessory card 2 adc driver"); - ret = spi_register_driver(&mts_spi_ap2_adc_driver); - if (ret) { - log_error("failed to register accessory card 2 adc driver"); - spi_unregister_driver(&mts_spi_ap2_adc_driver); - goto error1; - } - break; - case MTAC_MFSER_0_0: - log_info("loading MFSER accessory card in slot 2"); - if (! add_accessory_card_attributes(2)) { - log_error("failed to load MFSER accessory card in slot 2"); - } else { - log_info("successfully loaded MFSER accessory card in slot 2"); - } - break; - - default: - log_error("accessory card %s unsupported", ap1_eeprom.product_id); - } - } + if (NUM_AP) { + for (i = 0; i < NUM_AP; i++) { + port_info[i] = NULL; } + init_accessory_ports(); } mts_io_platform_device = platform_device_alloc(PLATFORM_NAME, -1); @@ -950,40 +783,21 @@ error3: platform_device_del(mts_io_platform_device); error2: platform_device_put(mts_io_platform_device); - - if (have_accessory_card_slot_1) { - switch (mts_ap1_product_id) { - case MTAC_GPIOB_0_0: - spi_unregister_driver(&mts_spi_ap1_dout_driver); - spi_unregister_driver(&mts_spi_ap1_din_driver); - spi_unregister_driver(&mts_spi_ap1_adc_driver); - break; - - default: - break; - } - } - - if (have_accessory_card_slot_2) { - switch (mts_ap2_product_id) { - case MTAC_GPIOB_0_0: - spi_unregister_driver(&mts_spi_ap2_dout_driver); - spi_unregister_driver(&mts_spi_ap2_din_driver); - spi_unregister_driver(&mts_spi_ap2_adc_driver); - break; - - default: - break; - } - } error1: log_error("init failed: %d", ret); + for (i = 0; i < NUM_AP; i++) { + if (port_info[i]) { + port_info[i]->teardown(i); + } + } return ret; } static void __exit mts_io_exit(void) { + int i; + if ( mts_product_id != MT100EOCG_0_0 ) { cancel_delayed_work_sync(&reset_work); } @@ -1004,38 +818,18 @@ static void __exit mts_io_exit(void) if (has_spi_sout) spi_unregister_driver(&mts_spi_sout_driver); - if (have_accessory_card_slot_1) { - switch (mts_ap1_product_id) { - case MTAC_GPIOB_0_0: - spi_unregister_driver(&mts_spi_ap1_dout_driver); - spi_unregister_driver(&mts_spi_ap1_din_driver); - spi_unregister_driver(&mts_spi_ap1_adc_driver); - break; - - default: - break; - } - } - - if (have_accessory_card_slot_2) { - switch (mts_ap2_product_id) { - case MTAC_GPIOB_0_0: - spi_unregister_driver(&mts_spi_ap2_dout_driver); - spi_unregister_driver(&mts_spi_ap2_din_driver); - spi_unregister_driver(&mts_spi_ap2_adc_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"); platform_device_unregister(mts_io_platform_device); + for (i = 0; i < NUM_AP; i++) { + if (port_info[i]) { + port_info[i]->teardown(i); + } + } + log_info("exiting"); } diff --git a/io-module/mts_io.h b/io-module/mts_io.h index b91423e..ac39463 100644 --- a/io-module/mts_io.h +++ b/io-module/mts_io.h @@ -102,5 +102,25 @@ enum { LED_FLASHING, }; +enum ap { + port_1 = 1, + port_2, +}; + +enum spi_devices { + din = 0, + dout = 1, + adc = 2, +}; + +// info for accessory port +// contains function pointers for setup and teardown and useful info +// each type of accessory card should have one of these +struct ap_info { + uint8_t product_id; + bool (*setup)(enum ap port); + bool (*teardown)(enum ap port); +}; + #endif /* ~__MTS_IO_H */ diff --git a/io-module/spi.c b/io-module/spi.c index e652b90..210371c 100644 --- a/io-module/spi.c +++ b/io-module/spi.c @@ -40,35 +40,6 @@ MODULE_PARM_DESC( "Maximum clock rate to be used with this device (default: 1 MHz)" ); -static struct spi_device *spi_ap1_dout_dev; -static struct spi_device *spi_ap2_dout_dev; -static u8 spi_ap_dout_value; -static DEFINE_MUTEX(spi_ap_dout_mutex); -static unsigned int ap_dout_max_speed_hz = 1 * 1000 * 1000; -module_param(ap_dout_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - ap_dout_max_speed_hz, - "Maximum clock rate to be used with this device (default: 1 MHz)" -); - -static struct spi_device *spi_ap1_din_dev; -static struct spi_device *spi_ap2_din_dev; -static unsigned int ap_din_max_speed_hz = 1 * 1000 * 1000; -module_param(ap_din_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - ap_din_max_speed_hz, - "Maximum clock rate to be used with this device (default: 1 MHz)" -); - -static struct spi_device *spi_ap1_adc_dev; -static struct spi_device *spi_ap2_adc_dev; -static unsigned int ap_adc_max_speed_hz = 20 * 1000 * 1000; -module_param(ap_adc_max_speed_hz, uint, S_IRUGO); -MODULE_PARM_DESC( - ap_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); @@ -598,272 +569,6 @@ static struct spi_driver mts_spi_din_driver = { .remove = mts_spi_din_remove, }; -static int mts_spi_ap1_dout_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_1 || mts_ap1_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 1 digital outputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_dout_max_speed_hz; - spi->mode = 0; - - log_debug("ap1_dout_max_speed_hz: %d", ap_dout_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 1 dout failed"); - return tmp; - } - - spi_ap_dout_value = 0x00; - spi_writen(spi, &spi_ap_dout_value, 1); - - spi_ap1_dout_dev = spi; - - return 0; -} - -static int mts_spi_ap1_dout_remove(struct spi_device *spi) -{ - spi_ap1_dout_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap1_dout_driver = { - .driver = { - .name = "mts-io-ap1-dout", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap1_dout_probe, - .remove = mts_spi_ap1_dout_remove, -}; - -static int mts_spi_ap1_din_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_1 || mts_ap1_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 1 digital inputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_din_max_speed_hz; - spi->mode = SPI_CPOL; - - log_debug("ap1_din_max_speed_hz: %d", ap_din_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 1 din failed"); - return tmp; - } - - spi_ap1_din_dev = spi; - - return 0; -} - -static int mts_spi_ap1_din_remove(struct spi_device *spi) -{ - spi_ap1_din_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap1_din_driver = { - .driver = { - .name = "mts-io-ap1-din", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap1_din_probe, - .remove = mts_spi_ap1_din_remove, -}; - -static int mts_spi_ap1_adc_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_1 || mts_ap1_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 1 analog to digital not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_adc_max_speed_hz; - spi->mode = 0; - - log_debug("ap1_adc_max_speed_hz: %d", ap_adc_max_speed_hz); - log_debug("ap1_adc_mode: %d", spi->mode); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 1 adc failed"); - return tmp; - } - - spi_ap1_adc_dev = spi; - - return 0; -} - -static int mts_spi_ap1_adc_remove(struct spi_device *spi) -{ - spi_ap1_adc_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap1_adc_driver = { - .driver = { - .name = "mts-io-ap1-adc", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap1_adc_probe, - .remove = mts_spi_ap1_adc_remove, -}; - -static int mts_spi_ap2_dout_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_2 || mts_ap2_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 2 digital outputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_dout_max_speed_hz; - spi->mode = 0; - - log_debug("ap2_dout_max_speed_hz: %d", ap_dout_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 2 dout failed"); - return tmp; - } - - spi_ap_dout_value = 0x00; - spi_writen(spi, &spi_ap_dout_value, 2); - - spi_ap2_dout_dev = spi; - - return 0; -} - -static int mts_spi_ap2_dout_remove(struct spi_device *spi) -{ - spi_ap2_dout_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap2_dout_driver = { - .driver = { - .name = "mts-io-ap2-dout", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap2_dout_probe, - .remove = mts_spi_ap2_dout_remove, -}; - -static int mts_spi_ap2_din_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_2 || mts_ap2_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 2 digital inputs not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_din_max_speed_hz; - spi->mode = SPI_CPOL; - - log_debug("ap2_din_max_speed_hz: %d", ap_din_max_speed_hz); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 2 din failed"); - return tmp; - } - - spi_ap2_din_dev = spi; - - return 0; -} - -static int mts_spi_ap2_din_remove(struct spi_device *spi) -{ - spi_ap2_din_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap2_din_driver = { - .driver = { - .name = "mts-io-ap2-din", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap2_din_probe, - .remove = mts_spi_ap2_din_remove, -}; - -static int mts_spi_ap2_adc_probe(struct spi_device *spi) -{ - int tmp; - - if (! have_accessory_card_slot_2 || mts_ap2_product_id != MTAC_GPIOB_0_0) { - log_error("accessory card 2 analog to digital not available"); - return -ENODEV; - } - - spi->max_speed_hz = ap_adc_max_speed_hz; - spi->mode = 0; - - log_debug("ap2_adc_max_speed_hz: %d", ap_adc_max_speed_hz); - log_debug("ap2_adc_mode: %d", spi->mode); - - tmp = spi_setup(spi); - if (tmp < 0) { - log_error("spi_setup accessory card 2 adc failed"); - return tmp; - } - - spi_ap2_adc_dev = spi; - - return 0; -} - -static int mts_spi_ap2_adc_remove(struct spi_device *spi) -{ - spi_ap2_adc_dev = NULL; - - return 0; -} - -static struct spi_driver mts_spi_ap2_adc_driver = { - .driver = { - .name = "mts-io-ap2-adc", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = mts_spi_ap2_adc_probe, - .remove = mts_spi_ap2_adc_remove, -}; - static int mts_spi_board_temp_probe(struct spi_device *spi) { int tmp; |