arm: common: move cpaccess sysfs node

cpaccess uses sysdev which is being deprecated.
Move the cpaccess node out of the /sys/devices/system
directory to /sys/devices. Temporarily leave the original
sysdev node for migration purposes, until userspace
applications can be moved to the new node.

Change-Id: Iacc776968f892fc6c6463764e576d987e4371716
Signed-off-by: Neil Leeder <nleeder@codeaurora.org>
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d7ebcfe..fa9703c 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2026,7 +2026,7 @@
 	  Provide support for Coprocessor register access using /sys
 	  interface. Read and write to CP registers from userspace
 	  through sysfs interface. A sys file (cp_rw) will be created under
-	  /sys/devices/system/cpaccess/cpaccess0.
+	  /sys/devices/cpaccess/cpaccess0.
 
 	  If unsure, say N.
 
diff --git a/arch/arm/common/cpaccess.c b/arch/arm/common/cpaccess.c
index daf378a..3572e5a 100644
--- a/arch/arm/common/cpaccess.c
+++ b/arch/arm/common/cpaccess.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -260,14 +260,10 @@
 /*
  * cp_register_write_sysfs - sysfs interface for writing to
  * CP register
- * @dev:	sys device
- * @attr:	device attribute
- * @buf:	write value
- * @cnt:	not used
- *
  */
-static ssize_t cp_register_write_sysfs(struct sys_device *dev,
-	struct sysdev_attribute *attr, const char *buf, size_t cnt)
+static ssize_t cp_register_write_sysfs(
+	struct kobject *kobj, struct kobj_attribute *attr,
+	const char *buf, size_t cnt)
 {
 	char *str_tmp = (char *)buf;
 
@@ -280,18 +276,24 @@
 }
 
 /*
+ * wrapper for deprecated sysdev write interface
+ */
+static ssize_t sysdev_cp_register_write_sysfs(struct sys_device *dev,
+	struct sysdev_attribute *attr, const char *buf, size_t cnt)
+{
+	return cp_register_write_sysfs(NULL, NULL, buf, cnt);
+}
+
+/*
  * cp_register_read_sysfs - sysfs interface for reading CP registers
- * @dev:        sys device
- * @attr:       device attribute
- * @buf:        write value
  *
  * Code to read in the CPxx crn, crm, op1, op2 variables, or into
  * the base MRC opcode, store to executable memory, clean/invalidate
  * caches and then execute the new instruction and provide the
  * result to the caller.
  */
-static ssize_t cp_register_read_sysfs(struct sys_device *dev,
-	struct sysdev_attribute *attr, char *buf)
+static ssize_t cp_register_read_sysfs(
+	struct kobject *kobj, struct kobj_attribute *attr, char *buf)
 {
 	int ret;
 
@@ -310,20 +312,52 @@
 }
 
 /*
+ * wrapper for deprecated sysdev read interface
+ */
+static ssize_t sysdev_cp_register_read_sysfs(struct sys_device *dev,
+	struct sysdev_attribute *attr, char *buf)
+{
+	return cp_register_read_sysfs(NULL, NULL, buf);
+}
+
+/*
  * Setup sysfs files
  */
-SYSDEV_ATTR(cp_rw, 0644, cp_register_read_sysfs, cp_register_write_sysfs);
+SYSDEV_ATTR(cp_rw, 0644, sysdev_cp_register_read_sysfs,
+	    sysdev_cp_register_write_sysfs);
 
 static struct sys_device device_cpaccess = {
 	.id     = 0,
 	.cls    = &cpaccess_sysclass,
 };
 
+static struct device cpaccess_dev = {
+	.init_name = "cpaccess",
+};
+
+static struct kobj_attribute cp_rw_attribute =
+	__ATTR(cp_rw, 0644, cp_register_read_sysfs, cp_register_write_sysfs);
+
+static struct attribute *attrs[] = {
+	&cp_rw_attribute.attr,
+	NULL,
+};
+
+static struct attribute_group attr_group = {
+	.name = "cpaccess0",
+	.attrs = attrs,
+};
+
 /*
  * init_cpaccess_sysfs - initialize sys devices
  */
 static int __init init_cpaccess_sysfs(void)
 {
+	/*
+	 * sysdev interface is deprecated and will be removed
+	 * after migration to new sysfs entry
+	 */
+
 	int error = sysdev_class_register(&cpaccess_sysclass);
 
 	if (!error)
@@ -336,12 +370,28 @@
 		 &attr_cp_rw);
 	else {
 		pr_err("Error initializing cpaccess interface\n");
-		sysdev_unregister(&device_cpaccess);
-		sysdev_class_unregister(&cpaccess_sysclass);
+		goto exit0;
+	}
+
+	error = device_register(&cpaccess_dev);
+	if (error) {
+		pr_err("Error registering cpaccess device\n");
+		goto exit0;
+	}
+	error = sysfs_create_group(&cpaccess_dev.kobj, &attr_group);
+	if (error) {
+		pr_err("Error creating cpaccess sysfs group\n");
+		goto exit1;
 	}
 
 	sema_init(&cp_sem, 1);
+	return 0;
 
+exit1:
+	device_unregister(&cpaccess_dev);
+exit0:
+	sysdev_unregister(&device_cpaccess);
+	sysdev_class_unregister(&cpaccess_sysclass);
 	return error;
 }
 
@@ -350,6 +400,9 @@
 	sysdev_remove_file(&device_cpaccess, &attr_cp_rw);
 	sysdev_unregister(&device_cpaccess);
 	sysdev_class_unregister(&cpaccess_sysclass);
+
+	sysfs_remove_group(&cpaccess_dev.kobj, &attr_group);
+	device_unregister(&cpaccess_dev);
 }
 
 module_init(init_cpaccess_sysfs);