diff options
author | Philippe Langlais <philippe.langlais@stericsson.com> | 2011-10-14 09:47:42 +0200 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:07:10 +0200 |
commit | f21deb0ceda2342d187ddaf611583cf636216696 (patch) | |
tree | 2d614e7aa83928ff44ef0587fc3e593a321164a5 /arch | |
parent | 079c8e0087da770a1daa749ad630bb8627d6191e (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.c | 186 |
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"); |