summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/mfd/kempld-core.c127
-rw-r--r--include/linux/mfd/kempld.h4
2 files changed, 110 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);
diff --git a/include/linux/mfd/kempld.h b/include/linux/mfd/kempld.h
index b911ef3add03..26e0b469e567 100644
--- a/include/linux/mfd/kempld.h
+++ b/include/linux/mfd/kempld.h
@@ -51,6 +51,8 @@
#define KEMPLD_TYPE_DEBUG 0x1
#define KEMPLD_TYPE_CUSTOM 0x2
+#define KEMPLD_VERSION_LEN 10
+
/**
* struct kempld_info - PLD device information structure
* @major: PLD major revision
@@ -60,6 +62,7 @@
* @type: PLD type
* @spec_major: PLD FW specification major revision
* @spec_minor: PLD FW specification minor revision
+ * @version: PLD version string
*/
struct kempld_info {
unsigned int major;
@@ -69,6 +72,7 @@ struct kempld_info {
unsigned int type;
unsigned int spec_major;
unsigned int spec_minor;
+ char version[KEMPLD_VERSION_LEN];
};
/**