aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/devices')
-rw-r--r--drivers/mtd/devices/docg3.c121
-rw-r--r--drivers/mtd/devices/docg3.h13
2 files changed, 134 insertions, 0 deletions
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 35df3778f8fd..d7df3114aa17 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1513,6 +1513,123 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
1513 return ret; 1513 return ret;
1514} 1514}
1515 1515
1516static struct docg3 *sysfs_dev2docg3(struct device *dev,
1517 struct device_attribute *attr)
1518{
1519 int floor;
1520 struct platform_device *pdev = to_platform_device(dev);
1521 struct mtd_info **docg3_floors = platform_get_drvdata(pdev);
1522
1523 floor = attr->attr.name[1] - '0';
1524 if (floor < 0 || floor >= DOC_MAX_NBFLOORS)
1525 return NULL;
1526 else
1527 return docg3_floors[floor]->priv;
1528}
1529
1530static ssize_t dps0_is_key_locked(struct device *dev,
1531 struct device_attribute *attr, char *buf)
1532{
1533 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1534 int dps0;
1535
1536 doc_set_device_id(docg3, docg3->device_id);
1537 dps0 = doc_register_readb(docg3, DOC_DPS0_STATUS);
1538 doc_set_device_id(docg3, 0);
1539
1540 return sprintf(buf, "%d\n", !(dps0 & DOC_DPS_KEY_OK));
1541}
1542
1543static ssize_t dps1_is_key_locked(struct device *dev,
1544 struct device_attribute *attr, char *buf)
1545{
1546 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1547 int dps1;
1548
1549 doc_set_device_id(docg3, docg3->device_id);
1550 dps1 = doc_register_readb(docg3, DOC_DPS1_STATUS);
1551 doc_set_device_id(docg3, 0);
1552
1553 return sprintf(buf, "%d\n", !(dps1 & DOC_DPS_KEY_OK));
1554}
1555
1556static ssize_t dps0_insert_key(struct device *dev,
1557 struct device_attribute *attr,
1558 const char *buf, size_t count)
1559{
1560 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1561 int i;
1562
1563 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1564 return -EINVAL;
1565
1566 doc_set_device_id(docg3, docg3->device_id);
1567 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1568 doc_writeb(docg3, buf[i], DOC_DPS0_KEY);
1569 doc_set_device_id(docg3, 0);
1570 return count;
1571}
1572
1573static ssize_t dps1_insert_key(struct device *dev,
1574 struct device_attribute *attr,
1575 const char *buf, size_t count)
1576{
1577 struct docg3 *docg3 = sysfs_dev2docg3(dev, attr);
1578 int i;
1579
1580 if (count != DOC_LAYOUT_DPS_KEY_LENGTH)
1581 return -EINVAL;
1582
1583 doc_set_device_id(docg3, docg3->device_id);
1584 for (i = 0; i < DOC_LAYOUT_DPS_KEY_LENGTH; i++)
1585 doc_writeb(docg3, buf[i], DOC_DPS1_KEY);
1586 doc_set_device_id(docg3, 0);
1587 return count;
1588}
1589
1590#define FLOOR_SYSFS(id) { \
1591 __ATTR(f##id##_dps0_is_keylocked, S_IRUGO, dps0_is_key_locked, NULL), \
1592 __ATTR(f##id##_dps1_is_keylocked, S_IRUGO, dps1_is_key_locked, NULL), \
1593 __ATTR(f##id##_dps0_protection_key, S_IWUGO, NULL, dps0_insert_key), \
1594 __ATTR(f##id##_dps1_protection_key, S_IWUGO, NULL, dps1_insert_key), \
1595}
1596
1597static struct device_attribute doc_sys_attrs[DOC_MAX_NBFLOORS][4] = {
1598 FLOOR_SYSFS(0), FLOOR_SYSFS(1), FLOOR_SYSFS(2), FLOOR_SYSFS(3)
1599};
1600
1601static int doc_register_sysfs(struct platform_device *pdev,
1602 struct mtd_info **floors)
1603{
1604 int ret = 0, floor, i = 0;
1605 struct device *dev = &pdev->dev;
1606
1607 for (floor = 0; !ret && floor < DOC_MAX_NBFLOORS && floors[floor];
1608 floor++)
1609 for (i = 0; !ret && i < 4; i++)
1610 ret = device_create_file(dev, &doc_sys_attrs[floor][i]);
1611 if (!ret)
1612 return 0;
1613 do {
1614 while (--i >= 0)
1615 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1616 i = 4;
1617 } while (--floor >= 0);
1618 return ret;
1619}
1620
1621static void doc_unregister_sysfs(struct platform_device *pdev,
1622 struct mtd_info **floors)
1623{
1624 struct device *dev = &pdev->dev;
1625 int floor, i;
1626
1627 for (floor = 0; floor < DOC_MAX_NBFLOORS && floors[floor];
1628 floor++)
1629 for (i = 0; i < 4; i++)
1630 device_remove_file(dev, &doc_sys_attrs[floor][i]);
1631}
1632
1516/* 1633/*
1517 * Debug sysfs entries 1634 * Debug sysfs entries
1518 */ 1635 */
@@ -1927,6 +2044,9 @@ static int __init docg3_probe(struct platform_device *pdev)
1927 found++; 2044 found++;
1928 } 2045 }
1929 2046
2047 ret = doc_register_sysfs(pdev, docg3_floors);
2048 if (ret)
2049 goto err_probe;
1930 if (!found) 2050 if (!found)
1931 goto notfound; 2051 goto notfound;
1932 2052
@@ -1963,6 +2083,7 @@ static int __exit docg3_release(struct platform_device *pdev)
1963 void __iomem *base = docg3->base; 2083 void __iomem *base = docg3->base;
1964 int floor; 2084 int floor;
1965 2085
2086 doc_unregister_sysfs(pdev, docg3_floors);
1966 doc_dbg_unregister(docg3); 2087 doc_dbg_unregister(docg3);
1967 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) 2088 for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++)
1968 if (docg3_floors[floor]) 2089 if (docg3_floors[floor])
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
index 07182f9d484d..a349915da77d 100644
--- a/drivers/mtd/devices/docg3.h
+++ b/drivers/mtd/devices/docg3.h
@@ -118,6 +118,8 @@
118#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0)) 118#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0))
119 119
120#define DOC_PROTECTION 0x1056 120#define DOC_PROTECTION 0x1056
121#define DOC_DPS0_KEY 0x105c
122#define DOC_DPS1_KEY 0x105e
121#define DOC_DPS0_ADDRLOW 0x1060 123#define DOC_DPS0_ADDRLOW 0x1060
122#define DOC_DPS0_ADDRHIGH 0x1062 124#define DOC_DPS0_ADDRHIGH 0x1062
123#define DOC_DPS1_ADDRLOW 0x1064 125#define DOC_DPS1_ADDRLOW 0x1064
@@ -252,6 +254,17 @@
252#define DOC_PLANES_STATUS_PLANE0_KO 0x02 254#define DOC_PLANES_STATUS_PLANE0_KO 0x02
253#define DOC_PLANES_STATUS_PLANE1_KO 0x04 255#define DOC_PLANES_STATUS_PLANE1_KO 0x04
254 256
257/*
258 * DPS key management
259 *
260 * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
261 * across block boundaries, and define whether these blocks can be read or
262 * written.
263 * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
264 * page 0 of blocks (4,5) for DPS1.
265 */
266#define DOC_LAYOUT_DPS_KEY_LENGTH 8
267
255/** 268/**
256 * struct docg3 - DiskOnChip driver private data 269 * struct docg3 - DiskOnChip driver private data
257 * @dev: the device currently under control 270 * @dev: the device currently under control