summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorPhilippe Langlais <philippe.langlais@stericsson.com>2011-10-14 09:47:42 +0200
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:07:10 +0200
commitf21deb0ceda2342d187ddaf611583cf636216696 (patch)
tree2d614e7aa83928ff44ef0587fc3e593a321164a5 /arch
parent079c8e0087da770a1daa749ad630bb8627d6191e (diff)
mach_ux500: Add support for mloader.
Add support for mloader platform driver for u4500. ST-Ericsson ID: AP 335929 ST-Ericsson FOSS-OUT ID: NA Change-Id: I0df37c29121097e078277b8989d33dfc9963a1f4 Signed-off-by: Sesahgiri.Holi <seshagiri.holi@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/21012 Reviewed-by: Martin PERSSON <martin.persson@stericsson.com> Reviewed-by: Preetham-rao K <preetham.rao@stericsson.com> Tested-by: Preetham-rao K <preetham.rao@stericsson.com> Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> Conflicts: arch/arm/mach-ux500/Kconfig arch/arm/mach-ux500/Makefile arch/arm/mach-ux500/board-u5500.c
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-ux500/mloader-db5500.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/arch/arm/mach-ux500/mloader-db5500.c b/arch/arm/mach-ux500/mloader-db5500.c
new file mode 100644
index 00000000000..946a0ff490d
--- /dev/null
+++ b/arch/arm/mach-ux500/mloader-db5500.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Authors: Jonas Aaberg <jonas.aberg@stericsson.com>
+ * Paer-Olof Haakansson <par-olof.hakansson@stericsson.com>
+ * for ST-Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/sysfs.h>
+#include <linux/slab.h>
+
+static ssize_t db5500_mloader_sysfs_addr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+
+static ssize_t db5500_mloader_sysfs_finalize(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
+
+
+static DEVICE_ATTR(addr, S_IRUSR|S_IRGRP, db5500_mloader_sysfs_addr, NULL);
+static DEVICE_ATTR(finalize, S_IWUSR, NULL, db5500_mloader_sysfs_finalize);
+
+static unsigned int db5500_bootargs_memmap_modem_start;
+static unsigned int db5500_bootargs_memmap_modem_total_size;
+
+static unsigned int db5500_mloader_shm_total_size;
+module_param_named(shm_total_size, db5500_mloader_shm_total_size, uint, 0600);
+MODULE_PARM_DESC(shm_total_size, "Total Size of SHM shared memory");
+
+static int __init db5500_bootargs_memmap(char *str)
+{
+ char start_val_str[10];
+ char *next_val_str;
+ int ret;
+
+ next_val_str = strchr(str, '$');
+ if (next_val_str == NULL)
+ return -EINVAL;
+ strncpy(start_val_str, str, next_val_str - str);
+ ret = strict_strtoul(start_val_str, 0,
+ &db5500_bootargs_memmap_modem_total_size);
+ if (ret < 0)
+ return -EINVAL;
+
+ ret = strict_strtoul(next_val_str + 1, 0,
+ &db5500_bootargs_memmap_modem_start);
+ if (ret < 0)
+ return -EINVAL;
+
+ return 1;
+}
+__setup("memmap=", db5500_bootargs_memmap);
+
+static int __init db5500_bootargs_shm_total_size(char *str)
+{
+ int ret;
+ ret = strict_strtoul(str, 0, &db5500_mloader_shm_total_size);
+ if (ret < 0)
+ return -EINVAL;
+ return 1;
+}
+__setup("mloader.shm_total_size=", db5500_bootargs_shm_total_size);
+
+static int __exit db5500_mloader_remove(struct platform_device *pdev)
+{
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_addr.attr);
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_finalize.attr);
+
+ return 0;
+}
+
+
+static struct platform_driver db5500_mloader_driver = {
+ .driver = {
+ .name = "db5500_mloader",
+ },
+ .remove = __exit_p(db5500_mloader_remove),
+};
+
+struct db5500_mloader {
+ struct work_struct work;
+ struct platform_device *pdev;
+};
+
+static void db5500_mloader_clean_up(struct work_struct *work)
+{
+ struct db5500_mloader *m = container_of(work,
+ struct db5500_mloader,
+ work);
+
+ /* Remove this module */
+ platform_device_unregister(m->pdev);
+
+ platform_driver_unregister(&db5500_mloader_driver);
+ kfree(m);
+
+}
+
+static ssize_t db5500_mloader_sysfs_addr(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "0x%x 0x%x 0x%x\n",
+ db5500_bootargs_memmap_modem_start,
+ db5500_bootargs_memmap_modem_total_size,
+ db5500_mloader_shm_total_size);
+}
+
+static ssize_t db5500_mloader_sysfs_finalize(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct db5500_mloader *m;
+
+ m = kmalloc(sizeof(struct db5500_mloader), GFP_KERNEL);
+
+ m->pdev = container_of(dev,
+ struct platform_device,
+ dev);
+
+ INIT_WORK(&m->work, db5500_mloader_clean_up);
+
+ /* The module can not remove itself while being in a sysfs function,
+ * it has to use a workqueue.
+ */
+ schedule_work(&m->work);
+
+ return count;
+}
+
+static void db5500_mloader_release(struct device *dev)
+{
+ /* Nothing to release */
+}
+
+static int __init db5500_mloader_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ pdev->dev.release = db5500_mloader_release;
+
+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_addr.attr);
+ if (ret)
+ return ret;
+ ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_finalize.attr);
+
+ if (ret) {
+ sysfs_remove_file(&pdev->dev.kobj, &dev_attr_addr.attr);
+ return ret;
+ }
+
+ return 0;
+
+}
+
+static int __init db5500_mloader_init(void)
+{
+/*
+ * mloader for Fairbanks. It exports the physical
+ * address where the modem side ELF should be located in a sysfs
+ * file to make it available for a user space utility.
+ * When the mLoader utility has picked up these settings, this module is no
+ * longer needed and can be removed by writing to sysfs finalize.
+ *
+ * The modem side should be loaded via mmap'ed /dev/mem
+ *
+ */
+
+ return platform_driver_probe(&db5500_mloader_driver,
+ db5500_mloader_probe);
+}
+module_init(db5500_mloader_init);
+
+
+static void __exit mloader_exit(void)
+{
+ platform_driver_unregister(&db5500_mloader_driver);
+}
+module_exit(mloader_exit);
+
+MODULE_AUTHOR("Jonas Aaberg <jonas.aberg@stericsson.com>");
+MODULE_LICENSE("GPL");