diff options
author | Mike Fiore <mfiore@multitech.com> | 2014-10-03 15:09:42 -0500 |
---|---|---|
committer | Mike Fiore <mfiore@multitech.com> | 2014-10-03 15:09:42 -0500 |
commit | f9010f0863063e6836394469edf43e86c98d49fe (patch) | |
tree | b7fde122fbc570786240836cfb057ba76dea84db /io-module/mtac_gpiob.c | |
parent | 0f0c9bb72a3be330512e60677c4e3693347bf66b (diff) | |
download | mts-io-f9010f0863063e6836394469edf43e86c98d49fe.tar.gz mts-io-f9010f0863063e6836394469edf43e86c98d49fe.tar.bz2 mts-io-f9010f0863063e6836394469edf43e86c98d49fe.zip |
mts-io: reorganize accessory card attributes, move them into subdirs under mts-io
subdirs named ap1, ap2, etc
create links to subdirs with name of card in port, e.g. gpiob, mfser, eth, etc
if 2 of same type of card, still make links but use gpiob-2, mfser-2, etc
Diffstat (limited to 'io-module/mtac_gpiob.c')
-rw-r--r-- | io-module/mtac_gpiob.c | 262 |
1 files changed, 162 insertions, 100 deletions
diff --git a/io-module/mtac_gpiob.c b/io-module/mtac_gpiob.c index f8652c6..3f9631d 100644 --- a/io-module/mtac_gpiob.c +++ b/io-module/mtac_gpiob.c @@ -1,7 +1,7 @@ struct spi_device *gpiob_spi[NUM_AP][3]; struct spi_driver gpiob_spi_drivers[NUM_AP][3]; -static u8 spi_ap_dout_value; +static u8 spi_ap_dout_value[NUM_AP]; 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); @@ -41,7 +41,7 @@ static int mts_spi_ap_probe(struct spi_device *spi) 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); + log_error("port %d is invalid", port); return -ENODEV; } @@ -66,13 +66,13 @@ static int mts_spi_ap_probe(struct spi_device *spi) tmp = spi_setup(gpiob_spi[port_index][dev]); if (tmp < 0) { - log_error("spi_setup ap %d %s failed", port, buf); + 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); + spi_ap_dout_value[port_index] = 0x00; + spi_writen(gpiob_spi[port_index][dev], &spi_ap_dout_value[port_index], 1); } return 0; @@ -87,7 +87,7 @@ static int mts_spi_ap_remove(struct spi_device *spi) 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); + log_error("port %d is invalid", port); return -ENODEV; } @@ -105,26 +105,35 @@ static int mts_spi_ap_remove(struct spi_device *spi) return 0; } -static char* gpiob_gpio_pin_name_by_attr_name(const char* name) { - if (! strcmp(name, "led1:1")) { - return "ap1-gpio3"; - } else if (! strcmp(name, "led2:1")) { - return "ap1-gpio4"; - } else if (! strcmp(name, "dout-enable:1")) { - return "ap1-gpio1"; - } else if (! strcmp(name, "reset:1")) { - return "ap1-reset"; - } else if (! strcmp(name, "led1:2")) { - return "ap2-gpio3"; - } else if (! strcmp(name, "led2:2")) { - return "ap2-gpio4"; - } else if (! strcmp(name, "dout-enable:2")) { - return "ap2-gpio1"; - } else if (! strcmp(name, "reset:2")) { - return "ap2-reset"; - } else { - log_error("attirbute name [%s] is invalid for GPIOB", name); - return ""; +static char* gpiob_gpio_pin_name_by_attr_name(const char* name, int port) { + switch (port) { + case port_1: + if (! strcmp(name, "led1")) { + return "ap1-gpio3"; + } else if (! strcmp(name, "led2")) { + return "ap1-gpio4"; + } else if (! strcmp(name, "dout-enable")) { + return "ap1-gpio1"; + } else if (! strcmp(name, "reset")) { + return "ap1-reset"; + } else { + log_error("attirbute name [%s] is invalid for GPIOB in port %d", name, port); + return ""; + } + + case port_2: + if (! strcmp(name, "led1")) { + return "ap2-gpio3"; + } else if (! strcmp(name, "led2")) { + return "ap2-gpio4"; + } else if (! strcmp(name, "dout-enable")) { + return "ap2-gpio1"; + } else if (! strcmp(name, "reset")) { + return "ap2-reset"; + } else { + log_error("attirbute name [%s] is invalid for GPIOB in port %d", name, port); + return ""; + } } } @@ -137,16 +146,18 @@ static ssize_t mts_attr_show_ap_din(struct kobject *kobj, struct kobj_attribute u8 bit; u8 byte; - sscanf(attr->attr.name, "din%d:%d", &channel, &port); - port_index = port - 1; + sscanf(attr->attr.name, "din%d", &channel); if (channel < 0 || channel > 3) { - log_error("channel [%d] is invalid", channel); + log_error("channel %d is invalid", channel); return -ENOENT; } - if (port < 1 || port > NUM_AP) { - log_error("port [%d] is invalid", port); - return -ENOENT; + + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } + port_index = port - 1; bit = BIT(channel); @@ -169,33 +180,35 @@ static ssize_t mts_attr_store_ap_dout(struct kobject *kobj, struct kobj_attribut int port_index; u8 bit; - sscanf(attr->attr.name, "dout%d:%d", &channel, &port); - port_index = port - 1; + sscanf(attr->attr.name, "dout%d", &channel); if (channel < 0 || channel > 3) { - log_error("channel [%d] is invalid", channel); + log_error("channel %d is invalid", channel); return -ENOENT; } - if (port < 1 || port > NUM_AP) { - log_error("port [%d] is invalid", port); - return -ENOENT; + + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } + port_index = port - 1; bit = BIT(channel); if (sscanf(buf, "%i", &value) != 1) { - log_error("accessory card dout attr invalid argument [%d]", value); + log_error("accessory card dout attr invalid argument %d", value); return -EINVAL; } mutex_lock(&spi_ap_dout_mutex); if (value) { - spi_ap_dout_value &= ~bit; + spi_ap_dout_value[port_index] &= ~bit; } else { - spi_ap_dout_value |= bit; + spi_ap_dout_value[port_index] |= bit; } - spi_writen(gpiob_spi[port_index][dout], &spi_ap_dout_value, 1); + spi_writen(gpiob_spi[port_index][dout], &spi_ap_dout_value[port_index], 1); mutex_unlock(&spi_ap_dout_mutex); @@ -207,23 +220,27 @@ static ssize_t mts_attr_show_ap_dout(struct kobject *kobj, struct kobj_attribute int value; int channel; int port; + int port_index; u8 bit; - sscanf(attr->attr.name, "dout%d:%d", &channel, &port); + sscanf(attr->attr.name, "dout%d", &channel); if (channel < 0 || channel > 3) { - log_error("channel [%d] is invalid", channel); + log_error("channel %d is invalid", channel); return -ENOENT; } - if (port < 1 || port > NUM_AP) { - log_error("port [%d] is invalid", port); - return -ENOENT; + + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } + port_index = port - 1; bit = BIT(channel); mutex_lock(&spi_ap_dout_mutex); - value = spi_ap_dout_value & bit ? 0 : 1; + value = spi_ap_dout_value[port_index] & bit ? 0 : 1; mutex_unlock(&spi_ap_dout_mutex); @@ -246,16 +263,18 @@ static ssize_t mts_attr_show_ap_adc(struct kobject *kobj, struct kobj_attribute memset(tx, 0, sizeof(tx)); memset(rx, 0, sizeof(rx)); - sscanf(attr->attr.name, "adc%d:%d", &channel, &port); - port_index = port - 1; + sscanf(attr->attr.name, "adc%d", &channel); if (channel < 0 || channel > 2) { - log_error("channel [%d] is invalid", channel); + log_error("channel %d is invalid", channel); return -ENOENT; } - if (port < 1 || port > NUM_AP) { - log_error("port [%d] is invalid", port); - return -ENOENT; + + port = port_from_kobject(kobj); + if (port < 0) { + log_error("port_from_kobject returned %d", port); + return -EINVAL; } + port_index = port - 1; /* 1st transfer to set up (5V reference, channel to read from) */ tx_data = manual_mode | ((channel << 7) & channel_mask); @@ -314,107 +333,142 @@ static bool gpiob_spi_driver_setup(struct spi_driver *driver, const char *driver // 1 product-id // 1 device-id // 1 hw-version -static int ap_gpiob_attrs_size = 19; +// NULL +static int ap_gpiob_attrs_size = 20; static bool gpiob_setup(enum ap port) { int i; int port_index = port - 1; - struct kobj_attribute *attr; + int index = 0; + int count = 0; + int ret; char buf[32]; + struct kobj_attribute* attr; + struct attribute **attrs; 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); + sprintf(buf, "ap%d", port); + ap_subdirs[port_index] = kobject_create_and_add(buf, &mts_io_platform_device->dev.kobj); + if (! ap_subdirs[port_index]) { + log_error("kobject_create_and_add for port %d failed", port); return false; } - // mark the attribute indices we're using so we know what to clean up - port_info[port_index]->attrs_start = device_attrs_size; - port_info[port_index]->attrs_end = device_attrs_size + ap_gpiob_attrs_size; + // create the link to the apX directory this card is in + // if we're in the first slot, we get plain "gpiob" + // if we're in a different slot, we might need to use "gpiob-2" to differentiate + if (port > 1) { + for (i = 1; i < port; i++) { + if (port_info[i - 1]) { + if (strstr(port_info[i - 1]->product_id, PRODUCT_ID_MTAC_GPIOB)) { + count++; + } + } + } + } + if (count > 0) { + sprintf(buf, "gpiob-%d", count + 1); + } else { + sprintf(buf, "gpiob"); + } + ret = sysfs_create_link(ap_subdirs[port_index]->parent, ap_subdirs[port_index], buf); + if (ret) { + log_error("failed to link [%s] to [%s], %d", buf, ap_subdirs[port_index]->name, ret); + } + + attrs = kzalloc(sizeof(struct attribute*) * ap_gpiob_attrs_size, GFP_KERNEL); + if (! attrs) { + log_error("failed to allocate attribute space for port %d", port); + return false; + } // add digital inputs for (i = 0; i < 4; i++) { - sprintf(buf, "din%d:%d", i, port); + sprintf(buf, "din%d", i); attr = create_attribute(buf, MTS_ATTR_MODE_RO); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s]", buf); return false; } attr->show = mts_attr_show_ap_din; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; } // add digital outputs for (i = 0; i < 4; i++) { - sprintf(buf, "dout%d:%d", i, port); + sprintf(buf, "dout%d", i); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for GPIOB in port %d", buf, port); return false; } attr->show = mts_attr_show_ap_dout; attr->store = mts_attr_store_ap_dout; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; } // add analog to digital for (i = 0; i < 3; i++) { - sprintf(buf, "adc%d:%d", i, port); + sprintf(buf, "adc%d", i); attr = create_attribute(buf, MTS_ATTR_MODE_RO); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for GPIOB in port %d", buf, port); return false; } attr->show = mts_attr_show_ap_adc; - device_attrs[device_attrs_size++] = &attr->attr; + attrs[index++] = &attr->attr; } // add LEDs for (i = 1; i <= 2; i++) { - sprintf(buf, "led%d:%d", i, port); + sprintf(buf, "led%d", i); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for GPIOB in port %d", buf, port); 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; - } - - // add attributes for eeprom contents - if (! ap_add_product_info_attributes(port, MTAC_GPIOB_0_0)) { - log_error("failed to add product info attributes"); - return false; + attrs[index++] = &attr->attr; } // add misc attributes - sprintf(buf, "dout-enable:%d", port); + sprintf(buf, "dout-enable"); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for GPIOB in port %d", buf, port); 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; + attrs[index++] = &attr->attr; - sprintf(buf, "reset:%d", port); + sprintf(buf, "reset"); attr = create_attribute(buf, MTS_ATTR_MODE_RW); if (! attr) { - log_error("failed to create attribute[%s]", buf); + log_error("failed to create attribute [%s] for GPIOB in port %d", buf, port); 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; + attrs[index++] = &attr->attr; + + // add attributes for eeprom contents + if (! ap_add_product_info_attributes(port, MTAC_GPIOB_0_0, attrs, &index)) { + log_error("failed to add product info attributes for GPIOB in port %d", port); + return false; + } + + attrs[index] = NULL; + + ap_attr_groups[port_index].attrs = attrs; // 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); + log_error("failed to set up spi driver [%s] for GPIOB in port %d", buf, port); return false; } if (spi_register_driver(&gpiob_spi_drivers[port_index][dout])) { @@ -426,7 +480,7 @@ static bool gpiob_setup(enum ap port) { 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); + log_error("failed to set up spi driver [%s] for GPIOB in port %d", buf, port); return false; } if (spi_register_driver(&gpiob_spi_drivers[port_index][din])) { @@ -438,7 +492,7 @@ static bool gpiob_setup(enum ap port) { 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); + log_error("failed to set up spi driver [%s] for GPIOB in port %d", buf, port); return false; } if (spi_register_driver(&gpiob_spi_drivers[port_index][adc])) { @@ -446,25 +500,39 @@ static bool gpiob_setup(enum ap port) { spi_unregister_driver(&gpiob_spi_drivers[port_index][adc]); return false; } + + if (sysfs_create_group(ap_subdirs[port_index], &ap_attr_groups[port_index])) { + log_error("sysfs_create_group failed for GPIOB in port %d", port); + return false; + } + return true; } static bool gpiob_teardown(enum ap port) { int i; int port_index = port - 1; + struct attribute **attrs = ap_attr_groups[port_index].attrs; log_info("unloading GPIOB accessory card in port %d", port); // clean up allocated memory for attributes - for (i = port_info[port_index]->attrs_start; i < port_info[port_index]->attrs_end; i++) { - if (device_attrs[i]) { - if (device_attrs[i]->name) - kfree(device_attrs[i]->name); + for (i = 0; i < ap_gpiob_attrs_size; i++) { + if (attrs[i]) { + if (attrs[i]->name) + kfree(attrs[i]->name); - kfree(device_attrs[i]); + kfree(attrs[i]); } } + kfree(attrs); + + // clean up our "apX/" kobject if it exists + if (ap_subdirs[port_index]) { + kobject_put(ap_subdirs[port_index]); + } + // clean up allocated memory for SPI drivers if (gpiob_spi_drivers[port_index][dout].driver.name) kfree(gpiob_spi_drivers[port_index][dout].driver.name); @@ -478,19 +546,13 @@ static bool gpiob_teardown(enum ap port) { spi_unregister_driver(&gpiob_spi_drivers[port_index][din]); spi_unregister_driver(&gpiob_spi_drivers[port_index][adc]); - // reset attribute index markers - port_info[port_index]->attrs_start = 0; - port_info[port_index]->attrs_end = 0; - return true; } bool set_gpiob_info(struct ap_info* info) { - info->product_id = MTAC_GPIOB_0_0; + snprintf(info->product_id, 32, "%s", PRODUCT_ID_MTAC_GPIOB); info->setup = &gpiob_setup; info->teardown = &gpiob_teardown; - info->attrs_start = 0; - info->attrs_end = 0; info->gpio_pin_name_by_attr_name = &gpiob_gpio_pin_name_by_attr_name; return true; |