diff options
author | Lee Jones <lee.jones@linaro.org> | 2012-01-05 14:19:50 +0000 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2012-01-05 14:19:50 +0000 |
commit | 90c7aee3617913742298b3e861fc139314e20ae6 (patch) | |
tree | a9c06e7fadcc56479ccaf560b100b2440a29724b /arch/arm/mach-ux500 | |
parent | e3cdaa3535ace42f553684d9cff72f05faf24df2 (diff) | |
parent | fbdfb62fca47323f1bd3d9b2862d10cd6fc1b334 (diff) |
Automatically merging tracking-igloo_kernel-modem into merge-integration-linux-ux500
Conflicting files:
Diffstat (limited to 'arch/arm/mach-ux500')
-rw-r--r-- | arch/arm/mach-ux500/Kconfig | 14 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/isa_ioctl.h | 51 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/mbox-db5500.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h | 72 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/mloader-dbx500.h | 48 | ||||
-rw-r--r-- | arch/arm/mach-ux500/include/mach/sim_detect.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-ux500/mloader-db5500.c | 202 | ||||
-rw-r--r-- | arch/arm/mach-ux500/mloader-db8500.c | 82 | ||||
-rw-r--r-- | arch/arm/mach-ux500/modem-irq-db5500.c | 6 |
9 files changed, 494 insertions, 2 deletions
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig index 21018ecfd67..92a85c202e6 100644 --- a/arch/arm/mach-ux500/Kconfig +++ b/arch/arm/mach-ux500/Kconfig @@ -140,4 +140,18 @@ source "arch/arm/mach-ux500/pm/Kconfig" source "arch/arm/mach-ux500/Kconfig-arch" +config DB8500_MLOADER + bool "Modem firmware upload/download support" + depends on UX500_SOC_DB8500 + select DBX500_MLOADER + help + Adds Modem firmware upload/download support to DB8500. + +config U5500_MLOADER + bool "mLoader, mem config from kernel boot args exported to sysfs" + depends on UX500_SOC_DB5500 + help + Link between boot args and user space program that loads the modem ELF. + This is used to expose the modem parameters using sysfs interface. + endif diff --git a/arch/arm/mach-ux500/include/mach/isa_ioctl.h b/arch/arm/mach-ux500/include/mach/isa_ioctl.h new file mode 100644 index 00000000000..b05726f8c3c --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/isa_ioctl.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------*/ +/* Copyright ST Ericsson, 2009. */ +/* This program is free software; you can redistribute it and/or modify it */ +/* under the terms of the GNU General Public License as published by the */ +/* Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* This program is distributed in the hope that it will be useful, but */ +/* WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +/* See the GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with this program. If not, see <http://www.gnu.org/licenses/>. */ +/*---------------------------------------------------------------------------*/ +#ifndef __MODEM_IPC_INCLUDED +#define __MODEM_IPC_INCLUDED + +#define DLP_IOCTL_MAGIC_NUMBER 'M' +#define COMMON_BUFFER_SIZE (1024*1024) + +/** +DLP Message Structure for Userland +*/ +struct t_dlp_message{ + unsigned int offset; + unsigned int size; +}; + +/** +mmap constants. +*/ +enum t_dlp_mmap_params { + MMAP_DLQUEUE, + MMAP_ULQUEUE +}; + +/** +DLP IOCTLs for Userland +*/ +#define DLP_IOC_ALLOCATE_BUFFER \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 0, struct t_dlp_message *) +#define DLP_IOC_DEALLOCATE_BUFFER \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 1, struct t_dlp_message *) +#define DLP_IOC_GET_MESSAGE \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 2, struct t_dlp_message *) +#define DLP_IOC_PUT_MESSAGE \ + _IOWR(DLP_IOCTL_MAGIC_NUMBER, 3, struct t_dlp_message *) + +#endif /*__MODEM_IPC_INCLUDED*/ + diff --git a/arch/arm/mach-ux500/include/mach/mbox-db5500.h b/arch/arm/mach-ux500/include/mach/mbox-db5500.h index 7f9da4d2fbd..24af854befe 100644 --- a/arch/arm/mach-ux500/include/mach/mbox-db5500.h +++ b/arch/arm/mach-ux500/include/mach/mbox-db5500.h @@ -40,6 +40,7 @@ typedef void mbox_recv_cb_t (u32 mbox_msg, void *priv); * @lock: Spinlock to protect this mailbox instance. * @write_index: Index in internal buffer to write to. * @read_index: Index in internal buffer to read from. + * @irq: mailbox interrupt. * @allocated: Indicates whether this particular mailbox * id has been allocated by someone. */ @@ -57,7 +58,11 @@ struct mbox { spinlock_t lock; u8 write_index; u8 read_index; + int irq; bool allocated; +#if defined(CONFIG_DEBUG_FS) + struct dentry *dentry; +#endif }; /** diff --git a/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h new file mode 100644 index 00000000000..0b2fc604873 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/mbox_channels-db5500.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Marcin Mielczarczyk <marcin.mielczarczyk@tieto.com> for ST-Ericsson. + * Bibek Basu <bibek.basu@stericsson.com> + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef __INC_MBOX_CHANNELS_H +#define __INC_MBOX_CHANNELS_H + +/* Maximum number of datawords which can be send in one PDU */ +#define MAILBOX_NR_OF_DATAWORDS 3 + +/** + * mbox_channel_cb_t - Definition of the mailbox channel callback. + * @data: Pointer to the data. + * @length: Length of the data. + * @priv: The client's private data. + * + * This function will be called upon reception of complete mbox channel PDU + * or after completion of send operation. + */ +typedef void mbox_channel_cb_t (u32 *data, u32 length, void *priv); + +/** + * struct mbox_channel_msg - Definition of mbox channel message + * @channel: Channel number. + * @data: Pointer to data to be sent. + * @length: Length of data to be sent. + * @cb: Pointer to the callback function to be called when send + * operation will be finished. + * @priv: The client's private data. + * + * This structure describes mailbox channel message. + */ +struct mbox_channel_msg { + u16 channel; + u32 *data; + u8 length; + mbox_channel_cb_t *cb; + void *priv; +}; + +/** + * mbox_channel_register - Set up a given mailbox channel. + * @channel: Mailbox channel number. + * @cb: Pointer to the callback function to be called when a new message + * is received. + * @priv: Client user data which will be returned in the callback. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_register(u16 channel, mbox_channel_cb_t *cb, void *priv); + +/** + * mbox_channel_send - Send data on given mailbox channel. + * @msg: Mailbox channel message to be sent. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_send(struct mbox_channel_msg *msg); + +/** + * mbox_channel_revoke_messages - Revoke messages on given mailbox channel. + * @channel: Mailbox channel number. + * + * Returns 0 on success or a negative error code on error. + */ +int mbox_channel_revoke_messages(u16 channel); + +#endif /*INC_STE_MBOX_H*/ + diff --git a/arch/arm/mach-ux500/include/mach/mloader-dbx500.h b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h new file mode 100644 index 00000000000..68fa55a3f53 --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/mloader-dbx500.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Ludovic Barre <ludovic.barre@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2 + */ + +#ifndef _MLOADER_UX500_H_ +#define _MLOADER_UX500_H_ + +/** + * struct dbx500_ml_area - data structure for modem memory areas description + * @name: name of the area + * @start: start address of the area + * @size: size of the area + */ +struct dbx500_ml_area { + const char *name; + u32 start; + u32 size; +}; + +/** + * struct dbx500_ml_fw - data stucture for modem firmwares description + * @name: firmware name + * @area: area where firmware is uploaded + * @offset: offset in the area where firmware is uploaded + */ +struct dbx500_ml_fw { + const char *name; + struct dbx500_ml_area *area; + u32 offset; +}; + +/** + * struct dbx500_mloader_pdata - data structure for platform specific data + * @fws: pointer on firmwares table + * @nr_fws: number of firmwares + * @areas: pointer on areas table + * @nr_areas: number of areas + */ +struct dbx500_mloader_pdata { + struct dbx500_ml_fw *fws; + int nr_fws; + struct dbx500_ml_area *areas; + int nr_areas; +}; + +#endif /* _MLOADER_UX500_H_ */ diff --git a/arch/arm/mach-ux500/include/mach/sim_detect.h b/arch/arm/mach-ux500/include/mach/sim_detect.h new file mode 100644 index 00000000000..8d6e81f1e8a --- /dev/null +++ b/arch/arm/mach-ux500/include/mach/sim_detect.h @@ -0,0 +1,16 @@ +/* + * Copyright ST-Ericsson 2010 SA. + * + * Author: Bibek Basu <bibek.basu@stericsson.com> + * Licensed under GPLv2. + */ + +#ifndef _AB8500_SIM_DETECT_H +#define _AB8500_SIM_DETECT_H + +struct sim_detect_platform_data { + int irq_num; +}; + +#endif + diff --git a/arch/arm/mach-ux500/mloader-db5500.c b/arch/arm/mach-ux500/mloader-db5500.c new file mode 100644 index 00000000000..bc3a57af28b --- /dev/null +++ b/arch/arm/mach-ux500/mloader-db5500.c @@ -0,0 +1,202 @@ +/* + * 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 ssize_t db5500_mloader_sysfs_itpmode(struct device *dev, + struct device_attribute *attr, + char *buf); + +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 DEVICE_ATTR(is_itpmode, S_IRUSR|S_IRGRP, db5500_mloader_sysfs_itpmode, NULL); + +static unsigned int db5500_bootargs_memmap_modem_start; +static unsigned int db5500_bootargs_memmap_modem_total_size; +static unsigned int db5500_mloader_itpmode; +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_modem_memmap(char *p) +{ + db5500_bootargs_memmap_modem_total_size = memparse(p, &p); + if (*p == '@') + db5500_bootargs_memmap_modem_start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_modem", db5500_bootargs_modem_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; +} +early_param("mloader.shm_total_size", db5500_bootargs_shm_total_size); + +static int __init db5500_bootargs_itpmode(char *p) +{ + int ret; + int count = 3; + if (!memcmp(p, "itp", count)) + db5500_mloader_itpmode = true; + else + db5500_mloader_itpmode = false; + return 1; +} +early_param("modem_boot_type", db5500_bootargs_itpmode); + +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); + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_is_itpmode.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_itpmode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "0x%x\n", + db5500_mloader_itpmode); +} + +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; + } + ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_is_itpmode.attr); + if (ret) { + sysfs_remove_file(&pdev->dev.kobj, &dev_attr_finalize.attr); + 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"); diff --git a/arch/arm/mach-ux500/mloader-db8500.c b/arch/arm/mach-ux500/mloader-db8500.c new file mode 100644 index 00000000000..6171a9db82f --- /dev/null +++ b/arch/arm/mach-ux500/mloader-db8500.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * + * Author: Maxime Coquelin <maxime.coquelin-nonst@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + */ +#include <linux/types.h> +#include <linux/platform_device.h> + +#include <mach/mloader-dbx500.h> + +static struct dbx500_ml_area modem_areas[] = { + { .name = "modem_trace", .start = 0x6000000, .size = 0xf00000 }, + { .name = "modem_shared", .start = 0x6f00000, .size = 0x100000 }, + { .name = "modem_priv", .start = 0x7000000, .size = 0x1000000 }, +}; + +static struct dbx500_ml_fw modem_fws[] = { + { .name = "MODEM", .area = &modem_areas[0], .offset = 0x0 }, + { .name = "IPL", .area = &modem_areas[1], .offset = 0x00 }, +}; + +static struct dbx500_mloader_pdata mloader_fw_data = { + .fws = modem_fws, + .nr_fws = ARRAY_SIZE(modem_fws), + .areas = modem_areas, + .nr_areas = ARRAY_SIZE(modem_areas), +}; + +struct platform_device mloader_fw_device = { + .name = "dbx500_mloader_fw", + .id = -1, + .dev = { + .platform_data = &mloader_fw_data, + }, + .num_resources = 0, +}; + +/* Default areas can be overloaded in cmdline */ +static int __init early_modem_priv(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[2]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_modem", early_modem_priv); + +static int __init early_modem_shared(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[1]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_mshared", early_modem_shared); + +static int __init early_modem_trace(char *p) +{ + struct dbx500_ml_area *area = &modem_areas[0]; + + area->size = memparse(p, &p); + + if (*p == '@') + area->start = memparse(p + 1, &p); + + return 0; +} +early_param("mem_mtrace", early_modem_trace); + diff --git a/arch/arm/mach-ux500/modem-irq-db5500.c b/arch/arm/mach-ux500/modem-irq-db5500.c index 6b86416c94c..7c2947af984 100644 --- a/arch/arm/mach-ux500/modem-irq-db5500.c +++ b/arch/arm/mach-ux500/modem-irq-db5500.c @@ -81,7 +81,7 @@ static irqreturn_t modem_cpu_irq_handler(int irq, void *data) virt_irq); if (virt_irq != 0) - generic_handle_irq(virt_irq); + handle_nested_irq(virt_irq); pr_debug("modem_irq: Done handling virtual IRQ %d!\n", virt_irq); @@ -91,6 +91,7 @@ static irqreturn_t modem_cpu_irq_handler(int irq, void *data) static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip) { irq_set_chip_and_handler(irq, modem_irq_chip, handle_simple_irq); + irq_set_nested_thread(irq, 1); set_irq_flags(irq, IRQF_VALID); pr_debug("modem_irq: Created virtual IRQ %d\n", irq); @@ -131,7 +132,8 @@ static int modem_irq_init(void) create_virtual_irq(MBOX_PAIR2_VIRT_IRQ, &modem_irq_chip); err = request_threaded_irq(IRQ_DB5500_MODEM, NULL, - modem_cpu_irq_handler, IRQF_ONESHOT, + modem_cpu_irq_handler, + IRQF_NO_SUSPEND | IRQF_ONESHOT, "modem_irq", mi); if (err) pr_err("modem_irq: Could not register IRQ %d\n", |