diff options
author | Iliyan Malchev <malchev@google.com> | 2011-10-17 16:24:34 -0700 |
---|---|---|
committer | Iliyan Malchev <malchev@google.com> | 2011-10-17 16:24:34 -0700 |
commit | 538081533cd0bf0493a639d9072e8c494efbed39 (patch) | |
tree | 699cee8b6431256295212db6988405c5a548a2e0 /arch/arm/plat-omap | |
parent | fd15d12179fc16a3a3c9a0a61f1eb0eb6c26a5bc (diff) | |
parent | 02c360221040924c2542113c4a72fe9d6af2d1ce (diff) | |
download | kernel_samsung_tuna-538081533cd0bf0493a639d9072e8c494efbed39.zip kernel_samsung_tuna-538081533cd0bf0493a639d9072e8c494efbed39.tar.gz kernel_samsung_tuna-538081533cd0bf0493a639d9072e8c494efbed39.tar.bz2 |
Merge branch 'linux-omap-3.0' into android-omap-3.0
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r-- | arch/arm/plat-omap/dma.c | 18 | ||||
-rw-r--r-- | arch/arm/plat-omap/include/plat/omap-serial.h | 1 | ||||
-rw-r--r-- | arch/arm/plat-omap/mailbox.c | 20 | ||||
-rw-r--r-- | arch/arm/plat-omap/omap_rpmsg.c | 117 |
4 files changed, 81 insertions, 75 deletions
diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index c22217c..3ec7ec5 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1024,12 +1024,26 @@ EXPORT_SYMBOL(omap_set_dma_callback); */ dma_addr_t omap_get_dma_src_pos(int lch) { + u32 cdac; dma_addr_t offset = 0; if (cpu_is_omap15xx()) offset = p->dma_read(CPC, lch); - else - offset = p->dma_read(CSAC, lch); + else { + /* + * CDAC != 0 indicates that the DMA transfer on the channel has + * been started already. + * If CDAC == 0, we can not trust the CSAC value since it has + * not been updated, and can contain random number. + * Return the start address in case the DMA has not jet started. + * This is valid since in fact the DMA has not yet progressed. + */ + cdac = p->dma_read(CDAC, lch); + if (likely(cdac)) + offset = p->dma_read(CSAC, lch); + else + offset = p->dma_read(CSSA, lch); + } if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) offset = p->dma_read(CSAC, lch); diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 56b63f8..2fbb5f0 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -141,6 +141,7 @@ struct uart_omap_port { unsigned char wer; int use_dma; + bool suspended; /* * Some bits in registers are cleared on a read, so they must * be saved whenever the register is read but the bits will not diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index a80e424..653153e 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -267,13 +267,6 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } if (!mbox->use_count++) { - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, - mbox->name, mbox); - if (unlikely(ret)) { - pr_err("failed to register mailbox interrupt:%d\n", - ret); - goto fail_request_irq; - } mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); if (!mq) { ret = -ENOMEM; @@ -288,15 +281,22 @@ static int omap_mbox_startup(struct omap_mbox *mbox) } mbox->rxq = mq; mq->mbox = mbox; + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + pr_err("failed to register mailbox interrupt:%d\n", + ret); + goto fail_request_irq; + } } mutex_unlock(&mbox_configured_lock); return 0; +fail_request_irq: + mbox_queue_free(mbox->rxq); fail_alloc_rxq: mbox_queue_free(mbox->txq); fail_alloc_txq: - free_irq(mbox->irq, mbox); -fail_request_irq: if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); mbox->use_count--; @@ -315,7 +315,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox) if (!--mbox->use_count) { free_irq(mbox->irq, mbox); tasklet_kill(&mbox->txq->tasklet); - flush_work_sync(&mbox->rxq->work); + flush_work_sync(&mbox->rxq->work); mbox_queue_free(mbox->txq); mbox_queue_free(mbox->rxq); } diff --git a/arch/arm/plat-omap/omap_rpmsg.c b/arch/arm/plat-omap/omap_rpmsg.c index 0cfd716..08f223e 100644 --- a/arch/arm/plat-omap/omap_rpmsg.c +++ b/arch/arm/plat-omap/omap_rpmsg.c @@ -50,10 +50,9 @@ struct omap_rpmsg_vproc { struct rproc *rproc; struct notifier_block nb; struct notifier_block rproc_nb; - struct notifier_block rproc_nb_pos_suspend; - struct notifier_block rproc_nb_resume; - struct notifier_block rproc_nb_error; struct work_struct reset_work; + bool slave_reset; + struct omap_rpmsg_vproc *slave_next; struct virtqueue *vq[2]; int base_vq_id; int num_of_vqs; @@ -201,39 +200,34 @@ static int omap_rpmsg_mbox_callback(struct notifier_block *this, return NOTIFY_DONE; } -static int rpmsg_rproc_error(struct notifier_block *this, - unsigned long type, void *data) +static void rpmsg_reset_devices(struct omap_rpmsg_vproc *rpdev) { - struct omap_rpmsg_vproc *rpdev = - container_of(this, struct omap_rpmsg_vproc, rproc_nb_error); + /* wait until previous reset requests have finished */ + flush_work_sync(&rpdev->reset_work); + schedule_work(&rpdev->reset_work); +} +static int rpmsg_rproc_error(struct omap_rpmsg_vproc *rpdev) +{ pr_err("Fatal error in %s\n", rpdev->rproc_name); #ifdef CONFIG_OMAP_RPMSG_RECOVERY - schedule_work(&rpdev->reset_work); + if (rpdev->slave_reset) + return NOTIFY_DONE; + rpmsg_reset_devices(rpdev); #endif return NOTIFY_DONE; } -static int rpmsg_rproc_suspend(struct notifier_block *this, - unsigned long type, void *data) +static int rpmsg_rproc_suspend(struct omap_rpmsg_vproc *rpdev) { - struct omap_rpmsg_vproc *rpdev = - container_of(this, struct omap_rpmsg_vproc, rproc_nb); - if (virtqueue_more_used(rpdev->vq[0])) return NOTIFY_BAD; return NOTIFY_DONE; } -static int rpmsg_rproc_pos_suspend(struct notifier_block *this, - unsigned long type, void *data) +static int rpmsg_rproc_pos_suspend(struct omap_rpmsg_vproc *rpdev) { - struct omap_rpmsg_vproc *rpdev = - container_of(this, - struct omap_rpmsg_vproc, - rproc_nb_pos_suspend); - if (rpdev->mbox) { omap_mbox_put(rpdev->mbox, &rpdev->nb); rpdev->mbox = NULL; @@ -242,19 +236,33 @@ static int rpmsg_rproc_pos_suspend(struct notifier_block *this, return NOTIFY_DONE; } -static int rpmsg_rproc_resume(struct notifier_block *this, - unsigned long type, void *data) +static int rpmsg_rproc_resume(struct omap_rpmsg_vproc *rpdev) { - struct omap_rpmsg_vproc *rpdev = - container_of(this, - struct omap_rpmsg_vproc, - rproc_nb_resume); - if (!rpdev->mbox) rpdev->mbox = omap_mbox_get(rpdev->mbox_name, &rpdev->nb); return NOTIFY_DONE; } + +static int rpmsg_rproc_events(struct notifier_block *this, + unsigned long type, void *data) +{ + struct omap_rpmsg_vproc *rpdev = container_of(this, + struct omap_rpmsg_vproc, rproc_nb); + + switch (type) { + case RPROC_ERROR: + return rpmsg_rproc_error(rpdev); + case RPROC_PRE_SUSPEND: + return rpmsg_rproc_suspend(rpdev); + case RPROC_POS_SUSPEND: + return rpmsg_rproc_pos_suspend(rpdev); + case RPROC_RESUME: + return rpmsg_rproc_resume(rpdev); + } + return NOTIFY_DONE; +} + static struct virtqueue *rp_find_vq(struct virtio_device *vdev, unsigned index, void (*callback)(struct virtqueue *vq), @@ -311,17 +319,7 @@ static void omap_rpmsg_del_vqs(struct virtio_device *vdev) struct virtqueue *vq, *n; struct omap_rpmsg_vproc *rpdev = to_omap_rpdev(vdev); - rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb, - RPROC_PRE_SUSPEND); - - rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb_pos_suspend, - RPROC_POS_SUSPEND); - - rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb_resume, - RPROC_RESUME); - - rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb_error, - RPROC_ERROR); + rproc_event_unregister(rpdev->rproc, &rpdev->rproc_nb); list_for_each_entry_safe(vq, n, &vdev->vqs, list) { struct omap_rpmsg_vq_info *rpvq = vq->priv; @@ -411,24 +409,9 @@ static int omap_rpmsg_find_vqs(struct virtio_device *vdev, unsigned nvqs, err = -EINVAL; goto put_mbox; } - /* register for remoteproc pre-suspend */ - rpdev->rproc_nb.notifier_call = rpmsg_rproc_suspend; - rproc_event_register(rpdev->rproc, &rpdev->rproc_nb, RPROC_PRE_SUSPEND); - - /* register for remoteproc post-suspend */ - rpdev->rproc_nb_pos_suspend.notifier_call = rpmsg_rproc_pos_suspend; - rproc_event_register(rpdev->rproc, - &rpdev->rproc_nb_pos_suspend, RPROC_POS_SUSPEND); - - /* register for remoteproc resume */ - rpdev->rproc_nb_resume.notifier_call = rpmsg_rproc_resume; - rproc_event_register(rpdev->rproc, - &rpdev->rproc_nb_resume, RPROC_RESUME); - - /* register for fatal errors */ - INIT_WORK(&rpdev->reset_work, rpmsg_reset_work); - rpdev->rproc_nb_error.notifier_call = rpmsg_rproc_error; - rproc_event_register(rpdev->rproc, &rpdev->rproc_nb_error, RPROC_ERROR); + /* register for remoteproc events */ + rpdev->rproc_nb.notifier_call = rpmsg_rproc_events; + rproc_event_register(rpdev->rproc, &rpdev->rproc_nb); return 0; @@ -483,15 +466,20 @@ static void rpmsg_reset_work(struct work_struct *work) { struct omap_rpmsg_vproc *rpdev = container_of(work, struct omap_rpmsg_vproc, reset_work); + struct omap_rpmsg_vproc *tmp; int ret; - pr_err("reseting virtio device %d\n", rpdev->vdev.index); - unregister_virtio_device(&rpdev->vdev); - memset(&rpdev->vdev.dev, 0, sizeof(struct device)); - rpdev->vdev.dev.release = omap_rpmsg_vproc_release; - ret = register_virtio_device(&rpdev->vdev); - if (ret) - pr_err("error creating virtio device %d\n", ret); + for (tmp = rpdev; tmp; tmp = tmp->slave_next) { + pr_err("reseting virtio device %d\n", tmp->vdev.index); + unregister_virtio_device(&tmp->vdev); + } + for (tmp = rpdev; tmp; tmp = tmp->slave_next) { + memset(&tmp->vdev.dev, 0, sizeof(struct device)); + tmp->vdev.dev.release = omap_rpmsg_vproc_release; + ret = register_virtio_device(&tmp->vdev); + if (ret) + pr_err("error creating virtio device %d\n", ret); + } } static struct virtio_config_ops omap_rpmsg_config_ops = { @@ -525,6 +513,7 @@ static struct omap_rpmsg_vproc omap_rpmsg_vprocs[] = { .rproc_name = "ipu", .base_vq_id = 0, .hardcoded_chnls = omap_ipuc0_hardcoded_chnls, + .slave_next = &omap_rpmsg_vprocs[1], }, /* ipu_c1's rpmsg backend */ { @@ -534,6 +523,7 @@ static struct omap_rpmsg_vproc omap_rpmsg_vprocs[] = { .rproc_name = "ipu", .base_vq_id = 2, .hardcoded_chnls = omap_ipuc1_hardcoded_chnls, + .slave_reset = true, }, }; @@ -561,6 +551,7 @@ static int __init omap_rpmsg_ini(void) rpdev->buf_size = RPMSG_BUFS_SPACE; rpdev->vring[0] = paddr + RPMSG_BUFS_SPACE; rpdev->vring[1] = paddr + RPMSG_BUFS_SPACE + RPMSG_RING_SIZE; + INIT_WORK(&rpdev->reset_work, rpmsg_reset_work); paddr += RPMSG_IPC_MEM; psize -= RPMSG_IPC_MEM; |