From 341408eca3f07f6595ebf1e1fe0c2228e206c751 Mon Sep 17 00:00:00 2001 From: Bibek Basu Date: Fri, 14 Oct 2011 12:45:50 +0530 Subject: u5500 : modem crashdump detection driver Detects modem crashdump ready and informs userspace ST-Ericsson Linux next: NA ST-Ericsson ID: 354626 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I204eeb48b7353509b07b9e3c6ec08bc7026985fa Signed-off-by: Bibek Basu Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34170 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Sandeep TRIPATHY Tested-by: Sandeep TRIPATHY Reviewed-by: Srinidhi KASAGAR --- drivers/modem/Kconfig | 13 +++- drivers/modem/Makefile | 1 + drivers/modem/mcdd.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 drivers/modem/mcdd.c diff --git a/drivers/modem/Kconfig b/drivers/modem/Kconfig index 323ef88af18..be8476ed0f9 100644 --- a/drivers/modem/Kconfig +++ b/drivers/modem/Kconfig @@ -1,6 +1,6 @@ config MODEM bool "Modem Access Framework" - default n + default y help Add support for Modem Access Framework. It allows different platform specific drivers to register modem access mechanisms @@ -8,6 +8,17 @@ config MODEM If unsure, say N. +config MODEM_U5500_MCDD + tristate "Modem crash dump detection driver for STE U5500 platform" + depends on (UX500_SOC_DB5500 && U5500_MODEM_IRQ && MODEM) + default y + help + Add support for Modem crash detection + driver for STE U5500 platform. + And inform userspace. + + If unsure, say N. + config MODEM_U8500 bool "Modem Access driver for STE U8500 platform" depends on MODEM diff --git a/drivers/modem/Makefile b/drivers/modem/Makefile index a7c1df50074..82921988f27 100644 --- a/drivers/modem/Makefile +++ b/drivers/modem/Makefile @@ -3,3 +3,4 @@ obj-$(CONFIG_MODEM_U8500) += modem_u8500.o obj-$(CONFIG_U8500_SHRM) += shrm/ obj-$(CONFIG_MODEM_M6718) += modem_m6718.o obj-$(CONFIG_MODEM_M6718_SPI) += m6718_spi/ +obj-$(CONFIG_MODEM_U5500_MCDD) += mcdd.o diff --git a/drivers/modem/mcdd.c b/drivers/modem/mcdd.c new file mode 100644 index 00000000000..d291944e810 --- /dev/null +++ b/drivers/modem/mcdd.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Modem Crash Detection Driver + * + * Author:Bibek Basu for ST-Ericsson + * + * License terms:GNU General Public License (GPLv2)version 2 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCDD_INTERRUPT_CLEAR (1 << 13) +#define MODEM_CRASH_EVT 1 + +struct mcdd_data { + bool modem_event; + u32 event_type; + wait_queue_head_t readq; + spinlock_t lock; + void __iomem *remap_intcon; + struct device *dev; + struct miscdevice misc_dev; +}; + +static struct mcdd_data *mcdd; + +static irqreturn_t mcdd_interrupt_cb(int irq, void *dev) +{ + writel(MCDD_INTERRUPT_CLEAR, (u32 *)mcdd->remap_intcon); + spin_lock(&mcdd->lock); + mcdd->modem_event = true; + mcdd->event_type = MODEM_CRASH_EVT; + spin_unlock(&mcdd->lock); + wake_up_interruptible(&mcdd->readq); + return IRQ_HANDLED; +} + +static unsigned int mcdd_select(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + unsigned long flags; + + poll_wait(filp, &mcdd->readq, wait); + spin_lock_irqsave(&mcdd->lock, flags); + + if (mcdd->modem_event == true) { + mask |= POLLPRI; + mcdd->modem_event = false; + } + spin_unlock_irqrestore(&mcdd->lock, flags); + + return mask; +} + +static int mcdd_open(struct inode *ino, struct file *filp) +{ + /* Do nothing */ + return 0; +} + +ssize_t mcdd_read(struct file *filp, char __user *buff, size_t size, loff_t *t) +{ + if (copy_to_user(buff, &mcdd->event_type, size)) + return -EFAULT; + return 0; +}; + +static const struct file_operations mcdd_fops = { + .open = mcdd_open, + .poll = mcdd_select, + .read = mcdd_read, + .owner = THIS_MODULE, +}; + +static int __devinit u5500_mcdd_probe(struct platform_device *pdev) +{ + struct resource *resource; + int ret = 0; + int irq; + + mcdd = kzalloc(sizeof(*mcdd), GFP_KERNEL); + if (!mcdd) { + dev_err(&pdev->dev, "Memory Allocation Failed"); + return -ENOMEM; + } + mcdd->dev = &pdev->dev; + mcdd->misc_dev.minor = MISC_DYNAMIC_MINOR; + mcdd->misc_dev.name = "mcdd"; + mcdd->misc_dev.fops = &mcdd_fops; + spin_lock_init(&mcdd->lock); + init_waitqueue_head(&(mcdd->readq)); + + /* Get addr for mcdd crash interrupt reset register and ioremap it */ + resource = platform_get_resource_byname(pdev, + IORESOURCE_MEM, + "mcdd_intreset_addr"); + if (resource == NULL) { + dev_err(&pdev->dev, + "Unable to retrieve mcdd_intreset_addr resource\n"); + goto exit_free; + } + mcdd->remap_intcon = ioremap(resource->start, resource_size(resource)); + if (!mcdd->remap_intcon) { + dev_err(&pdev->dev, "Unable to ioremap intcon mbox1\n"); + ret = -EINVAL; + goto exit_free; + } + + /* Get IRQ for mcdd mbox interrupt and allocate it */ + irq = platform_get_irq_byname(pdev, "mcdd_mbox_irq"); + if (irq < 0) { + dev_err(&pdev->dev, + "Unable to retrieve mcdd mbox irq resource\n"); + goto exit_unmap; + } + + ret = request_threaded_irq(irq, NULL, + mcdd_interrupt_cb, IRQF_NO_SUSPEND | IRQF_ONESHOT, + "mcdd", &mcdd); + if (ret < 0) { + dev_err(&pdev->dev, + "Could not allocate irq %d,error %d\n", + irq, ret); + goto exit_unmap; + } + + ret = misc_register(&mcdd->misc_dev); + if (ret) { + dev_err(&pdev->dev, "can't misc-register\n"); + goto exit_unmap; + } + dev_info(&pdev->dev, "mcdd driver registration done\n"); + return 0; + +exit_unmap: + iounmap(mcdd->remap_intcon); +exit_free: + kfree(mcdd); + return ret; +} + +static int u5500_mcdd_remove(struct platform_device *pdev) +{ + int ret = 0; + + if (mcdd) { + iounmap(mcdd->remap_intcon); + ret = misc_deregister(&mcdd->misc_dev); + kfree(mcdd); + } + return ret; +} + +static struct platform_driver u5500_mcdd_driver = { + .driver = { + .name = "u5500-mcdd-modem", + .owner = THIS_MODULE, + }, + .probe = u5500_mcdd_probe, + .remove = __devexit_p(u5500_mcdd_remove), +}; + +static int __init mcdd_init(void) +{ + return platform_driver_register(&u5500_mcdd_driver); +} +module_init(mcdd_init); + +static void __exit mcdd_exit(void) +{ + platform_driver_unregister(&u5500_mcdd_driver); +} +module_exit(mcdd_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("BIBEK BASU "); +MODULE_DESCRIPTION("Modem Dump Detection Driver"); +MODULE_ALIAS("mcdd driver"); -- cgit v1.2.3