Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 282828
b: refs/heads/master
c: 0f769d3
h: refs/heads/master
v: v3
  • Loading branch information
Robert Jarzmik authored and David Woodhouse committed Jan 9, 2012
1 parent 8117777 commit b2b6dff
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c3de8a8a5a28603f8d318245992dbcda2e88a007
refs/heads/master: 0f769d3f9e2ef3e88930ff190a20cfbfe6206d3a
121 changes: 121 additions & 0 deletions trunk/drivers/mtd/devices/docg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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])
Expand Down
13 changes: 13 additions & 0 deletions trunk/drivers/mtd/devices/docg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
#define DOC_BCH_SYNDROM(idx) (0x1048 + (idx << 0))

#define DOC_PROTECTION 0x1056
#define DOC_DPS0_KEY 0x105c
#define DOC_DPS1_KEY 0x105e
#define DOC_DPS0_ADDRLOW 0x1060
#define DOC_DPS0_ADDRHIGH 0x1062
#define DOC_DPS1_ADDRLOW 0x1064
Expand Down Expand Up @@ -252,6 +254,17 @@
#define DOC_PLANES_STATUS_PLANE0_KO 0x02
#define DOC_PLANES_STATUS_PLANE1_KO 0x04

/*
* DPS key management
*
* Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
* across block boundaries, and define whether these blocks can be read or
* written.
* The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
* page 0 of blocks (4,5) for DPS1.
*/
#define DOC_LAYOUT_DPS_KEY_LENGTH 8

/**
* struct docg3 - DiskOnChip driver private data
* @dev: the device currently under control
Expand Down

0 comments on commit b2b6dff

Please sign in to comment.