diff options
author | Michael Brunner <mibru@gmx.de> | 2014-04-08 08:21:06 +0200 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2014-06-03 08:11:11 +0100 |
commit | 58a9e5b98360e8dcf9c958c0552fb35279e3933f (patch) | |
tree | 0783e2632b01ab28f40ebe0ae8f781989f4b3e04 /drivers | |
parent | ed612a349c967dd235d83959f9a0878777a5ae18 (diff) |
mfd: Add sysfs attributes for Kontron PLD firmware revision
This patch adds attributes to the Kontron PLD driver to allow
applications to retrieve firmware information.
Additionally the format has been changed to conform with the
representation in other Kontron software.
Signed-off-by: Michael Brunner <michael.brunner@kontron.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mfd/kempld-core.c | 127 |
1 files changed, 106 insertions, 21 deletions
diff --git a/drivers/mfd/kempld-core.c b/drivers/mfd/kempld-core.c index 07692604e119..25c5ca6797da 100644 --- a/drivers/mfd/kempld-core.c +++ b/drivers/mfd/kempld-core.c @@ -288,9 +288,38 @@ EXPORT_SYMBOL_GPL(kempld_release_mutex); */ static int kempld_get_info(struct kempld_device_data *pld) { + int ret; struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); + char major, minor; + + ret = pdata->get_info(pld); + if (ret) + return ret; + + /* The Kontron PLD firmware version string has the following format: + * Pwxy.zzzz + * P: Fixed + * w: PLD number - 1 hex digit + * x: Major version - 1 alphanumerical digit (0-9A-V) + * y: Minor version - 1 alphanumerical digit (0-9A-V) + * zzzz: Build number - 4 zero padded hex digits */ - return pdata->get_info(pld); + if (pld->info.major < 10) + major = pld->info.major + '0'; + else + major = (pld->info.major - 10) + 'A'; + if (pld->info.minor < 10) + minor = pld->info.minor + '0'; + else + minor = (pld->info.minor - 10) + 'A'; + + ret = scnprintf(pld->info.version, sizeof(pld->info.version), + "P%X%c%c.%04X", pld->info.number, major, minor, + pld->info.buildnr); + if (ret < 0) + return ret; + + return 0; } /* @@ -307,9 +336,71 @@ static int kempld_register_cells(struct kempld_device_data *pld) return pdata->register_cells(pld); } +static const char *kempld_get_type_string(struct kempld_device_data *pld) +{ + const char *version_type; + + switch (pld->info.type) { + case 0: + version_type = "release"; + break; + case 1: + version_type = "debug"; + break; + case 2: + version_type = "custom"; + break; + default: + version_type = "unspecified"; + break; + } + + return version_type; +} + +static ssize_t kempld_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kempld_device_data *pld = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", pld->info.version); +} + +static ssize_t kempld_specification_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kempld_device_data *pld = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%d.%d\n", pld->info.spec_major, + pld->info.spec_minor); +} + +static ssize_t kempld_type_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kempld_device_data *pld = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", kempld_get_type_string(pld)); +} + +static DEVICE_ATTR(pld_version, S_IRUGO, kempld_version_show, NULL); +static DEVICE_ATTR(pld_specification, S_IRUGO, kempld_specification_show, + NULL); +static DEVICE_ATTR(pld_type, S_IRUGO, kempld_type_show, NULL); + +static struct attribute *pld_attributes[] = { + &dev_attr_pld_version.attr, + &dev_attr_pld_specification.attr, + &dev_attr_pld_type.attr, + NULL +}; + +static const struct attribute_group pld_attr_group = { + .attrs = pld_attributes, +}; + static int kempld_detect_device(struct kempld_device_data *pld) { - char *version_type; u8 index_reg; int ret; @@ -335,27 +426,19 @@ static int kempld_detect_device(struct kempld_device_data *pld) if (ret) return ret; - switch (pld->info.type) { - case 0: - version_type = "release"; - break; - case 1: - version_type = "debug"; - break; - case 2: - version_type = "custom"; - break; - default: - version_type = "unspecified"; - } + dev_info(pld->dev, "Found Kontron PLD - %s (%s), spec %d.%d\n", + pld->info.version, kempld_get_type_string(pld), + pld->info.spec_major, pld->info.spec_minor); + + ret = sysfs_create_group(&pld->dev->kobj, &pld_attr_group); + if (ret) + return ret; - dev_info(pld->dev, "Found Kontron PLD %d\n", pld->info.number); - dev_info(pld->dev, "%s version %d.%d build %d, specification %d.%d\n", - version_type, pld->info.major, pld->info.minor, - pld->info.buildnr, pld->info.spec_major, - pld->info.spec_minor); + ret = kempld_register_cells(pld); + if (ret) + sysfs_remove_group(&pld->dev->kobj, &pld_attr_group); - return kempld_register_cells(pld); + return ret; } static int kempld_probe(struct platform_device *pdev) @@ -399,6 +482,8 @@ static int kempld_remove(struct platform_device *pdev) struct kempld_device_data *pld = platform_get_drvdata(pdev); struct kempld_platform_data *pdata = dev_get_platdata(pld->dev); + sysfs_remove_group(&pld->dev->kobj, &pld_attr_group); + mfd_remove_devices(&pdev->dev); pdata->release_hardware_mutex(pld); |