|
@@ -1513,6 +1513,123 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+static struct docg3 *sysfs_dev2docg3(struct device *dev,
|
|
|
+ struct device_attribute *attr)
|
|
|
+{
|
|
|
+ int floor;
|
|
|
+ struct platform_device *pdev = to_platform_device(dev);
|
|
|
+ struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
|
|
|
+
|
|
|
+ floor = attr->attr.name[1] - '0';
|
|
|
+ if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
|
|
|
+ return NULL;
|
|
|
+ else
|
|
|
+ return docg3_floors[floor]->priv;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t dps0_is_key_locked(struct device *dev,
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
+{
|
|
|
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
|
|
|
+ int dps0;
|
|
|
+
|
|
|
+ doc_set_device_id(docg3, docg3->device_id);
|
|
|
+ dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
|
|
|
+ doc_set_device_id(docg3, 0);
|
|
|
+
|
|
|
+ return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK));
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t dps1_is_key_locked(struct device *dev,
|
|
|
+ struct device_attribute *attr, char *buf)
|
|
|
+{
|
|
|
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
|
|
|
+ int dps1;
|
|
|
+
|
|
|
+ doc_set_device_id(docg3, docg3->device_id);
|
|
|
+ dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
|
|
|
+ doc_set_device_id(docg3, 0);
|
|
|
+
|
|
|
+ return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK));
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t dps0_insert_key(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ doc_set_device_id(docg3, docg3->device_id);
|
|
|
+ for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
|
|
|
+ doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
|
|
|
+ doc_set_device_id(docg3, 0);
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t dps1_insert_key(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ doc_set_device_id(docg3, docg3->device_id);
|
|
|
+ for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
|
|
|
+ doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
|
|
|
+ doc_set_device_id(docg3, 0);
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+#define FLOOR_SYSFS(id) { \
|
|
|
+ __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
|
|
|
+ __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
|
|
|
+ __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
|
|
|
+ __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
|
|
|
+}
|
|
|
+
|
|
|
+static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
|
|
|
+ FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
|
|
|
+};
|
|
|
+
|
|
|
+static int doc_register_sysfs(struct platform_device *pdev,
|
|
|
+ struct mtd_info **floors)
|
|
|
+{
|
|
|
+ int ret = 0, floor, i = 0;
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
+
|
|
|
+ for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
|
|
|
+ floor++)
|
|
|
+ for (i = 0; !ret && i < 4; i++)
|
|
|
+ ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
|
|
|
+ if (!ret)
|
|
|
+ return 0;
|
|
|
+ do {
|
|
|
+ while (--i >= 0)
|
|
|
+ device_remove_file(dev, &doc_sys_attrs[floor][i]);
|
|
|
+ i = 4;
|
|
|
+ } while (--floor >= 0);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void doc_unregister_sysfs(struct platform_device *pdev,
|
|
|
+ struct mtd_info **floors)
|
|
|
+{
|
|
|
+ struct device *dev = &pdev->dev;
|
|
|
+ int floor, i;
|
|
|
+
|
|
|
+ for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
|
|
|
+ floor++)
|
|
|
+ for (i = 0; i < 4; i++)
|
|
|
+ device_remove_file(dev, &doc_sys_attrs[floor][i]);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Debug sysfs entries
|
|
|
*/
|
|
@@ -1927,6 +2044,9 @@ static int __init docg3_probe(struct platform_device *pdev)
|
|
|
found++;
|
|
|
}
|
|
|
|
|
|
+ ret = doc_register_sysfs(pdev, docg3_floors);
|
|
|
+ if (ret)
|
|
|
+ goto err_probe;
|
|
|
if (!found)
|
|
|
goto notfound;
|
|
|
|
|
@@ -1963,6 +2083,7 @@ static int __exit docg3_release(struct platform_device *pdev)
|
|
|
void __iomem *base = docg3->base;
|
|
|
int floor;
|
|
|
|
|
|
+ doc_unregister_sysfs(pdev, docg3_floors);
|
|
|
doc_dbg_unregister(docg3);
|
|
|
for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
|
|
|
if (docg3_floors[floor])
|