|
@@ -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);
|
|
|
|