From 40cbbb781d3eba5d6ac0860db078af490e5c7c6b Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 23 Apr 2009 11:05:19 +0900 Subject: block: implement and use [__]blk_end_request_all() There are many [__]blk_end_request() call sites which call it with full request length and expect full completion. Many of them ensure that the request actually completes by doing BUG_ON() the return value, which is awkward and error-prone. This patch adds [__]blk_end_request_all() which takes @rq and @error and fully completes the request. BUG_ON() is added to to ensure that this actually happens. Most conversions are simple but there are a few noteworthy ones. * cdrom/viocd: viocd_end_request() replaced with direct calls to __blk_end_request_all(). * s390/block/dasd: dasd_end_request() replaced with direct calls to __blk_end_request_all(). * s390/char/tape_block: tapeblock_end_request() replaced with direct calls to blk_end_request_all(). [ Impact: cleanup ] Signed-off-by: Tejun Heo Cc: Russell King Cc: Stephen Rothwell Cc: Mike Miller Cc: Martin Schwidefsky Cc: Jeff Garzik Cc: Rusty Russell Cc: Jeremy Fitzhardinge Cc: Alex Dubov Cc: James Bottomley --- arch/arm/plat-omap/mailbox.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 0abfbaa5987..cf81bad8aec 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -192,8 +192,7 @@ static void mbox_tx_work(struct work_struct *work) } spin_lock(q->queue_lock); - if (__blk_end_request(rq, 0, 0)) - BUG(); + __blk_end_request_all(rq, 0); spin_unlock(q->queue_lock); } } @@ -224,10 +223,7 @@ static void mbox_rx_work(struct work_struct *work) break; msg = (mbox_msg_t) rq->data; - - if (blk_end_request(rq, 0, 0)) - BUG(); - + blk_end_request_all(rq, 0); mbox->rxq->callback((void *)msg); } } @@ -337,8 +333,7 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) *p = (mbox_msg_t) rq->data; - if (blk_end_request(rq, 0, 0)) - BUG(); + blk_end_request_all(rq, 0); if (unlikely(mbox_seq_test(mbox, *p))) { pr_info("mbox: Illegal seq bit!(%08x) ignored\n", *p); -- cgit v1.2.3-70-g09d2 From ec24751a6b57e1373a12361e581b2458bc9bb791 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 23 Apr 2009 11:05:20 +0900 Subject: arm-omap: don't abuse rq->data omap mailbox uses rq->data as the second opaque pointer to carry mbox_msg_t and rq->special message argument which is needed only for tx. Add and use omap_msg_tx_data struct for tx and use rq->special for mbox_msg_t for rx such that only rq->special is used as opaque pointer. [ Impact: cleanup rq->data usage, extra kmalloc in msg_send ] Signed-off-by: Tejun Heo Cc: Russell King --- arch/arm/plat-omap/mailbox.c | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index cf81bad8aec..538ba7541d3 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -147,24 +147,40 @@ static int __mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void *arg) return ret; } +struct omap_msg_tx_data { + mbox_msg_t msg; + void *arg; +}; + +static void omap_msg_tx_end_io(struct request *rq, int error) +{ + kfree(rq->special); + __blk_put_request(rq->q, rq); +} + int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg, void* arg) { + struct omap_msg_tx_data *tx_data; struct request *rq; struct request_queue *q = mbox->txq->queue; - int ret = 0; + + tx_data = kmalloc(sizeof(*tx_data), GFP_ATOMIC); + if (unlikely(!tx_data)) + return -ENOMEM; rq = blk_get_request(q, WRITE, GFP_ATOMIC); if (unlikely(!rq)) { - ret = -ENOMEM; - goto fail; + kfree(tx_data); + return -ENOMEM; } - rq->data = (void *)msg; - blk_insert_request(q, rq, 0, arg); + tx_data->msg = msg; + tx_data->arg = arg; + rq->end_io = omap_msg_tx_end_io; + blk_insert_request(q, rq, 0, tx_data); schedule_work(&mbox->txq->work); - fail: - return ret; + return 0; } EXPORT_SYMBOL(omap_mbox_msg_send); @@ -178,6 +194,8 @@ static void mbox_tx_work(struct work_struct *work) struct request_queue *q = mbox->txq->queue; while (1) { + struct omap_msg_tx_data *tx_data; + spin_lock(q->queue_lock); rq = elv_next_request(q); spin_unlock(q->queue_lock); @@ -185,7 +203,9 @@ static void mbox_tx_work(struct work_struct *work) if (!rq) break; - ret = __mbox_msg_send(mbox, (mbox_msg_t) rq->data, rq->special); + tx_data = rq->special; + + ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg); if (ret) { enable_mbox_irq(mbox, IRQ_TX); return; @@ -222,7 +242,7 @@ static void mbox_rx_work(struct work_struct *work) if (!rq) break; - msg = (mbox_msg_t) rq->data; + msg = (mbox_msg_t)rq->special; blk_end_request_all(rq, 0); mbox->rxq->callback((void *)msg); } @@ -260,7 +280,6 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) goto nomem; msg = mbox_fifo_read(mbox); - rq->data = (void *)msg; if (unlikely(mbox_seq_test(mbox, msg))) { pr_info("mbox: Illegal seq bit!(%08x)\n", msg); @@ -268,7 +287,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) mbox->err_notify(); } - blk_insert_request(q, rq, 0, NULL); + blk_insert_request(q, rq, 0, (void *)msg); if (mbox->ops->type == OMAP_MBOX_TYPE1) break; } @@ -331,7 +350,7 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) if (!rq) break; - *p = (mbox_msg_t) rq->data; + *p = (mbox_msg_t)rq->special; blk_end_request_all(rq, 0); -- cgit v1.2.3-70-g09d2 From a9dcad5e375800fcb07f7617dba23b3aade8f09d Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 26 Jan 2009 15:13:40 +0200 Subject: omap iommu: tlb and pagetable primitives This patch provides: - iotlb_*() : iommu tlb operations - iopgtable_*() : iommu pagetable(twl) operations - iommu_*() : the other generic operations and the entry points to register and acquire iommu object. Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/include/mach/iommu.h | 168 ++++++ arch/arm/plat-omap/iommu.c | 996 ++++++++++++++++++++++++++++++++ arch/arm/plat-omap/iopgtable.h | 72 +++ 3 files changed, 1236 insertions(+) create mode 100644 arch/arm/plat-omap/include/mach/iommu.h create mode 100644 arch/arm/plat-omap/iommu.c create mode 100644 arch/arm/plat-omap/iopgtable.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/iommu.h b/arch/arm/plat-omap/include/mach/iommu.h new file mode 100644 index 00000000000..769b00b4c34 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/iommu.h @@ -0,0 +1,168 @@ +/* + * omap iommu: main structures + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU + * + * 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. + */ + +#ifndef __MACH_IOMMU_H +#define __MACH_IOMMU_H + +struct iotlb_entry { + u32 da; + u32 pa; + u32 pgsz, prsvd, valid; + union { + u16 ap; + struct { + u32 endian, elsz, mixed; + }; + }; +}; + +struct iommu { + const char *name; + struct module *owner; + struct clk *clk; + void __iomem *regbase; + struct device *dev; + + unsigned int refcount; + struct mutex iommu_lock; /* global for this whole object */ + + /* + * We don't change iopgd for a situation like pgd for a task, + * but share it globally for each iommu. + */ + u32 *iopgd; + spinlock_t page_table_lock; /* protect iopgd */ + + int nr_tlb_entries; + + struct list_head mmap; + struct mutex mmap_lock; /* protect mmap */ + + int (*isr)(struct iommu *obj); + + void *ctx; /* iommu context: registres saved area */ +}; + +struct cr_regs { + union { + struct { + u16 cam_l; + u16 cam_h; + }; + u32 cam; + }; + union { + struct { + u16 ram_l; + u16 ram_h; + }; + u32 ram; + }; +}; + +struct iotlb_lock { + short base; + short vict; +}; + +/* architecture specific functions */ +struct iommu_functions { + unsigned long version; + + int (*enable)(struct iommu *obj); + void (*disable)(struct iommu *obj); + u32 (*fault_isr)(struct iommu *obj, u32 *ra); + + void (*tlb_read_cr)(struct iommu *obj, struct cr_regs *cr); + void (*tlb_load_cr)(struct iommu *obj, struct cr_regs *cr); + + struct cr_regs *(*alloc_cr)(struct iommu *obj, struct iotlb_entry *e); + int (*cr_valid)(struct cr_regs *cr); + u32 (*cr_to_virt)(struct cr_regs *cr); + void (*cr_to_e)(struct cr_regs *cr, struct iotlb_entry *e); + ssize_t (*dump_cr)(struct iommu *obj, struct cr_regs *cr, char *buf); + + u32 (*get_pte_attr)(struct iotlb_entry *e); + + void (*save_ctx)(struct iommu *obj); + void (*restore_ctx)(struct iommu *obj); + ssize_t (*dump_ctx)(struct iommu *obj, char *buf); +}; + +struct iommu_platform_data { + const char *name; + const char *clk_name; + const int nr_tlb_entries; +}; + +#if defined(CONFIG_ARCH_OMAP1) +#error "iommu for this processor not implemented yet" +#else +#include +#endif + +/* + * utilities for super page(16MB, 1MB, 64KB and 4KB) + */ + +#define iopgsz_max(bytes) \ + (((bytes) >= SZ_16M) ? SZ_16M : \ + ((bytes) >= SZ_1M) ? SZ_1M : \ + ((bytes) >= SZ_64K) ? SZ_64K : \ + ((bytes) >= SZ_4K) ? SZ_4K : 0) + +#define bytes_to_iopgsz(bytes) \ + (((bytes) == SZ_16M) ? MMU_CAM_PGSZ_16M : \ + ((bytes) == SZ_1M) ? MMU_CAM_PGSZ_1M : \ + ((bytes) == SZ_64K) ? MMU_CAM_PGSZ_64K : \ + ((bytes) == SZ_4K) ? MMU_CAM_PGSZ_4K : -1) + +#define iopgsz_to_bytes(iopgsz) \ + (((iopgsz) == MMU_CAM_PGSZ_16M) ? SZ_16M : \ + ((iopgsz) == MMU_CAM_PGSZ_1M) ? SZ_1M : \ + ((iopgsz) == MMU_CAM_PGSZ_64K) ? SZ_64K : \ + ((iopgsz) == MMU_CAM_PGSZ_4K) ? SZ_4K : 0) + +#define iopgsz_ok(bytes) (bytes_to_iopgsz(bytes) >= 0) + +/* + * global functions + */ +extern u32 iommu_arch_version(void); + +extern void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e); +extern u32 iotlb_cr_to_virt(struct cr_regs *cr); + +extern int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e); +extern void flush_iotlb_page(struct iommu *obj, u32 da); +extern void flush_iotlb_range(struct iommu *obj, u32 start, u32 end); +extern void flush_iotlb_all(struct iommu *obj); + +extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e); +extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova); + +extern struct iommu *iommu_get(const char *name); +extern void iommu_put(struct iommu *obj); + +extern void iommu_save_ctx(struct iommu *obj); +extern void iommu_restore_ctx(struct iommu *obj); + +extern int install_iommu_arch(const struct iommu_functions *ops); +extern void uninstall_iommu_arch(const struct iommu_functions *ops); + +extern int foreach_iommu_device(void *data, + int (*fn)(struct device *, void *)); + +extern ssize_t iommu_dump_ctx(struct iommu *obj, char *buf); +extern size_t dump_tlb_entries(struct iommu *obj, char *buf); + +#endif /* __MACH_IOMMU_H */ diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c new file mode 100644 index 00000000000..4cf449fa2cb --- /dev/null +++ b/arch/arm/plat-omap/iommu.c @@ -0,0 +1,996 @@ +/* + * omap iommu: tlb and pagetable primitives + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU , + * Paul Mundt and Toshihiro Kobayashi + * + * 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 +#include +#include +#include +#include +#include + +#include + +#include + +#include "iopgtable.h" + +/* accommodate the difference between omap1 and omap2/3 */ +static const struct iommu_functions *arch_iommu; + +static struct platform_driver omap_iommu_driver; +static struct kmem_cache *iopte_cachep; + +/** + * install_iommu_arch - Install archtecure specific iommu functions + * @ops: a pointer to architecture specific iommu functions + * + * There are several kind of iommu algorithm(tlb, pagetable) among + * omap series. This interface installs such an iommu algorighm. + **/ +int install_iommu_arch(const struct iommu_functions *ops) +{ + if (arch_iommu) + return -EBUSY; + + arch_iommu = ops; + return 0; +} +EXPORT_SYMBOL_GPL(install_iommu_arch); + +/** + * uninstall_iommu_arch - Uninstall archtecure specific iommu functions + * @ops: a pointer to architecture specific iommu functions + * + * This interface uninstalls the iommu algorighm installed previously. + **/ +void uninstall_iommu_arch(const struct iommu_functions *ops) +{ + if (arch_iommu != ops) + pr_err("%s: not your arch\n", __func__); + + arch_iommu = NULL; +} +EXPORT_SYMBOL_GPL(uninstall_iommu_arch); + +/** + * iommu_save_ctx - Save registers for pm off-mode support + * @obj: target iommu + **/ +void iommu_save_ctx(struct iommu *obj) +{ + arch_iommu->save_ctx(obj); +} +EXPORT_SYMBOL_GPL(iommu_save_ctx); + +/** + * iommu_restore_ctx - Restore registers for pm off-mode support + * @obj: target iommu + **/ +void iommu_restore_ctx(struct iommu *obj) +{ + arch_iommu->restore_ctx(obj); +} +EXPORT_SYMBOL_GPL(iommu_restore_ctx); + +/** + * iommu_arch_version - Return running iommu arch version + **/ +u32 iommu_arch_version(void) +{ + return arch_iommu->version; +} +EXPORT_SYMBOL_GPL(iommu_arch_version); + +static int iommu_enable(struct iommu *obj) +{ + int err; + + if (!obj) + return -EINVAL; + + clk_enable(obj->clk); + + err = arch_iommu->enable(obj); + + clk_disable(obj->clk); + return err; +} + +static void iommu_disable(struct iommu *obj) +{ + if (!obj) + return; + + clk_enable(obj->clk); + + arch_iommu->disable(obj); + + clk_disable(obj->clk); +} + +/* + * TLB operations + */ +void iotlb_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e) +{ + BUG_ON(!cr || !e); + + arch_iommu->cr_to_e(cr, e); +} +EXPORT_SYMBOL_GPL(iotlb_cr_to_e); + +static inline int iotlb_cr_valid(struct cr_regs *cr) +{ + if (!cr) + return -EINVAL; + + return arch_iommu->cr_valid(cr); +} + +static inline struct cr_regs *iotlb_alloc_cr(struct iommu *obj, + struct iotlb_entry *e) +{ + if (!e) + return NULL; + + return arch_iommu->alloc_cr(obj, e); +} + +u32 iotlb_cr_to_virt(struct cr_regs *cr) +{ + return arch_iommu->cr_to_virt(cr); +} +EXPORT_SYMBOL_GPL(iotlb_cr_to_virt); + +static u32 get_iopte_attr(struct iotlb_entry *e) +{ + return arch_iommu->get_pte_attr(e); +} + +static u32 iommu_report_fault(struct iommu *obj, u32 *da) +{ + return arch_iommu->fault_isr(obj, da); +} + +static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l) +{ + u32 val; + + val = iommu_read_reg(obj, MMU_LOCK); + + l->base = MMU_LOCK_BASE(val); + l->vict = MMU_LOCK_VICT(val); + + BUG_ON(l->base != 0); /* Currently no preservation is used */ +} + +static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l) +{ + u32 val; + + BUG_ON(l->base != 0); /* Currently no preservation is used */ + + val = (l->base << MMU_LOCK_BASE_SHIFT); + val |= (l->vict << MMU_LOCK_VICT_SHIFT); + + iommu_write_reg(obj, val, MMU_LOCK); +} + +static void iotlb_read_cr(struct iommu *obj, struct cr_regs *cr) +{ + arch_iommu->tlb_read_cr(obj, cr); +} + +static void iotlb_load_cr(struct iommu *obj, struct cr_regs *cr) +{ + arch_iommu->tlb_load_cr(obj, cr); + + iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); + iommu_write_reg(obj, 1, MMU_LD_TLB); +} + +/** + * iotlb_dump_cr - Dump an iommu tlb entry into buf + * @obj: target iommu + * @cr: contents of cam and ram register + * @buf: output buffer + **/ +static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr, + char *buf) +{ + BUG_ON(!cr || !buf); + + return arch_iommu->dump_cr(obj, cr, buf); +} + +/** + * load_iotlb_entry - Set an iommu tlb entry + * @obj: target iommu + * @e: an iommu tlb entry info + **/ +int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) +{ + int i; + int err = 0; + struct iotlb_lock l; + struct cr_regs *cr; + + if (!obj || !obj->nr_tlb_entries || !e) + return -EINVAL; + + clk_enable(obj->clk); + + for (i = 0; i < obj->nr_tlb_entries; i++) { + struct cr_regs tmp; + + iotlb_lock_get(obj, &l); + l.vict = i; + iotlb_lock_set(obj, &l); + iotlb_read_cr(obj, &tmp); + if (!iotlb_cr_valid(&tmp)) + break; + } + + if (i == obj->nr_tlb_entries) { + dev_dbg(obj->dev, "%s: full: no entry\n", __func__); + err = -EBUSY; + goto out; + } + + cr = iotlb_alloc_cr(obj, e); + if (IS_ERR(cr)) { + clk_disable(obj->clk); + return PTR_ERR(cr); + } + + iotlb_load_cr(obj, cr); + kfree(cr); + + /* increment victim for next tlb load */ + if (++l.vict == obj->nr_tlb_entries) + l.vict = 0; + iotlb_lock_set(obj, &l); +out: + clk_disable(obj->clk); + return err; +} +EXPORT_SYMBOL_GPL(load_iotlb_entry); + +/** + * flush_iotlb_page - Clear an iommu tlb entry + * @obj: target iommu + * @da: iommu device virtual address + * + * Clear an iommu tlb entry which includes 'da' address. + **/ +void flush_iotlb_page(struct iommu *obj, u32 da) +{ + struct iotlb_lock l; + int i; + + clk_enable(obj->clk); + + for (i = 0; i < obj->nr_tlb_entries; i++) { + struct cr_regs cr; + u32 start; + size_t bytes; + + iotlb_lock_get(obj, &l); + l.vict = i; + iotlb_lock_set(obj, &l); + iotlb_read_cr(obj, &cr); + if (!iotlb_cr_valid(&cr)) + continue; + + start = iotlb_cr_to_virt(&cr); + bytes = iopgsz_to_bytes(cr.cam & 3); + + if ((start <= da) && (da < start + bytes)) { + dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", + __func__, start, da, bytes); + + iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); + } + } + clk_disable(obj->clk); + + if (i == obj->nr_tlb_entries) + dev_dbg(obj->dev, "%s: no page for %08x\n", __func__, da); +} +EXPORT_SYMBOL_GPL(flush_iotlb_page); + +/** + * flush_iotlb_range - Clear an iommu tlb entries + * @obj: target iommu + * @start: iommu device virtual address(start) + * @end: iommu device virtual address(end) + * + * Clear an iommu tlb entry which includes 'da' address. + **/ +void flush_iotlb_range(struct iommu *obj, u32 start, u32 end) +{ + u32 da = start; + + while (da < end) { + flush_iotlb_page(obj, da); + /* FIXME: Optimize for multiple page size */ + da += IOPTE_SIZE; + } +} +EXPORT_SYMBOL_GPL(flush_iotlb_range); + +/** + * flush_iotlb_all - Clear all iommu tlb entries + * @obj: target iommu + **/ +void flush_iotlb_all(struct iommu *obj) +{ + struct iotlb_lock l; + + clk_enable(obj->clk); + + l.base = 0; + l.vict = 0; + iotlb_lock_set(obj, &l); + + iommu_write_reg(obj, 1, MMU_GFLUSH); + + clk_disable(obj->clk); +} +EXPORT_SYMBOL_GPL(flush_iotlb_all); + +#if defined(CONFIG_OMAP_IOMMU_DEBUG_MODULE) + +ssize_t iommu_dump_ctx(struct iommu *obj, char *buf) +{ + ssize_t bytes; + + if (!obj || !buf) + return -EINVAL; + + clk_enable(obj->clk); + + bytes = arch_iommu->dump_ctx(obj, buf); + + clk_disable(obj->clk); + + return bytes; +} +EXPORT_SYMBOL_GPL(iommu_dump_ctx); + +static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs) +{ + int i; + struct iotlb_lock saved, l; + struct cr_regs *p = crs; + + clk_enable(obj->clk); + + iotlb_lock_get(obj, &saved); + memcpy(&l, &saved, sizeof(saved)); + + for (i = 0; i < obj->nr_tlb_entries; i++) { + struct cr_regs tmp; + + iotlb_lock_get(obj, &l); + l.vict = i; + iotlb_lock_set(obj, &l); + iotlb_read_cr(obj, &tmp); + if (!iotlb_cr_valid(&tmp)) + continue; + + *p++ = tmp; + } + iotlb_lock_set(obj, &saved); + clk_disable(obj->clk); + + return p - crs; +} + +/** + * dump_tlb_entries - dump cr arrays to given buffer + * @obj: target iommu + * @buf: output buffer + **/ +size_t dump_tlb_entries(struct iommu *obj, char *buf) +{ + int i, n; + struct cr_regs *cr; + char *p = buf; + + cr = kcalloc(obj->nr_tlb_entries, sizeof(*cr), GFP_KERNEL); + if (!cr) + return 0; + + n = __dump_tlb_entries(obj, cr); + for (i = 0; i < n; i++) + p += iotlb_dump_cr(obj, cr + i, p); + kfree(cr); + + return p - buf; +} +EXPORT_SYMBOL_GPL(dump_tlb_entries); + +int foreach_iommu_device(void *data, int (*fn)(struct device *, void *)) +{ + return driver_for_each_device(&omap_iommu_driver.driver, + NULL, data, fn); +} +EXPORT_SYMBOL_GPL(foreach_iommu_device); + +#endif /* CONFIG_OMAP_IOMMU_DEBUG_MODULE */ + +/* + * H/W pagetable operations + */ +static void flush_iopgd_range(u32 *first, u32 *last) +{ + /* FIXME: L2 cache should be taken care of if it exists */ + do { + asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pgd" + : : "r" (first)); + first += L1_CACHE_BYTES / sizeof(*first); + } while (first <= last); +} + +static void flush_iopte_range(u32 *first, u32 *last) +{ + /* FIXME: L2 cache should be taken care of if it exists */ + do { + asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pte" + : : "r" (first)); + first += L1_CACHE_BYTES / sizeof(*first); + } while (first <= last); +} + +static void iopte_free(u32 *iopte) +{ + /* Note: freed iopte's must be clean ready for re-use */ + kmem_cache_free(iopte_cachep, iopte); +} + +static u32 *iopte_alloc(struct iommu *obj, u32 *iopgd, u32 da) +{ + u32 *iopte; + + /* a table has already existed */ + if (*iopgd) + goto pte_ready; + + /* + * do the allocation outside the page table lock + */ + spin_unlock(&obj->page_table_lock); + iopte = kmem_cache_zalloc(iopte_cachep, GFP_KERNEL); + spin_lock(&obj->page_table_lock); + + if (!*iopgd) { + if (!iopte) + return ERR_PTR(-ENOMEM); + + *iopgd = virt_to_phys(iopte) | IOPGD_TABLE; + flush_iopgd_range(iopgd, iopgd); + + dev_vdbg(obj->dev, "%s: a new pte:%p\n", __func__, iopte); + } else { + /* We raced, free the reduniovant table */ + iopte_free(iopte); + } + +pte_ready: + iopte = iopte_offset(iopgd, da); + + dev_vdbg(obj->dev, + "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", + __func__, da, iopgd, *iopgd, iopte, *iopte); + + return iopte; +} + +static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot) +{ + u32 *iopgd = iopgd_offset(obj, da); + + *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION; + flush_iopgd_range(iopgd, iopgd); + return 0; +} + +static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot) +{ + u32 *iopgd = iopgd_offset(obj, da); + int i; + + for (i = 0; i < 16; i++) + *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER; + flush_iopgd_range(iopgd, iopgd + 15); + return 0; +} + +static int iopte_alloc_page(struct iommu *obj, u32 da, u32 pa, u32 prot) +{ + u32 *iopgd = iopgd_offset(obj, da); + u32 *iopte = iopte_alloc(obj, iopgd, da); + + if (IS_ERR(iopte)) + return PTR_ERR(iopte); + + *iopte = (pa & IOPAGE_MASK) | prot | IOPTE_SMALL; + flush_iopte_range(iopte, iopte); + + dev_vdbg(obj->dev, "%s: da:%08x pa:%08x pte:%p *pte:%08x\n", + __func__, da, pa, iopte, *iopte); + + return 0; +} + +static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot) +{ + u32 *iopgd = iopgd_offset(obj, da); + u32 *iopte = iopte_alloc(obj, iopgd, da); + int i; + + if (IS_ERR(iopte)) + return PTR_ERR(iopte); + + for (i = 0; i < 16; i++) + *(iopte + i) = (pa & IOLARGE_MASK) | prot | IOPTE_LARGE; + flush_iopte_range(iopte, iopte + 15); + return 0; +} + +static int iopgtable_store_entry_core(struct iommu *obj, struct iotlb_entry *e) +{ + int (*fn)(struct iommu *, u32, u32, u32); + u32 prot; + int err; + + if (!obj || !e) + return -EINVAL; + + switch (e->pgsz) { + case MMU_CAM_PGSZ_16M: + fn = iopgd_alloc_super; + break; + case MMU_CAM_PGSZ_1M: + fn = iopgd_alloc_section; + break; + case MMU_CAM_PGSZ_64K: + fn = iopte_alloc_large; + break; + case MMU_CAM_PGSZ_4K: + fn = iopte_alloc_page; + break; + default: + fn = NULL; + BUG(); + break; + } + + prot = get_iopte_attr(e); + + spin_lock(&obj->page_table_lock); + err = fn(obj, e->da, e->pa, prot); + spin_unlock(&obj->page_table_lock); + + return err; +} + +/** + * iopgtable_store_entry - Make an iommu pte entry + * @obj: target iommu + * @e: an iommu tlb entry info + **/ +int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e) +{ + int err; + + flush_iotlb_page(obj, e->da); + err = iopgtable_store_entry_core(obj, e); +#ifdef PREFETCH_IOTLB + if (!err) + load_iotlb_entry(obj, e); +#endif + return err; +} +EXPORT_SYMBOL_GPL(iopgtable_store_entry); + +/** + * iopgtable_lookup_entry - Lookup an iommu pte entry + * @obj: target iommu + * @da: iommu device virtual address + * @ppgd: iommu pgd entry pointer to be returned + * @ppte: iommu pte entry pointer to be returned + **/ +void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd, u32 **ppte) +{ + u32 *iopgd, *iopte = NULL; + + iopgd = iopgd_offset(obj, da); + if (!*iopgd) + goto out; + + if (*iopgd & IOPGD_TABLE) + iopte = iopte_offset(iopgd, da); +out: + *ppgd = iopgd; + *ppte = iopte; +} +EXPORT_SYMBOL_GPL(iopgtable_lookup_entry); + +static size_t iopgtable_clear_entry_core(struct iommu *obj, u32 da) +{ + size_t bytes; + u32 *iopgd = iopgd_offset(obj, da); + int nent = 1; + + if (!*iopgd) + return 0; + + if (*iopgd & IOPGD_TABLE) { + int i; + u32 *iopte = iopte_offset(iopgd, da); + + bytes = IOPTE_SIZE; + if (*iopte & IOPTE_LARGE) { + nent *= 16; + /* rewind to the 1st entry */ + iopte = (u32 *)((u32)iopte & IOLARGE_MASK); + } + bytes *= nent; + memset(iopte, 0, nent * sizeof(*iopte)); + flush_iopte_range(iopte, iopte + (nent - 1) * sizeof(*iopte)); + + /* + * do table walk to check if this table is necessary or not + */ + iopte = iopte_offset(iopgd, 0); + for (i = 0; i < PTRS_PER_IOPTE; i++) + if (iopte[i]) + goto out; + + iopte_free(iopte); + nent = 1; /* for the next L1 entry */ + } else { + bytes = IOPGD_SIZE; + if (*iopgd & IOPGD_SUPER) { + nent *= 16; + /* rewind to the 1st entry */ + iopgd = (u32 *)((u32)iopgd & IOSUPER_MASK); + } + bytes *= nent; + } + memset(iopgd, 0, nent * sizeof(*iopgd)); + flush_iopgd_range(iopgd, iopgd + (nent - 1) * sizeof(*iopgd)); +out: + return bytes; +} + +/** + * iopgtable_clear_entry - Remove an iommu pte entry + * @obj: target iommu + * @da: iommu device virtual address + **/ +size_t iopgtable_clear_entry(struct iommu *obj, u32 da) +{ + size_t bytes; + + spin_lock(&obj->page_table_lock); + + bytes = iopgtable_clear_entry_core(obj, da); + flush_iotlb_page(obj, da); + + spin_unlock(&obj->page_table_lock); + + return bytes; +} +EXPORT_SYMBOL_GPL(iopgtable_clear_entry); + +static void iopgtable_clear_entry_all(struct iommu *obj) +{ + int i; + + spin_lock(&obj->page_table_lock); + + for (i = 0; i < PTRS_PER_IOPGD; i++) { + u32 da; + u32 *iopgd; + + da = i << IOPGD_SHIFT; + iopgd = iopgd_offset(obj, da); + + if (!*iopgd) + continue; + + if (*iopgd & IOPGD_TABLE) + iopte_free(iopte_offset(iopgd, 0)); + + *iopgd = 0; + flush_iopgd_range(iopgd, iopgd); + } + + flush_iotlb_all(obj); + + spin_unlock(&obj->page_table_lock); +} + +/* + * Device IOMMU generic operations + */ +static irqreturn_t iommu_fault_handler(int irq, void *data) +{ + u32 stat, da; + u32 *iopgd, *iopte; + int err = -EIO; + struct iommu *obj = data; + + if (!obj->refcount) + return IRQ_NONE; + + /* Dynamic loading TLB or PTE */ + if (obj->isr) + err = obj->isr(obj); + + if (!err) + return IRQ_HANDLED; + + clk_enable(obj->clk); + stat = iommu_report_fault(obj, &da); + clk_disable(obj->clk); + if (!stat) + return IRQ_HANDLED; + + iopgd = iopgd_offset(obj, da); + + if (!(*iopgd & IOPGD_TABLE)) { + dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__, + da, iopgd, *iopgd); + return IRQ_NONE; + } + + iopte = iopte_offset(iopgd, da); + + dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x pte:%p *pte:%08x\n", + __func__, da, iopgd, *iopgd, iopte, *iopte); + + return IRQ_NONE; +} + +static int device_match_by_alias(struct device *dev, void *data) +{ + struct iommu *obj = to_iommu(dev); + const char *name = data; + + pr_debug("%s: %s %s\n", __func__, obj->name, name); + + return strcmp(obj->name, name) == 0; +} + +/** + * iommu_get - Get iommu handler + * @name: target iommu name + **/ +struct iommu *iommu_get(const char *name) +{ + int err = -ENOMEM; + struct device *dev; + struct iommu *obj; + + dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name, + device_match_by_alias); + if (!dev) + return ERR_PTR(-ENODEV); + + obj = to_iommu(dev); + + mutex_lock(&obj->iommu_lock); + + if (obj->refcount++ == 0) { + err = iommu_enable(obj); + if (err) + goto err_enable; + flush_iotlb_all(obj); + } + + if (!try_module_get(obj->owner)) + goto err_module; + + mutex_unlock(&obj->iommu_lock); + + dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); + return obj; + +err_module: + if (obj->refcount == 1) + iommu_disable(obj); +err_enable: + obj->refcount--; + mutex_unlock(&obj->iommu_lock); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(iommu_get); + +/** + * iommu_put - Put back iommu handler + * @obj: target iommu + **/ +void iommu_put(struct iommu *obj) +{ + if (!obj && IS_ERR(obj)) + return; + + mutex_lock(&obj->iommu_lock); + + if (--obj->refcount == 0) + iommu_disable(obj); + + module_put(obj->owner); + + mutex_unlock(&obj->iommu_lock); + + dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name); +} +EXPORT_SYMBOL_GPL(iommu_put); + +/* + * OMAP Device MMU(IOMMU) detection + */ +static int __devinit omap_iommu_probe(struct platform_device *pdev) +{ + int err = -ENODEV; + void *p; + int irq; + struct iommu *obj; + struct resource *res; + struct iommu_platform_data *pdata = pdev->dev.platform_data; + + if (pdev->num_resources != 2) + return -EINVAL; + + obj = kzalloc(sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL); + if (!obj) + return -ENOMEM; + + obj->clk = clk_get(&pdev->dev, pdata->clk_name); + if (IS_ERR(obj->clk)) + goto err_clk; + + obj->nr_tlb_entries = pdata->nr_tlb_entries; + obj->name = pdata->name; + obj->dev = &pdev->dev; + obj->ctx = (void *)obj + sizeof(*obj); + + mutex_init(&obj->iommu_lock); + mutex_init(&obj->mmap_lock); + spin_lock_init(&obj->page_table_lock); + INIT_LIST_HEAD(&obj->mmap); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -ENODEV; + goto err_mem; + } + obj->regbase = ioremap(res->start, resource_size(res)); + if (!obj->regbase) { + err = -ENOMEM; + goto err_mem; + } + + res = request_mem_region(res->start, resource_size(res), + dev_name(&pdev->dev)); + if (!res) { + err = -EIO; + goto err_mem; + } + + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + err = -ENODEV; + goto err_irq; + } + err = request_irq(irq, iommu_fault_handler, IRQF_SHARED, + dev_name(&pdev->dev), obj); + if (err < 0) + goto err_irq; + platform_set_drvdata(pdev, obj); + + p = (void *)__get_free_pages(GFP_KERNEL, get_order(IOPGD_TABLE_SIZE)); + if (!p) { + err = -ENOMEM; + goto err_pgd; + } + memset(p, 0, IOPGD_TABLE_SIZE); + clean_dcache_area(p, IOPGD_TABLE_SIZE); + obj->iopgd = p; + + BUG_ON(!IS_ALIGNED((unsigned long)obj->iopgd, IOPGD_TABLE_SIZE)); + + dev_info(&pdev->dev, "%s registered\n", obj->name); + return 0; + +err_pgd: + free_irq(irq, obj); +err_irq: + release_mem_region(res->start, resource_size(res)); + iounmap(obj->regbase); +err_mem: + clk_put(obj->clk); +err_clk: + kfree(obj); + return err; +} + +static int __devexit omap_iommu_remove(struct platform_device *pdev) +{ + int irq; + struct resource *res; + struct iommu *obj = platform_get_drvdata(pdev); + + platform_set_drvdata(pdev, NULL); + + iopgtable_clear_entry_all(obj); + free_pages((unsigned long)obj->iopgd, get_order(IOPGD_TABLE_SIZE)); + + irq = platform_get_irq(pdev, 0); + free_irq(irq, obj); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + release_mem_region(res->start, resource_size(res)); + iounmap(obj->regbase); + + clk_put(obj->clk); + dev_info(&pdev->dev, "%s removed\n", obj->name); + kfree(obj); + return 0; +} + +static struct platform_driver omap_iommu_driver = { + .probe = omap_iommu_probe, + .remove = __devexit_p(omap_iommu_remove), + .driver = { + .name = "omap-iommu", + }, +}; + +static void iopte_cachep_ctor(void *iopte) +{ + clean_dcache_area(iopte, IOPTE_TABLE_SIZE); +} + +static int __init omap_iommu_init(void) +{ + struct kmem_cache *p; + const unsigned long flags = SLAB_HWCACHE_ALIGN; + size_t align = 1 << 10; /* L2 pagetable alignement */ + + p = kmem_cache_create("iopte_cache", IOPTE_TABLE_SIZE, align, flags, + iopte_cachep_ctor); + if (!p) + return -ENOMEM; + iopte_cachep = p; + + return platform_driver_register(&omap_iommu_driver); +} +module_init(omap_iommu_init); + +static void __exit omap_iommu_exit(void) +{ + kmem_cache_destroy(iopte_cachep); + + platform_driver_unregister(&omap_iommu_driver); +} +module_exit(omap_iommu_exit); + +MODULE_DESCRIPTION("omap iommu: tlb and pagetable primitives"); +MODULE_ALIAS("platform:omap-iommu"); +MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi"); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/plat-omap/iopgtable.h b/arch/arm/plat-omap/iopgtable.h new file mode 100644 index 00000000000..37dac434c7a --- /dev/null +++ b/arch/arm/plat-omap/iopgtable.h @@ -0,0 +1,72 @@ +/* + * omap iommu: pagetable definitions + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU + * + * 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. + */ + +#ifndef __PLAT_OMAP_IOMMU_H +#define __PLAT_OMAP_IOMMU_H + +#define IOPGD_SHIFT 20 +#define IOPGD_SIZE (1 << IOPGD_SHIFT) +#define IOPGD_MASK (~(IOPGD_SIZE - 1)) +#define IOSECTION_MASK IOPGD_MASK +#define PTRS_PER_IOPGD (1 << (32 - IOPGD_SHIFT)) +#define IOPGD_TABLE_SIZE (PTRS_PER_IOPGD * sizeof(u32)) + +#define IOSUPER_SIZE (IOPGD_SIZE << 4) +#define IOSUPER_MASK (~(IOSUPER_SIZE - 1)) + +#define IOPTE_SHIFT 12 +#define IOPTE_SIZE (1 << IOPTE_SHIFT) +#define IOPTE_MASK (~(IOPTE_SIZE - 1)) +#define IOPAGE_MASK IOPTE_MASK +#define PTRS_PER_IOPTE (1 << (IOPGD_SHIFT - IOPTE_SHIFT)) +#define IOPTE_TABLE_SIZE (PTRS_PER_IOPTE * sizeof(u32)) + +#define IOLARGE_SIZE (IOPTE_SIZE << 4) +#define IOLARGE_MASK (~(IOLARGE_SIZE - 1)) + +#define IOPGD_TABLE (1 << 0) +#define IOPGD_SECTION (2 << 0) +#define IOPGD_SUPER (1 << 18 | 2 << 0) + +#define IOPTE_SMALL (2 << 0) +#define IOPTE_LARGE (1 << 0) + +#define iopgd_index(da) (((da) >> IOPGD_SHIFT) & (PTRS_PER_IOPGD - 1)) +#define iopgd_offset(obj, da) ((obj)->iopgd + iopgd_index(da)) + +#define iopte_paddr(iopgd) (*iopgd & ~((1 << 10) - 1)) +#define iopte_vaddr(iopgd) ((u32 *)phys_to_virt(iopte_paddr(iopgd))) + +#define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) +#define iopte_offset(iopgd, da) (iopte_vaddr(iopgd) + iopte_index(da)) + +static inline u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, + u32 flags) +{ + memset(e, 0, sizeof(*e)); + + e->da = da; + e->pa = pa; + e->valid = 1; + /* FIXME: add OMAP1 support */ + e->pgsz = flags & MMU_CAM_PGSZ_MASK; + e->endian = flags & MMU_RAM_ENDIAN_MASK; + e->elsz = flags & MMU_RAM_ELSZ_MASK; + e->mixed = flags & MMU_RAM_MIXED_MASK; + + return iopgsz_to_bytes(e->pgsz); +} + +#define to_iommu(dev) \ + (struct iommu *)platform_get_drvdata(to_platform_device(dev)) + +#endif /* __PLAT_OMAP_IOMMU_H */ -- cgit v1.2.3-70-g09d2 From 2bcb573343dbd7d913cb62b81463960644a3737f Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Mon, 26 Jan 2009 15:13:45 +0200 Subject: omap iommu: omap2 architecture specific functions The structure 'arch_mmu' accommodates the difference between omap1 and omap2/3. This patch provides omap2/3 specific functions Signed-off-by: Hiroshi DOYU --- arch/arm/mach-omap2/iommu2.c | 323 +++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/iommu2.h | 96 +++++++++ 2 files changed, 419 insertions(+) create mode 100644 arch/arm/mach-omap2/iommu2.c create mode 100644 arch/arm/plat-omap/include/mach/iommu2.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c new file mode 100644 index 00000000000..015f22a53ea --- /dev/null +++ b/arch/arm/mach-omap2/iommu2.c @@ -0,0 +1,323 @@ +/* + * omap iommu: omap2/3 architecture specific functions + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU , + * Paul Mundt and Toshihiro Kobayashi + * + * 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 +#include +#include +#include +#include + +#include + +/* + * omap2 architecture specific register bit definitions + */ +#define IOMMU_ARCH_VERSION 0x00000011 + +/* SYSCONF */ +#define MMU_SYS_IDLE_SHIFT 3 +#define MMU_SYS_IDLE_FORCE (0 << MMU_SYS_IDLE_SHIFT) +#define MMU_SYS_IDLE_NONE (1 << MMU_SYS_IDLE_SHIFT) +#define MMU_SYS_IDLE_SMART (2 << MMU_SYS_IDLE_SHIFT) +#define MMU_SYS_IDLE_MASK (3 << MMU_SYS_IDLE_SHIFT) + +#define MMU_SYS_SOFTRESET (1 << 1) +#define MMU_SYS_AUTOIDLE 1 + +/* SYSSTATUS */ +#define MMU_SYS_RESETDONE 1 + +/* IRQSTATUS & IRQENABLE */ +#define MMU_IRQ_MULTIHITFAULT (1 << 4) +#define MMU_IRQ_TABLEWALKFAULT (1 << 3) +#define MMU_IRQ_EMUMISS (1 << 2) +#define MMU_IRQ_TRANSLATIONFAULT (1 << 1) +#define MMU_IRQ_TLBMISS (1 << 0) +#define MMU_IRQ_MASK \ + (MMU_IRQ_MULTIHITFAULT | MMU_IRQ_TABLEWALKFAULT | MMU_IRQ_EMUMISS | \ + MMU_IRQ_TRANSLATIONFAULT) + +/* MMU_CNTL */ +#define MMU_CNTL_SHIFT 1 +#define MMU_CNTL_MASK (7 << MMU_CNTL_SHIFT) +#define MMU_CNTL_EML_TLB (1 << 3) +#define MMU_CNTL_TWL_EN (1 << 2) +#define MMU_CNTL_MMU_EN (1 << 1) + +#define get_cam_va_mask(pgsz) \ + (((pgsz) == MMU_CAM_PGSZ_16M) ? 0xff000000 : \ + ((pgsz) == MMU_CAM_PGSZ_1M) ? 0xfff00000 : \ + ((pgsz) == MMU_CAM_PGSZ_64K) ? 0xffff0000 : \ + ((pgsz) == MMU_CAM_PGSZ_4K) ? 0xfffff000 : 0) + +static int omap2_iommu_enable(struct iommu *obj) +{ + u32 l, pa; + unsigned long timeout; + + if (!obj->iopgd || !IS_ALIGNED((u32)obj->iopgd, SZ_16K)) + return -EINVAL; + + pa = virt_to_phys(obj->iopgd); + if (!IS_ALIGNED(pa, SZ_16K)) + return -EINVAL; + + iommu_write_reg(obj, MMU_SYS_SOFTRESET, MMU_SYSCONFIG); + + timeout = jiffies + msecs_to_jiffies(20); + do { + l = iommu_read_reg(obj, MMU_SYSSTATUS); + if (l & MMU_SYS_RESETDONE) + break; + } while (time_after(jiffies, timeout)); + + if (!(l & MMU_SYS_RESETDONE)) { + dev_err(obj->dev, "can't take mmu out of reset\n"); + return -ENODEV; + } + + l = iommu_read_reg(obj, MMU_REVISION); + dev_info(obj->dev, "%s: version %d.%d\n", obj->name, + (l >> 4) & 0xf, l & 0xf); + + l = iommu_read_reg(obj, MMU_SYSCONFIG); + l &= ~MMU_SYS_IDLE_MASK; + l |= (MMU_SYS_IDLE_SMART | MMU_SYS_AUTOIDLE); + iommu_write_reg(obj, l, MMU_SYSCONFIG); + + iommu_write_reg(obj, MMU_IRQ_MASK, MMU_IRQENABLE); + iommu_write_reg(obj, pa, MMU_TTB); + + l = iommu_read_reg(obj, MMU_CNTL); + l &= ~MMU_CNTL_MASK; + l |= (MMU_CNTL_MMU_EN | MMU_CNTL_TWL_EN); + iommu_write_reg(obj, l, MMU_CNTL); + + return 0; +} + +static void omap2_iommu_disable(struct iommu *obj) +{ + u32 l = iommu_read_reg(obj, MMU_CNTL); + + l &= ~MMU_CNTL_MASK; + iommu_write_reg(obj, l, MMU_CNTL); + iommu_write_reg(obj, MMU_SYS_IDLE_FORCE, MMU_SYSCONFIG); + + dev_dbg(obj->dev, "%s is shutting down\n", obj->name); +} + +static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra) +{ + int i; + u32 stat, da; + const char *err_msg[] = { + "tlb miss", + "translation fault", + "emulation miss", + "table walk fault", + "multi hit fault", + }; + + stat = iommu_read_reg(obj, MMU_IRQSTATUS); + stat &= MMU_IRQ_MASK; + if (!stat) + return 0; + + da = iommu_read_reg(obj, MMU_FAULT_AD); + *ra = da; + + dev_err(obj->dev, "%s:\tda:%08x ", __func__, da); + + for (i = 0; i < ARRAY_SIZE(err_msg); i++) { + if (stat & (1 << i)) + printk("%s ", err_msg[i]); + } + printk("\n"); + + iommu_write_reg(obj, stat, MMU_IRQSTATUS); + return stat; +} + +static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr) +{ + cr->cam = iommu_read_reg(obj, MMU_READ_CAM); + cr->ram = iommu_read_reg(obj, MMU_READ_RAM); +} + +static void omap2_tlb_load_cr(struct iommu *obj, struct cr_regs *cr) +{ + iommu_write_reg(obj, cr->cam | MMU_CAM_V, MMU_CAM); + iommu_write_reg(obj, cr->ram, MMU_RAM); +} + +static u32 omap2_cr_to_virt(struct cr_regs *cr) +{ + u32 page_size = cr->cam & MMU_CAM_PGSZ_MASK; + u32 mask = get_cam_va_mask(cr->cam & page_size); + + return cr->cam & mask; +} + +static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e) +{ + struct cr_regs *cr; + + if (e->da & ~(get_cam_va_mask(e->pgsz))) { + dev_err(obj->dev, "%s:\twrong alignment: %08x\n", __func__, + e->da); + return ERR_PTR(-EINVAL); + } + + cr = kmalloc(sizeof(*cr), GFP_KERNEL); + if (!cr) + return ERR_PTR(-ENOMEM); + + cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz; + cr->ram = e->pa | e->endian | e->elsz | e->mixed; + + return cr; +} + +static inline int omap2_cr_valid(struct cr_regs *cr) +{ + return cr->cam & MMU_CAM_V; +} + +static u32 omap2_get_pte_attr(struct iotlb_entry *e) +{ + u32 attr; + + attr = e->mixed << 5; + attr |= e->endian; + attr |= e->elsz >> 3; + attr <<= ((e->pgsz & MMU_CAM_PGSZ_4K) ? 0 : 6); + + return attr; +} + +static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf) +{ + char *p = buf; + + /* FIXME: Need more detail analysis of cam/ram */ + p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram); + + return p - buf; +} + +#define pr_reg(name) \ + p += sprintf(p, "%20s: %08x\n", \ + __stringify(name), iommu_read_reg(obj, MMU_##name)); + +static ssize_t omap2_iommu_dump_ctx(struct iommu *obj, char *buf) +{ + char *p = buf; + + pr_reg(REVISION); + pr_reg(SYSCONFIG); + pr_reg(SYSSTATUS); + pr_reg(IRQSTATUS); + pr_reg(IRQENABLE); + pr_reg(WALKING_ST); + pr_reg(CNTL); + pr_reg(FAULT_AD); + pr_reg(TTB); + pr_reg(LOCK); + pr_reg(LD_TLB); + pr_reg(CAM); + pr_reg(RAM); + pr_reg(GFLUSH); + pr_reg(FLUSH_ENTRY); + pr_reg(READ_CAM); + pr_reg(READ_RAM); + pr_reg(EMU_FAULT_AD); + + return p - buf; +} + +static void omap2_iommu_save_ctx(struct iommu *obj) +{ + int i; + u32 *p = obj->ctx; + + for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) { + p[i] = iommu_read_reg(obj, i * sizeof(u32)); + dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]); + } + + BUG_ON(p[0] != IOMMU_ARCH_VERSION); +} + +static void omap2_iommu_restore_ctx(struct iommu *obj) +{ + int i; + u32 *p = obj->ctx; + + for (i = 0; i < (MMU_REG_SIZE / sizeof(u32)); i++) { + iommu_write_reg(obj, p[i], i * sizeof(u32)); + dev_dbg(obj->dev, "%s\t[%02d] %08x\n", __func__, i, p[i]); + } + + BUG_ON(p[0] != IOMMU_ARCH_VERSION); +} + +static void omap2_cr_to_e(struct cr_regs *cr, struct iotlb_entry *e) +{ + e->da = cr->cam & MMU_CAM_VATAG_MASK; + e->pa = cr->ram & MMU_RAM_PADDR_MASK; + e->valid = cr->cam & MMU_CAM_V; + e->pgsz = cr->cam & MMU_CAM_PGSZ_MASK; + e->endian = cr->ram & MMU_RAM_ENDIAN_MASK; + e->elsz = cr->ram & MMU_RAM_ELSZ_MASK; + e->mixed = cr->ram & MMU_RAM_MIXED; +} + +static const struct iommu_functions omap2_iommu_ops = { + .version = IOMMU_ARCH_VERSION, + + .enable = omap2_iommu_enable, + .disable = omap2_iommu_disable, + .fault_isr = omap2_iommu_fault_isr, + + .tlb_read_cr = omap2_tlb_read_cr, + .tlb_load_cr = omap2_tlb_load_cr, + + .cr_to_e = omap2_cr_to_e, + .cr_to_virt = omap2_cr_to_virt, + .alloc_cr = omap2_alloc_cr, + .cr_valid = omap2_cr_valid, + .dump_cr = omap2_dump_cr, + + .get_pte_attr = omap2_get_pte_attr, + + .save_ctx = omap2_iommu_save_ctx, + .restore_ctx = omap2_iommu_restore_ctx, + .dump_ctx = omap2_iommu_dump_ctx, +}; + +static int __init omap2_iommu_init(void) +{ + return install_iommu_arch(&omap2_iommu_ops); +} +module_init(omap2_iommu_init); + +static void __exit omap2_iommu_exit(void) +{ + uninstall_iommu_arch(&omap2_iommu_ops); +} +module_exit(omap2_iommu_exit); + +MODULE_AUTHOR("Hiroshi DOYU, Paul Mundt and Toshihiro Kobayashi"); +MODULE_DESCRIPTION("omap iommu: omap2/3 architecture specific functions"); +MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/plat-omap/include/mach/iommu2.h b/arch/arm/plat-omap/include/mach/iommu2.h new file mode 100644 index 00000000000..10ad05f410e --- /dev/null +++ b/arch/arm/plat-omap/include/mach/iommu2.h @@ -0,0 +1,96 @@ +/* + * omap iommu: omap2 architecture specific definitions + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU + * + * 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. + */ + +#ifndef __MACH_IOMMU2_H +#define __MACH_IOMMU2_H + +#include + +/* + * MMU Register offsets + */ +#define MMU_REVISION 0x00 +#define MMU_SYSCONFIG 0x10 +#define MMU_SYSSTATUS 0x14 +#define MMU_IRQSTATUS 0x18 +#define MMU_IRQENABLE 0x1c +#define MMU_WALKING_ST 0x40 +#define MMU_CNTL 0x44 +#define MMU_FAULT_AD 0x48 +#define MMU_TTB 0x4c +#define MMU_LOCK 0x50 +#define MMU_LD_TLB 0x54 +#define MMU_CAM 0x58 +#define MMU_RAM 0x5c +#define MMU_GFLUSH 0x60 +#define MMU_FLUSH_ENTRY 0x64 +#define MMU_READ_CAM 0x68 +#define MMU_READ_RAM 0x6c +#define MMU_EMU_FAULT_AD 0x70 + +#define MMU_REG_SIZE 256 + +/* + * MMU Register bit definitions + */ +#define MMU_LOCK_BASE_SHIFT 10 +#define MMU_LOCK_BASE_MASK (0x1f << MMU_LOCK_BASE_SHIFT) +#define MMU_LOCK_BASE(x) \ + ((x & MMU_LOCK_BASE_MASK) >> MMU_LOCK_BASE_SHIFT) + +#define MMU_LOCK_VICT_SHIFT 4 +#define MMU_LOCK_VICT_MASK (0x1f << MMU_LOCK_VICT_SHIFT) +#define MMU_LOCK_VICT(x) \ + ((x & MMU_LOCK_VICT_MASK) >> MMU_LOCK_VICT_SHIFT) + +#define MMU_CAM_VATAG_SHIFT 12 +#define MMU_CAM_VATAG_MASK \ + ((~0UL >> MMU_CAM_VATAG_SHIFT) << MMU_CAM_VATAG_SHIFT) +#define MMU_CAM_P (1 << 3) +#define MMU_CAM_V (1 << 2) +#define MMU_CAM_PGSZ_MASK 3 +#define MMU_CAM_PGSZ_1M (0 << 0) +#define MMU_CAM_PGSZ_64K (1 << 0) +#define MMU_CAM_PGSZ_4K (2 << 0) +#define MMU_CAM_PGSZ_16M (3 << 0) + +#define MMU_RAM_PADDR_SHIFT 12 +#define MMU_RAM_PADDR_MASK \ + ((~0UL >> MMU_RAM_PADDR_SHIFT) << MMU_RAM_PADDR_SHIFT) +#define MMU_RAM_ENDIAN_SHIFT 9 +#define MMU_RAM_ENDIAN_MASK (1 << MMU_RAM_ENDIAN_SHIFT) +#define MMU_RAM_ENDIAN_BIG (1 << MMU_RAM_ENDIAN_SHIFT) +#define MMU_RAM_ENDIAN_LITTLE (0 << MMU_RAM_ENDIAN_SHIFT) +#define MMU_RAM_ELSZ_SHIFT 7 +#define MMU_RAM_ELSZ_MASK (3 << MMU_RAM_ELSZ_SHIFT) +#define MMU_RAM_ELSZ_8 (0 << MMU_RAM_ELSZ_SHIFT) +#define MMU_RAM_ELSZ_16 (1 << MMU_RAM_ELSZ_SHIFT) +#define MMU_RAM_ELSZ_32 (2 << MMU_RAM_ELSZ_SHIFT) +#define MMU_RAM_ELSZ_NONE (3 << MMU_RAM_ELSZ_SHIFT) +#define MMU_RAM_MIXED_SHIFT 6 +#define MMU_RAM_MIXED_MASK (1 << MMU_RAM_MIXED_SHIFT) +#define MMU_RAM_MIXED MMU_RAM_MIXED_MASK + +/* + * register accessors + */ +static inline u32 iommu_read_reg(struct iommu *obj, size_t offs) +{ + return __raw_readl(obj->regbase + offs); +} + +static inline void iommu_write_reg(struct iommu *obj, u32 val, size_t offs) +{ + __raw_writel(val, obj->regbase + offs); +} + +#endif /* __MACH_IOMMU2_H */ -- cgit v1.2.3-70-g09d2 From 296b2f6ae654581adc27f0d6f0af454c7f3d06ee Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 8 May 2009 11:54:15 +0900 Subject: block: convert to dequeueing model (easy ones) plat-omap/mailbox, floppy, viocd, mspro_block, i2o_block and mmc/card/queue are already pretty close to dequeueing model and can be converted with simple changes. Convert them. While at it, * xen-blkfront: !fs check moved downwards to share dequeue call with normal path. * mspro_block: __blk_end_request(..., blk_rq_cur_byte()) converted to __blk_end_request_cur() * mmc/card/queue: loop of __blk_end_request() converted to __blk_end_request_all() [ Impact: dequeue in-flight request ] Signed-off-by: Tejun Heo Cc: Rusty Russell Cc: Jeremy Fitzhardinge Cc: Stephen Rothwell Cc: Alex Dubov Cc: Markus Lidel Cc: Pierre Ossman Signed-off-by: Jens Axboe --- arch/arm/plat-omap/mailbox.c | 9 +++++++++ drivers/block/floppy.c | 4 +++- drivers/block/xen-blkfront.c | 13 +++++++------ drivers/cdrom/viocd.c | 2 ++ drivers/memstick/core/mspro_block.c | 8 +++++--- drivers/message/i2o/i2o_block.c | 6 ++++-- drivers/mmc/card/queue.c | 12 ++++++------ 7 files changed, 36 insertions(+), 18 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 538ba7541d3..7a1f5c25fd1 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -198,6 +198,8 @@ static void mbox_tx_work(struct work_struct *work) spin_lock(q->queue_lock); rq = elv_next_request(q); + if (rq) + blkdev_dequeue_request(rq); spin_unlock(q->queue_lock); if (!rq) @@ -208,6 +210,9 @@ static void mbox_tx_work(struct work_struct *work) ret = __mbox_msg_send(mbox, tx_data->msg, tx_data->arg); if (ret) { enable_mbox_irq(mbox, IRQ_TX); + spin_lock(q->queue_lock); + blk_requeue_request(q, rq); + spin_unlock(q->queue_lock); return; } @@ -238,6 +243,8 @@ static void mbox_rx_work(struct work_struct *work) while (1) { spin_lock_irqsave(q->queue_lock, flags); rq = elv_next_request(q); + if (rq) + blkdev_dequeue_request(rq); spin_unlock_irqrestore(q->queue_lock, flags); if (!rq) break; @@ -345,6 +352,8 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) while (1) { spin_lock_irqsave(q->queue_lock, flags); rq = elv_next_request(q); + if (rq) + blkdev_dequeue_request(rq); spin_unlock_irqrestore(q->queue_lock, flags); if (!rq) diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 1e27ed9208b..e2c70d2085a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -931,7 +931,7 @@ static inline void unlock_fdc(void) del_timer(&fd_timeout); cont = NULL; clear_bit(0, &fdc_busy); - if (elv_next_request(floppy_queue)) + if (current_req || elv_next_request(floppy_queue)) do_fd_request(floppy_queue); spin_unlock_irqrestore(&floppy_lock, flags); wake_up(&fdc_wait); @@ -2913,6 +2913,8 @@ static void redo_fd_request(void) spin_lock_irq(floppy_queue->queue_lock); req = elv_next_request(floppy_queue); + if (req) + blkdev_dequeue_request(req); spin_unlock_irq(floppy_queue->queue_lock); if (!req) { do_floppy = NULL; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 91fc56597e9..66f834571b8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -301,22 +301,23 @@ static void do_blkif_request(struct request_queue *rq) while ((req = elv_next_request(rq)) != NULL) { info = req->rq_disk->private_data; - if (!blk_fs_request(req)) { - __blk_end_request_cur(req, -EIO); - continue; - } if (RING_FULL(&info->ring)) goto wait; + blkdev_dequeue_request(req); + + if (!blk_fs_request(req)) { + __blk_end_request_all(req, -EIO); + continue; + } + pr_debug("do_blk_req %p: cmd %p, sec %lx, " "(%u/%u) buffer:%p [%s]\n", req, req->cmd, (unsigned long)blk_rq_pos(req), blk_rq_cur_sectors(req), blk_rq_sectors(req), req->buffer, rq_data_dir(req) ? "write" : "read"); - - blkdev_dequeue_request(req); if (blkif_queue_request(req)) { blk_requeue_request(rq, req); wait: diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 6e190a93d8d..bbe9f086734 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -298,6 +298,8 @@ static void do_viocd_request(struct request_queue *q) struct request *req; while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) { + blkdev_dequeue_request(req); + if (!blk_fs_request(req)) __blk_end_request_all(req, -EIO); else if (send_request(req) < 0) { diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 93b2c618565..58f5be8cd69 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -672,8 +672,7 @@ try_again: msb->req_sg); if (!msb->seg_count) { - chunk = __blk_end_request(msb->block_req, -ENOMEM, - blk_rq_cur_bytes(msb->block_req)); + chunk = __blk_end_request_cur(msb->block_req, -ENOMEM); continue; } @@ -711,6 +710,7 @@ try_again: dev_dbg(&card->dev, "issue end\n"); return -EAGAIN; } + blkdev_dequeue_request(msb->block_req); dev_dbg(&card->dev, "trying again\n"); chunk = 1; @@ -825,8 +825,10 @@ static void mspro_block_submit_req(struct request_queue *q) return; if (msb->eject) { - while ((req = elv_next_request(q)) != NULL) + while ((req = elv_next_request(q)) != NULL) { + blkdev_dequeue_request(req); __blk_end_request_all(req, -ENODEV); + } return; } diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index e153f5d5237..8b5cbfc3ba9 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -916,8 +916,10 @@ static void i2o_block_request_fn(struct request_queue *q) blk_stop_queue(q); break; } - } else - __blk_end_request_cur(req, -EIO); + } else { + blkdev_dequeue_request(req); + __blk_end_request_all(req, -EIO); + } } }; diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 7a72e75d5c6..4b70f1e2834 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -54,8 +54,11 @@ static int mmc_queue_thread(void *d) spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!blk_queue_plugged(q)) + if (!blk_queue_plugged(q)) { req = elv_next_request(q); + if (req) + blkdev_dequeue_request(req); + } mq->req = req; spin_unlock_irq(q->queue_lock); @@ -88,15 +91,12 @@ static void mmc_request(struct request_queue *q) { struct mmc_queue *mq = q->queuedata; struct request *req; - int ret; if (!mq) { printk(KERN_ERR "MMC: killing requests for dead queue\n"); while ((req = elv_next_request(q)) != NULL) { - do { - ret = __blk_end_request(req, -EIO, - blk_rq_cur_bytes(req)); - } while (ret); + blkdev_dequeue_request(req); + __blk_end_request_all(req, -EIO); } return; } -- cgit v1.2.3-70-g09d2 From 9934c8c04561413609d2bc38c6b9f268cba774a4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 8 May 2009 11:54:16 +0900 Subject: block: implement and enforce request peek/start/fetch Till now block layer allowed two separate modes of request execution. A request is always acquired from the request queue via elv_next_request(). After that, drivers are free to either dequeue it or process it without dequeueing. Dequeue allows elv_next_request() to return the next request so that multiple requests can be in flight. Executing requests without dequeueing has its merits mostly in allowing drivers for simpler devices which can't do sg to deal with segments only without considering request boundary. However, the benefit this brings is dubious and declining while the cost of the API ambiguity is increasing. Segment based drivers are usually for very old or limited devices and as converting to dequeueing model isn't difficult, it doesn't justify the API overhead it puts on block layer and its more modern users. Previous patches converted all block low level drivers to dequeueing model. This patch completes the API transition by... * renaming elv_next_request() to blk_peek_request() * renaming blkdev_dequeue_request() to blk_start_request() * adding blk_fetch_request() which is combination of peek and start * disallowing completion of queued (not started) requests * applying new API to all LLDs Renamings are for consistency and to break out of tree code so that it's apparent that out of tree drivers need updating. [ Impact: block request issue API cleanup, no functional change ] Signed-off-by: Tejun Heo Cc: Rusty Russell Cc: James Bottomley Cc: Mike Miller Cc: unsik Kim Cc: Paul Clements Cc: Tim Waugh Cc: Geert Uytterhoeven Cc: David S. Miller Cc: Laurent Vivier Cc: Jeff Garzik Cc: Jeremy Fitzhardinge Cc: Grant Likely Cc: Adrian McMenamin Cc: Stephen Rothwell Cc: Bartlomiej Zolnierkiewicz Cc: Borislav Petkov Cc: Sergei Shtylyov Cc: Alex Dubov Cc: Pierre Ossman Cc: David Woodhouse Cc: Markus Lidel Cc: Stefan Weinhuber Cc: Martin Schwidefsky Cc: Pete Zaitcev Cc: FUJITA Tomonori Signed-off-by: Jens Axboe --- arch/arm/plat-omap/mailbox.c | 12 ++--- arch/um/drivers/ubd_kern.c | 3 +- block/blk-barrier.c | 4 +- block/blk-core.c | 105 ++++++++++++++++++++++++++---------- block/blk-tag.c | 2 +- block/blk.h | 1 + drivers/block/DAC960.c | 4 +- drivers/block/amiflop.c | 3 +- drivers/block/ataflop.c | 3 +- drivers/block/cciss.c | 4 +- drivers/block/cpqarray.c | 4 +- drivers/block/floppy.c | 6 +-- drivers/block/hd.c | 3 +- drivers/block/mg_disk.c | 12 ++--- drivers/block/nbd.c | 4 +- drivers/block/paride/pcd.c | 3 +- drivers/block/paride/pd.c | 7 +-- drivers/block/paride/pf.c | 3 +- drivers/block/ps3disk.c | 4 +- drivers/block/sunvdc.c | 3 +- drivers/block/swim.c | 12 ++--- drivers/block/swim3.c | 3 +- drivers/block/sx8.c | 8 ++- drivers/block/ub.c | 8 +-- drivers/block/viodasd.c | 4 +- drivers/block/virtio_blk.c | 4 +- drivers/block/xd.c | 12 ++--- drivers/block/xen-blkfront.c | 4 +- drivers/block/xsysace.c | 10 ++-- drivers/block/z2ram.c | 12 ++--- drivers/cdrom/gdrom.c | 4 +- drivers/cdrom/viocd.c | 4 +- drivers/ide/ide-atapi.c | 2 +- drivers/ide/ide-io.c | 9 ++-- drivers/memstick/core/mspro_block.c | 9 ++-- drivers/message/i2o/i2o_block.c | 6 +-- drivers/mmc/card/queue.c | 11 ++-- drivers/mtd/mtd_blkdevs.c | 7 +-- drivers/s390/block/dasd.c | 16 ++---- drivers/s390/char/tape_block.c | 7 +-- drivers/sbus/char/jsflash.c | 12 ++--- drivers/scsi/scsi_lib.c | 10 ++-- drivers/scsi/scsi_transport_sas.c | 4 +- include/linux/blkdev.h | 9 +++- include/linux/elevator.h | 2 - 45 files changed, 172 insertions(+), 207 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 7a1f5c25fd1..40424edae93 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -197,9 +197,7 @@ static void mbox_tx_work(struct work_struct *work) struct omap_msg_tx_data *tx_data; spin_lock(q->queue_lock); - rq = elv_next_request(q); - if (rq) - blkdev_dequeue_request(rq); + rq = blk_fetch_request(q); spin_unlock(q->queue_lock); if (!rq) @@ -242,9 +240,7 @@ static void mbox_rx_work(struct work_struct *work) while (1) { spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - if (rq) - blkdev_dequeue_request(rq); + rq = blk_fetch_request(q); spin_unlock_irqrestore(q->queue_lock, flags); if (!rq) break; @@ -351,9 +347,7 @@ omap_mbox_read(struct device *dev, struct device_attribute *attr, char *buf) while (1) { spin_lock_irqsave(q->queue_lock, flags); - rq = elv_next_request(q); - if (rq) - blkdev_dequeue_request(rq); + rq = blk_fetch_request(q); spin_unlock_irqrestore(q->queue_lock, flags); if (!rq) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 402ba8f70fc..aa9e926e13d 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1228,12 +1228,11 @@ static void do_ubd_request(struct request_queue *q) while(1){ struct ubd *dev = q->queuedata; if(dev->end_sg == 0){ - struct request *req = elv_next_request(q); + struct request *req = blk_fetch_request(q); if(req == NULL) return; dev->request = req; - blkdev_dequeue_request(req); dev->start_sg = 0; dev->end_sg = blk_rq_map_sg(q, req, dev->sg); } diff --git a/block/blk-barrier.c b/block/blk-barrier.c index 8713c2fbc4f..0ab81a0a750 100644 --- a/block/blk-barrier.c +++ b/block/blk-barrier.c @@ -180,7 +180,7 @@ static inline bool start_ordered(struct request_queue *q, struct request **rqp) } /* stash away the original request */ - elv_dequeue_request(q, rq); + blk_dequeue_request(rq); q->orig_bar_rq = rq; rq = NULL; @@ -248,7 +248,7 @@ bool blk_do_ordered(struct request_queue *q, struct request **rqp) * Queue ordering not supported. Terminate * with prejudice. */ - elv_dequeue_request(q, rq); + blk_dequeue_request(rq); __blk_end_request_all(rq, -EOPNOTSUPP); *rqp = NULL; return false; diff --git a/block/blk-core.c b/block/blk-core.c index 6226a380fb6..93691d2ac5a 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -902,6 +902,8 @@ EXPORT_SYMBOL(blk_get_request); */ void blk_requeue_request(struct request_queue *q, struct request *rq) { + BUG_ON(blk_queued_rq(rq)); + blk_delete_timer(rq); blk_clear_rq_complete(rq); trace_block_rq_requeue(q, rq); @@ -1610,28 +1612,6 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) } EXPORT_SYMBOL_GPL(blk_insert_cloned_request); -/** - * blkdev_dequeue_request - dequeue request and start timeout timer - * @req: request to dequeue - * - * Dequeue @req and start timeout timer on it. This hands off the - * request to the driver. - * - * Block internal functions which don't want to start timer should - * call elv_dequeue_request(). - */ -void blkdev_dequeue_request(struct request *req) -{ - elv_dequeue_request(req->q, req); - - /* - * We are now handing the request to the hardware, add the - * timeout handler. - */ - blk_add_timer(req); -} -EXPORT_SYMBOL(blkdev_dequeue_request); - static void blk_account_io_completion(struct request *req, unsigned int bytes) { if (blk_do_io_stat(req)) { @@ -1671,7 +1651,23 @@ static void blk_account_io_done(struct request *req) } } -struct request *elv_next_request(struct request_queue *q) +/** + * blk_peek_request - peek at the top of a request queue + * @q: request queue to peek at + * + * Description: + * Return the request at the top of @q. The returned request + * should be started using blk_start_request() before LLD starts + * processing it. + * + * Return: + * Pointer to the request at the top of @q if available. Null + * otherwise. + * + * Context: + * queue_lock must be held. + */ +struct request *blk_peek_request(struct request_queue *q) { struct request *rq; int ret; @@ -1748,10 +1744,12 @@ struct request *elv_next_request(struct request_queue *q) return rq; } -EXPORT_SYMBOL(elv_next_request); +EXPORT_SYMBOL(blk_peek_request); -void elv_dequeue_request(struct request_queue *q, struct request *rq) +void blk_dequeue_request(struct request *rq) { + struct request_queue *q = rq->q; + BUG_ON(list_empty(&rq->queuelist)); BUG_ON(ELV_ON_HASH(rq)); @@ -1766,6 +1764,58 @@ void elv_dequeue_request(struct request_queue *q, struct request *rq) q->in_flight++; } +/** + * blk_start_request - start request processing on the driver + * @req: request to dequeue + * + * Description: + * Dequeue @req and start timeout timer on it. This hands off the + * request to the driver. + * + * Block internal functions which don't want to start timer should + * call blk_dequeue_request(). + * + * Context: + * queue_lock must be held. + */ +void blk_start_request(struct request *req) +{ + blk_dequeue_request(req); + + /* + * We are now handing the request to the hardware, add the + * timeout handler. + */ + blk_add_timer(req); +} +EXPORT_SYMBOL(blk_start_request); + +/** + * blk_fetch_request - fetch a request from a request queue + * @q: request queue to fetch a request from + * + * Description: + * Return the request at the top of @q. The request is started on + * return and LLD can start processing it immediately. + * + * Return: + * Pointer to the request at the top of @q if available. Null + * otherwise. + * + * Context: + * queue_lock must be held. + */ +struct request *blk_fetch_request(struct request_queue *q) +{ + struct request *rq; + + rq = blk_peek_request(q); + if (rq) + blk_start_request(rq); + return rq; +} +EXPORT_SYMBOL(blk_fetch_request); + /** * blk_update_request - Special helper function for request stacking drivers * @rq: the request being processed @@ -1937,12 +1987,11 @@ static bool blk_update_bidi_request(struct request *rq, int error, */ static void blk_finish_request(struct request *req, int error) { + BUG_ON(blk_queued_rq(req)); + if (blk_rq_tagged(req)) blk_queue_end_tag(req->q, req); - if (blk_queued_rq(req)) - elv_dequeue_request(req->q, req); - if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); diff --git a/block/blk-tag.c b/block/blk-tag.c index 3c518e3303a..c260f7c30dd 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -374,7 +374,7 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) rq->cmd_flags |= REQ_QUEUED; rq->tag = tag; bqt->tag_index[tag] = rq; - blkdev_dequeue_request(rq); + blk_start_request(rq); list_add(&rq->queuelist, &q->tag_busy_list); return 0; } diff --git a/block/blk.h b/block/blk.h index ab54529103c..9e0042ca949 100644 --- a/block/blk.h +++ b/block/blk.h @@ -13,6 +13,7 @@ extern struct kobj_type blk_queue_ktype; void init_request_from_bio(struct request *req, struct bio *bio); void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio); +void blk_dequeue_request(struct request *rq); void __blk_queue_free_tags(struct request_queue *q); void blk_unplug_work(struct work_struct *work); diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 774ab05973a..668dc234b8e 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -3321,7 +3321,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ DAC960_Command_T *Command; while(1) { - Request = elv_next_request(req_q); + Request = blk_peek_request(req_q); if (!Request) return 1; @@ -3341,7 +3341,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ Command->BlockNumber = blk_rq_pos(Request); Command->BlockCount = blk_rq_sectors(Request); Command->Request = Request; - blkdev_dequeue_request(Request); + blk_start_request(Request); Command->SegmentCount = blk_rq_map_sg(req_q, Command->Request, Command->cmd_sglist); /* pci_map_sg MAY change the value of SegCount */ diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 80a68b2e045..9c6e5b0fe89 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1342,12 +1342,11 @@ static void redo_fd_request(void) int err; next_req: - rq = elv_next_request(floppy_queue); + rq = blk_fetch_request(floppy_queue); if (!rq) { /* Nothing left to do */ return; } - blkdev_dequeue_request(rq); floppy = rq->rq_disk->private_data; drive = floppy - unit; diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 89a591d9c83..f5e7180d7f4 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1404,10 +1404,9 @@ static void redo_fd_request(void) repeat: if (!fd_request) { - fd_request = elv_next_request(floppy_queue); + fd_request = blk_fetch_request(floppy_queue); if (!fd_request) goto the_end; - blkdev_dequeue_request(fd_request); } floppy = fd_request->rq_disk->private_data; diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index ab7b04c0db7..e714e7cce6f 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2801,7 +2801,7 @@ static void do_cciss_request(struct request_queue *q) goto startio; queue: - creq = elv_next_request(q); + creq = blk_peek_request(q); if (!creq) goto startio; @@ -2810,7 +2810,7 @@ static void do_cciss_request(struct request_queue *q) if ((c = cmd_alloc(h, 1)) == NULL) goto full; - blkdev_dequeue_request(creq); + blk_start_request(creq); spin_unlock_irq(q->queue_lock); diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index a5caeff4718..a02dcfc00f1 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -903,7 +903,7 @@ static void do_ida_request(struct request_queue *q) goto startio; queue_next: - creq = elv_next_request(q); + creq = blk_peek_request(q); if (!creq) goto startio; @@ -912,7 +912,7 @@ queue_next: if ((c = cmd_alloc(h,1)) == NULL) goto startio; - blkdev_dequeue_request(creq); + blk_start_request(creq); c->ctlr = h->ctlr; c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index e2c70d2085a..90877fee0ee 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -931,7 +931,7 @@ static inline void unlock_fdc(void) del_timer(&fd_timeout); cont = NULL; clear_bit(0, &fdc_busy); - if (current_req || elv_next_request(floppy_queue)) + if (current_req || blk_peek_request(floppy_queue)) do_fd_request(floppy_queue); spin_unlock_irqrestore(&floppy_lock, flags); wake_up(&fdc_wait); @@ -2912,9 +2912,7 @@ static void redo_fd_request(void) struct request *req; spin_lock_irq(floppy_queue->queue_lock); - req = elv_next_request(floppy_queue); - if (req) - blkdev_dequeue_request(req); + req = blk_fetch_request(floppy_queue); spin_unlock_irq(floppy_queue->queue_lock); if (!req) { do_floppy = NULL; diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 288ab63c102..961de56d00a 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c @@ -592,12 +592,11 @@ repeat: del_timer(&device_timer); if (!hd_req) { - hd_req = elv_next_request(hd_queue); + hd_req = blk_fetch_request(hd_queue); if (!hd_req) { do_hd = NULL; return; } - blkdev_dequeue_request(hd_req); } req = hd_req; diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index 1ca5d1423fa..c0cd0a03f69 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c @@ -671,10 +671,8 @@ static void mg_request_poll(struct request_queue *q) while (1) { if (!host->req) { - host->req = elv_next_request(q); - if (host->req) - blkdev_dequeue_request(host->req); - else + host->req = blk_fetch_request(q); + if (!host->req) break; } @@ -744,10 +742,8 @@ static void mg_request(struct request_queue *q) while (1) { if (!host->req) { - host->req = elv_next_request(q); - if (host->req) - blkdev_dequeue_request(host->req); - else + host->req = blk_fetch_request(q); + if (!host->req) break; } req = host->req; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index fad167de23b..5d23ffad7c7 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -533,11 +533,9 @@ static void do_nbd_request(struct request_queue *q) { struct request *req; - while ((req = elv_next_request(q)) != NULL) { + while ((req = blk_fetch_request(q)) != NULL) { struct nbd_device *lo; - blkdev_dequeue_request(req); - spin_unlock_irq(q->queue_lock); dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index 425f81586a3..911dfd98d81 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c @@ -720,10 +720,9 @@ static void do_pcd_request(struct request_queue * q) return; while (1) { if (!pcd_req) { - pcd_req = elv_next_request(q); + pcd_req = blk_fetch_request(q); if (!pcd_req) return; - blkdev_dequeue_request(pcd_req); } if (rq_data_dir(pcd_req) == READ) { diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index d2ca3f55206..bf5955b3d87 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -412,11 +412,9 @@ static void run_fsm(void) spin_lock_irqsave(&pd_lock, saved_flags); if (!__blk_end_request_cur(pd_req, res == Ok ? 0 : -EIO)) { - pd_req = elv_next_request(pd_queue); + pd_req = blk_fetch_request(pd_queue); if (!pd_req) stop = 1; - else - blkdev_dequeue_request(pd_req); } spin_unlock_irqrestore(&pd_lock, saved_flags); if (stop) @@ -706,10 +704,9 @@ static void do_pd_request(struct request_queue * q) { if (pd_req) return; - pd_req = elv_next_request(q); + pd_req = blk_fetch_request(q); if (!pd_req) return; - blkdev_dequeue_request(pd_req); schedule_fsm(); } diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index d6f7bd84ed3..68a90834e99 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -762,10 +762,9 @@ static void do_pf_request(struct request_queue * q) return; repeat: if (!pf_req) { - pf_req = elv_next_request(q); + pf_req = blk_fetch_request(q); if (!pf_req) return; - blkdev_dequeue_request(pf_req); } pf_current = pf_req->rq_disk->private_data; diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index f4d8db944e7..338cee4cc0b 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -194,9 +194,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); - while ((req = elv_next_request(q))) { - blkdev_dequeue_request(req); - + while ((req = blk_fetch_request(q))) { if (blk_fs_request(req)) { if (ps3disk_submit_request_sg(dev, req)) break; diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 9f351bfa15e..cbfd9c0aef0 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -441,12 +441,11 @@ out: static void do_vdc_request(struct request_queue *q) { while (1) { - struct request *req = elv_next_request(q); + struct request *req = blk_fetch_request(q); if (!req) break; - blkdev_dequeue_request(req); if (__send_request(req) < 0) __blk_end_request_all(req, -EIO); } diff --git a/drivers/block/swim.c b/drivers/block/swim.c index dedd4893f5e..cf7877fb8a7 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c @@ -528,10 +528,7 @@ static void redo_fd_request(struct request_queue *q) struct request *req; struct floppy_state *fs; - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - + req = blk_fetch_request(q); while (req) { int err = -EIO; @@ -554,11 +551,8 @@ static void redo_fd_request(struct request_queue *q) break; } done: - if (!__blk_end_request_cur(req, err)) { - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - } + if (!__blk_end_request_cur(req, err)) + req = blk_fetch_request(q); } } diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index f48c6dd47e0..80df93e3cdd 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c @@ -326,10 +326,9 @@ static void start_request(struct floppy_state *fs) } while (fs->state == idle) { if (!fd_req) { - fd_req = elv_next_request(swim3_queue); + fd_req = blk_fetch_request(swim3_queue); if (!fd_req) break; - blkdev_dequeue_request(fd_req); } req = fd_req; #if 0 diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index 087c94c8b2d..da403b6a7f4 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -810,12 +810,10 @@ static void carm_oob_rq_fn(struct request_queue *q) while (1) { DPRINTK("get req\n"); - rq = elv_next_request(q); + rq = blk_fetch_request(q); if (!rq) break; - blkdev_dequeue_request(rq); - crq = rq->special; assert(crq != NULL); assert(crq->rq == rq); @@ -846,7 +844,7 @@ static void carm_rq_fn(struct request_queue *q) queue_one_request: VPRINTK("get req\n"); - rq = elv_next_request(q); + rq = blk_peek_request(q); if (!rq) return; @@ -857,7 +855,7 @@ queue_one_request: } crq->rq = rq; - blkdev_dequeue_request(rq); + blk_start_request(rq); if (rq_data_dir(rq) == WRITE) { writing = 1; diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 40d03cf63f2..178f459a50e 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -627,7 +627,7 @@ static void ub_request_fn(struct request_queue *q) struct ub_lun *lun = q->queuedata; struct request *rq; - while ((rq = elv_next_request(q)) != NULL) { + while ((rq = blk_peek_request(q)) != NULL) { if (ub_request_fn_1(lun, rq) != 0) { blk_stop_queue(q); break; @@ -643,13 +643,13 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) int n_elem; if (atomic_read(&sc->poison)) { - blkdev_dequeue_request(rq); + blk_start_request(rq); ub_end_rq(rq, DID_NO_CONNECT << 16, blk_rq_bytes(rq)); return 0; } if (lun->changed && !blk_pc_request(rq)) { - blkdev_dequeue_request(rq); + blk_start_request(rq); ub_end_rq(rq, SAM_STAT_CHECK_CONDITION, blk_rq_bytes(rq)); return 0; } @@ -660,7 +660,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) return -1; memset(cmd, 0, sizeof(struct ub_scsi_cmd)); - blkdev_dequeue_request(rq); + blk_start_request(rq); urq = &lun->urq; memset(urq, 0, sizeof(struct ub_request)); diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index 2086cb12d3e..390d69bb7c4 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c @@ -361,11 +361,9 @@ static void do_viodasd_request(struct request_queue *q) * back later. */ while (num_req_outstanding < VIOMAXREQ) { - req = elv_next_request(q); + req = blk_fetch_request(q); if (req == NULL) return; - /* dequeue the current request from the queue */ - blkdev_dequeue_request(req); /* check that request contains a valid command */ if (!blk_fs_request(req)) { viodasd_end_request(req, -EIO, blk_rq_sectors(req)); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 1980ab45635..29a9daf4862 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -128,7 +128,7 @@ static void do_virtblk_request(struct request_queue *q) struct request *req; unsigned int issued = 0; - while ((req = elv_next_request(q)) != NULL) { + while ((req = blk_peek_request(q)) != NULL) { vblk = req->rq_disk->private_data; BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); @@ -138,7 +138,7 @@ static void do_virtblk_request(struct request_queue *q) blk_stop_queue(q); break; } - blkdev_dequeue_request(req); + blk_start_request(req); issued++; } diff --git a/drivers/block/xd.c b/drivers/block/xd.c index d4c4352354b..ce242921992 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c @@ -305,10 +305,7 @@ static void do_xd_request (struct request_queue * q) if (xdc_busy) return; - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - + req = blk_fetch_request(q); while (req) { unsigned block = blk_rq_pos(req); unsigned count = blk_rq_cur_sectors(req); @@ -325,11 +322,8 @@ static void do_xd_request (struct request_queue * q) block, count); done: /* wrap up, 0 = success, -errno = fail */ - if (!__blk_end_request_cur(req, res)) { - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - } + if (!__blk_end_request_cur(req, res)) + req = blk_fetch_request(q); } } diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 66f834571b8..6d4ac76c280 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -299,13 +299,13 @@ static void do_blkif_request(struct request_queue *rq) queued = 0; - while ((req = elv_next_request(rq)) != NULL) { + while ((req = blk_peek_request(rq)) != NULL) { info = req->rq_disk->private_data; if (RING_FULL(&info->ring)) goto wait; - blkdev_dequeue_request(req); + blk_start_request(req); if (!blk_fs_request(req)) { __blk_end_request_all(req, -EIO); diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index edf137b6c37..3a4397edab7 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -463,10 +463,10 @@ struct request *ace_get_next_request(struct request_queue * q) { struct request *req; - while ((req = elv_next_request(q)) != NULL) { + while ((req = blk_peek_request(q)) != NULL) { if (blk_fs_request(req)) break; - blkdev_dequeue_request(req); + blk_start_request(req); __blk_end_request_all(req, -EIO); } return req; @@ -498,10 +498,8 @@ static void ace_fsm_dostate(struct ace_device *ace) __blk_end_request_all(ace->req, -EIO); ace->req = NULL; } - while ((req = elv_next_request(ace->queue)) != NULL) { - blkdev_dequeue_request(req); + while ((req = blk_fetch_request(ace->queue)) != NULL) __blk_end_request_all(req, -EIO); - } /* Drop back to IDLE state and notify waiters */ ace->fsm_state = ACE_FSM_STATE_IDLE; @@ -649,7 +647,7 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state = ACE_FSM_STATE_IDLE; break; } - blkdev_dequeue_request(req); + blk_start_request(req); /* Okay, it's a data request, set it up for transfer */ dev_dbg(ace->dev, diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index c909c1a3f65..4575171e5be 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c @@ -71,10 +71,7 @@ static void do_z2_request(struct request_queue *q) { struct request *req; - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - + req = blk_fetch_request(q); while (req) { unsigned long start = blk_rq_pos(req) << 9; unsigned long len = blk_rq_cur_bytes(req); @@ -100,11 +97,8 @@ static void do_z2_request(struct request_queue *q) len -= size; } done: - if (!__blk_end_request_cur(req, err)) { - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - } + if (!__blk_end_request_cur(req, err)) + req = blk_fetch_request(q); } } diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 3cc02bfe828..1e366ad8f68 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -642,9 +642,7 @@ static void gdrom_request(struct request_queue *rq) { struct request *req; - while ((req = elv_next_request(rq)) != NULL) { - blkdev_dequeue_request(req); - + while ((req = blk_fetch_request(rq)) != NULL) { if (!blk_fs_request(req)) { printk(KERN_DEBUG "GDROM: Non-fs request ignored\n"); __blk_end_request_all(req, -EIO); diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index bbe9f086734..ca741c21e4a 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -297,9 +297,7 @@ static void do_viocd_request(struct request_queue *q) { struct request *req; - while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) { - blkdev_dequeue_request(req); - + while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) { if (!blk_fs_request(req)) __blk_end_request_all(req, -EIO); else if (send_request(req) < 0) { diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 2874c3d703a..8a894fa37b5 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -269,7 +269,7 @@ void ide_retry_pc(ide_drive_t *drive) blk_requeue_request(failed_rq->q, failed_rq); drive->hwif->rq = NULL; if (ide_queue_sense_rq(drive, pc)) { - blkdev_dequeue_request(failed_rq); + blk_start_request(failed_rq); ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq)); } } diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index abda7337b3f..e4e3a0e3201 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -519,11 +519,8 @@ repeat: * we know that the queue isn't empty, but this can happen * if the q->prep_rq_fn() decides to kill a request */ - if (!rq) { - rq = elv_next_request(drive->queue); - if (rq) - blkdev_dequeue_request(rq); - } + if (!rq) + rq = blk_fetch_request(drive->queue); spin_unlock_irq(q->queue_lock); spin_lock_irq(&hwif->lock); @@ -536,7 +533,7 @@ repeat: /* * Sanity: don't accept a request that isn't a PM request * if we are currently power managed. This is very important as - * blk_stop_queue() doesn't prevent the elv_next_request() + * blk_stop_queue() doesn't prevent the blk_fetch_request() * above to return us whatever is in the queue. Since we call * ide_do_request() ourselves, we end up taking requests while * the queue is blocked... diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index 58f5be8cd69..c0bebc6a2f2 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -704,13 +704,12 @@ try_again: return 0; } - dev_dbg(&card->dev, "elv_next\n"); - msb->block_req = elv_next_request(msb->queue); + dev_dbg(&card->dev, "blk_fetch\n"); + msb->block_req = blk_fetch_request(msb->queue); if (!msb->block_req) { dev_dbg(&card->dev, "issue end\n"); return -EAGAIN; } - blkdev_dequeue_request(msb->block_req); dev_dbg(&card->dev, "trying again\n"); chunk = 1; @@ -825,10 +824,8 @@ static void mspro_block_submit_req(struct request_queue *q) return; if (msb->eject) { - while ((req = elv_next_request(q)) != NULL) { - blkdev_dequeue_request(req); + while ((req = blk_fetch_request(q)) != NULL) __blk_end_request_all(req, -ENODEV); - } return; } diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index 8b5cbfc3ba9..6573ef4408f 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c @@ -877,7 +877,7 @@ static void i2o_block_request_fn(struct request_queue *q) struct request *req; while (!blk_queue_plugged(q)) { - req = elv_next_request(q); + req = blk_peek_request(q); if (!req) break; @@ -890,7 +890,7 @@ static void i2o_block_request_fn(struct request_queue *q) if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { if (!i2o_block_transfer(req)) { - blkdev_dequeue_request(req); + blk_start_request(req); continue; } else osm_info("transfer error\n"); @@ -917,7 +917,7 @@ static void i2o_block_request_fn(struct request_queue *q) break; } } else { - blkdev_dequeue_request(req); + blk_start_request(req); __blk_end_request_all(req, -EIO); } } diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 4b70f1e2834..49e582356c6 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -54,11 +54,8 @@ static int mmc_queue_thread(void *d) spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); - if (!blk_queue_plugged(q)) { - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - } + if (!blk_queue_plugged(q)) + req = blk_fetch_request(q); mq->req = req; spin_unlock_irq(q->queue_lock); @@ -94,10 +91,8 @@ static void mmc_request(struct request_queue *q) if (!mq) { printk(KERN_ERR "MMC: killing requests for dead queue\n"); - while ((req = elv_next_request(q)) != NULL) { - blkdev_dequeue_request(req); + while ((req = blk_fetch_request(q)) != NULL) __blk_end_request_all(req, -EIO); - } return; } diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 3e10442615d..502622f628b 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -100,12 +100,7 @@ static int mtd_blktrans_thread(void *arg) struct mtd_blktrans_dev *dev; int res; - if (!req) { - req = elv_next_request(rq); - if (req) - blkdev_dequeue_request(req); - } - if (!req) { + if (!req && !(req = blk_fetch_request(rq))) { set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irq(rq->queue_lock); schedule(); diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 7df03c7aea0..e64f62d5e0f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1656,17 +1656,13 @@ static void __dasd_process_request_queue(struct dasd_block *block) if (basedev->state < DASD_STATE_READY) return; /* Now we try to fetch requests from the request queue */ - while (!blk_queue_plugged(queue) && - elv_next_request(queue)) { - - req = elv_next_request(queue); - + while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) { if (basedev->features & DASD_FEATURE_READONLY && rq_data_dir(req) == WRITE) { DBF_DEV_EVENT(DBF_ERR, basedev, "Rejecting write request %p", req); - blkdev_dequeue_request(req); + blk_start_request(req); __blk_end_request_all(req, -EIO); continue; } @@ -1695,7 +1691,7 @@ static void __dasd_process_request_queue(struct dasd_block *block) "CCW creation failed (rc=%ld) " "on request %p", PTR_ERR(cqr), req); - blkdev_dequeue_request(req); + blk_start_request(req); __blk_end_request_all(req, -EIO); continue; } @@ -1705,7 +1701,7 @@ static void __dasd_process_request_queue(struct dasd_block *block) */ cqr->callback_data = (void *) req; cqr->status = DASD_CQR_FILLED; - blkdev_dequeue_request(req); + blk_start_request(req); list_add_tail(&cqr->blocklist, &block->ccw_queue); dasd_profile_start(block, cqr, req); } @@ -2029,10 +2025,8 @@ static void dasd_flush_request_queue(struct dasd_block *block) return; spin_lock_irq(&block->request_queue_lock); - while ((req = elv_next_request(block->request_queue))) { - blkdev_dequeue_request(req); + while ((req = blk_fetch_request(block->request_queue))) __blk_end_request_all(req, -EIO); - } spin_unlock_irq(&block->request_queue_lock); } diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 5d035e4939d..1e796767598 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -93,7 +93,7 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data) device->blk_data.block_position = -1; device->discipline->free_bread(ccw_req); if (!list_empty(&device->req_queue) || - elv_next_request(device->blk_data.request_queue)) + blk_peek_request(device->blk_data.request_queue)) tapeblock_trigger_requeue(device); } @@ -162,19 +162,16 @@ tapeblock_requeue(struct work_struct *work) { spin_lock_irq(&device->blk_data.request_queue_lock); while ( !blk_queue_plugged(queue) && - elv_next_request(queue) && + (req = blk_fetch_request(queue)) && nr_queued < TAPEBLOCK_MIN_REQUEUE ) { - req = elv_next_request(queue); if (rq_data_dir(req) == WRITE) { DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); - blkdev_dequeue_request(req); spin_unlock_irq(&device->blk_data.request_queue_lock); blk_end_request_all(req, -EIO); spin_lock_irq(&device->blk_data.request_queue_lock); continue; } - blkdev_dequeue_request(req); nr_queued++; spin_unlock_irq(&device->blk_data.request_queue_lock); rc = tapeblock_start_request(device, req); diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index f572a4a1d14..6d465168468 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -186,10 +186,7 @@ static void jsfd_do_request(struct request_queue *q) { struct request *req; - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - + req = blk_fetch_request(q); while (req) { struct jsfd_part *jdp = req->rq_disk->private_data; unsigned long offset = blk_rq_pos(req) << 9; @@ -212,11 +209,8 @@ static void jsfd_do_request(struct request_queue *q) jsfd_read(req->buffer, jdp->dbase + offset, len); err = 0; end: - if (!__blk_end_request_cur(req, err)) { - req = elv_next_request(q); - if (req) - blkdev_dequeue_request(req); - } + if (!__blk_end_request_cur(req, err)) + req = blk_fetch_request(q); } } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ee308f6f798..b12750f8216 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1207,7 +1207,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) break; case BLKPREP_DEFER: /* - * If we defer, the elv_next_request() returns NULL, but the + * If we defer, the blk_peek_request() returns NULL, but the * queue must be restarted, so we plug here if no returning * command will automatically do that. */ @@ -1385,7 +1385,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) struct scsi_target *starget = scsi_target(sdev); struct Scsi_Host *shost = sdev->host; - blkdev_dequeue_request(req); + blk_start_request(req); if (unlikely(cmd == NULL)) { printk(KERN_CRIT "impossible request in %s.\n", @@ -1477,7 +1477,7 @@ static void scsi_request_fn(struct request_queue *q) if (!sdev) { printk("scsi: killing requests for dead queue\n"); - while ((req = elv_next_request(q)) != NULL) + while ((req = blk_peek_request(q)) != NULL) scsi_kill_request(req, q); return; } @@ -1498,7 +1498,7 @@ static void scsi_request_fn(struct request_queue *q) * that the request is fully prepared even if we cannot * accept it. */ - req = elv_next_request(q); + req = blk_peek_request(q); if (!req || !scsi_dev_queue_ready(q, sdev)) break; @@ -1514,7 +1514,7 @@ static void scsi_request_fn(struct request_queue *q) * Remove the request from the request list. */ if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) - blkdev_dequeue_request(req); + blk_start_request(req); sdev->device_busy++; spin_unlock(q->queue_lock); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 50988cbf7b2..d606452297c 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -163,12 +163,10 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); while (!blk_queue_plugged(q)) { - req = elv_next_request(q); + req = blk_fetch_request(q); if (!req) break; - blkdev_dequeue_request(req); - spin_unlock_irq(q->queue_lock); handler = to_sas_internal(shost->transportt)->f->smp_handler; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index c7558034570..6e59d3b92ff 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -818,8 +818,6 @@ static inline void blk_run_address_space(struct address_space *mapping) blk_run_backing_dev(mapping->backing_dev_info, NULL); } -extern void blkdev_dequeue_request(struct request *req); - /* * blk_rq_pos() : the current sector * blk_rq_bytes() : bytes left in the entire request @@ -852,6 +850,13 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) return blk_rq_cur_bytes(rq) >> 9; } +/* + * Request issue related functions. + */ +extern struct request *blk_peek_request(struct request_queue *q); +extern void blk_start_request(struct request *rq); +extern struct request *blk_fetch_request(struct request_queue *q); + /* * Request completion related functions. * diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 4e462878c9c..1cb3372e65d 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -103,10 +103,8 @@ extern int elv_merge(struct request_queue *, struct request **, struct bio *); extern void elv_merge_requests(struct request_queue *, struct request *, struct request *); extern void elv_merged_request(struct request_queue *, struct request *, int); -extern void elv_dequeue_request(struct request_queue *, struct request *); extern void elv_requeue_request(struct request_queue *, struct request *); extern int elv_queue_empty(struct request_queue *); -extern struct request *elv_next_request(struct request_queue *q); extern struct request *elv_former_request(struct request_queue *, struct request *); extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); -- cgit v1.2.3-70-g09d2 From 72af2b363107df9cd67985ecb8495bbdff3c9857 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 11 May 2009 09:58:19 -0700 Subject: ARM: OMAP: Fix printing of reserved memory for frambuffer Print reserved memory only if it was actually reserved. Signed-off-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/fb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/fb.c b/arch/arm/plat-omap/fb.c index ce6b4baeede..3746222bed1 100644 --- a/arch/arm/plat-omap/fb.c +++ b/arch/arm/plat-omap/fb.c @@ -206,9 +206,10 @@ void __init omapfb_reserve_sdram(void) config_invalid = 1; return; } - if (rg.paddr) + if (rg.paddr) { reserve_bootmem(rg.paddr, rg.size, BOOTMEM_DEFAULT); - reserved += rg.size; + reserved += rg.size; + } omapfb_config.mem_desc.region[i] = rg; configured_regions++; } -- cgit v1.2.3-70-g09d2 From d9295746c0ed3991bdec18c6a5890d71d88904b4 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:27:09 -0600 Subject: OMAP3 SRAM: mark OCM RAM as Non-cacheable Normal memory Mark the SRAM (aka OCM RAM) as Non-cacheable Normal memory[1]. This is to prevent the ARM from evicting existing cache lines to SDRAM while code is executing from the SRAM. Necessary since one of the primary uses for the SRAM is to hold the code and data for the CORE DPLL M2 divider reprogramming code, which must execute while the SDRC is idled. If the ARM attempts to write cache lines back to the while the SRAM code is running, the ARM will stall[2]. TI deals with this problem in the CDP kernel by marking the SRAM as Strongly-ordered memory. Tero Kristo caught a bug in an earlier version of this patch - thanks Tero. ... 1. ARMv7 ARM (DDI 0406A) pp. A3-30, A3-31, B3-32. 2. Private communication with Richard Woodruff Signed-off-by: Paul Walmsley Cc: Tero Kristo Cc: Richard Woodruff --- arch/arm/plat-omap/sram.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index fa5297d643d..38353386e91 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -201,6 +201,15 @@ void __init omap_map_sram(void) base = OMAP3_SRAM_PA; base = ROUND_DOWN(base, PAGE_SIZE); omap_sram_io_desc[0].pfn = __phys_to_pfn(base); + + /* + * SRAM must be marked as non-cached on OMAP3 since the + * CORE DPLL M2 divider change code (in SRAM) runs with the + * SDRAM controller disabled, and if it is marked cached, + * the ARM may attempt to write cache lines back to SDRAM + * which will cause the system to hang. + */ + omap_sram_io_desc[0].type = MT_MEMORY_NONCACHED; } omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ -- cgit v1.2.3-70-g09d2 From 4519c2bf433b97d091635eb51e4ba8ffa1c84d62 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:26:32 -0600 Subject: OMAP3 clock: only unlock SDRC DLL if SDRC clk < 83MHz According to the 34xx TRM Rev. K section 11.2.4.4.11.1 "Purpose of the DLL/CDL Module," the SDRC delay-locked-loop can be locked at any SDRC clock frequency from 83MHz to 166MHz. CDP code unconditionally unlocked the DLL whenever shifting to a lower SDRC speed, but this seems unnecessary and error-prone, as the DLL is no longer able to compensate for process, voltage, and temperature variations. Instead, only unlock the DLL when the SDRC clock rate would be less than 83MHz. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap2/clock34xx.c | 10 +++++++++- arch/arm/mach-omap2/sram34xx.S | 13 +++++++------ arch/arm/plat-omap/include/mach/sram.h | 6 ++++-- arch/arm/plat-omap/sram.c | 7 ++++--- 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 0a14dca31e3..811360af60d 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -281,6 +281,8 @@ static struct omap_clk omap34xx_clks[] = { #define MAX_DPLL_WAIT_TRIES 1000000 +#define MIN_SDRC_DLL_LOCK_FREQ 83000000 + /** * omap3_dpll_recalc - recalculate DPLL rate * @clk: DPLL struct clk @@ -703,6 +705,7 @@ static int omap3_dpll4_set_rate(struct clk *clk, unsigned long rate) static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) { u32 new_div = 0; + u32 unlock_dll = 0; unsigned long validrate, sdrcrate; struct omap_sdrc_params *sp; @@ -729,6 +732,11 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) if (!sp) return -EINVAL; + if (sdrcrate < MIN_SDRC_DLL_LOCK_FREQ) { + pr_debug("clock: will unlock SDRC DLL\n"); + unlock_dll = 1; + } + pr_info("clock: changing CORE DPLL rate from %lu to %lu\n", clk->rate, validrate); pr_info("clock: SDRC timing params used: %08x %08x %08x\n", @@ -739,7 +747,7 @@ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate) /* REVISIT: Add SDRC_MR changing to this code also */ omap3_configure_core_dpll(sp->rfr_ctrl, sp->actim_ctrla, - sp->actim_ctrlb, new_div); + sp->actim_ctrlb, new_div, unlock_dll); return 0; } diff --git a/arch/arm/mach-omap2/sram34xx.S b/arch/arm/mach-omap2/sram34xx.S index 35131e5bc7d..c080c82521e 100644 --- a/arch/arm/mach-omap2/sram34xx.S +++ b/arch/arm/mach-omap2/sram34xx.S @@ -40,22 +40,23 @@ /* * Change frequency of core dpll * r0 = sdrc_rfr_ctrl r1 = sdrc_actim_ctrla r2 = sdrc_actim_ctrlb r3 = M2 + * r4 = Unlock SDRC DLL? (1 = yes, 0 = no) -- only unlock DLL for + * SDRC rates < 83MHz */ ENTRY(omap3_sram_configure_core_dpll) stmfd sp!, {r1-r12, lr} @ store regs to stack + ldr r4, [sp, #52] @ pull extra args off the stack dsb @ flush buffered writes to interconnect cmp r3, #0x2 blne configure_sdrc - cmp r3, #0x2 + cmp r4, #0x1 + bleq unlock_dll blne lock_dll - cmp r3, #0x1 - blne unlock_dll bl sdram_in_selfrefresh @ put the SDRAM in self refresh bl configure_core_dpll bl enable_sdrc - cmp r3, #0x1 - blne wait_dll_unlock - cmp r3, #0x2 + cmp r4, #0x1 + bleq wait_dll_unlock blne wait_dll_lock cmp r3, #0x1 blne configure_sdrc diff --git a/arch/arm/plat-omap/include/mach/sram.h b/arch/arm/plat-omap/include/mach/sram.h index ab35d622dcf..dca7c16ae90 100644 --- a/arch/arm/plat-omap/include/mach/sram.h +++ b/arch/arm/plat-omap/include/mach/sram.h @@ -23,7 +23,8 @@ extern u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); extern u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, - u32 sdrc_actim_ctrlb, u32 m2); + u32 sdrc_actim_ctrlb, u32 m2, + u32 unlock_dll); /* Do not use these */ extern void omap1_sram_reprogram_clock(u32 ckctl, u32 dpllctl); @@ -60,7 +61,8 @@ extern unsigned long omap243x_sram_reprogram_sdrc_sz; extern u32 omap3_sram_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, - u32 sdrc_actim_ctrlb, u32 m2); + u32 sdrc_actim_ctrlb, u32 m2, + u32 unlock_dll); extern unsigned long omap3_sram_configure_core_dpll_sz; #endif diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 38353386e91..876f5a7ecaf 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -365,16 +365,17 @@ static inline int omap243x_sram_init(void) static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, u32 sdrc_actim_ctrlb, - u32 m2); + u32 m2, u32 unlock_dll); u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, - u32 sdrc_actim_ctrlb, u32 m2) + u32 sdrc_actim_ctrlb, u32 m2, u32 unlock_dll) { if (!_omap3_sram_configure_core_dpll) omap_sram_error(); return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, sdrc_actim_ctrla, - sdrc_actim_ctrlb, m2); + sdrc_actim_ctrlb, m2, + unlock_dll); } /* REVISIT: Should this be same as omap34xx_sram_init() after off-idle? */ -- cgit v1.2.3-70-g09d2 From 7971687094ef48695aa56a0c03416b609bd4d1fd Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 12 May 2009 17:50:30 -0600 Subject: OMAP2xxx clock: rename clk_init_one() to clk_preinit() Rename clk_init_one() to clk_preinit() to distinguish its function from clk_init() and the individual struct clk init functions. Signed-off-by: Paul Walmsley --- arch/arm/mach-omap1/clock.c | 2 +- arch/arm/mach-omap2/clock24xx.c | 2 +- arch/arm/mach-omap2/clock34xx.c | 2 +- arch/arm/plat-omap/clock.c | 4 ++-- arch/arm/plat-omap/include/mach/clock.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap1/clock.c b/arch/arm/mach-omap1/clock.c index 336e51dc612..436eed22801 100644 --- a/arch/arm/mach-omap1/clock.c +++ b/arch/arm/mach-omap1/clock.c @@ -776,7 +776,7 @@ int __init omap1_clk_init(void) arm_idlect1_mask = ~0; for (c = omap_clks; c < omap_clks + ARRAY_SIZE(omap_clks); c++) - clk_init_one(c->lk.clk); + clk_preinit(c->lk.clk); cpu_mask = 0; if (cpu_is_omap16xx()) diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index efc59c49341..cc94672f9e2 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -722,7 +722,7 @@ int __init omap2_clk_init(void) clk_init(&omap2_clk_functions); for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++) - clk_init_one(c->lk.clk); + clk_preinit(c->lk.clk); osc_ck.rate = omap2_osc_clk_recalc(&osc_ck); propagate_rate(&osc_ck); diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 2ee58fa5dc7..62092f282de 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -964,7 +964,7 @@ int __init omap2_clk_init(void) clk_init(&omap2_clk_functions); for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) - clk_init_one(c->lk.clk); + clk_preinit(c->lk.clk); for (c = omap34xx_clks; c < omap34xx_clks + ARRAY_SIZE(omap34xx_clks); c++) if (c->cpu & cpu_clkflg) { diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 29efc279287..508c96ab24e 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -240,13 +240,13 @@ void recalculate_root_clocks(void) } /** - * clk_init_one - initialize any fields in the struct clk before clk init + * clk_preinit - initialize any fields in the struct clk before clk init * @clk: struct clk * to initialize * * Initialize any struct clk fields needed before normal clk initialization * can run. No return value. */ -void clk_init_one(struct clk *clk) +void clk_preinit(struct clk *clk) { INIT_LIST_HEAD(&clk->children); } diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 073a2c5569f..d7bd19c8ce3 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -119,7 +119,7 @@ struct clk_functions { extern unsigned int mpurate; extern int clk_init(struct clk_functions *custom_clocks); -extern void clk_init_one(struct clk *clk); +extern void clk_preinit(struct clk *clk); extern int clk_register(struct clk *clk); extern void clk_reparent(struct clk *child, struct clk *parent); extern void clk_unregister(struct clk *clk); -- cgit v1.2.3-70-g09d2 From e102657ed16bbed49820d9c58509220fc8d9289a Mon Sep 17 00:00:00 2001 From: Vikram Pandita Date: Sat, 16 May 2009 08:28:16 -0700 Subject: ARM: OMAP3: Fix number of GPIO lines for 34xx As per 3430 TRM, there are 6 banks [0 to 191] Signed-off-by: Tom Rix Signed-off-by: Vikram Pandita Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 17d7afe42b8..ee0b21f5b09 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -307,7 +307,7 @@ static inline int gpio_valid(int gpio) return 0; if (cpu_is_omap24xx() && gpio < 128) return 0; - if (cpu_is_omap34xx() && gpio < 160) + if (cpu_is_omap34xx() && gpio < 192) return 0; return -1; } -- cgit v1.2.3-70-g09d2 From 69d3a84a646d6ad6cd693a7a3d5b9af414113d2c Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Wed, 28 Jan 2009 21:32:08 +0200 Subject: omap iommu: simple virtual address space management This patch provides a device drivers, which has a omap iommu, with address mapping APIs between device virtual address(iommu), physical address and MPU virtual address. There are 4 possible patterns for iommu virtual address(iova/da) mapping. |iova/ mapping iommu_ page | da pa va (d)-(p)-(v) function type --------------------------------------------------------------------------- 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s 3 | c d c 1 - n - 1 _vmap() / _vunmap() s 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n* 'iova': device iommu virtual address 'da': alias of 'iova' 'pa': physical address 'va': mpu virtual address 'c': contiguous memory area 'd': dicontiguous memory area 'a': anonymous memory allocation '()': optional feature 'n': a normal page(4KB) size is used. 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used. '*': not yet, but feasible. Signed-off-by: Hiroshi DOYU --- arch/arm/include/asm/mach/map.h | 8 + arch/arm/mm/ioremap.c | 6 + arch/arm/mm/mmu.c | 1 + arch/arm/plat-omap/include/mach/iovmm.h | 94 ++++ arch/arm/plat-omap/iovmm.c | 896 ++++++++++++++++++++++++++++++++ 5 files changed, 1005 insertions(+) create mode 100644 arch/arm/plat-omap/include/mach/iovmm.h create mode 100644 arch/arm/plat-omap/iovmm.c (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/include/asm/mach/map.h b/arch/arm/include/asm/mach/map.h index 58cf91f38e6..742c2aaeb02 100644 --- a/arch/arm/include/asm/mach/map.h +++ b/arch/arm/include/asm/mach/map.h @@ -30,6 +30,14 @@ struct map_desc { #ifdef CONFIG_MMU extern void iotable_init(struct map_desc *, int); + +struct mem_type; +extern const struct mem_type *get_mem_type(unsigned int type); +/* + * external interface to remap single page with appropriate type + */ +extern int ioremap_page(unsigned long virt, unsigned long phys, + const struct mem_type *mtype); #else #define iotable_init(map,num) do { } while (0) #endif diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 9f88dd3be60..0ab75c60f7c 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -110,6 +110,12 @@ static int remap_area_pages(unsigned long start, unsigned long pfn, return err; } +int ioremap_page(unsigned long virt, unsigned long phys, + const struct mem_type *mtype) +{ + return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, mtype); +} +EXPORT_SYMBOL(ioremap_page); void __check_kvm_seq(struct mm_struct *mm) { diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index e6344ece00c..70974d75a07 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -255,6 +255,7 @@ const struct mem_type *get_mem_type(unsigned int type) { return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL; } +EXPORT_SYMBOL(get_mem_type); /* * Adjust the PMD section entries according to the CPU in use. diff --git a/arch/arm/plat-omap/include/mach/iovmm.h b/arch/arm/plat-omap/include/mach/iovmm.h new file mode 100644 index 00000000000..bdc7ce5d7a4 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/iovmm.h @@ -0,0 +1,94 @@ +/* + * omap iommu: simple virtual address space management + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU + * + * 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. + */ + +#ifndef __IOMMU_MMAP_H +#define __IOMMU_MMAP_H + +struct iovm_struct { + struct iommu *iommu; /* iommu object which this belongs to */ + u32 da_start; /* area definition */ + u32 da_end; + u32 flags; /* IOVMF_: see below */ + struct list_head list; /* linked in ascending order */ + const struct sg_table *sgt; /* keep 'page' <-> 'da' mapping */ + void *va; /* mpu side mapped address */ +}; + +/* + * IOVMF_FLAGS: attribute for iommu virtual memory area(iovma) + * + * lower 16 bit is used for h/w and upper 16 bit is for s/w. + */ +#define IOVMF_SW_SHIFT 16 +#define IOVMF_HW_SIZE (1 << IOVMF_SW_SHIFT) +#define IOVMF_HW_MASK (IOVMF_HW_SIZE - 1) +#define IOVMF_SW_MASK (~IOVMF_HW_MASK)UL + +/* + * iovma: h/w flags derived from cam and ram attribute + */ +#define IOVMF_CAM_MASK (~((1 << 10) - 1)) +#define IOVMF_RAM_MASK (~IOVMF_CAM_MASK) + +#define IOVMF_PGSZ_MASK (3 << 0) +#define IOVMF_PGSZ_1M MMU_CAM_PGSZ_1M +#define IOVMF_PGSZ_64K MMU_CAM_PGSZ_64K +#define IOVMF_PGSZ_4K MMU_CAM_PGSZ_4K +#define IOVMF_PGSZ_16M MMU_CAM_PGSZ_16M + +#define IOVMF_ENDIAN_MASK (1 << 9) +#define IOVMF_ENDIAN_BIG MMU_RAM_ENDIAN_BIG +#define IOVMF_ENDIAN_LITTLE MMU_RAM_ENDIAN_LITTLE + +#define IOVMF_ELSZ_MASK (3 << 7) +#define IOVMF_ELSZ_8 MMU_RAM_ELSZ_8 +#define IOVMF_ELSZ_16 MMU_RAM_ELSZ_16 +#define IOVMF_ELSZ_32 MMU_RAM_ELSZ_32 +#define IOVMF_ELSZ_NONE MMU_RAM_ELSZ_NONE + +#define IOVMF_MIXED_MASK (1 << 6) +#define IOVMF_MIXED MMU_RAM_MIXED + +/* + * iovma: s/w flags, used for mapping and umapping internally. + */ +#define IOVMF_MMIO (1 << IOVMF_SW_SHIFT) +#define IOVMF_ALLOC (2 << IOVMF_SW_SHIFT) +#define IOVMF_ALLOC_MASK (3 << IOVMF_SW_SHIFT) + +/* "superpages" is supported just with physically linear pages */ +#define IOVMF_DISCONT (1 << (2 + IOVMF_SW_SHIFT)) +#define IOVMF_LINEAR (2 << (2 + IOVMF_SW_SHIFT)) +#define IOVMF_LINEAR_MASK (3 << (2 + IOVMF_SW_SHIFT)) + +#define IOVMF_DA_FIXED (1 << (4 + IOVMF_SW_SHIFT)) +#define IOVMF_DA_ANON (2 << (4 + IOVMF_SW_SHIFT)) +#define IOVMF_DA_MASK (3 << (4 + IOVMF_SW_SHIFT)) + + +extern struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da); +extern u32 iommu_vmap(struct iommu *obj, u32 da, + const struct sg_table *sgt, u32 flags); +extern struct sg_table *iommu_vunmap(struct iommu *obj, u32 da); +extern u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, + u32 flags); +extern void iommu_vfree(struct iommu *obj, const u32 da); +extern u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, + u32 flags); +extern void iommu_kunmap(struct iommu *obj, u32 da); +extern u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, + u32 flags); +extern void iommu_kfree(struct iommu *obj, u32 da); + +extern void *da_to_va(struct iommu *obj, u32 da); + +#endif /* __IOMMU_MMAP_H */ diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c new file mode 100644 index 00000000000..2fce2c151a9 --- /dev/null +++ b/arch/arm/plat-omap/iovmm.c @@ -0,0 +1,896 @@ +/* + * omap iommu: simple virtual address space management + * + * Copyright (C) 2008-2009 Nokia Corporation + * + * Written by Hiroshi DOYU + * + * 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 +#include +#include +#include + +#include +#include + +#include +#include + +#include "iopgtable.h" + +/* + * A device driver needs to create address mappings between: + * + * - iommu/device address + * - physical address + * - mpu virtual address + * + * There are 4 possible patterns for them: + * + * |iova/ mapping iommu_ page + * | da pa va (d)-(p)-(v) function type + * --------------------------------------------------------------------------- + * 1 | c c c 1 - 1 - 1 _kmap() / _kunmap() s + * 2 | c c,a c 1 - 1 - 1 _kmalloc()/ _kfree() s + * 3 | c d c 1 - n - 1 _vmap() / _vunmap() s + * 4 | c d,a c 1 - n - 1 _vmalloc()/ _vfree() n* + * + * + * 'iova': device iommu virtual address + * 'da': alias of 'iova' + * 'pa': physical address + * 'va': mpu virtual address + * + * 'c': contiguous memory area + * 'd': dicontiguous memory area + * 'a': anonymous memory allocation + * '()': optional feature + * + * 'n': a normal page(4KB) size is used. + * 's': multiple iommu superpage(16MB, 1MB, 64KB, 4KB) size is used. + * + * '*': not yet, but feasible. + */ + +static struct kmem_cache *iovm_area_cachep; + +/* return total bytes of sg buffers */ +static size_t sgtable_len(const struct sg_table *sgt) +{ + unsigned int i, total = 0; + struct scatterlist *sg; + + if (!sgt) + return 0; + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + size_t bytes; + + bytes = sg_dma_len(sg); + + if (!iopgsz_ok(bytes)) { + pr_err("%s: sg[%d] not iommu pagesize(%x)\n", + __func__, i, bytes); + return 0; + } + + total += bytes; + } + + return total; +} +#define sgtable_ok(x) (!!sgtable_len(x)) + +/* + * calculate the optimal number sg elements from total bytes based on + * iommu superpages + */ +static unsigned int sgtable_nents(size_t bytes) +{ + int i; + unsigned int nr_entries; + const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, }; + + if (!IS_ALIGNED(bytes, PAGE_SIZE)) { + pr_err("%s: wrong size %08x\n", __func__, bytes); + return 0; + } + + nr_entries = 0; + for (i = 0; i < ARRAY_SIZE(pagesize); i++) { + if (bytes >= pagesize[i]) { + nr_entries += (bytes / pagesize[i]); + bytes %= pagesize[i]; + } + } + BUG_ON(bytes); + + return nr_entries; +} + +/* allocate and initialize sg_table header(a kind of 'superblock') */ +static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags) +{ + unsigned int nr_entries; + int err; + struct sg_table *sgt; + + if (!bytes) + return ERR_PTR(-EINVAL); + + if (!IS_ALIGNED(bytes, PAGE_SIZE)) + return ERR_PTR(-EINVAL); + + /* FIXME: IOVMF_DA_FIXED should support 'superpages' */ + if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) { + nr_entries = sgtable_nents(bytes); + if (!nr_entries) + return ERR_PTR(-EINVAL); + } else + nr_entries = bytes / PAGE_SIZE; + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); + + err = sg_alloc_table(sgt, nr_entries, GFP_KERNEL); + if (err) + return ERR_PTR(err); + + pr_debug("%s: sgt:%p(%d entries)\n", __func__, sgt, nr_entries); + + return sgt; +} + +/* free sg_table header(a kind of superblock) */ +static void sgtable_free(struct sg_table *sgt) +{ + if (!sgt) + return; + + sg_free_table(sgt); + kfree(sgt); + + pr_debug("%s: sgt:%p\n", __func__, sgt); +} + +/* map 'sglist' to a contiguous mpu virtual area and return 'va' */ +static void *vmap_sg(const struct sg_table *sgt) +{ + u32 va; + size_t total; + unsigned int i; + struct scatterlist *sg; + struct vm_struct *new; + const struct mem_type *mtype; + + mtype = get_mem_type(MT_DEVICE); + if (!mtype) + return ERR_PTR(-EINVAL); + + total = sgtable_len(sgt); + if (!total) + return ERR_PTR(-EINVAL); + + new = __get_vm_area(total, VM_IOREMAP, VMALLOC_START, VMALLOC_END); + if (!new) + return ERR_PTR(-ENOMEM); + va = (u32)new->addr; + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + size_t bytes; + u32 pa; + int err; + + pa = sg_phys(sg); + bytes = sg_dma_len(sg); + + BUG_ON(bytes != PAGE_SIZE); + + err = ioremap_page(va, pa, mtype); + if (err) + goto err_out; + + va += bytes; + } + + flush_cache_vmap(new->addr, total); + return new->addr; + +err_out: + WARN_ON(1); /* FIXME: cleanup some mpu mappings */ + vunmap(new->addr); + return ERR_PTR(-EAGAIN); +} + +static inline void vunmap_sg(const void *va) +{ + vunmap(va); +} + +static struct iovm_struct *__find_iovm_area(struct iommu *obj, const u32 da) +{ + struct iovm_struct *tmp; + + list_for_each_entry(tmp, &obj->mmap, list) { + if ((da >= tmp->da_start) && (da < tmp->da_end)) { + size_t len; + + len = tmp->da_end - tmp->da_start; + + dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", + __func__, tmp->da_start, da, tmp->da_end, len, + tmp->flags); + + return tmp; + } + } + + return NULL; +} + +/** + * find_iovm_area - find iovma which includes @da + * @da: iommu device virtual address + * + * Find the existing iovma starting at @da + */ +struct iovm_struct *find_iovm_area(struct iommu *obj, u32 da) +{ + struct iovm_struct *area; + + mutex_lock(&obj->mmap_lock); + area = __find_iovm_area(obj, da); + mutex_unlock(&obj->mmap_lock); + + return area; +} +EXPORT_SYMBOL_GPL(find_iovm_area); + +/* + * This finds the hole(area) which fits the requested address and len + * in iovmas mmap, and returns the new allocated iovma. + */ +static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, + size_t bytes, u32 flags) +{ + struct iovm_struct *new, *tmp; + u32 start, prev_end, alignement; + + if (!obj || !bytes) + return ERR_PTR(-EINVAL); + + start = da; + alignement = PAGE_SIZE; + + if (flags & IOVMF_DA_ANON) { + /* + * Reserve the first page for NULL + */ + start = PAGE_SIZE; + if (flags & IOVMF_LINEAR) + alignement = iopgsz_max(bytes); + start = roundup(start, alignement); + } + + tmp = NULL; + if (list_empty(&obj->mmap)) + goto found; + + prev_end = 0; + list_for_each_entry(tmp, &obj->mmap, list) { + + if ((prev_end <= start) && (start + bytes < tmp->da_start)) + goto found; + + if (flags & IOVMF_DA_ANON) + start = roundup(tmp->da_end, alignement); + + prev_end = tmp->da_end; + } + + if ((start >= prev_end) && (ULONG_MAX - start >= bytes)) + goto found; + + dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", + __func__, da, bytes, flags); + + return ERR_PTR(-EINVAL); + +found: + new = kmem_cache_zalloc(iovm_area_cachep, GFP_KERNEL); + if (!new) + return ERR_PTR(-ENOMEM); + + new->iommu = obj; + new->da_start = start; + new->da_end = start + bytes; + new->flags = flags; + + /* + * keep ascending order of iovmas + */ + if (tmp) + list_add_tail(&new->list, &tmp->list); + else + list_add(&new->list, &obj->mmap); + + dev_dbg(obj->dev, "%s: found %08x-%08x-%08x(%x) %08x\n", + __func__, new->da_start, start, new->da_end, bytes, flags); + + return new; +} + +static void free_iovm_area(struct iommu *obj, struct iovm_struct *area) +{ + size_t bytes; + + BUG_ON(!obj || !area); + + bytes = area->da_end - area->da_start; + + dev_dbg(obj->dev, "%s: %08x-%08x(%x) %08x\n", + __func__, area->da_start, area->da_end, bytes, area->flags); + + list_del(&area->list); + kmem_cache_free(iovm_area_cachep, area); +} + +/** + * da_to_va - convert (d) to (v) + * @obj: objective iommu + * @da: iommu device virtual address + * @va: mpu virtual address + * + * Returns mpu virtual addr which corresponds to a given device virtual addr + */ +void *da_to_va(struct iommu *obj, u32 da) +{ + void *va = NULL; + struct iovm_struct *area; + + mutex_lock(&obj->mmap_lock); + + area = __find_iovm_area(obj, da); + if (!area) { + dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da); + goto out; + } + va = area->va; + mutex_unlock(&obj->mmap_lock); +out: + return va; +} +EXPORT_SYMBOL_GPL(da_to_va); + +static void sgtable_fill_vmalloc(struct sg_table *sgt, void *_va) +{ + unsigned int i; + struct scatterlist *sg; + void *va = _va; + void *va_end; + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + struct page *pg; + const size_t bytes = PAGE_SIZE; + + /* + * iommu 'superpage' isn't supported with 'iommu_vmalloc()' + */ + pg = vmalloc_to_page(va); + BUG_ON(!pg); + sg_set_page(sg, pg, bytes, 0); + + va += bytes; + } + + va_end = _va + PAGE_SIZE * i; + flush_cache_vmap(_va, va_end); +} + +static inline void sgtable_drain_vmalloc(struct sg_table *sgt) +{ + /* + * Actually this is not necessary at all, just exists for + * consistency of the code readibility. + */ + BUG_ON(!sgt); +} + +static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len) +{ + unsigned int i; + struct scatterlist *sg; + void *va; + + va = phys_to_virt(pa); + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + size_t bytes; + + bytes = iopgsz_max(len); + + BUG_ON(!iopgsz_ok(bytes)); + + sg_set_buf(sg, phys_to_virt(pa), bytes); + /* + * 'pa' is cotinuous(linear). + */ + pa += bytes; + len -= bytes; + } + BUG_ON(len); + + clean_dcache_area(va, len); +} + +static inline void sgtable_drain_kmalloc(struct sg_table *sgt) +{ + /* + * Actually this is not necessary at all, just exists for + * consistency of the code readibility + */ + BUG_ON(!sgt); +} + +/* create 'da' <-> 'pa' mapping from 'sgt' */ +static int map_iovm_area(struct iommu *obj, struct iovm_struct *new, + const struct sg_table *sgt, u32 flags) +{ + int err; + unsigned int i, j; + struct scatterlist *sg; + u32 da = new->da_start; + + if (!obj || !new || !sgt) + return -EINVAL; + + BUG_ON(!sgtable_ok(sgt)); + + for_each_sg(sgt->sgl, sg, sgt->nents, i) { + u32 pa; + int pgsz; + size_t bytes; + struct iotlb_entry e; + + pa = sg_phys(sg); + bytes = sg_dma_len(sg); + + flags &= ~IOVMF_PGSZ_MASK; + pgsz = bytes_to_iopgsz(bytes); + if (pgsz < 0) + goto err_out; + flags |= pgsz; + + pr_debug("%s: [%d] %08x %08x(%x)\n", __func__, + i, da, pa, bytes); + + iotlb_init_entry(&e, da, pa, flags); + err = iopgtable_store_entry(obj, &e); + if (err) + goto err_out; + + da += bytes; + } + return 0; + +err_out: + da = new->da_start; + + for_each_sg(sgt->sgl, sg, i, j) { + size_t bytes; + + bytes = iopgtable_clear_entry(obj, da); + + BUG_ON(!iopgsz_ok(bytes)); + + da += bytes; + } + return err; +} + +/* release 'da' <-> 'pa' mapping */ +static void unmap_iovm_area(struct iommu *obj, struct iovm_struct *area) +{ + u32 start; + size_t total = area->da_end - area->da_start; + + BUG_ON((!total) || !IS_ALIGNED(total, PAGE_SIZE)); + + start = area->da_start; + while (total > 0) { + size_t bytes; + + bytes = iopgtable_clear_entry(obj, start); + if (bytes == 0) + bytes = PAGE_SIZE; + else + dev_dbg(obj->dev, "%s: unmap %08x(%x) %08x\n", + __func__, start, bytes, area->flags); + + BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE)); + + total -= bytes; + start += bytes; + } + BUG_ON(total); +} + +/* template function for all unmapping */ +static struct sg_table *unmap_vm_area(struct iommu *obj, const u32 da, + void (*fn)(const void *), u32 flags) +{ + struct sg_table *sgt = NULL; + struct iovm_struct *area; + + if (!IS_ALIGNED(da, PAGE_SIZE)) { + dev_err(obj->dev, "%s: alignment err(%08x)\n", __func__, da); + return NULL; + } + + mutex_lock(&obj->mmap_lock); + + area = __find_iovm_area(obj, da); + if (!area) { + dev_dbg(obj->dev, "%s: no da area(%08x)\n", __func__, da); + goto out; + } + + if ((area->flags & flags) != flags) { + dev_err(obj->dev, "%s: wrong flags(%08x)\n", __func__, + area->flags); + goto out; + } + sgt = (struct sg_table *)area->sgt; + + unmap_iovm_area(obj, area); + + fn(area->va); + + dev_dbg(obj->dev, "%s: %08x-%08x-%08x(%x) %08x\n", __func__, + area->da_start, da, area->da_end, + area->da_end - area->da_start, area->flags); + + free_iovm_area(obj, area); +out: + mutex_unlock(&obj->mmap_lock); + + return sgt; +} + +static u32 map_iommu_region(struct iommu *obj, u32 da, + const struct sg_table *sgt, void *va, size_t bytes, u32 flags) +{ + int err = -ENOMEM; + struct iovm_struct *new; + + mutex_lock(&obj->mmap_lock); + + new = alloc_iovm_area(obj, da, bytes, flags); + if (IS_ERR(new)) { + err = PTR_ERR(new); + goto err_alloc_iovma; + } + new->va = va; + new->sgt = sgt; + + if (map_iovm_area(obj, new, sgt, new->flags)) + goto err_map; + + mutex_unlock(&obj->mmap_lock); + + dev_dbg(obj->dev, "%s: da:%08x(%x) flags:%08x va:%p\n", + __func__, new->da_start, bytes, new->flags, va); + + return new->da_start; + +err_map: + free_iovm_area(obj, new); +err_alloc_iovma: + mutex_unlock(&obj->mmap_lock); + return err; +} + +static inline u32 __iommu_vmap(struct iommu *obj, u32 da, + const struct sg_table *sgt, void *va, size_t bytes, u32 flags) +{ + return map_iommu_region(obj, da, sgt, va, bytes, flags); +} + +/** + * iommu_vmap - (d)-(p)-(v) address mapper + * @obj: objective iommu + * @sgt: address of scatter gather table + * @flags: iovma and page property + * + * Creates 1-n-1 mapping with given @sgt and returns @da. + * All @sgt element must be io page size aligned. + */ +u32 iommu_vmap(struct iommu *obj, u32 da, const struct sg_table *sgt, + u32 flags) +{ + size_t bytes; + void *va; + + if (!obj || !obj->dev || !sgt) + return -EINVAL; + + bytes = sgtable_len(sgt); + if (!bytes) + return -EINVAL; + bytes = PAGE_ALIGN(bytes); + + va = vmap_sg(sgt); + if (IS_ERR(va)) + return PTR_ERR(va); + + flags &= IOVMF_HW_MASK; + flags |= IOVMF_DISCONT; + flags |= IOVMF_MMIO; + flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); + + da = __iommu_vmap(obj, da, sgt, va, bytes, flags); + if (IS_ERR_VALUE(da)) + vunmap_sg(va); + + return da; +} +EXPORT_SYMBOL_GPL(iommu_vmap); + +/** + * iommu_vunmap - release virtual mapping obtained by 'iommu_vmap()' + * @obj: objective iommu + * @da: iommu device virtual address + * + * Free the iommu virtually contiguous memory area starting at + * @da, which was returned by 'iommu_vmap()'. + */ +struct sg_table *iommu_vunmap(struct iommu *obj, u32 da) +{ + struct sg_table *sgt; + /* + * 'sgt' is allocated before 'iommu_vmalloc()' is called. + * Just returns 'sgt' to the caller to free + */ + sgt = unmap_vm_area(obj, da, vunmap_sg, IOVMF_DISCONT | IOVMF_MMIO); + if (!sgt) + dev_dbg(obj->dev, "%s: No sgt\n", __func__); + return sgt; +} +EXPORT_SYMBOL_GPL(iommu_vunmap); + +/** + * iommu_vmalloc - (d)-(p)-(v) address allocator and mapper + * @obj: objective iommu + * @da: contiguous iommu virtual memory + * @bytes: allocation size + * @flags: iovma and page property + * + * Allocate @bytes linearly and creates 1-n-1 mapping and returns + * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set. + */ +u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) +{ + void *va; + struct sg_table *sgt; + + if (!obj || !obj->dev || !bytes) + return -EINVAL; + + bytes = PAGE_ALIGN(bytes); + + va = vmalloc(bytes); + if (!va) + return -ENOMEM; + + sgt = sgtable_alloc(bytes, flags); + if (IS_ERR(sgt)) { + da = PTR_ERR(sgt); + goto err_sgt_alloc; + } + sgtable_fill_vmalloc(sgt, va); + + flags &= IOVMF_HW_MASK; + flags |= IOVMF_DISCONT; + flags |= IOVMF_ALLOC; + flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); + + da = __iommu_vmap(obj, da, sgt, va, bytes, flags); + if (IS_ERR_VALUE(da)) + goto err_iommu_vmap; + + return da; + +err_iommu_vmap: + sgtable_drain_vmalloc(sgt); + sgtable_free(sgt); +err_sgt_alloc: + vfree(va); + return da; +} +EXPORT_SYMBOL_GPL(iommu_vmalloc); + +/** + * iommu_vfree - release memory allocated by 'iommu_vmalloc()' + * @obj: objective iommu + * @da: iommu device virtual address + * + * Frees the iommu virtually continuous memory area starting at + * @da, as obtained from 'iommu_vmalloc()'. + */ +void iommu_vfree(struct iommu *obj, const u32 da) +{ + struct sg_table *sgt; + + sgt = unmap_vm_area(obj, da, vfree, IOVMF_DISCONT | IOVMF_ALLOC); + if (!sgt) + dev_dbg(obj->dev, "%s: No sgt\n", __func__); + sgtable_free(sgt); +} +EXPORT_SYMBOL_GPL(iommu_vfree); + +static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va, + size_t bytes, u32 flags) +{ + struct sg_table *sgt; + + sgt = sgtable_alloc(bytes, flags); + if (IS_ERR(sgt)) + return PTR_ERR(sgt); + + sgtable_fill_kmalloc(sgt, pa, bytes); + + da = map_iommu_region(obj, da, sgt, va, bytes, flags); + if (IS_ERR_VALUE(da)) { + sgtable_drain_kmalloc(sgt); + sgtable_free(sgt); + } + + return da; +} + +/** + * iommu_kmap - (d)-(p)-(v) address mapper + * @obj: objective iommu + * @da: contiguous iommu virtual memory + * @pa: contiguous physical memory + * @flags: iovma and page property + * + * Creates 1-1-1 mapping and returns @da again, which can be + * adjusted if 'IOVMF_DA_ANON' is set. + */ +u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes, + u32 flags) +{ + void *va; + + if (!obj || !obj->dev || !bytes) + return -EINVAL; + + bytes = PAGE_ALIGN(bytes); + + va = ioremap(pa, bytes); + if (!va) + return -ENOMEM; + + flags &= IOVMF_HW_MASK; + flags |= IOVMF_LINEAR; + flags |= IOVMF_MMIO; + flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); + + da = __iommu_kmap(obj, da, pa, va, bytes, flags); + if (IS_ERR_VALUE(da)) + iounmap(va); + + return da; +} +EXPORT_SYMBOL_GPL(iommu_kmap); + +/** + * iommu_kunmap - release virtual mapping obtained by 'iommu_kmap()' + * @obj: objective iommu + * @da: iommu device virtual address + * + * Frees the iommu virtually contiguous memory area starting at + * @da, which was passed to and was returned by'iommu_kmap()'. + */ +void iommu_kunmap(struct iommu *obj, u32 da) +{ + struct sg_table *sgt; + typedef void (*func_t)(const void *); + + sgt = unmap_vm_area(obj, da, (func_t)__iounmap, + IOVMF_LINEAR | IOVMF_MMIO); + if (!sgt) + dev_dbg(obj->dev, "%s: No sgt\n", __func__); + sgtable_free(sgt); +} +EXPORT_SYMBOL_GPL(iommu_kunmap); + +/** + * iommu_kmalloc - (d)-(p)-(v) address allocator and mapper + * @obj: objective iommu + * @da: contiguous iommu virtual memory + * @bytes: bytes for allocation + * @flags: iovma and page property + * + * Allocate @bytes linearly and creates 1-1-1 mapping and returns + * @da again, which might be adjusted if 'IOVMF_DA_ANON' is set. + */ +u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) +{ + void *va; + u32 pa; + + if (!obj || !obj->dev || !bytes) + return -EINVAL; + + bytes = PAGE_ALIGN(bytes); + + va = kmalloc(bytes, GFP_KERNEL | GFP_DMA); + if (!va) + return -ENOMEM; + pa = virt_to_phys(va); + + flags &= IOVMF_HW_MASK; + flags |= IOVMF_LINEAR; + flags |= IOVMF_ALLOC; + flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); + + da = __iommu_kmap(obj, da, pa, va, bytes, flags); + if (IS_ERR_VALUE(da)) + kfree(va); + + return da; +} +EXPORT_SYMBOL_GPL(iommu_kmalloc); + +/** + * iommu_kfree - release virtual mapping obtained by 'iommu_kmalloc()' + * @obj: objective iommu + * @da: iommu device virtual address + * + * Frees the iommu virtually contiguous memory area starting at + * @da, which was passed to and was returned by'iommu_kmalloc()'. + */ +void iommu_kfree(struct iommu *obj, u32 da) +{ + struct sg_table *sgt; + + sgt = unmap_vm_area(obj, da, kfree, IOVMF_LINEAR | IOVMF_ALLOC); + if (!sgt) + dev_dbg(obj->dev, "%s: No sgt\n", __func__); + sgtable_free(sgt); +} +EXPORT_SYMBOL_GPL(iommu_kfree); + + +static int __init iovmm_init(void) +{ + const unsigned long flags = SLAB_HWCACHE_ALIGN; + struct kmem_cache *p; + + p = kmem_cache_create("iovm_area_cache", sizeof(struct iovm_struct), 0, + flags, NULL); + if (!p) + return -ENOMEM; + iovm_area_cachep = p; + + return 0; +} +module_init(iovmm_init); + +static void __exit iovmm_exit(void) +{ + kmem_cache_destroy(iovm_area_cachep); +} +module_exit(iovmm_exit); + +MODULE_DESCRIPTION("omap iommu: simple virtual address space management"); +MODULE_AUTHOR("Hiroshi DOYU "); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3-70-g09d2 From e769421de22422461f0becae0ec6e792ec6f4476 Mon Sep 17 00:00:00 2001 From: Hiroshi DOYU Date: Wed, 28 Jan 2009 21:32:08 +0200 Subject: omap iommu: entries for Kconfig and Makefile Signed-off-by: Hiroshi DOYU --- arch/arm/plat-omap/Kconfig | 3 +++ arch/arm/plat-omap/Makefile | 1 + 2 files changed, 4 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9dd68fafb37..d483b2592ec 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -115,6 +115,9 @@ config OMAP_MBOX_FWK Say Y here if you want to use OMAP Mailbox framework support for DSP, IVA1.0 and IVA2 in OMAP1/2/3. +config OMAP_IOMMU + tristate + choice prompt "System timer" default OMAP_MPU_TIMER diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile index 04a100cfb8e..a8327952395 100644 --- a/arch/arm/plat-omap/Makefile +++ b/arch/arm/plat-omap/Makefile @@ -13,6 +13,7 @@ obj- := obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o +obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o obj-$(CONFIG_CPU_FREQ) += cpu-omap.o obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o -- cgit v1.2.3-70-g09d2 From bed8b97d88b56fdad5677585262e20c5f0a1a8e2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:08:33 -0700 Subject: ARM: OMAP2/3: Remove OMAP2_32KSYNCT_BASE Use processor specific defines instead. As an extra bonus, this patch fixes the problem of CONFIG_DEBUG_SPINLOCK calling sched_clock before we have things initialized: http://patchwork.kernel.org/patch/15810/ Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sram242x.S | 4 +- arch/arm/mach-omap2/sram243x.S | 4 +- arch/arm/plat-omap/common.c | 69 +++++++++++++++++++++++++----- arch/arm/plat-omap/include/mach/omap24xx.h | 2 - arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 5 files changed, 62 insertions(+), 18 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index af4bd349022..cbb89304248 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -128,7 +128,7 @@ omap242x_sdi_prcm_voltctrl: prcm_mask_val: .word 0xFFFF3FFC omap242x_sdi_timer_32ksynct_cr: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ENTRY(omap242x_sram_ddr_init_sz) .word . - omap242x_sram_ddr_init @@ -224,7 +224,7 @@ omap242x_srs_prcm_voltctrl: ddr_prcm_mask_val: .word 0xFFFF3FFC omap242x_srs_timer_32ksynct: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ENTRY(omap242x_sram_reprogram_sdrc_sz) .word . - omap242x_sram_reprogram_sdrc diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index 84363e269e8..054b0f357ac 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -128,7 +128,7 @@ omap243x_sdi_prcm_voltctrl: prcm_mask_val: .word 0xFFFF3FFC omap243x_sdi_timer_32ksynct_cr: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_ddr_init_sz) .word . - omap243x_sram_ddr_init @@ -224,7 +224,7 @@ omap243x_srs_prcm_voltctrl: ddr_prcm_mask_val: .word 0xFFFF3FFC omap243x_srs_timer_32ksynct: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_reprogram_sdrc_sz) .word . - omap243x_sram_reprogram_sdrc diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 433021f3d7c..e1add789835 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -175,25 +175,61 @@ console_initcall(omap_add_serial_console); * but systems won't necessarily want to spend resources that way. */ -#if defined(CONFIG_ARCH_OMAP16XX) -#define TIMER_32K_SYNCHRONIZED 0xfffbc410 -#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -#define TIMER_32K_SYNCHRONIZED (OMAP2_32KSYNCT_BASE + 0x10) -#endif +#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 -#ifdef TIMER_32K_SYNCHRONIZED +#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) #include -static cycle_t omap_32k_read(struct clocksource *cs) +#ifdef CONFIG_ARCH_OMAP16XX +static cycle_t omap16xx_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED); +} +#else +#define omap16xx_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP2420 +static cycle_t omap2420_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10); +} +#else +#define omap2420_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP2430 +static cycle_t omap2430_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10); +} +#else +#define omap2430_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP34XX +static cycle_t omap34xx_32k_read(struct clocksource *cs) { - return omap_readl(TIMER_32K_SYNCHRONIZED); + return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10); +} +#else +#define omap34xx_32k_read NULL +#endif + +/* + * Kernel assumes that sched_clock can be called early but may not have + * things ready yet. + */ +static cycle_t omap_32k_read_dummy(struct clocksource *cs) +{ + return 0; } static struct clocksource clocksource_32k = { .name = "32k_counter", .rating = 250, - .read = omap_32k_read, + .read = omap_32k_read_dummy, .mask = CLOCKSOURCE_MASK(32), .shift = 10, .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -207,7 +243,7 @@ unsigned long long sched_clock(void) { unsigned long long ret; - ret = (unsigned long long)omap_32k_read(&clocksource_32k); + ret = (unsigned long long)clocksource_32k.read(&clocksource_32k); ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift; return ret; } @@ -220,6 +256,17 @@ static int __init omap_init_clocksource_32k(void) if (cpu_is_omap16xx() || cpu_class_is_omap2()) { struct clk *sync_32k_ick; + if (cpu_is_omap16xx()) + clocksource_32k.read = omap16xx_32k_read; + else if (cpu_is_omap2420()) + clocksource_32k.read = omap2420_32k_read; + else if (cpu_is_omap2430()) + clocksource_32k.read = omap2430_32k_read; + else if (cpu_is_omap34xx()) + clocksource_32k.read = omap34xx_32k_read; + else + return -ENODEV; + sync_32k_ick = clk_get(NULL, "omap_32ksync_ick"); if (sync_32k_ick) clk_enable(sync_32k_ick); @@ -234,7 +281,7 @@ static int __init omap_init_clocksource_32k(void) } arch_initcall(omap_init_clocksource_32k); -#endif /* TIMER_32K_SYNCHRONIZED */ +#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */ /* Global address base setup code */ diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 24335d4932f..4202cf457e2 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -87,7 +87,6 @@ #if defined(CONFIG_ARCH_OMAP2420) -#define OMAP2_32KSYNCT_BASE OMAP2420_32KSYNCT_BASE #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE #define OMAP2_PRM_BASE OMAP2420_PRM_BASE @@ -95,7 +94,6 @@ #elif defined(CONFIG_ARCH_OMAP2430) -#define OMAP2_32KSYNCT_BASE OMAP2430_32KSYNCT_BASE #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE #define OMAP2_PRM_BASE OMAP2430_PRM_BASE diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index ab640151d3e..581d9103c35 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -85,7 +85,6 @@ #if defined(CONFIG_ARCH_OMAP3430) -#define OMAP2_32KSYNCT_BASE OMAP3430_32KSYNCT_BASE #define OMAP2_CM_BASE OMAP3430_CM_BASE #define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) -- cgit v1.2.3-70-g09d2 From 23b7dd3166fcd88d82ada7e13478fbe4c2231ddf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:08:34 -0700 Subject: ARM: OMAP2/3: Remove OMAP_PRM_REGADDR and OMAP2_PRM_BASE Remove OMAP_PRM_REGADDR and use processor specific defines instead. Also fold in a patch from Kevin Hilman to add _OFFSET #defines for the PRCM registers to be used with the prm_[read|write]_* macros. These are used extensively in the forthcoming OMAP PM support. Also remove now unused OMAP2_PRM_BASE. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock.c | 4 +- arch/arm/mach-omap2/clock24xx.c | 21 +-- arch/arm/mach-omap2/clock24xx.h | 9 ++ arch/arm/mach-omap2/cm.h | 1 + arch/arm/mach-omap2/prm.h | 205 ++++++++++++++++++----------- arch/arm/mach-omap2/sdrc2xxx.c | 5 +- arch/arm/mach-omap2/sram242x.S | 6 +- arch/arm/mach-omap2/sram243x.S | 6 +- arch/arm/plat-omap/include/mach/omap24xx.h | 2 - arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 10 files changed, 160 insertions(+), 100 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 4247a153441..dd37483f3d1 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -91,9 +91,9 @@ static void _omap2xxx_clk_commit(struct clk *clk) return; prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD, - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); + OMAP2_PRCM_CLKCFG_CTRL_OFFSET); /* OCP barrier */ - prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); + prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP2_PRCM_CLKCFG_CTRL_OFFSET); } /* diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index e4cef333e29..c442fe9f998 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -233,6 +233,8 @@ static struct prcm_config *curr_prcm_set; static struct clk *vclk; static struct clk *sclk; +static void __iomem *prcm_clksrc_ctrl; + /*------------------------------------------------------------------------- * Omap24xx specific clock functions *-------------------------------------------------------------------------*/ @@ -269,10 +271,9 @@ static int omap2_enable_osc_ck(struct clk *clk) { u32 pcc; - pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + pcc = __raw_readl(prcm_clksrc_ctrl); - __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, - OMAP24XX_PRCM_CLKSRC_CTRL); + __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); return 0; } @@ -281,10 +282,9 @@ static void omap2_disable_osc_ck(struct clk *clk) { u32 pcc; - pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + pcc = __raw_readl(prcm_clksrc_ctrl); - __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, - OMAP24XX_PRCM_CLKSRC_CTRL); + __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); } static const struct clkops clkops_oscck = { @@ -654,7 +654,7 @@ static u32 omap2_get_sysclkdiv(void) { u32 div; - div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + div = __raw_readl(prcm_clksrc_ctrl); div &= OMAP_SYSCLKDIV_MASK; div >>= OMAP_SYSCLKDIV_SHIFT; @@ -714,10 +714,13 @@ int __init omap2_clk_init(void) struct omap_clk *c; u32 clkrate; - if (cpu_is_omap242x()) + if (cpu_is_omap242x()) { + prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL; cpu_mask = RATE_IN_242X; - else if (cpu_is_omap2430()) + } else if (cpu_is_omap2430()) { + prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL; cpu_mask = RATE_IN_243X; + } clk_init(&omap2_clk_functions); diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 88c5acb40fc..f0e4480b4eb 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -24,6 +24,15 @@ #include "cm-regbits-24xx.h" #include "sdrc.h" +/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ +#ifdef CONFIG_ARCH_OMAP2420 +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL +#else +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL +#endif + static unsigned long omap2_table_mpu_recalc(struct clk *clk); static int omap2_select_table_rate(struct clk *clk, unsigned long rate); static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate); diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index 65fdf78c91e..efc082a1d27 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -38,6 +38,7 @@ #define OMAP3430_CM_SYSCONFIG OMAP_CM_REGADDR(OCP_MOD, 0x0010) #define OMAP3430_CM_POLCTRL OMAP_CM_REGADDR(OCP_MOD, 0x009c) +#define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070 #define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070) /* diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 826d326b806..7c8e0c42b05 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -16,17 +16,12 @@ #include "prcm-common.h" -#ifndef __ASSEMBLER__ -#define OMAP_PRM_REGADDR(module, reg) \ - IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg)) -#else #define OMAP2420_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg)) #define OMAP2430_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg)) #define OMAP34XX_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg)) -#endif /* * Architecture-specific global PRM registers @@ -38,80 +33,132 @@ * */ -/* Global 24xx registers in GR_MOD (Same as OCP_MOD for 24xx) */ -#define OMAP24XX_PRCM_VOLTCTRL_OFFSET 0x0050 -#define OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET 0x0080 - -/* 242x GR_MOD registers, use these only for assembly code */ -#define OMAP242X_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_VOLTCTRL_OFFSET) -#define OMAP242X_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET) - -/* 243x GR_MOD registers, use these only for assembly code */ -#define OMAP243X_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_VOLTCTRL_OFFSET) -#define OMAP243X_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET) - -/* These will disappear */ -#define OMAP24XX_PRCM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0000) -#define OMAP24XX_PRCM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0010) - -#define OMAP24XX_PRCM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018) -#define OMAP24XX_PRCM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c) - -#define OMAP24XX_PRCM_VOLTST OMAP_PRM_REGADDR(OCP_MOD, 0x0054) -#define OMAP24XX_PRCM_CLKSRC_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0060) -#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0070) -#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0078) -#define OMAP24XX_PRCM_CLKCFG_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0080) -#define OMAP24XX_PRCM_CLKCFG_STATUS OMAP_PRM_REGADDR(OCP_MOD, 0x0084) -#define OMAP24XX_PRCM_VOLTSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0090) -#define OMAP24XX_PRCM_CLKSSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0094) -#define OMAP24XX_PRCM_POLCTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0098) - -#define OMAP3430_PRM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0004) -#define OMAP3430_PRM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0014) - -#define OMAP3430_PRM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018) -#define OMAP3430_PRM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c) - - -#define OMAP3430_PRM_VC_SMPS_SA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020) -#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024) -#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028) -#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c) -#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030) -#define OMAP3430_PRM_VC_CH_CONF OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034) -#define OMAP3430_PRM_VC_I2C_CFG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038) -#define OMAP3430_PRM_VC_BYPASS_VAL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c) -#define OMAP3430_PRM_RSTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050) -#define OMAP3430_PRM_RSTTIME OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054) -#define OMAP3430_PRM_RSTST OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058) -#define OMAP3430_PRM_VOLTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060) -#define OMAP3430_PRM_SRAM_PCHARGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064) -#define OMAP3430_PRM_CLKSRC_CTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070) -#define OMAP3430_PRM_VOLTSETUP1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090) -#define OMAP3430_PRM_VOLTOFFSET OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094) -#define OMAP3430_PRM_CLKSETUP OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098) -#define OMAP3430_PRM_POLCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c) -#define OMAP3430_PRM_VOLTSETUP2 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0) -#define OMAP3430_PRM_VP1_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0) -#define OMAP3430_PRM_VP1_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4) -#define OMAP3430_PRM_VP1_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8) -#define OMAP3430_PRM_VP1_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc) -#define OMAP3430_PRM_VP1_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0) -#define OMAP3430_PRM_VP1_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4) -#define OMAP3430_PRM_VP2_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0) -#define OMAP3430_PRM_VP2_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4) -#define OMAP3430_PRM_VP2_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8) -#define OMAP3430_PRM_VP2_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc) -#define OMAP3430_PRM_VP2_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0) -#define OMAP3430_PRM_VP2_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4) - -#define OMAP3430_PRM_CLKSEL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040) -#define OMAP3430_PRM_CLKOUT_CTRL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070) +#define OMAP2_PRCM_REVISION_OFFSET 0x0000 +#define OMAP2420_PRCM_REVISION OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000) +#define OMAP2_PRCM_SYSCONFIG_OFFSET 0x0010 +#define OMAP2420_PRCM_SYSCONFIG OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010) + +#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET 0x0018 +#define OMAP2420_PRCM_IRQSTATUS_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET 0x001c +#define OMAP2420_PRCM_IRQENABLE_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c) + +#define OMAP2_PRCM_VOLTCTRL_OFFSET 0x0050 +#define OMAP2420_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050) +#define OMAP2_PRCM_VOLTST_OFFSET 0x0054 +#define OMAP2420_PRCM_VOLTST OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054) +#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET 0x0060 +#define OMAP2420_PRCM_CLKSRC_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060) +#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET 0x0070 +#define OMAP2420_PRCM_CLKOUT_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070) +#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET 0x0078 +#define OMAP2420_PRCM_CLKEMUL_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078) +#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET 0x0080 +#define OMAP2420_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080) +#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET 0x0084 +#define OMAP2420_PRCM_CLKCFG_STATUS OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084) +#define OMAP2_PRCM_VOLTSETUP_OFFSET 0x0090 +#define OMAP2420_PRCM_VOLTSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090) +#define OMAP2_PRCM_CLKSSETUP_OFFSET 0x0094 +#define OMAP2420_PRCM_CLKSSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094) +#define OMAP2_PRCM_POLCTRL_OFFSET 0x0098 +#define OMAP2420_PRCM_POLCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098) + +#define OMAP2430_PRCM_REVISION OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000) +#define OMAP2430_PRCM_SYSCONFIG OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010) + +#define OMAP2430_PRCM_IRQSTATUS_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP2430_PRCM_IRQENABLE_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c) + +#define OMAP2430_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050) +#define OMAP2430_PRCM_VOLTST OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054) +#define OMAP2430_PRCM_CLKSRC_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060) +#define OMAP2430_PRCM_CLKOUT_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070) +#define OMAP2430_PRCM_CLKEMUL_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078) +#define OMAP2430_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080) +#define OMAP2430_PRCM_CLKCFG_STATUS OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084) +#define OMAP2430_PRCM_VOLTSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090) +#define OMAP2430_PRCM_CLKSSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094) +#define OMAP2430_PRCM_POLCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098) + +#define OMAP3_PRM_REVISION_OFFSET 0x0004 +#define OMAP3430_PRM_REVISION OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004) +#define OMAP3_PRM_SYSCONFIG_OFFSET 0x0014 +#define OMAP3430_PRM_SYSCONFIG OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014) + +#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET 0x0018 +#define OMAP3430_PRM_IRQSTATUS_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP3_PRM_IRQENABLE_MPU_OFFSET 0x001c +#define OMAP3430_PRM_IRQENABLE_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c) + + +#define OMAP3_PRM_VC_SMPS_SA_OFFSET 0x0020 +#define OMAP3430_PRM_VC_SMPS_SA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020) +#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET 0x0024 +#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024) +#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET 0x0028 +#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028) +#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET 0x002c +#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c) +#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET 0x0030 +#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030) +#define OMAP3_PRM_VC_CH_CONF_OFFSET 0x0034 +#define OMAP3430_PRM_VC_CH_CONF OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034) +#define OMAP3_PRM_VC_I2C_CFG_OFFSET 0x0038 +#define OMAP3430_PRM_VC_I2C_CFG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038) +#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET 0x003c +#define OMAP3430_PRM_VC_BYPASS_VAL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c) +#define OMAP3_PRM_RSTCTRL_OFFSET 0x0050 +#define OMAP3430_PRM_RSTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050) +#define OMAP3_PRM_RSTTIME_OFFSET 0x0054 +#define OMAP3430_PRM_RSTTIME OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054) +#define OMAP3_PRM_RSTST_OFFSET 0x0058 +#define OMAP3430_PRM_RSTST OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058) +#define OMAP3_PRM_VOLTCTRL_OFFSET 0x0060 +#define OMAP3430_PRM_VOLTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060) +#define OMAP3_PRM_SRAM_PCHARGE_OFFSET 0x0064 +#define OMAP3430_PRM_SRAM_PCHARGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064) +#define OMAP3_PRM_CLKSRC_CTRL_OFFSET 0x0070 +#define OMAP3430_PRM_CLKSRC_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070) +#define OMAP3_PRM_VOLTSETUP1_OFFSET 0x0090 +#define OMAP3430_PRM_VOLTSETUP1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090) +#define OMAP3_PRM_VOLTOFFSET_OFFSET 0x0094 +#define OMAP3430_PRM_VOLTOFFSET OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094) +#define OMAP3_PRM_CLKSETUP_OFFSET 0x0098 +#define OMAP3430_PRM_CLKSETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098) +#define OMAP3_PRM_POLCTRL_OFFSET 0x009c +#define OMAP3430_PRM_POLCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c) +#define OMAP3_PRM_VOLTSETUP2_OFFSET 0x00a0 +#define OMAP3430_PRM_VOLTSETUP2 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0) +#define OMAP3_PRM_VP1_CONFIG_OFFSET 0x00b0 +#define OMAP3430_PRM_VP1_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0) +#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET 0x00b4 +#define OMAP3430_PRM_VP1_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4) +#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET 0x00b8 +#define OMAP3430_PRM_VP1_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8) +#define OMAP3_PRM_VP1_VLIMITTO_OFFSET 0x00bc +#define OMAP3430_PRM_VP1_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc) +#define OMAP3_PRM_VP1_VOLTAGE_OFFSET 0x00c0 +#define OMAP3430_PRM_VP1_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0) +#define OMAP3_PRM_VP1_STATUS_OFFSET 0x00c4 +#define OMAP3430_PRM_VP1_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4) +#define OMAP3_PRM_VP2_CONFIG_OFFSET 0x00d0 +#define OMAP3430_PRM_VP2_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0) +#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET 0x00d4 +#define OMAP3430_PRM_VP2_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4) +#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET 0x00d8 +#define OMAP3430_PRM_VP2_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8) +#define OMAP3_PRM_VP2_VLIMITTO_OFFSET 0x00dc +#define OMAP3430_PRM_VP2_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc) +#define OMAP3_PRM_VP2_VOLTAGE_OFFSET 0x00e0 +#define OMAP3430_PRM_VP2_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0) +#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4 +#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4) + +#define OMAP3_PRM_CLKSEL_OFFSET 0x0040 +#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040) +#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070 +#define OMAP3430_PRM_CLKOUT_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070) /* * Module specific PRM registers from PRM_BASE + domain offset diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 0afdad5ae9f..feaec7eaf6b 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -99,7 +99,10 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u32 force) m_type = omap2xxx_sdrc_get_type(); local_irq_save(flags); - __raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP); + if (cpu_is_omap2420()) + __raw_writel(0xffff, OMAP2420_PRCM_VOLTSETUP); + else + __raw_writel(0xffff, OMAP2430_PRCM_VOLTSETUP); omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type); curr_perf_level = level; local_irq_restore(flags); diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index cbb89304248..bb299851116 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -124,7 +124,7 @@ omap242x_sdi_cm_clksel2_pll: omap242x_sdi_sdrc_dlla_ctrl: .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap242x_sdi_prcm_voltctrl: - .word OMAP242X_PRCM_VOLTCTRL + .word OMAP2420_PRCM_VOLTCTRL prcm_mask_val: .word 0xFFFF3FFC omap242x_sdi_timer_32ksynct_cr: @@ -220,7 +220,7 @@ omap242x_srs_sdrc_dlla_ctrl: omap242x_srs_sdrc_rfr_ctrl: .word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap242x_srs_prcm_voltctrl: - .word OMAP242X_PRCM_VOLTCTRL + .word OMAP2420_PRCM_VOLTCTRL ddr_prcm_mask_val: .word 0xFFFF3FFC omap242x_srs_timer_32ksynct: @@ -305,7 +305,7 @@ wait_dll_lock: ldmfd sp!, {r0-r12, pc} @ restore regs and return omap242x_ssp_set_config: - .word OMAP242X_PRCM_CLKCFG_CTRL + .word OMAP2420_PRCM_CLKCFG_CTRL omap242x_ssp_pll_ctl: .word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKEN) omap242x_ssp_pll_stat: diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index 054b0f357ac..9955abcaeb3 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -124,7 +124,7 @@ omap243x_sdi_cm_clksel2_pll: omap243x_sdi_sdrc_dlla_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap243x_sdi_prcm_voltctrl: - .word OMAP243X_PRCM_VOLTCTRL + .word OMAP2430_PRCM_VOLTCTRL prcm_mask_val: .word 0xFFFF3FFC omap243x_sdi_timer_32ksynct_cr: @@ -220,7 +220,7 @@ omap243x_srs_sdrc_dlla_ctrl: omap243x_srs_sdrc_rfr_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap243x_srs_prcm_voltctrl: - .word OMAP243X_PRCM_VOLTCTRL + .word OMAP2430_PRCM_VOLTCTRL ddr_prcm_mask_val: .word 0xFFFF3FFC omap243x_srs_timer_32ksynct: @@ -305,7 +305,7 @@ wait_dll_lock: ldmfd sp!, {r0-r12, pc} @ restore regs and return omap243x_ssp_set_config: - .word OMAP243X_PRCM_CLKCFG_CTRL + .word OMAP2430_PRCM_CLKCFG_CTRL omap243x_ssp_pll_ctl: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN) omap243x_ssp_pll_stat: diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 4202cf457e2..10a6413c73e 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -89,14 +89,12 @@ #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE -#define OMAP2_PRM_BASE OMAP2420_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #elif defined(CONFIG_ARCH_OMAP2430) #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE -#define OMAP2_PRM_BASE OMAP2430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #endif diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 581d9103c35..42330644420 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -86,7 +86,6 @@ #if defined(CONFIG_ARCH_OMAP3430) #define OMAP2_CM_BASE OMAP3430_CM_BASE -#define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif -- cgit v1.2.3-70-g09d2 From 8a424bb3c92b2df17008dfa17ac55b602290267b Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:08:35 -0700 Subject: ARM: OMAP2/3: Move define of OMAP2_VA_IC_BASE to be local to entry-macro.S Move define of OMAP2_VA_IC_BASE to be local to entry-macro.S Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/entry-macro.S | 9 ++++++--- arch/arm/plat-omap/include/mach/omap24xx.h | 2 -- arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S index 2276f89671d..33256a0e9a2 100644 --- a/arch/arm/plat-omap/include/mach/entry-macro.S +++ b/arch/arm/plat-omap/include/mach/entry-macro.S @@ -58,11 +58,14 @@ #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -#if defined(CONFIG_ARCH_OMAP24XX) #include -#endif -#if defined(CONFIG_ARCH_OMAP34XX) #include + +/* REVISIT: This should be set dynamically if CONFIG_MULTI_OMAP2 is selected */ +#if defined(CONFIG_ARCH_OMAP2420) || defined(CONFIG_ARCH_OMAP2430) +#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) +#elif defined(CONFIG_ARCH_OMAP34XX) +#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* Active interrupt offset */ diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 10a6413c73e..4ce9b6a60a5 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -89,13 +89,11 @@ #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #elif defined(CONFIG_ARCH_OMAP2430) #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #endif diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 42330644420..36c99ca0825 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -86,7 +86,6 @@ #if defined(CONFIG_ARCH_OMAP3430) #define OMAP2_CM_BASE OMAP3430_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif -- cgit v1.2.3-70-g09d2 From c28150ee688df25861bb8eeff445ed95baf29321 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:08:35 -0700 Subject: ARM: OMAP2/3: Remove OMAP2_PRCM_BASE It's currently unused, and processor specific defines should be used instead. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/omap24xx.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 4ce9b6a60a5..60f83244924 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -87,12 +87,10 @@ #if defined(CONFIG_ARCH_OMAP2420) -#define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE #elif defined(CONFIG_ARCH_OMAP2430) -#define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE #endif -- cgit v1.2.3-70-g09d2 From eb0d0ee1c256492edd56e55c2704bbb1fe1d8bc0 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:08:36 -0700 Subject: ARM: OMAP2/3: Remove OMAP_CM_REGADDR Processor specific macros should be used instead. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock24xx.h | 2 ++ arch/arm/mach-omap2/clock34xx.h | 2 ++ arch/arm/mach-omap2/cm.h | 5 ----- arch/arm/plat-omap/include/mach/omap24xx.h | 10 ---------- arch/arm/plat-omap/include/mach/omap34xx.h | 6 ------ 5 files changed, 4 insertions(+), 21 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index f0e4480b4eb..458f00cdcbe 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -26,9 +26,11 @@ /* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ #ifdef CONFIG_ARCH_OMAP2420 +#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR #define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL #define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL #else +#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR #define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL #define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL #endif diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 017a30e9aa1..496f0e9caeb 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -27,6 +27,8 @@ #include "prm.h" #include "prm-regbits-34xx.h" +#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR + static unsigned long omap3_dpll_recalc(struct clk *clk); static unsigned long omap3_clkoutx2_recalc(struct clk *clk); static void omap3_dpll_allow_idle(struct clk *clk); diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index efc082a1d27..1d3c93bf86d 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -16,17 +16,12 @@ #include "prcm-common.h" -#ifndef __ASSEMBLER__ -#define OMAP_CM_REGADDR(module, reg) \ - IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg)) -#else #define OMAP2420_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg)) #define OMAP2430_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg)) #define OMAP34XX_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg)) -#endif /* * Architecture-specific global CM registers diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 60f83244924..696edfc145a 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -85,15 +85,5 @@ #define OMAP24XX_SEC_AES_BASE (OMAP24XX_SEC_BASE + 0x6000) #define OMAP24XX_SEC_PKA_BASE (OMAP24XX_SEC_BASE + 0x8000) -#if defined(CONFIG_ARCH_OMAP2420) - -#define OMAP2_CM_BASE OMAP2420_CM_BASE - -#elif defined(CONFIG_ARCH_OMAP2430) - -#define OMAP2_CM_BASE OMAP2430_CM_BASE - -#endif - #endif /* __ASM_ARCH_OMAP24XX_H */ diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 36c99ca0825..cc2573330dc 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -83,12 +83,6 @@ #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) -#if defined(CONFIG_ARCH_OMAP3430) - -#define OMAP2_CM_BASE OMAP3430_CM_BASE - -#endif - #define OMAP34XX_DSP_BASE 0x58000000 #define OMAP34XX_DSP_MEM_BASE (OMAP34XX_DSP_BASE + 0x0) #define OMAP34XX_DSP_IPI_BASE (OMAP34XX_DSP_BASE + 0x1000000) -- cgit v1.2.3-70-g09d2 From aea2a5b03c6476175c6f498a72cfbe73f7f47528 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:08:36 -0700 Subject: ARM: OMAP: Remove unwanted type casts and fix the compiler warning. This patch fixes the compiler warning "assignment from incompatible pointer type" in dmtimer.c and removes the tye casts. These warnings were suppressed by type catsing. The proposed fix was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 55bb9963129..ee206122f50 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -214,7 +214,7 @@ static const char *omap2_dm_source_names[] __initdata = { NULL }; -static struct clk **omap2_dm_source_clocks[3]; +static struct clk *omap2_dm_source_clocks[3]; static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers); #elif defined(CONFIG_ARCH_OMAP3) @@ -247,7 +247,7 @@ static const char *omap3_dm_source_names[] __initdata = { NULL }; -static struct clk **omap3_dm_source_clocks[2]; +static struct clk *omap3_dm_source_clocks[2]; static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers); #else @@ -257,7 +257,7 @@ static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers); #endif static struct omap_dm_timer *dm_timers; -static char **dm_source_names; +static const char **dm_source_names; static struct clk **dm_source_clocks; static spinlock_t dm_timer_lock; @@ -705,12 +705,12 @@ int __init omap_dm_timer_init(void) dm_timers = omap1_dm_timers; else if (cpu_is_omap24xx()) { dm_timers = omap2_dm_timers; - dm_source_names = (char **)omap2_dm_source_names; - dm_source_clocks = (struct clk **)omap2_dm_source_clocks; + dm_source_names = omap2_dm_source_names; + dm_source_clocks = omap2_dm_source_clocks; } else if (cpu_is_omap34xx()) { dm_timers = omap3_dm_timers; - dm_source_names = (char **)omap3_dm_source_names; - dm_source_clocks = (struct clk **)omap3_dm_source_clocks; + dm_source_names = omap3_dm_source_names; + dm_source_clocks = omap3_dm_source_clocks; } if (cpu_class_is_omap2()) -- cgit v1.2.3-70-g09d2 From af5703f2beb490fc700a30d0b87e84da0cf42086 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:08:37 -0700 Subject: ARM: OMAP: Remove useless omap_sram_error function. This patch removes fixes omap_sram_error() function and replace the error paths with BUG_ON. The proposed fix was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/sram.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index fa5297d643d..e1493d83a7c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -242,20 +242,13 @@ void * omap_sram_push(void * start, unsigned long size) return (void *)omap_sram_ceil; } -static void omap_sram_error(void) -{ - panic("Uninitialized SRAM function\n"); -} - #ifdef CONFIG_ARCH_OMAP1 static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl); void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) { - if (!_omap_sram_reprogram_clock) - omap_sram_error(); - + BUG_ON(!_omap_sram_reprogram_clock); _omap_sram_reprogram_clock(dpllctl, ckctl); } @@ -280,9 +273,7 @@ static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, u32 base_cs, u32 force_unlock) { - if (!_omap2_sram_ddr_init) - omap_sram_error(); - + BUG_ON(!_omap2_sram_ddr_init); _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl, base_cs, force_unlock); } @@ -292,9 +283,7 @@ static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val, void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type) { - if (!_omap2_sram_reprogram_sdrc) - omap_sram_error(); - + BUG_ON(!_omap2_sram_reprogram_sdrc); _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type); } @@ -302,9 +291,7 @@ static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass) { - if (!_omap2_set_prcm) - omap_sram_error(); - + BUG_ON(!_omap2_set_prcm); return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass); } #endif @@ -360,9 +347,7 @@ static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, u32 sdrc_actim_ctrlb, u32 m2) { - if (!_omap3_sram_configure_core_dpll) - omap_sram_error(); - + BUG_ON(!_omap3_sram_configure_core_dpll); return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, sdrc_actim_ctrla, sdrc_actim_ctrlb, m2); -- cgit v1.2.3-70-g09d2 From 00aeeffffadab39dcbd8d2360a1f2dc4469f4f1a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:08:37 -0700 Subject: ARM: OMAP: Remove unnecessary omap2_globals. This patch removes unnecessary omap2_globals and pass the global structures directly as function argument. The proposed cleanup was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/common.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index e1add789835..70b68ef8320 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -287,9 +287,7 @@ arch_initcall(omap_init_clocksource_32k); #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -static struct omap_globals *omap2_globals; - -static void __init __omap2_set_globals(void) +static void __init __omap2_set_globals(struct omap_globals *omap2_globals) { omap2_set_globals_tap(omap2_globals); omap2_set_globals_sdrc(omap2_globals); @@ -313,8 +311,7 @@ static struct omap_globals omap242x_globals = { void __init omap2_set_globals_242x(void) { - omap2_globals = &omap242x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap242x_globals); } #endif @@ -332,8 +329,7 @@ static struct omap_globals omap243x_globals = { void __init omap2_set_globals_243x(void) { - omap2_globals = &omap243x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap243x_globals); } #endif @@ -351,8 +347,7 @@ static struct omap_globals omap343x_globals = { void __init omap2_set_globals_343x(void) { - omap2_globals = &omap343x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap343x_globals); } #endif -- cgit v1.2.3-70-g09d2 From e85c205ac1427f2405021a36f083280ff0d0a35e Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Mon, 25 May 2009 11:08:41 -0700 Subject: ARM: OMAP: Increase VMALLOC_END to allow 256MB RAM This increases VMALLOC_END to 0x18000000, making room for 256MB RAM with the default 128MB vmalloc region. Note that after this patch there's no longer a hole between vmalloc space and the beginning of IO space on omap2 as the first virtual mapping starts at 0xd8000000. Also fold in a related change from Paul Walmsley to change the OMAP2_SRAM addresses accordingly. Signed-off-by: Mans Rullgard Signed-off-by: Paul Walmsley Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/vmalloc.h | 2 +- arch/arm/plat-omap/sram.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/vmalloc.h b/arch/arm/plat-omap/include/mach/vmalloc.h index dc104cd9619..b97dfafeebd 100644 --- a/arch/arm/plat-omap/include/mach/vmalloc.h +++ b/arch/arm/plat-omap/include/mach/vmalloc.h @@ -17,5 +17,5 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#define VMALLOC_END (PAGE_OFFSET + 0x10000000) +#define VMALLOC_END (PAGE_OFFSET + 0x18000000) diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index e1493d83a7c..102c9f71a3c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -38,8 +38,8 @@ #define OMAP1_SRAM_VA VMALLOC_END #define OMAP2_SRAM_PA 0x40200000 #define OMAP2_SRAM_PUB_PA 0x4020f800 -#define OMAP2_SRAM_VA VMALLOC_END -#define OMAP2_SRAM_PUB_VA (VMALLOC_END + 0x800) +#define OMAP2_SRAM_VA 0xe3000000 +#define OMAP2_SRAM_PUB_VA (OMAP2_SRAM_VA + 0x800) #define OMAP3_SRAM_PA 0x40200000 #define OMAP3_SRAM_VA 0xd7000000 #define OMAP3_SRAM_PUB_PA 0x40208000 -- cgit v1.2.3-70-g09d2 From d6d834b010908380c9054d8ad339a902833a3bab Mon Sep 17 00:00:00 2001 From: Eero Nurkkala Date: Mon, 25 May 2009 11:08:42 -0700 Subject: ARM: OMAP: McBSP: Fix legacy interrupts to clear their status If XSYNCERR or RSYNCERR interrupts are enabled, they are never cleared causing the IRQ handler to be continuously called. This patch clears the IRQs in question in the event they are enabled and taken. Signed-off-by: Eero Nurkkala Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/mcbsp.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 28b0a824b8c..efa0e0111f3 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -91,11 +91,20 @@ static void omap_mcbsp_dump_reg(u8 id) static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) { struct omap_mcbsp *mcbsp_tx = dev_id; + u16 irqst_spcr2; - dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2)); + irqst_spcr2 = OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2); + dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2); - complete(&mcbsp_tx->tx_irq_completion); + if (irqst_spcr2 & XSYNC_ERR) { + dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n", + irqst_spcr2); + /* Writing zero to XSYNC_ERR clears the IRQ */ + OMAP_MCBSP_WRITE(mcbsp_tx->io_base, SPCR2, + irqst_spcr2 & ~(XSYNC_ERR)); + } else { + complete(&mcbsp_tx->tx_irq_completion); + } return IRQ_HANDLED; } @@ -103,11 +112,20 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) { struct omap_mcbsp *mcbsp_rx = dev_id; + u16 irqst_spcr1; - dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", - OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2)); + irqst_spcr1 = OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR1); + dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1); - complete(&mcbsp_rx->rx_irq_completion); + if (irqst_spcr1 & RSYNC_ERR) { + dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n", + irqst_spcr1); + /* Writing zero to RSYNC_ERR clears the IRQ */ + OMAP_MCBSP_WRITE(mcbsp_rx->io_base, SPCR1, + irqst_spcr1 & ~(RSYNC_ERR)); + } else { + complete(&mcbsp_rx->tx_irq_completion); + } return IRQ_HANDLED; } -- cgit v1.2.3-70-g09d2 From ddf25dfe3a744d4e11a73e1508121f74267dda68 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Mon, 25 May 2009 11:08:43 -0700 Subject: ARM: OMAP: Update contact address of I2C registration helper This email address is going to expire soon so update it. Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a303071d5e3..8b848391f0c 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -5,7 +5,7 @@ * * Copyright (C) 2007 Nokia Corporation. * - * Contact: Jarkko Nikula + * Contact: Jarkko Nikula * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v1.2.3-70-g09d2 From a4ab0d836bbdbbfdb892135a92b339107530b710 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:26:41 -0700 Subject: ARM: OMAP2/3: Remove OMAP2_32KSYNCT_BASE Use processor specific defines instead. As an extra bonus, this patch fixes the problem of CONFIG_DEBUG_SPINLOCK calling sched_clock before we have things initialized: http://patchwork.kernel.org/patch/15810/ Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sram242x.S | 4 +- arch/arm/mach-omap2/sram243x.S | 4 +- arch/arm/plat-omap/common.c | 69 +++++++++++++++++++++++++----- arch/arm/plat-omap/include/mach/omap24xx.h | 2 - arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 5 files changed, 62 insertions(+), 18 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index af4bd349022..cbb89304248 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -128,7 +128,7 @@ omap242x_sdi_prcm_voltctrl: prcm_mask_val: .word 0xFFFF3FFC omap242x_sdi_timer_32ksynct_cr: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ENTRY(omap242x_sram_ddr_init_sz) .word . - omap242x_sram_ddr_init @@ -224,7 +224,7 @@ omap242x_srs_prcm_voltctrl: ddr_prcm_mask_val: .word 0xFFFF3FFC omap242x_srs_timer_32ksynct: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2420_32KSYNCT_BASE + 0x010) ENTRY(omap242x_sram_reprogram_sdrc_sz) .word . - omap242x_sram_reprogram_sdrc diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index 84363e269e8..054b0f357ac 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -128,7 +128,7 @@ omap243x_sdi_prcm_voltctrl: prcm_mask_val: .word 0xFFFF3FFC omap243x_sdi_timer_32ksynct_cr: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_ddr_init_sz) .word . - omap243x_sram_ddr_init @@ -224,7 +224,7 @@ omap243x_srs_prcm_voltctrl: ddr_prcm_mask_val: .word 0xFFFF3FFC omap243x_srs_timer_32ksynct: - .word IO_ADDRESS(OMAP2_32KSYNCT_BASE + 0x010) + .word IO_ADDRESS(OMAP2430_32KSYNCT_BASE + 0x010) ENTRY(omap243x_sram_reprogram_sdrc_sz) .word . - omap243x_sram_reprogram_sdrc diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 433021f3d7c..e1add789835 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -175,25 +175,61 @@ console_initcall(omap_add_serial_console); * but systems won't necessarily want to spend resources that way. */ -#if defined(CONFIG_ARCH_OMAP16XX) -#define TIMER_32K_SYNCHRONIZED 0xfffbc410 -#elif defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -#define TIMER_32K_SYNCHRONIZED (OMAP2_32KSYNCT_BASE + 0x10) -#endif +#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410 -#ifdef TIMER_32K_SYNCHRONIZED +#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) #include -static cycle_t omap_32k_read(struct clocksource *cs) +#ifdef CONFIG_ARCH_OMAP16XX +static cycle_t omap16xx_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED); +} +#else +#define omap16xx_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP2420 +static cycle_t omap2420_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10); +} +#else +#define omap2420_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP2430 +static cycle_t omap2430_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10); +} +#else +#define omap2430_32k_read NULL +#endif + +#ifdef CONFIG_ARCH_OMAP34XX +static cycle_t omap34xx_32k_read(struct clocksource *cs) { - return omap_readl(TIMER_32K_SYNCHRONIZED); + return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10); +} +#else +#define omap34xx_32k_read NULL +#endif + +/* + * Kernel assumes that sched_clock can be called early but may not have + * things ready yet. + */ +static cycle_t omap_32k_read_dummy(struct clocksource *cs) +{ + return 0; } static struct clocksource clocksource_32k = { .name = "32k_counter", .rating = 250, - .read = omap_32k_read, + .read = omap_32k_read_dummy, .mask = CLOCKSOURCE_MASK(32), .shift = 10, .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -207,7 +243,7 @@ unsigned long long sched_clock(void) { unsigned long long ret; - ret = (unsigned long long)omap_32k_read(&clocksource_32k); + ret = (unsigned long long)clocksource_32k.read(&clocksource_32k); ret = (ret * clocksource_32k.mult_orig) >> clocksource_32k.shift; return ret; } @@ -220,6 +256,17 @@ static int __init omap_init_clocksource_32k(void) if (cpu_is_omap16xx() || cpu_class_is_omap2()) { struct clk *sync_32k_ick; + if (cpu_is_omap16xx()) + clocksource_32k.read = omap16xx_32k_read; + else if (cpu_is_omap2420()) + clocksource_32k.read = omap2420_32k_read; + else if (cpu_is_omap2430()) + clocksource_32k.read = omap2430_32k_read; + else if (cpu_is_omap34xx()) + clocksource_32k.read = omap34xx_32k_read; + else + return -ENODEV; + sync_32k_ick = clk_get(NULL, "omap_32ksync_ick"); if (sync_32k_ick) clk_enable(sync_32k_ick); @@ -234,7 +281,7 @@ static int __init omap_init_clocksource_32k(void) } arch_initcall(omap_init_clocksource_32k); -#endif /* TIMER_32K_SYNCHRONIZED */ +#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */ /* Global address base setup code */ diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 24335d4932f..4202cf457e2 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -87,7 +87,6 @@ #if defined(CONFIG_ARCH_OMAP2420) -#define OMAP2_32KSYNCT_BASE OMAP2420_32KSYNCT_BASE #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE #define OMAP2_PRM_BASE OMAP2420_PRM_BASE @@ -95,7 +94,6 @@ #elif defined(CONFIG_ARCH_OMAP2430) -#define OMAP2_32KSYNCT_BASE OMAP2430_32KSYNCT_BASE #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE #define OMAP2_PRM_BASE OMAP2430_PRM_BASE diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index ab640151d3e..581d9103c35 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -85,7 +85,6 @@ #if defined(CONFIG_ARCH_OMAP3430) -#define OMAP2_32KSYNCT_BASE OMAP3430_32KSYNCT_BASE #define OMAP2_CM_BASE OMAP3430_CM_BASE #define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) -- cgit v1.2.3-70-g09d2 From 8e3bd351d1d2505e17d0b10c17bf8d7655eb9faf Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:26:42 -0700 Subject: ARM: OMAP2/3: Remove OMAP_PRM_REGADDR and OMAP2_PRM_BASE Remove OMAP_PRM_REGADDR and use processor specific defines instead. Also fold in a patch from Kevin Hilman to add _OFFSET #defines for the PRCM registers to be used with the prm_[read|write]_* macros. These are used extensively in the forthcoming OMAP PM support. Also remove now unused OMAP2_PRM_BASE. Signed-off-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock.c | 4 +- arch/arm/mach-omap2/clock24xx.c | 21 +-- arch/arm/mach-omap2/clock24xx.h | 9 ++ arch/arm/mach-omap2/cm.h | 1 + arch/arm/mach-omap2/prm.h | 205 ++++++++++++++++++----------- arch/arm/mach-omap2/sdrc2xxx.c | 5 +- arch/arm/mach-omap2/sram242x.S | 6 +- arch/arm/mach-omap2/sram243x.S | 6 +- arch/arm/plat-omap/include/mach/omap24xx.h | 2 - arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 10 files changed, 160 insertions(+), 100 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c index 4247a153441..dd37483f3d1 100644 --- a/arch/arm/mach-omap2/clock.c +++ b/arch/arm/mach-omap2/clock.c @@ -91,9 +91,9 @@ static void _omap2xxx_clk_commit(struct clk *clk) return; prm_write_mod_reg(OMAP24XX_VALID_CONFIG, OMAP24XX_GR_MOD, - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); + OMAP2_PRCM_CLKCFG_CTRL_OFFSET); /* OCP barrier */ - prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET); + prm_read_mod_reg(OMAP24XX_GR_MOD, OMAP2_PRCM_CLKCFG_CTRL_OFFSET); } /* diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c index e4cef333e29..c442fe9f998 100644 --- a/arch/arm/mach-omap2/clock24xx.c +++ b/arch/arm/mach-omap2/clock24xx.c @@ -233,6 +233,8 @@ static struct prcm_config *curr_prcm_set; static struct clk *vclk; static struct clk *sclk; +static void __iomem *prcm_clksrc_ctrl; + /*------------------------------------------------------------------------- * Omap24xx specific clock functions *-------------------------------------------------------------------------*/ @@ -269,10 +271,9 @@ static int omap2_enable_osc_ck(struct clk *clk) { u32 pcc; - pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + pcc = __raw_readl(prcm_clksrc_ctrl); - __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, - OMAP24XX_PRCM_CLKSRC_CTRL); + __raw_writel(pcc & ~OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); return 0; } @@ -281,10 +282,9 @@ static void omap2_disable_osc_ck(struct clk *clk) { u32 pcc; - pcc = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + pcc = __raw_readl(prcm_clksrc_ctrl); - __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, - OMAP24XX_PRCM_CLKSRC_CTRL); + __raw_writel(pcc | OMAP_AUTOEXTCLKMODE_MASK, prcm_clksrc_ctrl); } static const struct clkops clkops_oscck = { @@ -654,7 +654,7 @@ static u32 omap2_get_sysclkdiv(void) { u32 div; - div = __raw_readl(OMAP24XX_PRCM_CLKSRC_CTRL); + div = __raw_readl(prcm_clksrc_ctrl); div &= OMAP_SYSCLKDIV_MASK; div >>= OMAP_SYSCLKDIV_SHIFT; @@ -714,10 +714,13 @@ int __init omap2_clk_init(void) struct omap_clk *c; u32 clkrate; - if (cpu_is_omap242x()) + if (cpu_is_omap242x()) { + prcm_clksrc_ctrl = OMAP2420_PRCM_CLKSRC_CTRL; cpu_mask = RATE_IN_242X; - else if (cpu_is_omap2430()) + } else if (cpu_is_omap2430()) { + prcm_clksrc_ctrl = OMAP2430_PRCM_CLKSRC_CTRL; cpu_mask = RATE_IN_243X; + } clk_init(&omap2_clk_functions); diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index 88c5acb40fc..f0e4480b4eb 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -24,6 +24,15 @@ #include "cm-regbits-24xx.h" #include "sdrc.h" +/* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ +#ifdef CONFIG_ARCH_OMAP2420 +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL +#else +#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL +#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL +#endif + static unsigned long omap2_table_mpu_recalc(struct clk *clk); static int omap2_select_table_rate(struct clk *clk, unsigned long rate); static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate); diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index 65fdf78c91e..efc082a1d27 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -38,6 +38,7 @@ #define OMAP3430_CM_SYSCONFIG OMAP_CM_REGADDR(OCP_MOD, 0x0010) #define OMAP3430_CM_POLCTRL OMAP_CM_REGADDR(OCP_MOD, 0x009c) +#define OMAP3_CM_CLKOUT_CTRL_OFFSET 0x0070 #define OMAP3430_CM_CLKOUT_CTRL OMAP_CM_REGADDR(OMAP3430_CCR_MOD, 0x0070) /* diff --git a/arch/arm/mach-omap2/prm.h b/arch/arm/mach-omap2/prm.h index 826d326b806..7c8e0c42b05 100644 --- a/arch/arm/mach-omap2/prm.h +++ b/arch/arm/mach-omap2/prm.h @@ -16,17 +16,12 @@ #include "prcm-common.h" -#ifndef __ASSEMBLER__ -#define OMAP_PRM_REGADDR(module, reg) \ - IO_ADDRESS(OMAP2_PRM_BASE + (module) + (reg)) -#else #define OMAP2420_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2420_PRM_BASE + (module) + (reg)) #define OMAP2430_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2430_PRM_BASE + (module) + (reg)) #define OMAP34XX_PRM_REGADDR(module, reg) \ IO_ADDRESS(OMAP3430_PRM_BASE + (module) + (reg)) -#endif /* * Architecture-specific global PRM registers @@ -38,80 +33,132 @@ * */ -/* Global 24xx registers in GR_MOD (Same as OCP_MOD for 24xx) */ -#define OMAP24XX_PRCM_VOLTCTRL_OFFSET 0x0050 -#define OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET 0x0080 - -/* 242x GR_MOD registers, use these only for assembly code */ -#define OMAP242X_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_VOLTCTRL_OFFSET) -#define OMAP242X_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET) - -/* 243x GR_MOD registers, use these only for assembly code */ -#define OMAP243X_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_VOLTCTRL_OFFSET) -#define OMAP243X_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OMAP24XX_GR_MOD, \ - OMAP24XX_PRCM_CLKCFG_CTRL_OFFSET) - -/* These will disappear */ -#define OMAP24XX_PRCM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0000) -#define OMAP24XX_PRCM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0010) - -#define OMAP24XX_PRCM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018) -#define OMAP24XX_PRCM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c) - -#define OMAP24XX_PRCM_VOLTST OMAP_PRM_REGADDR(OCP_MOD, 0x0054) -#define OMAP24XX_PRCM_CLKSRC_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0060) -#define OMAP24XX_PRCM_CLKOUT_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0070) -#define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0078) -#define OMAP24XX_PRCM_CLKCFG_CTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0080) -#define OMAP24XX_PRCM_CLKCFG_STATUS OMAP_PRM_REGADDR(OCP_MOD, 0x0084) -#define OMAP24XX_PRCM_VOLTSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0090) -#define OMAP24XX_PRCM_CLKSSETUP OMAP_PRM_REGADDR(OCP_MOD, 0x0094) -#define OMAP24XX_PRCM_POLCTRL OMAP_PRM_REGADDR(OCP_MOD, 0x0098) - -#define OMAP3430_PRM_REVISION OMAP_PRM_REGADDR(OCP_MOD, 0x0004) -#define OMAP3430_PRM_SYSCONFIG OMAP_PRM_REGADDR(OCP_MOD, 0x0014) - -#define OMAP3430_PRM_IRQSTATUS_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x0018) -#define OMAP3430_PRM_IRQENABLE_MPU OMAP_PRM_REGADDR(OCP_MOD, 0x001c) - - -#define OMAP3430_PRM_VC_SMPS_SA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020) -#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024) -#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028) -#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c) -#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030) -#define OMAP3430_PRM_VC_CH_CONF OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034) -#define OMAP3430_PRM_VC_I2C_CFG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038) -#define OMAP3430_PRM_VC_BYPASS_VAL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c) -#define OMAP3430_PRM_RSTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050) -#define OMAP3430_PRM_RSTTIME OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054) -#define OMAP3430_PRM_RSTST OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058) -#define OMAP3430_PRM_VOLTCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060) -#define OMAP3430_PRM_SRAM_PCHARGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064) -#define OMAP3430_PRM_CLKSRC_CTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070) -#define OMAP3430_PRM_VOLTSETUP1 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090) -#define OMAP3430_PRM_VOLTOFFSET OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094) -#define OMAP3430_PRM_CLKSETUP OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098) -#define OMAP3430_PRM_POLCTRL OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c) -#define OMAP3430_PRM_VOLTSETUP2 OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0) -#define OMAP3430_PRM_VP1_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0) -#define OMAP3430_PRM_VP1_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4) -#define OMAP3430_PRM_VP1_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8) -#define OMAP3430_PRM_VP1_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc) -#define OMAP3430_PRM_VP1_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0) -#define OMAP3430_PRM_VP1_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4) -#define OMAP3430_PRM_VP2_CONFIG OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0) -#define OMAP3430_PRM_VP2_VSTEPMIN OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4) -#define OMAP3430_PRM_VP2_VSTEPMAX OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8) -#define OMAP3430_PRM_VP2_VLIMITTO OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc) -#define OMAP3430_PRM_VP2_VOLTAGE OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0) -#define OMAP3430_PRM_VP2_STATUS OMAP_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4) - -#define OMAP3430_PRM_CLKSEL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040) -#define OMAP3430_PRM_CLKOUT_CTRL OMAP_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070) +#define OMAP2_PRCM_REVISION_OFFSET 0x0000 +#define OMAP2420_PRCM_REVISION OMAP2420_PRM_REGADDR(OCP_MOD, 0x0000) +#define OMAP2_PRCM_SYSCONFIG_OFFSET 0x0010 +#define OMAP2420_PRCM_SYSCONFIG OMAP2420_PRM_REGADDR(OCP_MOD, 0x0010) + +#define OMAP2_PRCM_IRQSTATUS_MPU_OFFSET 0x0018 +#define OMAP2420_PRCM_IRQSTATUS_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP2_PRCM_IRQENABLE_MPU_OFFSET 0x001c +#define OMAP2420_PRCM_IRQENABLE_MPU OMAP2420_PRM_REGADDR(OCP_MOD, 0x001c) + +#define OMAP2_PRCM_VOLTCTRL_OFFSET 0x0050 +#define OMAP2420_PRCM_VOLTCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0050) +#define OMAP2_PRCM_VOLTST_OFFSET 0x0054 +#define OMAP2420_PRCM_VOLTST OMAP2420_PRM_REGADDR(OCP_MOD, 0x0054) +#define OMAP2_PRCM_CLKSRC_CTRL_OFFSET 0x0060 +#define OMAP2420_PRCM_CLKSRC_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0060) +#define OMAP2_PRCM_CLKOUT_CTRL_OFFSET 0x0070 +#define OMAP2420_PRCM_CLKOUT_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0070) +#define OMAP2_PRCM_CLKEMUL_CTRL_OFFSET 0x0078 +#define OMAP2420_PRCM_CLKEMUL_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0078) +#define OMAP2_PRCM_CLKCFG_CTRL_OFFSET 0x0080 +#define OMAP2420_PRCM_CLKCFG_CTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0080) +#define OMAP2_PRCM_CLKCFG_STATUS_OFFSET 0x0084 +#define OMAP2420_PRCM_CLKCFG_STATUS OMAP2420_PRM_REGADDR(OCP_MOD, 0x0084) +#define OMAP2_PRCM_VOLTSETUP_OFFSET 0x0090 +#define OMAP2420_PRCM_VOLTSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0090) +#define OMAP2_PRCM_CLKSSETUP_OFFSET 0x0094 +#define OMAP2420_PRCM_CLKSSETUP OMAP2420_PRM_REGADDR(OCP_MOD, 0x0094) +#define OMAP2_PRCM_POLCTRL_OFFSET 0x0098 +#define OMAP2420_PRCM_POLCTRL OMAP2420_PRM_REGADDR(OCP_MOD, 0x0098) + +#define OMAP2430_PRCM_REVISION OMAP2430_PRM_REGADDR(OCP_MOD, 0x0000) +#define OMAP2430_PRCM_SYSCONFIG OMAP2430_PRM_REGADDR(OCP_MOD, 0x0010) + +#define OMAP2430_PRCM_IRQSTATUS_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP2430_PRCM_IRQENABLE_MPU OMAP2430_PRM_REGADDR(OCP_MOD, 0x001c) + +#define OMAP2430_PRCM_VOLTCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0050) +#define OMAP2430_PRCM_VOLTST OMAP2430_PRM_REGADDR(OCP_MOD, 0x0054) +#define OMAP2430_PRCM_CLKSRC_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0060) +#define OMAP2430_PRCM_CLKOUT_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0070) +#define OMAP2430_PRCM_CLKEMUL_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0078) +#define OMAP2430_PRCM_CLKCFG_CTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0080) +#define OMAP2430_PRCM_CLKCFG_STATUS OMAP2430_PRM_REGADDR(OCP_MOD, 0x0084) +#define OMAP2430_PRCM_VOLTSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0090) +#define OMAP2430_PRCM_CLKSSETUP OMAP2430_PRM_REGADDR(OCP_MOD, 0x0094) +#define OMAP2430_PRCM_POLCTRL OMAP2430_PRM_REGADDR(OCP_MOD, 0x0098) + +#define OMAP3_PRM_REVISION_OFFSET 0x0004 +#define OMAP3430_PRM_REVISION OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0004) +#define OMAP3_PRM_SYSCONFIG_OFFSET 0x0014 +#define OMAP3430_PRM_SYSCONFIG OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0014) + +#define OMAP3_PRM_IRQSTATUS_MPU_OFFSET 0x0018 +#define OMAP3430_PRM_IRQSTATUS_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x0018) +#define OMAP3_PRM_IRQENABLE_MPU_OFFSET 0x001c +#define OMAP3430_PRM_IRQENABLE_MPU OMAP34XX_PRM_REGADDR(OCP_MOD, 0x001c) + + +#define OMAP3_PRM_VC_SMPS_SA_OFFSET 0x0020 +#define OMAP3430_PRM_VC_SMPS_SA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0020) +#define OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET 0x0024 +#define OMAP3430_PRM_VC_SMPS_VOL_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0024) +#define OMAP3_PRM_VC_SMPS_CMD_RA_OFFSET 0x0028 +#define OMAP3430_PRM_VC_SMPS_CMD_RA OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0028) +#define OMAP3_PRM_VC_CMD_VAL_0_OFFSET 0x002c +#define OMAP3430_PRM_VC_CMD_VAL_0 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x002c) +#define OMAP3_PRM_VC_CMD_VAL_1_OFFSET 0x0030 +#define OMAP3430_PRM_VC_CMD_VAL_1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0030) +#define OMAP3_PRM_VC_CH_CONF_OFFSET 0x0034 +#define OMAP3430_PRM_VC_CH_CONF OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0034) +#define OMAP3_PRM_VC_I2C_CFG_OFFSET 0x0038 +#define OMAP3430_PRM_VC_I2C_CFG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0038) +#define OMAP3_PRM_VC_BYPASS_VAL_OFFSET 0x003c +#define OMAP3430_PRM_VC_BYPASS_VAL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x003c) +#define OMAP3_PRM_RSTCTRL_OFFSET 0x0050 +#define OMAP3430_PRM_RSTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0050) +#define OMAP3_PRM_RSTTIME_OFFSET 0x0054 +#define OMAP3430_PRM_RSTTIME OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0054) +#define OMAP3_PRM_RSTST_OFFSET 0x0058 +#define OMAP3430_PRM_RSTST OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0058) +#define OMAP3_PRM_VOLTCTRL_OFFSET 0x0060 +#define OMAP3430_PRM_VOLTCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0060) +#define OMAP3_PRM_SRAM_PCHARGE_OFFSET 0x0064 +#define OMAP3430_PRM_SRAM_PCHARGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0064) +#define OMAP3_PRM_CLKSRC_CTRL_OFFSET 0x0070 +#define OMAP3430_PRM_CLKSRC_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0070) +#define OMAP3_PRM_VOLTSETUP1_OFFSET 0x0090 +#define OMAP3430_PRM_VOLTSETUP1 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0090) +#define OMAP3_PRM_VOLTOFFSET_OFFSET 0x0094 +#define OMAP3430_PRM_VOLTOFFSET OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0094) +#define OMAP3_PRM_CLKSETUP_OFFSET 0x0098 +#define OMAP3430_PRM_CLKSETUP OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x0098) +#define OMAP3_PRM_POLCTRL_OFFSET 0x009c +#define OMAP3430_PRM_POLCTRL OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x009c) +#define OMAP3_PRM_VOLTSETUP2_OFFSET 0x00a0 +#define OMAP3430_PRM_VOLTSETUP2 OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00a0) +#define OMAP3_PRM_VP1_CONFIG_OFFSET 0x00b0 +#define OMAP3430_PRM_VP1_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b0) +#define OMAP3_PRM_VP1_VSTEPMIN_OFFSET 0x00b4 +#define OMAP3430_PRM_VP1_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b4) +#define OMAP3_PRM_VP1_VSTEPMAX_OFFSET 0x00b8 +#define OMAP3430_PRM_VP1_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00b8) +#define OMAP3_PRM_VP1_VLIMITTO_OFFSET 0x00bc +#define OMAP3430_PRM_VP1_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00bc) +#define OMAP3_PRM_VP1_VOLTAGE_OFFSET 0x00c0 +#define OMAP3430_PRM_VP1_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c0) +#define OMAP3_PRM_VP1_STATUS_OFFSET 0x00c4 +#define OMAP3430_PRM_VP1_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00c4) +#define OMAP3_PRM_VP2_CONFIG_OFFSET 0x00d0 +#define OMAP3430_PRM_VP2_CONFIG OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d0) +#define OMAP3_PRM_VP2_VSTEPMIN_OFFSET 0x00d4 +#define OMAP3430_PRM_VP2_VSTEPMIN OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d4) +#define OMAP3_PRM_VP2_VSTEPMAX_OFFSET 0x00d8 +#define OMAP3430_PRM_VP2_VSTEPMAX OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00d8) +#define OMAP3_PRM_VP2_VLIMITTO_OFFSET 0x00dc +#define OMAP3430_PRM_VP2_VLIMITTO OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00dc) +#define OMAP3_PRM_VP2_VOLTAGE_OFFSET 0x00e0 +#define OMAP3430_PRM_VP2_VOLTAGE OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e0) +#define OMAP3_PRM_VP2_STATUS_OFFSET 0x00e4 +#define OMAP3430_PRM_VP2_STATUS OMAP34XX_PRM_REGADDR(OMAP3430_GR_MOD, 0x00e4) + +#define OMAP3_PRM_CLKSEL_OFFSET 0x0040 +#define OMAP3430_PRM_CLKSEL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0040) +#define OMAP3_PRM_CLKOUT_CTRL_OFFSET 0x0070 +#define OMAP3430_PRM_CLKOUT_CTRL OMAP34XX_PRM_REGADDR(OMAP3430_CCR_MOD, 0x0070) /* * Module specific PRM registers from PRM_BASE + domain offset diff --git a/arch/arm/mach-omap2/sdrc2xxx.c b/arch/arm/mach-omap2/sdrc2xxx.c index 0afdad5ae9f..feaec7eaf6b 100644 --- a/arch/arm/mach-omap2/sdrc2xxx.c +++ b/arch/arm/mach-omap2/sdrc2xxx.c @@ -99,7 +99,10 @@ u32 omap2xxx_sdrc_reprogram(u32 level, u32 force) m_type = omap2xxx_sdrc_get_type(); local_irq_save(flags); - __raw_writel(0xffff, OMAP24XX_PRCM_VOLTSETUP); + if (cpu_is_omap2420()) + __raw_writel(0xffff, OMAP2420_PRCM_VOLTSETUP); + else + __raw_writel(0xffff, OMAP2430_PRCM_VOLTSETUP); omap2_sram_reprogram_sdrc(level, dll_ctrl, m_type); curr_perf_level = level; local_irq_restore(flags); diff --git a/arch/arm/mach-omap2/sram242x.S b/arch/arm/mach-omap2/sram242x.S index cbb89304248..bb299851116 100644 --- a/arch/arm/mach-omap2/sram242x.S +++ b/arch/arm/mach-omap2/sram242x.S @@ -124,7 +124,7 @@ omap242x_sdi_cm_clksel2_pll: omap242x_sdi_sdrc_dlla_ctrl: .word OMAP242X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap242x_sdi_prcm_voltctrl: - .word OMAP242X_PRCM_VOLTCTRL + .word OMAP2420_PRCM_VOLTCTRL prcm_mask_val: .word 0xFFFF3FFC omap242x_sdi_timer_32ksynct_cr: @@ -220,7 +220,7 @@ omap242x_srs_sdrc_dlla_ctrl: omap242x_srs_sdrc_rfr_ctrl: .word OMAP242X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap242x_srs_prcm_voltctrl: - .word OMAP242X_PRCM_VOLTCTRL + .word OMAP2420_PRCM_VOLTCTRL ddr_prcm_mask_val: .word 0xFFFF3FFC omap242x_srs_timer_32ksynct: @@ -305,7 +305,7 @@ wait_dll_lock: ldmfd sp!, {r0-r12, pc} @ restore regs and return omap242x_ssp_set_config: - .word OMAP242X_PRCM_CLKCFG_CTRL + .word OMAP2420_PRCM_CLKCFG_CTRL omap242x_ssp_pll_ctl: .word OMAP2420_CM_REGADDR(PLL_MOD, CM_CLKEN) omap242x_ssp_pll_stat: diff --git a/arch/arm/mach-omap2/sram243x.S b/arch/arm/mach-omap2/sram243x.S index 054b0f357ac..9955abcaeb3 100644 --- a/arch/arm/mach-omap2/sram243x.S +++ b/arch/arm/mach-omap2/sram243x.S @@ -124,7 +124,7 @@ omap243x_sdi_cm_clksel2_pll: omap243x_sdi_sdrc_dlla_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_DLLA_CTRL) omap243x_sdi_prcm_voltctrl: - .word OMAP243X_PRCM_VOLTCTRL + .word OMAP2430_PRCM_VOLTCTRL prcm_mask_val: .word 0xFFFF3FFC omap243x_sdi_timer_32ksynct_cr: @@ -220,7 +220,7 @@ omap243x_srs_sdrc_dlla_ctrl: omap243x_srs_sdrc_rfr_ctrl: .word OMAP243X_SDRC_REGADDR(SDRC_RFR_CTRL_0) omap243x_srs_prcm_voltctrl: - .word OMAP243X_PRCM_VOLTCTRL + .word OMAP2430_PRCM_VOLTCTRL ddr_prcm_mask_val: .word 0xFFFF3FFC omap243x_srs_timer_32ksynct: @@ -305,7 +305,7 @@ wait_dll_lock: ldmfd sp!, {r0-r12, pc} @ restore regs and return omap243x_ssp_set_config: - .word OMAP243X_PRCM_CLKCFG_CTRL + .word OMAP2430_PRCM_CLKCFG_CTRL omap243x_ssp_pll_ctl: .word OMAP2430_CM_REGADDR(PLL_MOD, CM_CLKEN) omap243x_ssp_pll_stat: diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 4202cf457e2..10a6413c73e 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -89,14 +89,12 @@ #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE -#define OMAP2_PRM_BASE OMAP2420_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #elif defined(CONFIG_ARCH_OMAP2430) #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE -#define OMAP2_PRM_BASE OMAP2430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #endif diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 581d9103c35..42330644420 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -86,7 +86,6 @@ #if defined(CONFIG_ARCH_OMAP3430) #define OMAP2_CM_BASE OMAP3430_CM_BASE -#define OMAP2_PRM_BASE OMAP3430_PRM_BASE #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif -- cgit v1.2.3-70-g09d2 From 2e693f841f70508a082ded0276a33b2e503d98b7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:26:45 -0700 Subject: ARM: OMAP2/3: Move define of OMAP2_VA_IC_BASE to be local to entry-macro.S Move define of OMAP2_VA_IC_BASE to be local to entry-macro.S Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/entry-macro.S | 9 ++++++--- arch/arm/plat-omap/include/mach/omap24xx.h | 2 -- arch/arm/plat-omap/include/mach/omap34xx.h | 1 - 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S index 2276f89671d..33256a0e9a2 100644 --- a/arch/arm/plat-omap/include/mach/entry-macro.S +++ b/arch/arm/plat-omap/include/mach/entry-macro.S @@ -58,11 +58,14 @@ #endif #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) -#if defined(CONFIG_ARCH_OMAP24XX) #include -#endif -#if defined(CONFIG_ARCH_OMAP34XX) #include + +/* REVISIT: This should be set dynamically if CONFIG_MULTI_OMAP2 is selected */ +#if defined(CONFIG_ARCH_OMAP2420) || defined(CONFIG_ARCH_OMAP2430) +#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) +#elif defined(CONFIG_ARCH_OMAP34XX) +#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* Active interrupt offset */ diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 10a6413c73e..4ce9b6a60a5 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -89,13 +89,11 @@ #define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #elif defined(CONFIG_ARCH_OMAP2430) #define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP24XX_IC_BASE) #endif diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 42330644420..36c99ca0825 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -86,7 +86,6 @@ #if defined(CONFIG_ARCH_OMAP3430) #define OMAP2_CM_BASE OMAP3430_CM_BASE -#define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif -- cgit v1.2.3-70-g09d2 From 07b95d000d48bd44e6f573566c1eba985ef25ed4 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:26:46 -0700 Subject: ARM: OMAP2/3: Remove OMAP2_PRCM_BASE It's currently unused, and processor specific defines should be used instead. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/omap24xx.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 4ce9b6a60a5..60f83244924 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -87,12 +87,10 @@ #if defined(CONFIG_ARCH_OMAP2420) -#define OMAP2_PRCM_BASE OMAP2420_PRCM_BASE #define OMAP2_CM_BASE OMAP2420_CM_BASE #elif defined(CONFIG_ARCH_OMAP2430) -#define OMAP2_PRCM_BASE OMAP2430_PRCM_BASE #define OMAP2_CM_BASE OMAP2430_CM_BASE #endif -- cgit v1.2.3-70-g09d2 From ef6685a6ded6a20ff33a868cc2c0dba0505b7e4c Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 25 May 2009 11:26:46 -0700 Subject: ARM: OMAP2/3: Remove OMAP_CM_REGADDR Processor specific macros should be used instead. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/clock24xx.h | 2 ++ arch/arm/mach-omap2/clock34xx.h | 2 ++ arch/arm/mach-omap2/cm.h | 5 ----- arch/arm/plat-omap/include/mach/omap24xx.h | 10 ---------- arch/arm/plat-omap/include/mach/omap34xx.h | 6 ------ 5 files changed, 4 insertions(+), 21 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock24xx.h b/arch/arm/mach-omap2/clock24xx.h index f0e4480b4eb..458f00cdcbe 100644 --- a/arch/arm/mach-omap2/clock24xx.h +++ b/arch/arm/mach-omap2/clock24xx.h @@ -26,9 +26,11 @@ /* REVISIT: These should be set dynamically for CONFIG_MULTI_OMAP2 */ #ifdef CONFIG_ARCH_OMAP2420 +#define OMAP_CM_REGADDR OMAP2420_CM_REGADDR #define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2420_PRCM_CLKOUT_CTRL #define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2420_PRCM_CLKEMUL_CTRL #else +#define OMAP_CM_REGADDR OMAP2430_CM_REGADDR #define OMAP24XX_PRCM_CLKOUT_CTRL OMAP2430_PRCM_CLKOUT_CTRL #define OMAP24XX_PRCM_CLKEMUL_CTRL OMAP2430_PRCM_CLKEMUL_CTRL #endif diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 017a30e9aa1..496f0e9caeb 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -27,6 +27,8 @@ #include "prm.h" #include "prm-regbits-34xx.h" +#define OMAP_CM_REGADDR OMAP34XX_CM_REGADDR + static unsigned long omap3_dpll_recalc(struct clk *clk); static unsigned long omap3_clkoutx2_recalc(struct clk *clk); static void omap3_dpll_allow_idle(struct clk *clk); diff --git a/arch/arm/mach-omap2/cm.h b/arch/arm/mach-omap2/cm.h index efc082a1d27..1d3c93bf86d 100644 --- a/arch/arm/mach-omap2/cm.h +++ b/arch/arm/mach-omap2/cm.h @@ -16,17 +16,12 @@ #include "prcm-common.h" -#ifndef __ASSEMBLER__ -#define OMAP_CM_REGADDR(module, reg) \ - IO_ADDRESS(OMAP2_CM_BASE + (module) + (reg)) -#else #define OMAP2420_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2420_CM_BASE + (module) + (reg)) #define OMAP2430_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP2430_CM_BASE + (module) + (reg)) #define OMAP34XX_CM_REGADDR(module, reg) \ IO_ADDRESS(OMAP3430_CM_BASE + (module) + (reg)) -#endif /* * Architecture-specific global CM registers diff --git a/arch/arm/plat-omap/include/mach/omap24xx.h b/arch/arm/plat-omap/include/mach/omap24xx.h index 60f83244924..696edfc145a 100644 --- a/arch/arm/plat-omap/include/mach/omap24xx.h +++ b/arch/arm/plat-omap/include/mach/omap24xx.h @@ -85,15 +85,5 @@ #define OMAP24XX_SEC_AES_BASE (OMAP24XX_SEC_BASE + 0x6000) #define OMAP24XX_SEC_PKA_BASE (OMAP24XX_SEC_BASE + 0x8000) -#if defined(CONFIG_ARCH_OMAP2420) - -#define OMAP2_CM_BASE OMAP2420_CM_BASE - -#elif defined(CONFIG_ARCH_OMAP2430) - -#define OMAP2_CM_BASE OMAP2430_CM_BASE - -#endif - #endif /* __ASM_ARCH_OMAP24XX_H */ diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index 36c99ca0825..cc2573330dc 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -83,12 +83,6 @@ #define OMAP34XX_MAILBOX_BASE (L4_34XX_BASE + 0x94000) -#if defined(CONFIG_ARCH_OMAP3430) - -#define OMAP2_CM_BASE OMAP3430_CM_BASE - -#endif - #define OMAP34XX_DSP_BASE 0x58000000 #define OMAP34XX_DSP_MEM_BASE (OMAP34XX_DSP_BASE + 0x0) #define OMAP34XX_DSP_IPI_BASE (OMAP34XX_DSP_BASE + 0x1000000) -- cgit v1.2.3-70-g09d2 From ce8a17fd3f19baac0171611a73d5ac2072f45c7a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:26:47 -0700 Subject: ARM: OMAP: Remove unwanted type casts and fix the compiler warning. This patch fixes the compiler warning "assignment from incompatible pointer type" in dmtimer.c and removes the tye casts. These warnings were suppressed by type catsing. The proposed fix was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dmtimer.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 55bb9963129..ee206122f50 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -214,7 +214,7 @@ static const char *omap2_dm_source_names[] __initdata = { NULL }; -static struct clk **omap2_dm_source_clocks[3]; +static struct clk *omap2_dm_source_clocks[3]; static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers); #elif defined(CONFIG_ARCH_OMAP3) @@ -247,7 +247,7 @@ static const char *omap3_dm_source_names[] __initdata = { NULL }; -static struct clk **omap3_dm_source_clocks[2]; +static struct clk *omap3_dm_source_clocks[2]; static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers); #else @@ -257,7 +257,7 @@ static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers); #endif static struct omap_dm_timer *dm_timers; -static char **dm_source_names; +static const char **dm_source_names; static struct clk **dm_source_clocks; static spinlock_t dm_timer_lock; @@ -705,12 +705,12 @@ int __init omap_dm_timer_init(void) dm_timers = omap1_dm_timers; else if (cpu_is_omap24xx()) { dm_timers = omap2_dm_timers; - dm_source_names = (char **)omap2_dm_source_names; - dm_source_clocks = (struct clk **)omap2_dm_source_clocks; + dm_source_names = omap2_dm_source_names; + dm_source_clocks = omap2_dm_source_clocks; } else if (cpu_is_omap34xx()) { dm_timers = omap3_dm_timers; - dm_source_names = (char **)omap3_dm_source_names; - dm_source_clocks = (struct clk **)omap3_dm_source_clocks; + dm_source_names = omap3_dm_source_names; + dm_source_clocks = omap3_dm_source_clocks; } if (cpu_class_is_omap2()) -- cgit v1.2.3-70-g09d2 From da7a0649bc8f3f65a01cb14e8b5c97e2ff40098a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:26:48 -0700 Subject: ARM: OMAP: Remove useless omap_sram_error function. This patch removes fixes omap_sram_error() function and replace the error paths with BUG_ON. The proposed fix was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/sram.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index fa5297d643d..e1493d83a7c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -242,20 +242,13 @@ void * omap_sram_push(void * start, unsigned long size) return (void *)omap_sram_ceil; } -static void omap_sram_error(void) -{ - panic("Uninitialized SRAM function\n"); -} - #ifdef CONFIG_ARCH_OMAP1 static void (*_omap_sram_reprogram_clock)(u32 dpllctl, u32 ckctl); void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) { - if (!_omap_sram_reprogram_clock) - omap_sram_error(); - + BUG_ON(!_omap_sram_reprogram_clock); _omap_sram_reprogram_clock(dpllctl, ckctl); } @@ -280,9 +273,7 @@ static void (*_omap2_sram_ddr_init)(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl, u32 base_cs, u32 force_unlock) { - if (!_omap2_sram_ddr_init) - omap_sram_error(); - + BUG_ON(!_omap2_sram_ddr_init); _omap2_sram_ddr_init(slow_dll_ctrl, fast_dll_ctrl, base_cs, force_unlock); } @@ -292,9 +283,7 @@ static void (*_omap2_sram_reprogram_sdrc)(u32 perf_level, u32 dll_val, void omap2_sram_reprogram_sdrc(u32 perf_level, u32 dll_val, u32 mem_type) { - if (!_omap2_sram_reprogram_sdrc) - omap_sram_error(); - + BUG_ON(!_omap2_sram_reprogram_sdrc); _omap2_sram_reprogram_sdrc(perf_level, dll_val, mem_type); } @@ -302,9 +291,7 @@ static u32 (*_omap2_set_prcm)(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass); u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass) { - if (!_omap2_set_prcm) - omap_sram_error(); - + BUG_ON(!_omap2_set_prcm); return _omap2_set_prcm(dpll_ctrl_val, sdrc_rfr_val, bypass); } #endif @@ -360,9 +347,7 @@ static u32 (*_omap3_sram_configure_core_dpll)(u32 sdrc_rfr_ctrl, u32 omap3_configure_core_dpll(u32 sdrc_rfr_ctrl, u32 sdrc_actim_ctrla, u32 sdrc_actim_ctrlb, u32 m2) { - if (!_omap3_sram_configure_core_dpll) - omap_sram_error(); - + BUG_ON(!_omap3_sram_configure_core_dpll); return _omap3_sram_configure_core_dpll(sdrc_rfr_ctrl, sdrc_actim_ctrla, sdrc_actim_ctrlb, m2); -- cgit v1.2.3-70-g09d2 From 8f9ccfeeb2cecb54dd093119291ab271ab0fd94a Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Mon, 25 May 2009 11:26:48 -0700 Subject: ARM: OMAP: Remove unnecessary omap2_globals. This patch removes unnecessary omap2_globals and pass the global structures directly as function argument. The proposed cleanup was suggested by Russell King Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/common.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index e1add789835..70b68ef8320 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -287,9 +287,7 @@ arch_initcall(omap_init_clocksource_32k); #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -static struct omap_globals *omap2_globals; - -static void __init __omap2_set_globals(void) +static void __init __omap2_set_globals(struct omap_globals *omap2_globals) { omap2_set_globals_tap(omap2_globals); omap2_set_globals_sdrc(omap2_globals); @@ -313,8 +311,7 @@ static struct omap_globals omap242x_globals = { void __init omap2_set_globals_242x(void) { - omap2_globals = &omap242x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap242x_globals); } #endif @@ -332,8 +329,7 @@ static struct omap_globals omap243x_globals = { void __init omap2_set_globals_243x(void) { - omap2_globals = &omap243x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap243x_globals); } #endif @@ -351,8 +347,7 @@ static struct omap_globals omap343x_globals = { void __init omap2_set_globals_343x(void) { - omap2_globals = &omap343x_globals; - __omap2_set_globals(); + __omap2_set_globals(&omap343x_globals); } #endif -- cgit v1.2.3-70-g09d2 From 8bd229492209c0c7d050e2f9a600c12f035d72f7 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 28 May 2009 10:56:16 -0700 Subject: OMAP2/3: PM: push core PM code from linux-omap This patch is to sync the core linux-omap PM code with mainline. This code has evolved and been used for a while the linux-omap tree, but the attempt here is to finally get this into mainline. Following this will be a series of patches from the 'PM branch' of the linux-omap tree to add full PM hardware support from the linux-omap tree. Much of this PM core code was written by Jouni Hogander with significant contributions from Paul Walmsley as well as many others from Nokia, Texas Instruments and linux-omap community. Signed-off-by: Jouni Hogander Cc: Paul Walmsley Signed-off-by: Kevin Hilman --- arch/arm/mach-omap1/pm.h | 345 ++++++++++++++++++++ arch/arm/mach-omap2/Makefile | 4 +- arch/arm/mach-omap2/pm-debug.c | 152 +++++++++ arch/arm/mach-omap2/pm.c | 111 ------- arch/arm/mach-omap2/pm.h | 38 +++ arch/arm/mach-omap2/pm24xx.c | 548 +++++++++++++++++++++++++++++++ arch/arm/mach-omap2/pm34xx.c | 606 +++++++++++++++++++++++++++++++++++ arch/arm/mach-omap2/prcm-common.h | 2 + arch/arm/mach-omap2/sdrc.c | 5 +- arch/arm/mach-omap2/sleep24xx.S | 1 - arch/arm/mach-omap2/sleep34xx.S | 436 +++++++++++++++++++++++++ arch/arm/mach-omap2/usb-musb.c | 1 - arch/arm/plat-omap/Kconfig | 2 +- arch/arm/plat-omap/common.c | 1 - arch/arm/plat-omap/include/mach/pm.h | 345 -------------------- drivers/mtd/onenand/omap2.c | 1 - 16 files changed, 2135 insertions(+), 463 deletions(-) create mode 100644 arch/arm/mach-omap1/pm.h create mode 100644 arch/arm/mach-omap2/pm-debug.c delete mode 100644 arch/arm/mach-omap2/pm.c create mode 100644 arch/arm/mach-omap2/pm.h create mode 100644 arch/arm/mach-omap2/pm24xx.c create mode 100644 arch/arm/mach-omap2/pm34xx.c create mode 100644 arch/arm/mach-omap2/sleep34xx.S delete mode 100644 arch/arm/plat-omap/include/mach/pm.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap1/pm.h b/arch/arm/mach-omap1/pm.h new file mode 100644 index 00000000000..ce6ee792753 --- /dev/null +++ b/arch/arm/mach-omap1/pm.h @@ -0,0 +1,345 @@ +/* + * arch/arm/plat-omap/include/mach/pm.h + * + * Header file for OMAP Power Management Routines + * + * Author: MontaVista Software, Inc. + * support@mvista.com + * + * Copyright 2002 MontaVista Software Inc. + * + * Cleanup 2004 for Linux 2.6 by Dirk Behme + * + * 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 of the License, or (at your + * option) any later version. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ASM_ARCH_OMAP_PM_H +#define __ASM_ARCH_OMAP_PM_H + +/* + * ---------------------------------------------------------------------------- + * Register and offset definitions to be used in PM assembler code + * ---------------------------------------------------------------------------- + */ +#define CLKGEN_REG_ASM_BASE IO_ADDRESS(0xfffece00) +#define ARM_IDLECT1_ASM_OFFSET 0x04 +#define ARM_IDLECT2_ASM_OFFSET 0x08 + +#define TCMIF_ASM_BASE IO_ADDRESS(0xfffecc00) +#define EMIFS_CONFIG_ASM_OFFSET 0x0c +#define EMIFF_SDRAM_CONFIG_ASM_OFFSET 0x20 + +/* + * ---------------------------------------------------------------------------- + * Power management bitmasks + * ---------------------------------------------------------------------------- + */ +#define IDLE_WAIT_CYCLES 0x00000fff +#define PERIPHERAL_ENABLE 0x2 + +#define SELF_REFRESH_MODE 0x0c000001 +#define IDLE_EMIFS_REQUEST 0xc +#define MODEM_32K_EN 0x1 +#define PER_EN 0x1 + +#define CPU_SUSPEND_SIZE 200 +#define ULPD_LOW_PWR_EN 0x0001 +#define ULPD_DEEP_SLEEP_TRANSITION_EN 0x0010 +#define ULPD_SETUP_ANALOG_CELL_3_VAL 0 +#define ULPD_POWER_CTRL_REG_VAL 0x0219 + +#define DSP_IDLE_DELAY 10 +#define DSP_IDLE 0x0040 +#define DSP_RST 0x0004 +#define DSP_ENABLE 0x0002 +#define SUFFICIENT_DSP_RESET_TIME 1000 +#define DEFAULT_MPUI_CONFIG 0x05cf +#define ENABLE_XORCLK 0x2 +#define DSP_CLOCK_ENABLE 0x2000 +#define DSP_IDLE_MODE 0x2 +#define TC_IDLE_REQUEST (0x0000000c) + +#define IRQ_LEVEL2 (1<<0) +#define IRQ_KEYBOARD (1<<1) +#define IRQ_UART2 (1<<15) + +#define PDE_BIT 0x08 +#define PWD_EN_BIT 0x04 +#define EN_PERCK_BIT 0x04 + +#define OMAP1510_DEEP_SLEEP_REQUEST 0x0ec7 +#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5 +#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00 +#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2 + +/* Both big sleep and deep sleep use same values. Difference is in ULPD. */ +#define OMAP1610_IDLECT1_SLEEP_VAL 0x13c7 +#define OMAP1610_IDLECT2_SLEEP_VAL 0x09c7 +#define OMAP1610_IDLECT3_VAL 0x3f +#define OMAP1610_IDLECT3_SLEEP_ORMASK 0x2c +#define OMAP1610_IDLECT3 0xfffece24 +#define OMAP1610_IDLE_LOOP_REQUEST 0x0400 + +#define OMAP730_IDLECT1_SLEEP_VAL 0x16c7 +#define OMAP730_IDLECT2_SLEEP_VAL 0x09c7 +#define OMAP730_IDLECT3_VAL 0x3f +#define OMAP730_IDLECT3 0xfffece24 +#define OMAP730_IDLE_LOOP_REQUEST 0x0C00 + +#if !defined(CONFIG_ARCH_OMAP730) && \ + !defined(CONFIG_ARCH_OMAP15XX) && \ + !defined(CONFIG_ARCH_OMAP16XX) && \ + !defined(CONFIG_ARCH_OMAP24XX) +#warning "Power management for this processor not implemented yet" +#endif + +#ifndef __ASSEMBLER__ + +#include + +extern void prevent_idle_sleep(void); +extern void allow_idle_sleep(void); + +extern void omap_pm_idle(void); +extern void omap_pm_suspend(void); +extern void omap730_cpu_suspend(unsigned short, unsigned short); +extern void omap1510_cpu_suspend(unsigned short, unsigned short); +extern void omap1610_cpu_suspend(unsigned short, unsigned short); +extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, + void __iomem *sdrc_power); +extern void omap730_idle_loop_suspend(void); +extern void omap1510_idle_loop_suspend(void); +extern void omap1610_idle_loop_suspend(void); +extern void omap24xx_idle_loop_suspend(void); + +extern unsigned int omap730_cpu_suspend_sz; +extern unsigned int omap1510_cpu_suspend_sz; +extern unsigned int omap1610_cpu_suspend_sz; +extern unsigned int omap24xx_cpu_suspend_sz; +extern unsigned int omap730_idle_loop_suspend_sz; +extern unsigned int omap1510_idle_loop_suspend_sz; +extern unsigned int omap1610_idle_loop_suspend_sz; +extern unsigned int omap24xx_idle_loop_suspend_sz; + +#ifdef CONFIG_OMAP_SERIAL_WAKE +extern void omap_serial_wake_trigger(int enable); +#else +#define omap_serial_wakeup_init() {} +#define omap_serial_wake_trigger(x) {} +#endif /* CONFIG_OMAP_SERIAL_WAKE */ + +#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x) +#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x)) +#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] + +#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x) +#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x)) +#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] + +#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x) +#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) +#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] + +#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x) +#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x)) +#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] + +#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x) +#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x)) +#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] + +#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x) +#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x)) +#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] + +#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x +#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] +#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] + +/* + * List of global OMAP registers to preserve. + * More ones like CP and general purpose register values are preserved + * with the stack pointer in sleep.S. + */ + +enum arm_save_state { + ARM_SLEEP_SAVE_START = 0, + /* + * MPU control registers 32 bits + */ + ARM_SLEEP_SAVE_ARM_CKCTL, + ARM_SLEEP_SAVE_ARM_IDLECT1, + ARM_SLEEP_SAVE_ARM_IDLECT2, + ARM_SLEEP_SAVE_ARM_IDLECT3, + ARM_SLEEP_SAVE_ARM_EWUPCT, + ARM_SLEEP_SAVE_ARM_RSTCT1, + ARM_SLEEP_SAVE_ARM_RSTCT2, + ARM_SLEEP_SAVE_ARM_SYSST, + ARM_SLEEP_SAVE_SIZE +}; + +enum dsp_save_state { + DSP_SLEEP_SAVE_START = 0, + /* + * DSP registers 16 bits + */ + DSP_SLEEP_SAVE_DSP_IDLECT2, + DSP_SLEEP_SAVE_SIZE +}; + +enum ulpd_save_state { + ULPD_SLEEP_SAVE_START = 0, + /* + * ULPD registers 16 bits + */ + ULPD_SLEEP_SAVE_ULPD_IT_STATUS, + ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL, + ULPD_SLEEP_SAVE_ULPD_SOFT_REQ, + ULPD_SLEEP_SAVE_ULPD_STATUS_REQ, + ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL, + ULPD_SLEEP_SAVE_ULPD_POWER_CTRL, + ULPD_SLEEP_SAVE_SIZE +}; + +enum mpui1510_save_state { + MPUI1510_SLEEP_SAVE_START = 0, + /* + * MPUI registers 32 bits + */ + MPUI1510_SLEEP_SAVE_MPUI_CTRL, + MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, + MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG, + MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS, + MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, + MPUI1510_SLEEP_SAVE_EMIFS_CONFIG, + MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR, + MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR, +#if defined(CONFIG_ARCH_OMAP15XX) + MPUI1510_SLEEP_SAVE_SIZE +#else + MPUI1510_SLEEP_SAVE_SIZE = 0 +#endif +}; + +enum mpui730_save_state { + MPUI730_SLEEP_SAVE_START = 0, + /* + * MPUI registers 32 bits + */ + MPUI730_SLEEP_SAVE_MPUI_CTRL, + MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, + MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG, + MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS, + MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, + MPUI730_SLEEP_SAVE_EMIFS_CONFIG, + MPUI730_SLEEP_SAVE_OMAP_IH1_MIR, + MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR, + MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR, +#if defined(CONFIG_ARCH_OMAP730) + MPUI730_SLEEP_SAVE_SIZE +#else + MPUI730_SLEEP_SAVE_SIZE = 0 +#endif +}; + +enum mpui1610_save_state { + MPUI1610_SLEEP_SAVE_START = 0, + /* + * MPUI registers 32 bits + */ + MPUI1610_SLEEP_SAVE_MPUI_CTRL, + MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, + MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG, + MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS, + MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, + MPUI1610_SLEEP_SAVE_EMIFS_CONFIG, + MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR, + MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR, + MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR, + MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR, + MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR, +#if defined(CONFIG_ARCH_OMAP16XX) + MPUI1610_SLEEP_SAVE_SIZE +#else + MPUI1610_SLEEP_SAVE_SIZE = 0 +#endif +}; + +enum omap24xx_save_state { + OMAP24XX_SLEEP_SAVE_START = 0, + OMAP24XX_SLEEP_SAVE_INTC_MIR0, + OMAP24XX_SLEEP_SAVE_INTC_MIR1, + OMAP24XX_SLEEP_SAVE_INTC_MIR2, + + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MPU, + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE, + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX, + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP, + OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM, + + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU, + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE, + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX, + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP, + OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM, + + OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE, + OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE, + OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE, + OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE, + OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX, + OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP, + OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN, + OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP, + OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM, + + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP, + OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM, + + OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE, + OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE, + OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE, + OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE, + OMAP24XX_SLEEP_SAVE_CM_ICLKEN3_CORE, + OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE, + OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1, + OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1, + OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1, + OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1, + OMAP24XX_SLEEP_SAVE_GPIO3_OE, + OMAP24XX_SLEEP_SAVE_GPIO4_OE, + OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT, + OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT, + OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2, + OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX, + OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX, + OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0, + OMAP24XX_SLEEP_SAVE_SIZE +}; + +#endif /* ASSEMBLER */ +#endif /* __ASM_ARCH_OMAP_PM_H */ diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bf3827ae2c5..6fd1c1f7739 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -25,8 +25,10 @@ obj-$(CONFIG_ARCH_OMAP2) += sdrc2xxx.o # Power Management ifeq ($(CONFIG_PM),y) -obj-y += pm.o +obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o obj-$(CONFIG_ARCH_OMAP24XX) += sleep24xx.o +obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o +obj-$(CONFIG_PM_DEBUG) += pm-debug.o endif # Clock framework diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c new file mode 100644 index 00000000000..6cc375a275b --- /dev/null +++ b/arch/arm/mach-omap2/pm-debug.c @@ -0,0 +1,152 @@ +/* + * OMAP Power Management debug routines + * + * Copyright (C) 2005 Texas Instruments, Inc. + * Copyright (C) 2006-2008 Nokia Corporation + * + * Written by: + * Richard Woodruff + * Tony Lindgren + * Juha Yrjola + * Amit Kucheria + * Igor Stoppa + * Jouni Hogander + * + * Based on pm.c for omap2 + * + * 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 +#include +#include +#include +#include + +#include +#include + +#include "prm.h" +#include "cm.h" +#include "pm.h" + +int omap2_pm_debug; + +#define DUMP_PRM_MOD_REG(mod, reg) \ + regs[reg_count].name = #mod "." #reg; \ + regs[reg_count++].val = prm_read_mod_reg(mod, reg) +#define DUMP_CM_MOD_REG(mod, reg) \ + regs[reg_count].name = #mod "." #reg; \ + regs[reg_count++].val = cm_read_mod_reg(mod, reg) +#define DUMP_PRM_REG(reg) \ + regs[reg_count].name = #reg; \ + regs[reg_count++].val = __raw_readl(reg) +#define DUMP_CM_REG(reg) \ + regs[reg_count].name = #reg; \ + regs[reg_count++].val = __raw_readl(reg) +#define DUMP_INTC_REG(reg, off) \ + regs[reg_count].name = #reg; \ + regs[reg_count++].val = __raw_readl(IO_ADDRESS(0x480fe000 + (off))) + +void omap2_pm_dump(int mode, int resume, unsigned int us) +{ + struct reg { + const char *name; + u32 val; + } regs[32]; + int reg_count = 0, i; + const char *s1 = NULL, *s2 = NULL; + + if (!resume) { +#if 0 + /* MPU */ + DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRM_IRQENABLE_MPU_OFFSET); + DUMP_CM_MOD_REG(MPU_MOD, CM_CLKSTCTRL); + DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTCTRL); + DUMP_PRM_MOD_REG(MPU_MOD, PM_PWSTST); + DUMP_PRM_MOD_REG(MPU_MOD, PM_WKDEP); +#endif +#if 0 + /* INTC */ + DUMP_INTC_REG(INTC_MIR0, 0x0084); + DUMP_INTC_REG(INTC_MIR1, 0x00a4); + DUMP_INTC_REG(INTC_MIR2, 0x00c4); +#endif +#if 0 + DUMP_CM_MOD_REG(CORE_MOD, CM_FCLKEN1); + if (cpu_is_omap24xx()) { + DUMP_CM_MOD_REG(CORE_MOD, OMAP24XX_CM_FCLKEN2); + DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD, + OMAP2_PRCM_CLKEMUL_CTRL_OFFSET); + DUMP_PRM_MOD_REG(OMAP24XX_GR_MOD, + OMAP2_PRCM_CLKSRC_CTRL_OFFSET); + } + DUMP_CM_MOD_REG(WKUP_MOD, CM_FCLKEN); + DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN1); + DUMP_CM_MOD_REG(CORE_MOD, CM_ICLKEN2); + DUMP_CM_MOD_REG(WKUP_MOD, CM_ICLKEN); + DUMP_CM_MOD_REG(PLL_MOD, CM_CLKEN); + DUMP_CM_MOD_REG(PLL_MOD, CM_AUTOIDLE); + DUMP_PRM_MOD_REG(CORE_MOD, PM_PWSTST); +#endif +#if 0 + /* DSP */ + if (cpu_is_omap24xx()) { + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_FCLKEN); + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_ICLKEN); + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_IDLEST); + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_AUTOIDLE); + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSEL); + DUMP_CM_MOD_REG(OMAP24XX_DSP_MOD, CM_CLKSTCTRL); + DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTCTRL); + DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, RM_RSTST); + DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTCTRL); + DUMP_PRM_MOD_REG(OMAP24XX_DSP_MOD, PM_PWSTST); + } +#endif + } else { + DUMP_PRM_MOD_REG(CORE_MOD, PM_WKST1); + if (cpu_is_omap24xx()) + DUMP_PRM_MOD_REG(CORE_MOD, OMAP24XX_PM_WKST2); + DUMP_PRM_MOD_REG(WKUP_MOD, PM_WKST); + DUMP_PRM_MOD_REG(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); +#if 1 + DUMP_INTC_REG(INTC_PENDING_IRQ0, 0x0098); + DUMP_INTC_REG(INTC_PENDING_IRQ1, 0x00b8); + DUMP_INTC_REG(INTC_PENDING_IRQ2, 0x00d8); +#endif + } + + switch (mode) { + case 0: + s1 = "full"; + s2 = "retention"; + break; + case 1: + s1 = "MPU"; + s2 = "retention"; + break; + case 2: + s1 = "MPU"; + s2 = "idle"; + break; + } + + if (!resume) +#ifdef CONFIG_NO_HZ + printk(KERN_INFO + "--- Going to %s %s (next timer after %u ms)\n", s1, s2, + jiffies_to_msecs(get_next_timer_interrupt(jiffies) - + jiffies)); +#else + printk(KERN_INFO "--- Going to %s %s\n", s1, s2); +#endif + else + printk(KERN_INFO "--- Woke up (slept for %u.%03u ms)\n", + us / 1000, us % 1000); + + for (i = 0; i < reg_count; i++) + printk(KERN_INFO "%-20s: 0x%08x\n", regs[i].name, regs[i].val); +} diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c deleted file mode 100644 index ea8ceaed09c..00000000000 --- a/arch/arm/mach-omap2/pm.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * linux/arch/arm/mach-omap2/pm.c - * - * OMAP2 Power Management Routines - * - * Copyright (C) 2006 Nokia Corporation - * Tony Lindgren - * - * Copyright (C) 2005 Texas Instruments, Inc. - * Richard Woodruff - * - * Based on pm.c for omap1 - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct clk *vclk; -static void (*omap2_sram_idle)(void); -static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev); -static void (*saved_idle)(void); - -extern void __init pmdomain_init(void); -extern void pmdomain_set_autoidle(void); - -static unsigned int omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_SIZE]; - -void omap2_pm_idle(void) -{ - local_irq_disable(); - local_fiq_disable(); - if (need_resched()) { - local_fiq_enable(); - local_irq_enable(); - return; - } - - omap2_sram_idle(); - local_fiq_enable(); - local_irq_enable(); -} - -static int omap2_pm_prepare(void) -{ - /* We cannot sleep in idle until we have resumed */ - saved_idle = pm_idle; - pm_idle = NULL; - return 0; -} - -static int omap2_pm_suspend(void) -{ - return 0; -} - -static int omap2_pm_enter(suspend_state_t state) -{ - int ret = 0; - - switch (state) - { - case PM_SUSPEND_STANDBY: - case PM_SUSPEND_MEM: - ret = omap2_pm_suspend(); - break; - default: - ret = -EINVAL; - } - - return ret; -} - -static void omap2_pm_finish(void) -{ - pm_idle = saved_idle; -} - -static struct platform_suspend_ops omap_pm_ops = { - .prepare = omap2_pm_prepare, - .enter = omap2_pm_enter, - .finish = omap2_pm_finish, - .valid = suspend_valid_only_mem, -}; - -static int __init omap2_pm_init(void) -{ - return 0; -} - -__initcall(omap2_pm_init); diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h new file mode 100644 index 00000000000..f7b3baf7667 --- /dev/null +++ b/arch/arm/mach-omap2/pm.h @@ -0,0 +1,38 @@ +/* + * OMAP2/3 Power Management Routines + * + * Copyright (C) 2008 Nokia Corporation + * Jouni Hogander + * + * 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. + */ +#ifndef __ARCH_ARM_MACH_OMAP2_PM_H +#define __ARCH_ARM_MACH_OMAP2_PM_H + +extern int omap2_pm_init(void); +extern int omap3_pm_init(void); + +#ifdef CONFIG_PM_DEBUG +extern void omap2_pm_dump(int mode, int resume, unsigned int us); +extern int omap2_pm_debug; +#else +#define omap2_pm_dump(mode, resume, us) do {} while (0); +#define omap2_pm_debug 0 +#endif /* CONFIG_PM_DEBUG */ + +extern void omap24xx_idle_loop_suspend(void); + +extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, + void __iomem *sdrc_power); +extern void omap34xx_cpu_suspend(u32 *addr, int save_state); +extern void save_secure_ram_context(u32 *addr); + +extern unsigned int omap24xx_idle_loop_suspend_sz; +extern unsigned int omap34xx_suspend_sz; +extern unsigned int save_secure_ram_context_sz; +extern unsigned int omap24xx_cpu_suspend_sz; +extern unsigned int omap34xx_cpu_suspend_sz; + +#endif diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c new file mode 100644 index 00000000000..232b9f6032e --- /dev/null +++ b/arch/arm/mach-omap2/pm24xx.c @@ -0,0 +1,548 @@ +/* + * OMAP2 Power Management Routines + * + * Copyright (C) 2005 Texas Instruments, Inc. + * Copyright (C) 2006-2008 Nokia Corporation + * + * Written by: + * Richard Woodruff + * Tony Lindgren + * Juha Yrjola + * Amit Kucheria + * Igor Stoppa + * + * Based on pm.c for omap1 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "prm.h" +#include "prm-regbits-24xx.h" +#include "cm.h" +#include "cm-regbits-24xx.h" +#include "sdrc.h" +#include "pm.h" + +#include +#include + +static void (*omap2_sram_idle)(void); +static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl, + void __iomem *sdrc_power); + +static struct powerdomain *mpu_pwrdm; +static struct powerdomain *core_pwrdm; + +static struct clockdomain *dsp_clkdm; +static struct clockdomain *gfx_clkdm; + +static struct clk *osc_ck, *emul_ck; + +static int omap2_fclks_active(void) +{ + u32 f1, f2; + + f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); + f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); + if (f1 | f2) + return 1; + return 0; +} + +static int omap2_irq_pending(void) +{ + u32 pending_reg = 0x480fe098; + int i; + + for (i = 0; i < 4; i++) { + if (omap_readl(pending_reg)) + return 1; + pending_reg += 0x20; + } + return 0; +} + +static void omap2_enter_full_retention(void) +{ + u32 l; + struct timespec ts_preidle, ts_postidle, ts_idle; + + /* There is 1 reference hold for all children of the oscillator + * clock, the following will remove it. If no one else uses the + * oscillator itself it will be disabled if/when we enter retention + * mode. + */ + clk_disable(osc_ck); + + /* Clear old wake-up events */ + /* REVISIT: These write to reserved bits? */ + prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); + prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); + prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST); + + /* + * Set MPU powerdomain's next power state to RETENTION; + * preserve logic state during retention + */ + pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); + + /* Workaround to kill USB */ + l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL; + omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0); + + omap2_gpio_prepare_for_retention(); + + if (omap2_pm_debug) { + omap2_pm_dump(0, 0, 0); + getnstimeofday(&ts_preidle); + } + + /* One last check for pending IRQs to avoid extra latency due + * to sleeping unnecessarily. */ + if (omap2_irq_pending()) + goto no_sleep; + + /* Jump to SRAM suspend code */ + omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), + OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), + OMAP_SDRC_REGADDR(SDRC_POWER)); +no_sleep: + + if (omap2_pm_debug) { + unsigned long long tmp; + + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; + omap2_pm_dump(0, 1, tmp); + } + omap2_gpio_resume_after_retention(); + + clk_enable(osc_ck); + + /* clear CORE wake-up events */ + prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); + prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); + + /* wakeup domain events - bit 1: GPT1, bit5 GPIO */ + prm_clear_mod_reg_bits(0x4 | 0x1, WKUP_MOD, PM_WKST); + + /* MPU domain wake events */ + l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); + if (l & 0x01) + prm_write_mod_reg(0x01, OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); + if (l & 0x20) + prm_write_mod_reg(0x20, OCP_MOD, + OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); + + /* Mask future PRCM-to-MPU interrupts */ + prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET); +} + +static int omap2_i2c_active(void) +{ + u32 l; + + l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); + return l & (OMAP2420_EN_I2C2 | OMAP2420_EN_I2C1); +} + +static int sti_console_enabled; + +static int omap2_allow_mpu_retention(void) +{ + u32 l; + + /* Check for MMC, UART2, UART1, McSPI2, McSPI1 and DSS1. */ + l = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); + if (l & (OMAP2420_EN_MMC | OMAP24XX_EN_UART2 | + OMAP24XX_EN_UART1 | OMAP24XX_EN_MCSPI2 | + OMAP24XX_EN_MCSPI1 | OMAP24XX_EN_DSS1)) + return 0; + /* Check for UART3. */ + l = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); + if (l & OMAP24XX_EN_UART3) + return 0; + if (sti_console_enabled) + return 0; + + return 1; +} + +static void omap2_enter_mpu_retention(void) +{ + int only_idle = 0; + struct timespec ts_preidle, ts_postidle, ts_idle; + + /* Putting MPU into the WFI state while a transfer is active + * seems to cause the I2C block to timeout. Why? Good question. */ + if (omap2_i2c_active()) + return; + + /* The peripherals seem not to be able to wake up the MPU when + * it is in retention mode. */ + if (omap2_allow_mpu_retention()) { + /* REVISIT: These write to reserved bits? */ + prm_write_mod_reg(0xffffffff, CORE_MOD, PM_WKST1); + prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2); + prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST); + + /* Try to enter MPU retention */ + prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) | + OMAP_LOGICRETSTATE, + MPU_MOD, PM_PWSTCTRL); + } else { + /* Block MPU retention */ + + prm_write_mod_reg(OMAP_LOGICRETSTATE, MPU_MOD, PM_PWSTCTRL); + only_idle = 1; + } + + if (omap2_pm_debug) { + omap2_pm_dump(only_idle ? 2 : 1, 0, 0); + getnstimeofday(&ts_preidle); + } + + omap2_sram_idle(); + + if (omap2_pm_debug) { + unsigned long long tmp; + + getnstimeofday(&ts_postidle); + ts_idle = timespec_sub(ts_postidle, ts_preidle); + tmp = timespec_to_ns(&ts_idle) * NSEC_PER_USEC; + omap2_pm_dump(only_idle ? 2 : 1, 1, tmp); + } +} + +static int omap2_can_sleep(void) +{ + if (omap2_fclks_active()) + return 0; + if (osc_ck->usecount > 1) + return 0; + if (omap_dma_running()) + return 0; + + return 1; +} + +static void omap2_pm_idle(void) +{ + local_irq_disable(); + local_fiq_disable(); + + if (!omap2_can_sleep()) { + if (omap2_irq_pending()) + goto out; + omap2_enter_mpu_retention(); + goto out; + } + + if (omap2_irq_pending()) + goto out; + + omap2_enter_full_retention(); + +out: + local_fiq_enable(); + local_irq_enable(); +} + +static int omap2_pm_prepare(void) +{ + /* We cannot sleep in idle until we have resumed */ + disable_hlt(); + return 0; +} + +static int omap2_pm_suspend(void) +{ + u32 wken_wkup, mir1; + + wken_wkup = prm_read_mod_reg(WKUP_MOD, PM_WKEN); + prm_write_mod_reg(wken_wkup & ~OMAP24XX_EN_GPT1, WKUP_MOD, PM_WKEN); + + /* Mask GPT1 */ + mir1 = omap_readl(0x480fe0a4); + omap_writel(1 << 5, 0x480fe0ac); + + omap2_enter_full_retention(); + + omap_writel(mir1, 0x480fe0a4); + prm_write_mod_reg(wken_wkup, WKUP_MOD, PM_WKEN); + + return 0; +} + +static int omap2_pm_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + ret = omap2_pm_suspend(); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static void omap2_pm_finish(void) +{ + enable_hlt(); +} + +static struct platform_suspend_ops omap_pm_ops = { + .prepare = omap2_pm_prepare, + .enter = omap2_pm_enter, + .finish = omap2_pm_finish, + .valid = suspend_valid_only_mem, +}; + +static int _pm_clkdm_enable_hwsup(struct clockdomain *clkdm) +{ + omap2_clkdm_allow_idle(clkdm); + return 0; +} + +static void __init prcm_setup_regs(void) +{ + int i, num_mem_banks; + struct powerdomain *pwrdm; + + /* Enable autoidle */ + prm_write_mod_reg(OMAP24XX_AUTOIDLE, OCP_MOD, + OMAP2_PRCM_SYSCONFIG_OFFSET); + + /* Set all domain wakeup dependencies */ + prm_write_mod_reg(OMAP_EN_WKUP_MASK, MPU_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP24XX_DSP_MOD, PM_WKDEP); + prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); + prm_write_mod_reg(0, CORE_MOD, PM_WKDEP); + if (cpu_is_omap2430()) + prm_write_mod_reg(0, OMAP2430_MDM_MOD, PM_WKDEP); + + /* + * Set CORE powerdomain memory banks to retain their contents + * during RETENTION + */ + num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm); + for (i = 0; i < num_mem_banks; i++) + pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET); + + /* Set CORE powerdomain's next power state to RETENTION */ + pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET); + + /* + * Set MPU powerdomain's next power state to RETENTION; + * preserve logic state during retention + */ + pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET); + pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET); + + /* Force-power down DSP, GFX powerdomains */ + + pwrdm = clkdm_get_pwrdm(dsp_clkdm); + pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); + omap2_clkdm_sleep(dsp_clkdm); + + pwrdm = clkdm_get_pwrdm(gfx_clkdm); + pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF); + omap2_clkdm_sleep(gfx_clkdm); + + /* Enable clockdomain hardware-supervised control for all clkdms */ + clkdm_for_each(_pm_clkdm_enable_hwsup); + + /* Enable clock autoidle for all domains */ + cm_write_mod_reg(OMAP24XX_AUTO_CAM | + OMAP24XX_AUTO_MAILBOXES | + OMAP24XX_AUTO_WDT4 | + OMAP2420_AUTO_WDT3 | + OMAP24XX_AUTO_MSPRO | + OMAP2420_AUTO_MMC | + OMAP24XX_AUTO_FAC | + OMAP2420_AUTO_EAC | + OMAP24XX_AUTO_HDQ | + OMAP24XX_AUTO_UART2 | + OMAP24XX_AUTO_UART1 | + OMAP24XX_AUTO_I2C2 | + OMAP24XX_AUTO_I2C1 | + OMAP24XX_AUTO_MCSPI2 | + OMAP24XX_AUTO_MCSPI1 | + OMAP24XX_AUTO_MCBSP2 | + OMAP24XX_AUTO_MCBSP1 | + OMAP24XX_AUTO_GPT12 | + OMAP24XX_AUTO_GPT11 | + OMAP24XX_AUTO_GPT10 | + OMAP24XX_AUTO_GPT9 | + OMAP24XX_AUTO_GPT8 | + OMAP24XX_AUTO_GPT7 | + OMAP24XX_AUTO_GPT6 | + OMAP24XX_AUTO_GPT5 | + OMAP24XX_AUTO_GPT4 | + OMAP24XX_AUTO_GPT3 | + OMAP24XX_AUTO_GPT2 | + OMAP2420_AUTO_VLYNQ | + OMAP24XX_AUTO_DSS, + CORE_MOD, CM_AUTOIDLE1); + cm_write_mod_reg(OMAP24XX_AUTO_UART3 | + OMAP24XX_AUTO_SSI | + OMAP24XX_AUTO_USB, + CORE_MOD, CM_AUTOIDLE2); + cm_write_mod_reg(OMAP24XX_AUTO_SDRC | + OMAP24XX_AUTO_GPMC | + OMAP24XX_AUTO_SDMA, + CORE_MOD, CM_AUTOIDLE3); + cm_write_mod_reg(OMAP24XX_AUTO_PKA | + OMAP24XX_AUTO_AES | + OMAP24XX_AUTO_RNG | + OMAP24XX_AUTO_SHA | + OMAP24XX_AUTO_DES, + CORE_MOD, OMAP24XX_CM_AUTOIDLE4); + + cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI, OMAP24XX_DSP_MOD, CM_AUTOIDLE); + + /* Put DPLL and both APLLs into autoidle mode */ + cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) | + (0x03 << OMAP24XX_AUTO_96M_SHIFT) | + (0x03 << OMAP24XX_AUTO_54M_SHIFT), + PLL_MOD, CM_AUTOIDLE); + + cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL | + OMAP24XX_AUTO_WDT1 | + OMAP24XX_AUTO_MPU_WDT | + OMAP24XX_AUTO_GPIOS | + OMAP24XX_AUTO_32KSYNC | + OMAP24XX_AUTO_GPT1, + WKUP_MOD, CM_AUTOIDLE); + + /* REVISIT: Configure number of 32 kHz clock cycles for sys_clk + * stabilisation */ + prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, + OMAP2_PRCM_CLKSSETUP_OFFSET); + + /* Configure automatic voltage transition */ + prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD, + OMAP2_PRCM_VOLTSETUP_OFFSET); + prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT | + (0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) | + OMAP24XX_MEMRETCTRL | + (0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) | + (0x0 << OMAP24XX_VOLT_LEVEL_SHIFT), + OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET); + + /* Enable wake-up events */ + prm_write_mod_reg(OMAP24XX_EN_GPIOS | OMAP24XX_EN_GPT1, + WKUP_MOD, PM_WKEN); +} + +int __init omap2_pm_init(void) +{ + u32 l; + + if (!cpu_is_omap24xx()) + return -ENODEV; + + printk(KERN_INFO "Power Management for OMAP2 initializing\n"); + l = prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET); + printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f); + + /* Look up important powerdomains, clockdomains */ + + mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); + if (!mpu_pwrdm) + pr_err("PM: mpu_pwrdm not found\n"); + + core_pwrdm = pwrdm_lookup("core_pwrdm"); + if (!core_pwrdm) + pr_err("PM: core_pwrdm not found\n"); + + dsp_clkdm = clkdm_lookup("dsp_clkdm"); + if (!dsp_clkdm) + pr_err("PM: mpu_clkdm not found\n"); + + gfx_clkdm = clkdm_lookup("gfx_clkdm"); + if (!gfx_clkdm) + pr_err("PM: gfx_clkdm not found\n"); + + + osc_ck = clk_get(NULL, "osc_ck"); + if (IS_ERR(osc_ck)) { + printk(KERN_ERR "could not get osc_ck\n"); + return -ENODEV; + } + + if (cpu_is_omap242x()) { + emul_ck = clk_get(NULL, "emul_ck"); + if (IS_ERR(emul_ck)) { + printk(KERN_ERR "could not get emul_ck\n"); + clk_put(osc_ck); + return -ENODEV; + } + } + + prcm_setup_regs(); + + /* Hack to prevent MPU retention when STI console is enabled. */ + { + const struct omap_sti_console_config *sti; + + sti = omap_get_config(OMAP_TAG_STI_CONSOLE, + struct omap_sti_console_config); + if (sti != NULL && sti->enable) + sti_console_enabled = 1; + } + + /* + * We copy the assembler sleep/wakeup routines to SRAM. + * These routines need to be in SRAM as that's the only + * memory the MPU can see when it wakes up. + */ + if (cpu_is_omap24xx()) { + omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend, + omap24xx_idle_loop_suspend_sz); + + omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend, + omap24xx_cpu_suspend_sz); + } + + suspend_set_ops(&omap_pm_ops); + pm_idle = omap2_pm_idle; + + return 0; +} + +late_initcall(omap2_pm_init); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c new file mode 100644 index 00000000000..4474947ddd6 --- /dev/null +++ b/arch/arm/mach-omap2/pm34xx.c @@ -0,0 +1,606 @@ +/* + * OMAP3 Power Management Routines + * + * Copyright (C) 2006-2008 Nokia Corporation + * Tony Lindgren + * Jouni Hogander + * + * Copyright (C) 2005 Texas Instruments, Inc. + * Richard Woodruff + * + * Based on pm.c for omap1 + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "cm.h" +#include "cm-regbits-34xx.h" +#include "prm-regbits-34xx.h" + +#include "prm.h" +#include "pm.h" + +struct power_state { + struct powerdomain *pwrdm; + u32 next_state; + u32 saved_state; + struct list_head node; +}; + +static LIST_HEAD(pwrst_list); + +static void (*_omap_sram_idle)(u32 *addr, int save_state); + +static struct powerdomain *mpu_pwrdm; + +/* PRCM Interrupt Handler for wakeups */ +static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id) +{ + u32 wkst, irqstatus_mpu; + u32 fclk, iclk; + + /* WKUP */ + wkst = prm_read_mod_reg(WKUP_MOD, PM_WKST); + if (wkst) { + iclk = cm_read_mod_reg(WKUP_MOD, CM_ICLKEN); + fclk = cm_read_mod_reg(WKUP_MOD, CM_FCLKEN); + cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_ICLKEN); + cm_set_mod_reg_bits(wkst, WKUP_MOD, CM_FCLKEN); + prm_write_mod_reg(wkst, WKUP_MOD, PM_WKST); + while (prm_read_mod_reg(WKUP_MOD, PM_WKST)) + cpu_relax(); + cm_write_mod_reg(iclk, WKUP_MOD, CM_ICLKEN); + cm_write_mod_reg(fclk, WKUP_MOD, CM_FCLKEN); + } + + /* CORE */ + wkst = prm_read_mod_reg(CORE_MOD, PM_WKST1); + if (wkst) { + iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN1); + fclk = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); + cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN1); + cm_set_mod_reg_bits(wkst, CORE_MOD, CM_FCLKEN1); + prm_write_mod_reg(wkst, CORE_MOD, PM_WKST1); + while (prm_read_mod_reg(CORE_MOD, PM_WKST1)) + cpu_relax(); + cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN1); + cm_write_mod_reg(fclk, CORE_MOD, CM_FCLKEN1); + } + wkst = prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3); + if (wkst) { + iclk = cm_read_mod_reg(CORE_MOD, CM_ICLKEN3); + fclk = cm_read_mod_reg(CORE_MOD, OMAP3430ES2_CM_FCLKEN3); + cm_set_mod_reg_bits(wkst, CORE_MOD, CM_ICLKEN3); + cm_set_mod_reg_bits(wkst, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); + prm_write_mod_reg(wkst, CORE_MOD, OMAP3430ES2_PM_WKST3); + while (prm_read_mod_reg(CORE_MOD, OMAP3430ES2_PM_WKST3)) + cpu_relax(); + cm_write_mod_reg(iclk, CORE_MOD, CM_ICLKEN3); + cm_write_mod_reg(fclk, CORE_MOD, OMAP3430ES2_CM_FCLKEN3); + } + + /* PER */ + wkst = prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST); + if (wkst) { + iclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_ICLKEN); + fclk = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN); + cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_ICLKEN); + cm_set_mod_reg_bits(wkst, OMAP3430_PER_MOD, CM_FCLKEN); + prm_write_mod_reg(wkst, OMAP3430_PER_MOD, PM_WKST); + while (prm_read_mod_reg(OMAP3430_PER_MOD, PM_WKST)) + cpu_relax(); + cm_write_mod_reg(iclk, OMAP3430_PER_MOD, CM_ICLKEN); + cm_write_mod_reg(fclk, OMAP3430_PER_MOD, CM_FCLKEN); + } + + if (omap_rev() > OMAP3430_REV_ES1_0) { + /* USBHOST */ + wkst = prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, PM_WKST); + if (wkst) { + iclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, + CM_ICLKEN); + fclk = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, + CM_FCLKEN); + cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, + CM_ICLKEN); + cm_set_mod_reg_bits(wkst, OMAP3430ES2_USBHOST_MOD, + CM_FCLKEN); + prm_write_mod_reg(wkst, OMAP3430ES2_USBHOST_MOD, + PM_WKST); + while (prm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, + PM_WKST)) + cpu_relax(); + cm_write_mod_reg(iclk, OMAP3430ES2_USBHOST_MOD, + CM_ICLKEN); + cm_write_mod_reg(fclk, OMAP3430ES2_USBHOST_MOD, + CM_FCLKEN); + } + } + + irqstatus_mpu = prm_read_mod_reg(OCP_MOD, + OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + prm_write_mod_reg(irqstatus_mpu, OCP_MOD, + OMAP3_PRM_IRQSTATUS_MPU_OFFSET); + + while (prm_read_mod_reg(OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET)) + cpu_relax(); + + return IRQ_HANDLED; +} + +static void omap_sram_idle(void) +{ + /* Variable to tell what needs to be saved and restored + * in omap_sram_idle*/ + /* save_state = 0 => Nothing to save and restored */ + /* save_state = 1 => Only L1 and logic lost */ + /* save_state = 2 => Only L2 lost */ + /* save_state = 3 => L1, L2 and logic lost */ + int save_state = 0, mpu_next_state; + + if (!_omap_sram_idle) + return; + + mpu_next_state = pwrdm_read_next_pwrst(mpu_pwrdm); + switch (mpu_next_state) { + case PWRDM_POWER_RET: + /* No need to save context */ + save_state = 0; + break; + default: + /* Invalid state */ + printk(KERN_ERR "Invalid mpu state in sram_idle\n"); + return; + } + omap2_gpio_prepare_for_retention(); + + _omap_sram_idle(NULL, save_state); + cpu_init(); + + omap2_gpio_resume_after_retention(); +} + +/* + * Check if functional clocks are enabled before entering + * sleep. This function could be behind CONFIG_PM_DEBUG + * when all drivers are configuring their sysconfig registers + * properly and using their clocks properly. + */ +static int omap3_fclks_active(void) +{ + u32 fck_core1 = 0, fck_core3 = 0, fck_sgx = 0, fck_dss = 0, + fck_cam = 0, fck_per = 0, fck_usbhost = 0; + + fck_core1 = cm_read_mod_reg(CORE_MOD, + CM_FCLKEN1); + if (omap_rev() > OMAP3430_REV_ES1_0) { + fck_core3 = cm_read_mod_reg(CORE_MOD, + OMAP3430ES2_CM_FCLKEN3); + fck_sgx = cm_read_mod_reg(OMAP3430ES2_SGX_MOD, + CM_FCLKEN); + fck_usbhost = cm_read_mod_reg(OMAP3430ES2_USBHOST_MOD, + CM_FCLKEN); + } else + fck_sgx = cm_read_mod_reg(GFX_MOD, + OMAP3430ES2_CM_FCLKEN3); + fck_dss = cm_read_mod_reg(OMAP3430_DSS_MOD, + CM_FCLKEN); + fck_cam = cm_read_mod_reg(OMAP3430_CAM_MOD, + CM_FCLKEN); + fck_per = cm_read_mod_reg(OMAP3430_PER_MOD, + CM_FCLKEN); + if (fck_core1 | fck_core3 | fck_sgx | fck_dss | + fck_cam | fck_per | fck_usbhost) + return 1; + return 0; +} + +static int omap3_can_sleep(void) +{ + if (omap3_fclks_active()) + return 0; + return 1; +} + +/* This sets pwrdm state (other than mpu & core. Currently only ON & + * RET are supported. Function is assuming that clkdm doesn't have + * hw_sup mode enabled. */ +static int set_pwrdm_state(struct powerdomain *pwrdm, u32 state) +{ + u32 cur_state; + int sleep_switch = 0; + int ret = 0; + + if (pwrdm == NULL || IS_ERR(pwrdm)) + return -EINVAL; + + while (!(pwrdm->pwrsts & (1 << state))) { + if (state == PWRDM_POWER_OFF) + return ret; + state--; + } + + cur_state = pwrdm_read_next_pwrst(pwrdm); + if (cur_state == state) + return ret; + + if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) { + omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]); + sleep_switch = 1; + pwrdm_wait_transition(pwrdm); + } + + ret = pwrdm_set_next_pwrst(pwrdm, state); + if (ret) { + printk(KERN_ERR "Unable to set state of powerdomain: %s\n", + pwrdm->name); + goto err; + } + + if (sleep_switch) { + omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]); + pwrdm_wait_transition(pwrdm); + } + +err: + return ret; +} + +static void omap3_pm_idle(void) +{ + local_irq_disable(); + local_fiq_disable(); + + if (!omap3_can_sleep()) + goto out; + + if (omap_irq_pending()) + goto out; + + omap_sram_idle(); + +out: + local_fiq_enable(); + local_irq_enable(); +} + +static int omap3_pm_prepare(void) +{ + disable_hlt(); + return 0; +} + +static int omap3_pm_suspend(void) +{ + struct power_state *pwrst; + int state, ret = 0; + + /* Read current next_pwrsts */ + list_for_each_entry(pwrst, &pwrst_list, node) + pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm); + /* Set ones wanted by suspend */ + list_for_each_entry(pwrst, &pwrst_list, node) { + if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state)) + goto restore; + if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm)) + goto restore; + } + + omap_sram_idle(); + +restore: + /* Restore next_pwrsts */ + list_for_each_entry(pwrst, &pwrst_list, node) { + set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state); + state = pwrdm_read_prev_pwrst(pwrst->pwrdm); + if (state > pwrst->next_state) { + printk(KERN_INFO "Powerdomain (%s) didn't enter " + "target state %d\n", + pwrst->pwrdm->name, pwrst->next_state); + ret = -1; + } + } + if (ret) + printk(KERN_ERR "Could not enter target state in pm_suspend\n"); + else + printk(KERN_INFO "Successfully put all powerdomains " + "to target state\n"); + + return ret; +} + +static int omap3_pm_enter(suspend_state_t state) +{ + int ret = 0; + + switch (state) { + case PM_SUSPEND_STANDBY: + case PM_SUSPEND_MEM: + ret = omap3_pm_suspend(); + break; + default: + ret = -EINVAL; + } + + return ret; +} + +static void omap3_pm_finish(void) +{ + enable_hlt(); +} + +static struct platform_suspend_ops omap_pm_ops = { + .prepare = omap3_pm_prepare, + .enter = omap3_pm_enter, + .finish = omap3_pm_finish, + .valid = suspend_valid_only_mem, +}; + +static void __init prcm_setup_regs(void) +{ + /* reset modem */ + prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON | + OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST, + CORE_MOD, RM_RSTCTRL); + prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL); + + /* XXX Reset all wkdeps. This should be done when initializing + * powerdomains */ + prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); + prm_write_mod_reg(0, MPU_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP); + if (omap_rev() > OMAP3430_REV_ES1_0) { + prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP); + prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP); + } else + prm_write_mod_reg(0, GFX_MOD, PM_WKDEP); + + /* + * Enable interface clock autoidle for all modules. + * Note that in the long run this should be done by clockfw + */ + cm_write_mod_reg( + OMAP3430ES2_AUTO_MMC3 | + OMAP3430ES2_AUTO_ICR | + OMAP3430_AUTO_AES2 | + OMAP3430_AUTO_SHA12 | + OMAP3430_AUTO_DES2 | + OMAP3430_AUTO_MMC2 | + OMAP3430_AUTO_MMC1 | + OMAP3430_AUTO_MSPRO | + OMAP3430_AUTO_HDQ | + OMAP3430_AUTO_MCSPI4 | + OMAP3430_AUTO_MCSPI3 | + OMAP3430_AUTO_MCSPI2 | + OMAP3430_AUTO_MCSPI1 | + OMAP3430_AUTO_I2C3 | + OMAP3430_AUTO_I2C2 | + OMAP3430_AUTO_I2C1 | + OMAP3430_AUTO_UART2 | + OMAP3430_AUTO_UART1 | + OMAP3430_AUTO_GPT11 | + OMAP3430_AUTO_GPT10 | + OMAP3430_AUTO_MCBSP5 | + OMAP3430_AUTO_MCBSP1 | + OMAP3430ES1_AUTO_FAC | /* This is es1 only */ + OMAP3430_AUTO_MAILBOXES | + OMAP3430_AUTO_OMAPCTRL | + OMAP3430ES1_AUTO_FSHOSTUSB | + OMAP3430_AUTO_HSOTGUSB | + OMAP3430ES1_AUTO_D2D | /* This is es1 only */ + OMAP3430_AUTO_SSI, + CORE_MOD, CM_AUTOIDLE1); + + cm_write_mod_reg( + OMAP3430_AUTO_PKA | + OMAP3430_AUTO_AES1 | + OMAP3430_AUTO_RNG | + OMAP3430_AUTO_SHA11 | + OMAP3430_AUTO_DES1, + CORE_MOD, CM_AUTOIDLE2); + + if (omap_rev() > OMAP3430_REV_ES1_0) { + cm_write_mod_reg( + OMAP3430ES2_AUTO_USBTLL, + CORE_MOD, CM_AUTOIDLE3); + } + + cm_write_mod_reg( + OMAP3430_AUTO_WDT2 | + OMAP3430_AUTO_WDT1 | + OMAP3430_AUTO_GPIO1 | + OMAP3430_AUTO_32KSYNC | + OMAP3430_AUTO_GPT12 | + OMAP3430_AUTO_GPT1 , + WKUP_MOD, CM_AUTOIDLE); + + cm_write_mod_reg( + OMAP3430_AUTO_DSS, + OMAP3430_DSS_MOD, + CM_AUTOIDLE); + + cm_write_mod_reg( + OMAP3430_AUTO_CAM, + OMAP3430_CAM_MOD, + CM_AUTOIDLE); + + cm_write_mod_reg( + OMAP3430_AUTO_GPIO6 | + OMAP3430_AUTO_GPIO5 | + OMAP3430_AUTO_GPIO4 | + OMAP3430_AUTO_GPIO3 | + OMAP3430_AUTO_GPIO2 | + OMAP3430_AUTO_WDT3 | + OMAP3430_AUTO_UART3 | + OMAP3430_AUTO_GPT9 | + OMAP3430_AUTO_GPT8 | + OMAP3430_AUTO_GPT7 | + OMAP3430_AUTO_GPT6 | + OMAP3430_AUTO_GPT5 | + OMAP3430_AUTO_GPT4 | + OMAP3430_AUTO_GPT3 | + OMAP3430_AUTO_GPT2 | + OMAP3430_AUTO_MCBSP4 | + OMAP3430_AUTO_MCBSP3 | + OMAP3430_AUTO_MCBSP2, + OMAP3430_PER_MOD, + CM_AUTOIDLE); + + if (omap_rev() > OMAP3430_REV_ES1_0) { + cm_write_mod_reg( + OMAP3430ES2_AUTO_USBHOST, + OMAP3430ES2_USBHOST_MOD, + CM_AUTOIDLE); + } + + /* + * Set all plls to autoidle. This is needed until autoidle is + * enabled by clockfw + */ + cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT, + OMAP3430_IVA2_MOD, CM_AUTOIDLE2); + cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT, + MPU_MOD, + CM_AUTOIDLE2); + cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) | + (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT), + PLL_MOD, + CM_AUTOIDLE); + cm_write_mod_reg(1 << OMAP3430ES2_AUTO_PERIPH2_DPLL_SHIFT, + PLL_MOD, + CM_AUTOIDLE2); + + /* + * Enable control of expternal oscillator through + * sys_clkreq. In the long run clock framework should + * take care of this. + */ + prm_rmw_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, + 1 << OMAP_AUTOEXTCLKMODE_SHIFT, + OMAP3430_GR_MOD, + OMAP3_PRM_CLKSRC_CTRL_OFFSET); + + /* setup wakup source */ + prm_write_mod_reg(OMAP3430_EN_IO | OMAP3430_EN_GPIO1 | + OMAP3430_EN_GPT1 | OMAP3430_EN_GPT12, + WKUP_MOD, PM_WKEN); + /* No need to write EN_IO, that is always enabled */ + prm_write_mod_reg(OMAP3430_EN_GPIO1 | OMAP3430_EN_GPT1 | + OMAP3430_EN_GPT12, + WKUP_MOD, OMAP3430_PM_MPUGRPSEL); + /* For some reason IO doesn't generate wakeup event even if + * it is selected to mpu wakeup goup */ + prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN, + OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); +} + +static int __init pwrdms_setup(struct powerdomain *pwrdm) +{ + struct power_state *pwrst; + + if (!pwrdm->pwrsts) + return 0; + + pwrst = kmalloc(sizeof(struct power_state), GFP_KERNEL); + if (!pwrst) + return -ENOMEM; + pwrst->pwrdm = pwrdm; + pwrst->next_state = PWRDM_POWER_RET; + list_add(&pwrst->node, &pwrst_list); + + if (pwrdm_has_hdwr_sar(pwrdm)) + pwrdm_enable_hdwr_sar(pwrdm); + + return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state); +} + +/* + * Enable hw supervised mode for all clockdomains if it's + * supported. Initiate sleep transition for other clockdomains, if + * they are not used + */ +static int __init clkdms_setup(struct clockdomain *clkdm) +{ + if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO) + omap2_clkdm_allow_idle(clkdm); + else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP && + atomic_read(&clkdm->usecount) == 0) + omap2_clkdm_sleep(clkdm); + return 0; +} + +int __init omap3_pm_init(void) +{ + struct power_state *pwrst, *tmp; + int ret; + + if (!cpu_is_omap34xx()) + return -ENODEV; + + printk(KERN_ERR "Power Management for TI OMAP3.\n"); + + /* XXX prcm_setup_regs needs to be before enabling hw + * supervised mode for powerdomains */ + prcm_setup_regs(); + + ret = request_irq(INT_34XX_PRCM_MPU_IRQ, + (irq_handler_t)prcm_interrupt_handler, + IRQF_DISABLED, "prcm", NULL); + if (ret) { + printk(KERN_ERR "request_irq failed to register for 0x%x\n", + INT_34XX_PRCM_MPU_IRQ); + goto err1; + } + + ret = pwrdm_for_each(pwrdms_setup); + if (ret) { + printk(KERN_ERR "Failed to setup powerdomains\n"); + goto err2; + } + + (void) clkdm_for_each(clkdms_setup); + + mpu_pwrdm = pwrdm_lookup("mpu_pwrdm"); + if (mpu_pwrdm == NULL) { + printk(KERN_ERR "Failed to get mpu_pwrdm\n"); + goto err2; + } + + _omap_sram_idle = omap_sram_push(omap34xx_cpu_suspend, + omap34xx_cpu_suspend_sz); + + suspend_set_ops(&omap_pm_ops); + + pm_idle = omap3_pm_idle; + +err1: + return ret; +err2: + free_irq(INT_34XX_PRCM_MPU_IRQ, NULL); + list_for_each_entry_safe(pwrst, tmp, &pwrst_list, node) { + list_del(&pwrst->node); + kfree(pwrst); + } + return ret; +} + +late_initcall(omap3_pm_init); diff --git a/arch/arm/mach-omap2/prcm-common.h b/arch/arm/mach-omap2/prcm-common.h index 812d50ee495..cb1ae84e092 100644 --- a/arch/arm/mach-omap2/prcm-common.h +++ b/arch/arm/mach-omap2/prcm-common.h @@ -276,6 +276,8 @@ /* CM_FCLKEN_WKUP, CM_ICLKEN_WKUP, PM_WKEN_WKUP shared bits */ #define OMAP3430_EN_GPIO1 (1 << 3) #define OMAP3430_EN_GPIO1_SHIFT 3 +#define OMAP3430_EN_GPT12 (1 << 1) +#define OMAP3430_EN_GPT12_SHIFT 1 #define OMAP3430_EN_GPT1 (1 << 0) #define OMAP3430_EN_GPT1_SHIFT 0 diff --git a/arch/arm/mach-omap2/sdrc.c b/arch/arm/mach-omap2/sdrc.c index d62e4e10d4b..2045441e838 100644 --- a/arch/arm/mach-omap2/sdrc.c +++ b/arch/arm/mach-omap2/sdrc.c @@ -60,9 +60,12 @@ struct omap_sdrc_params *omap2_sdrc_get_params(unsigned long r) { struct omap_sdrc_params *sp; + if (!sdrc_init_params) + return NULL; + sp = sdrc_init_params; - while (sp->rate != r) + while (sp->rate && sp->rate != r) sp++; if (!sp->rate) diff --git a/arch/arm/mach-omap2/sleep24xx.S b/arch/arm/mach-omap2/sleep24xx.S index bf9e96105e1..130aadbfa08 100644 --- a/arch/arm/mach-omap2/sleep24xx.S +++ b/arch/arm/mach-omap2/sleep24xx.S @@ -28,7 +28,6 @@ #include #include #include -#include #include diff --git a/arch/arm/mach-omap2/sleep34xx.S b/arch/arm/mach-omap2/sleep34xx.S new file mode 100644 index 00000000000..e5e2553e79a --- /dev/null +++ b/arch/arm/mach-omap2/sleep34xx.S @@ -0,0 +1,436 @@ +/* + * linux/arch/arm/mach-omap2/sleep.S + * + * (C) Copyright 2007 + * Texas Instruments + * Karthik Dasu + * + * (C) Copyright 2004 + * Texas Instruments, + * Richard Woodruff + * + * 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 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include +#include +#include +#include + +#include "prm.h" +#include "sdrc.h" + +#define PM_PREPWSTST_CORE_V OMAP34XX_PRM_REGADDR(CORE_MOD, \ + OMAP3430_PM_PREPWSTST) +#define PM_PREPWSTST_MPU_V OMAP34XX_PRM_REGADDR(MPU_MOD, \ + OMAP3430_PM_PREPWSTST) +#define PM_PWSTCTRL_MPU_P OMAP34XX_PRM_REGADDR(MPU_MOD, PM_PWSTCTRL) +#define SCRATCHPAD_MEM_OFFS 0x310 /* Move this as correct place is + * available */ +#define SCRATCHPAD_BASE_P OMAP343X_CTRL_REGADDR(\ + OMAP343X_CONTROL_MEM_WKUP +\ + SCRATCHPAD_MEM_OFFS) +#define SDRC_POWER_V OMAP34XX_SDRC_REGADDR(SDRC_POWER) + + .text +/* Function call to get the restore pointer for resume from OFF */ +ENTRY(get_restore_pointer) + stmfd sp!, {lr} @ save registers on stack + adr r0, restore + ldmfd sp!, {pc} @ restore regs and return +ENTRY(get_restore_pointer_sz) + .word . - get_restore_pointer_sz +/* + * Forces OMAP into idle state + * + * omap34xx_suspend() - This bit of code just executes the WFI + * for normal idles. + * + * Note: This code get's copied to internal SRAM at boot. When the OMAP + * wakes up it continues execution at the point it went to sleep. + */ +ENTRY(omap34xx_cpu_suspend) + stmfd sp!, {r0-r12, lr} @ save registers on stack +loop: + /*b loop*/ @Enable to debug by stepping through code + /* r0 contains restore pointer in sdram */ + /* r1 contains information about saving context */ + ldr r4, sdrc_power @ read the SDRC_POWER register + ldr r5, [r4] @ read the contents of SDRC_POWER + orr r5, r5, #0x40 @ enable self refresh on idle req + str r5, [r4] @ write back to SDRC_POWER register + + cmp r1, #0x0 + /* If context save is required, do that and execute wfi */ + bne save_context_wfi + /* Data memory barrier and Data sync barrier */ + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 + mcr p15, 0, r1, c7, c10, 5 + + wfi @ wait for interrupt + + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + bl i_dll_wait + + ldmfd sp!, {r0-r12, pc} @ restore regs and return +restore: + /* b restore*/ @ Enable to debug restore code + /* Check what was the reason for mpu reset and store the reason in r9*/ + /* 1 - Only L1 and logic lost */ + /* 2 - Only L2 lost - In this case, we wont be here */ + /* 3 - Both L1 and L2 lost */ + ldr r1, pm_pwstctrl_mpu + ldr r2, [r1] + and r2, r2, #0x3 + cmp r2, #0x0 @ Check if target power state was OFF or RET + moveq r9, #0x3 @ MPU OFF => L1 and L2 lost + movne r9, #0x1 @ Only L1 and L2 lost => avoid L2 invalidation + bne logic_l1_restore + /* Execute smi to invalidate L2 cache */ + mov r12, #0x1 @ set up to invalide L2 +smi: .word 0xE1600070 @ Call SMI monitor (smieq) +logic_l1_restore: + mov r1, #0 + /* Invalidate all instruction caches to PoU + * and flush branch target cache */ + mcr p15, 0, r1, c7, c5, 0 + + ldr r4, scratchpad_base + ldr r3, [r4,#0xBC] + ldmia r3!, {r4-r6} + mov sp, r4 + msr spsr_cxsf, r5 + mov lr, r6 + + ldmia r3!, {r4-r9} + /* Coprocessor access Control Register */ + mcr p15, 0, r4, c1, c0, 2 + + /* TTBR0 */ + MCR p15, 0, r5, c2, c0, 0 + /* TTBR1 */ + MCR p15, 0, r6, c2, c0, 1 + /* Translation table base control register */ + MCR p15, 0, r7, c2, c0, 2 + /*domain access Control Register */ + MCR p15, 0, r8, c3, c0, 0 + /* data fault status Register */ + MCR p15, 0, r9, c5, c0, 0 + + ldmia r3!,{r4-r8} + /* instruction fault status Register */ + MCR p15, 0, r4, c5, c0, 1 + /*Data Auxiliary Fault Status Register */ + MCR p15, 0, r5, c5, c1, 0 + /*Instruction Auxiliary Fault Status Register*/ + MCR p15, 0, r6, c5, c1, 1 + /*Data Fault Address Register */ + MCR p15, 0, r7, c6, c0, 0 + /*Instruction Fault Address Register*/ + MCR p15, 0, r8, c6, c0, 2 + ldmia r3!,{r4-r7} + + /* user r/w thread and process ID */ + MCR p15, 0, r4, c13, c0, 2 + /* user ro thread and process ID */ + MCR p15, 0, r5, c13, c0, 3 + /*Privileged only thread and process ID */ + MCR p15, 0, r6, c13, c0, 4 + /* cache size selection */ + MCR p15, 2, r7, c0, c0, 0 + ldmia r3!,{r4-r8} + /* Data TLB lockdown registers */ + MCR p15, 0, r4, c10, c0, 0 + /* Instruction TLB lockdown registers */ + MCR p15, 0, r5, c10, c0, 1 + /* Secure or Nonsecure Vector Base Address */ + MCR p15, 0, r6, c12, c0, 0 + /* FCSE PID */ + MCR p15, 0, r7, c13, c0, 0 + /* Context PID */ + MCR p15, 0, r8, c13, c0, 1 + + ldmia r3!,{r4-r5} + /* primary memory remap register */ + MCR p15, 0, r4, c10, c2, 0 + /*normal memory remap register */ + MCR p15, 0, r5, c10, c2, 1 + + /* Restore cpsr */ + ldmia r3!,{r4} /*load CPSR from SDRAM*/ + msr cpsr, r4 /*store cpsr */ + + /* Enabling MMU here */ + mrc p15, 0, r7, c2, c0, 2 /* Read TTBRControl */ + /* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1*/ + and r7, #0x7 + cmp r7, #0x0 + beq usettbr0 +ttbr_error: + /* More work needs to be done to support N[0:2] value other than 0 + * So looping here so that the error can be detected + */ + b ttbr_error +usettbr0: + mrc p15, 0, r2, c2, c0, 0 + ldr r5, ttbrbit_mask + and r2, r5 + mov r4, pc + ldr r5, table_index_mask + and r4, r5 /* r4 = 31 to 20 bits of pc */ + /* Extract the value to be written to table entry */ + ldr r1, table_entry + add r1, r1, r4 /* r1 has value to be written to table entry*/ + /* Getting the address of table entry to modify */ + lsr r4, #18 + add r2, r4 /* r2 has the location which needs to be modified */ + /* Storing previous entry of location being modified */ + ldr r5, scratchpad_base + ldr r4, [r2] + str r4, [r5, #0xC0] + /* Modify the table entry */ + str r1, [r2] + /* Storing address of entry being modified + * - will be restored after enabling MMU */ + ldr r5, scratchpad_base + str r2, [r5, #0xC4] + + mov r0, #0 + mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer + mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array + mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB + mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB + /* Restore control register but dont enable caches here*/ + /* Caches will be enabled after restoring MMU table entry */ + ldmia r3!, {r4} + /* Store previous value of control register in scratchpad */ + str r4, [r5, #0xC8] + ldr r2, cache_pred_disable_mask + and r4, r2 + mcr p15, 0, r4, c1, c0, 0 + + ldmfd sp!, {r0-r12, pc} @ restore regs and return +save_context_wfi: + /*b save_context_wfi*/ @ enable to debug save code + mov r8, r0 /* Store SDRAM address in r8 */ + /* Check what that target sleep state is:stored in r1*/ + /* 1 - Only L1 and logic lost */ + /* 2 - Only L2 lost */ + /* 3 - Both L1 and L2 lost */ + cmp r1, #0x2 /* Only L2 lost */ + beq clean_l2 + cmp r1, #0x1 /* L2 retained */ + /* r9 stores whether to clean L2 or not*/ + moveq r9, #0x0 /* Dont Clean L2 */ + movne r9, #0x1 /* Clean L2 */ +l1_logic_lost: + /* Store sp and spsr to SDRAM */ + mov r4, sp + mrs r5, spsr + mov r6, lr + stmia r8!, {r4-r6} + /* Save all ARM registers */ + /* Coprocessor access control register */ + mrc p15, 0, r6, c1, c0, 2 + stmia r8!, {r6} + /* TTBR0, TTBR1 and Translation table base control */ + mrc p15, 0, r4, c2, c0, 0 + mrc p15, 0, r5, c2, c0, 1 + mrc p15, 0, r6, c2, c0, 2 + stmia r8!, {r4-r6} + /* Domain access control register, data fault status register, + and instruction fault status register */ + mrc p15, 0, r4, c3, c0, 0 + mrc p15, 0, r5, c5, c0, 0 + mrc p15, 0, r6, c5, c0, 1 + stmia r8!, {r4-r6} + /* Data aux fault status register, instruction aux fault status, + datat fault address register and instruction fault address register*/ + mrc p15, 0, r4, c5, c1, 0 + mrc p15, 0, r5, c5, c1, 1 + mrc p15, 0, r6, c6, c0, 0 + mrc p15, 0, r7, c6, c0, 2 + stmia r8!, {r4-r7} + /* user r/w thread and process ID, user r/o thread and process ID, + priv only thread and process ID, cache size selection */ + mrc p15, 0, r4, c13, c0, 2 + mrc p15, 0, r5, c13, c0, 3 + mrc p15, 0, r6, c13, c0, 4 + mrc p15, 2, r7, c0, c0, 0 + stmia r8!, {r4-r7} + /* Data TLB lockdown, instruction TLB lockdown registers */ + mrc p15, 0, r5, c10, c0, 0 + mrc p15, 0, r6, c10, c0, 1 + stmia r8!, {r5-r6} + /* Secure or non secure vector base address, FCSE PID, Context PID*/ + mrc p15, 0, r4, c12, c0, 0 + mrc p15, 0, r5, c13, c0, 0 + mrc p15, 0, r6, c13, c0, 1 + stmia r8!, {r4-r6} + /* Primary remap, normal remap registers */ + mrc p15, 0, r4, c10, c2, 0 + mrc p15, 0, r5, c10, c2, 1 + stmia r8!,{r4-r5} + + /* Store current cpsr*/ + mrs r2, cpsr + stmia r8!, {r2} + + mrc p15, 0, r4, c1, c0, 0 + /* save control register */ + stmia r8!, {r4} +clean_caches: + /* Clean Data or unified cache to POU*/ + /* How to invalidate only L1 cache???? - #FIX_ME# */ + /* mcr p15, 0, r11, c7, c11, 1 */ + cmp r9, #1 /* Check whether L2 inval is required or not*/ + bne skip_l2_inval +clean_l2: + /* read clidr */ + mrc p15, 1, r0, c0, c0, 1 + /* extract loc from clidr */ + ands r3, r0, #0x7000000 + /* left align loc bit field */ + mov r3, r3, lsr #23 + /* if loc is 0, then no need to clean */ + beq finished + /* start clean at cache level 0 */ + mov r10, #0 +loop1: + /* work out 3x current cache level */ + add r2, r10, r10, lsr #1 + /* extract cache type bits from clidr*/ + mov r1, r0, lsr r2 + /* mask of the bits for current cache only */ + and r1, r1, #7 + /* see what cache we have at this level */ + cmp r1, #2 + /* skip if no cache, or just i-cache */ + blt skip + /* select current cache level in cssr */ + mcr p15, 2, r10, c0, c0, 0 + /* isb to sych the new cssr&csidr */ + isb + /* read the new csidr */ + mrc p15, 1, r1, c0, c0, 0 + /* extract the length of the cache lines */ + and r2, r1, #7 + /* add 4 (line length offset) */ + add r2, r2, #4 + ldr r4, assoc_mask + /* find maximum number on the way size */ + ands r4, r4, r1, lsr #3 + /* find bit position of way size increment */ + clz r5, r4 + ldr r7, numset_mask + /* extract max number of the index size*/ + ands r7, r7, r1, lsr #13 +loop2: + mov r9, r4 + /* create working copy of max way size*/ +loop3: + /* factor way and cache number into r11 */ + orr r11, r10, r9, lsl r5 + /* factor index number into r11 */ + orr r11, r11, r7, lsl r2 + /*clean & invalidate by set/way */ + mcr p15, 0, r11, c7, c10, 2 + /* decrement the way*/ + subs r9, r9, #1 + bge loop3 + /*decrement the index */ + subs r7, r7, #1 + bge loop2 +skip: + add r10, r10, #2 + /* increment cache number */ + cmp r3, r10 + bgt loop1 +finished: + /*swith back to cache level 0 */ + mov r10, #0 + /* select current cache level in cssr */ + mcr p15, 2, r10, c0, c0, 0 + isb +skip_l2_inval: + /* Data memory barrier and Data sync barrier */ + mov r1, #0 + mcr p15, 0, r1, c7, c10, 4 + mcr p15, 0, r1, c7, c10, 5 + + wfi @ wait for interrupt + nop + nop + nop + nop + nop + nop + nop + nop + nop + nop + bl i_dll_wait + /* restore regs and return */ + ldmfd sp!, {r0-r12, pc} + +i_dll_wait: + ldr r4, clk_stabilize_delay + +i_dll_delay: + subs r4, r4, #0x1 + bne i_dll_delay + ldr r4, sdrc_power + ldr r5, [r4] + bic r5, r5, #0x40 + str r5, [r4] + bx lr +pm_prepwstst_core: + .word PM_PREPWSTST_CORE_V +pm_prepwstst_mpu: + .word PM_PREPWSTST_MPU_V +pm_pwstctrl_mpu: + .word PM_PWSTCTRL_MPU_P +scratchpad_base: + .word SCRATCHPAD_BASE_P +sdrc_power: + .word SDRC_POWER_V +context_mem: + .word 0x803E3E14 +clk_stabilize_delay: + .word 0x000001FF +assoc_mask: + .word 0x3ff +numset_mask: + .word 0x7fff +ttbrbit_mask: + .word 0xFFFFC000 +table_index_mask: + .word 0xFFF00000 +table_entry: + .word 0x00000C02 +cache_pred_disable_mask: + .word 0xFFFFE7FB +ENTRY(omap34xx_cpu_suspend_sz) + .word . - omap34xx_cpu_suspend diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 34a56a136ef..215d463b70e 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -28,7 +28,6 @@ #include #include -#include #include #include diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9dd68fafb37..4bc9ed701dc 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -171,7 +171,7 @@ endchoice config OMAP_SERIAL_WAKE bool "Enable wake-up events for serial ports" - depends on OMAP_MUX + depends on ARCH_OMAP1 && OMAP_MUX default y help Select this option if you want to have your system wake up diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 70b68ef8320..86ee23d6f73 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/arm/plat-omap/include/mach/pm.h b/arch/arm/plat-omap/include/mach/pm.h deleted file mode 100644 index ce6ee792753..00000000000 --- a/arch/arm/plat-omap/include/mach/pm.h +++ /dev/null @@ -1,345 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/pm.h - * - * Header file for OMAP Power Management Routines - * - * Author: MontaVista Software, Inc. - * support@mvista.com - * - * Copyright 2002 MontaVista Software Inc. - * - * Cleanup 2004 for Linux 2.6 by Dirk Behme - * - * 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 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __ASM_ARCH_OMAP_PM_H -#define __ASM_ARCH_OMAP_PM_H - -/* - * ---------------------------------------------------------------------------- - * Register and offset definitions to be used in PM assembler code - * ---------------------------------------------------------------------------- - */ -#define CLKGEN_REG_ASM_BASE IO_ADDRESS(0xfffece00) -#define ARM_IDLECT1_ASM_OFFSET 0x04 -#define ARM_IDLECT2_ASM_OFFSET 0x08 - -#define TCMIF_ASM_BASE IO_ADDRESS(0xfffecc00) -#define EMIFS_CONFIG_ASM_OFFSET 0x0c -#define EMIFF_SDRAM_CONFIG_ASM_OFFSET 0x20 - -/* - * ---------------------------------------------------------------------------- - * Power management bitmasks - * ---------------------------------------------------------------------------- - */ -#define IDLE_WAIT_CYCLES 0x00000fff -#define PERIPHERAL_ENABLE 0x2 - -#define SELF_REFRESH_MODE 0x0c000001 -#define IDLE_EMIFS_REQUEST 0xc -#define MODEM_32K_EN 0x1 -#define PER_EN 0x1 - -#define CPU_SUSPEND_SIZE 200 -#define ULPD_LOW_PWR_EN 0x0001 -#define ULPD_DEEP_SLEEP_TRANSITION_EN 0x0010 -#define ULPD_SETUP_ANALOG_CELL_3_VAL 0 -#define ULPD_POWER_CTRL_REG_VAL 0x0219 - -#define DSP_IDLE_DELAY 10 -#define DSP_IDLE 0x0040 -#define DSP_RST 0x0004 -#define DSP_ENABLE 0x0002 -#define SUFFICIENT_DSP_RESET_TIME 1000 -#define DEFAULT_MPUI_CONFIG 0x05cf -#define ENABLE_XORCLK 0x2 -#define DSP_CLOCK_ENABLE 0x2000 -#define DSP_IDLE_MODE 0x2 -#define TC_IDLE_REQUEST (0x0000000c) - -#define IRQ_LEVEL2 (1<<0) -#define IRQ_KEYBOARD (1<<1) -#define IRQ_UART2 (1<<15) - -#define PDE_BIT 0x08 -#define PWD_EN_BIT 0x04 -#define EN_PERCK_BIT 0x04 - -#define OMAP1510_DEEP_SLEEP_REQUEST 0x0ec7 -#define OMAP1510_BIG_SLEEP_REQUEST 0x0cc5 -#define OMAP1510_IDLE_LOOP_REQUEST 0x0c00 -#define OMAP1510_IDLE_CLOCK_DOMAINS 0x2 - -/* Both big sleep and deep sleep use same values. Difference is in ULPD. */ -#define OMAP1610_IDLECT1_SLEEP_VAL 0x13c7 -#define OMAP1610_IDLECT2_SLEEP_VAL 0x09c7 -#define OMAP1610_IDLECT3_VAL 0x3f -#define OMAP1610_IDLECT3_SLEEP_ORMASK 0x2c -#define OMAP1610_IDLECT3 0xfffece24 -#define OMAP1610_IDLE_LOOP_REQUEST 0x0400 - -#define OMAP730_IDLECT1_SLEEP_VAL 0x16c7 -#define OMAP730_IDLECT2_SLEEP_VAL 0x09c7 -#define OMAP730_IDLECT3_VAL 0x3f -#define OMAP730_IDLECT3 0xfffece24 -#define OMAP730_IDLE_LOOP_REQUEST 0x0C00 - -#if !defined(CONFIG_ARCH_OMAP730) && \ - !defined(CONFIG_ARCH_OMAP15XX) && \ - !defined(CONFIG_ARCH_OMAP16XX) && \ - !defined(CONFIG_ARCH_OMAP24XX) -#warning "Power management for this processor not implemented yet" -#endif - -#ifndef __ASSEMBLER__ - -#include - -extern void prevent_idle_sleep(void); -extern void allow_idle_sleep(void); - -extern void omap_pm_idle(void); -extern void omap_pm_suspend(void); -extern void omap730_cpu_suspend(unsigned short, unsigned short); -extern void omap1510_cpu_suspend(unsigned short, unsigned short); -extern void omap1610_cpu_suspend(unsigned short, unsigned short); -extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl, - void __iomem *sdrc_power); -extern void omap730_idle_loop_suspend(void); -extern void omap1510_idle_loop_suspend(void); -extern void omap1610_idle_loop_suspend(void); -extern void omap24xx_idle_loop_suspend(void); - -extern unsigned int omap730_cpu_suspend_sz; -extern unsigned int omap1510_cpu_suspend_sz; -extern unsigned int omap1610_cpu_suspend_sz; -extern unsigned int omap24xx_cpu_suspend_sz; -extern unsigned int omap730_idle_loop_suspend_sz; -extern unsigned int omap1510_idle_loop_suspend_sz; -extern unsigned int omap1610_idle_loop_suspend_sz; -extern unsigned int omap24xx_idle_loop_suspend_sz; - -#ifdef CONFIG_OMAP_SERIAL_WAKE -extern void omap_serial_wake_trigger(int enable); -#else -#define omap_serial_wakeup_init() {} -#define omap_serial_wake_trigger(x) {} -#endif /* CONFIG_OMAP_SERIAL_WAKE */ - -#define ARM_SAVE(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] = omap_readl(x) -#define ARM_RESTORE(x) omap_writel((arm_sleep_save[ARM_SLEEP_SAVE_##x]), (x)) -#define ARM_SHOW(x) arm_sleep_save[ARM_SLEEP_SAVE_##x] - -#define DSP_SAVE(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] = __raw_readw(x) -#define DSP_RESTORE(x) __raw_writew((dsp_sleep_save[DSP_SLEEP_SAVE_##x]), (x)) -#define DSP_SHOW(x) dsp_sleep_save[DSP_SLEEP_SAVE_##x] - -#define ULPD_SAVE(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] = omap_readw(x) -#define ULPD_RESTORE(x) omap_writew((ulpd_sleep_save[ULPD_SLEEP_SAVE_##x]), (x)) -#define ULPD_SHOW(x) ulpd_sleep_save[ULPD_SLEEP_SAVE_##x] - -#define MPUI730_SAVE(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] = omap_readl(x) -#define MPUI730_RESTORE(x) omap_writel((mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x]), (x)) -#define MPUI730_SHOW(x) mpui730_sleep_save[MPUI730_SLEEP_SAVE_##x] - -#define MPUI1510_SAVE(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] = omap_readl(x) -#define MPUI1510_RESTORE(x) omap_writel((mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x]), (x)) -#define MPUI1510_SHOW(x) mpui1510_sleep_save[MPUI1510_SLEEP_SAVE_##x] - -#define MPUI1610_SAVE(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] = omap_readl(x) -#define MPUI1610_RESTORE(x) omap_writel((mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x]), (x)) -#define MPUI1610_SHOW(x) mpui1610_sleep_save[MPUI1610_SLEEP_SAVE_##x] - -#define OMAP24XX_SAVE(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] = x -#define OMAP24XX_RESTORE(x) x = omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] -#define OMAP24XX_SHOW(x) omap24xx_sleep_save[OMAP24XX_SLEEP_SAVE_##x] - -/* - * List of global OMAP registers to preserve. - * More ones like CP and general purpose register values are preserved - * with the stack pointer in sleep.S. - */ - -enum arm_save_state { - ARM_SLEEP_SAVE_START = 0, - /* - * MPU control registers 32 bits - */ - ARM_SLEEP_SAVE_ARM_CKCTL, - ARM_SLEEP_SAVE_ARM_IDLECT1, - ARM_SLEEP_SAVE_ARM_IDLECT2, - ARM_SLEEP_SAVE_ARM_IDLECT3, - ARM_SLEEP_SAVE_ARM_EWUPCT, - ARM_SLEEP_SAVE_ARM_RSTCT1, - ARM_SLEEP_SAVE_ARM_RSTCT2, - ARM_SLEEP_SAVE_ARM_SYSST, - ARM_SLEEP_SAVE_SIZE -}; - -enum dsp_save_state { - DSP_SLEEP_SAVE_START = 0, - /* - * DSP registers 16 bits - */ - DSP_SLEEP_SAVE_DSP_IDLECT2, - DSP_SLEEP_SAVE_SIZE -}; - -enum ulpd_save_state { - ULPD_SLEEP_SAVE_START = 0, - /* - * ULPD registers 16 bits - */ - ULPD_SLEEP_SAVE_ULPD_IT_STATUS, - ULPD_SLEEP_SAVE_ULPD_CLOCK_CTRL, - ULPD_SLEEP_SAVE_ULPD_SOFT_REQ, - ULPD_SLEEP_SAVE_ULPD_STATUS_REQ, - ULPD_SLEEP_SAVE_ULPD_DPLL_CTRL, - ULPD_SLEEP_SAVE_ULPD_POWER_CTRL, - ULPD_SLEEP_SAVE_SIZE -}; - -enum mpui1510_save_state { - MPUI1510_SLEEP_SAVE_START = 0, - /* - * MPUI registers 32 bits - */ - MPUI1510_SLEEP_SAVE_MPUI_CTRL, - MPUI1510_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, - MPUI1510_SLEEP_SAVE_MPUI_DSP_API_CONFIG, - MPUI1510_SLEEP_SAVE_MPUI_DSP_STATUS, - MPUI1510_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, - MPUI1510_SLEEP_SAVE_EMIFS_CONFIG, - MPUI1510_SLEEP_SAVE_OMAP_IH1_MIR, - MPUI1510_SLEEP_SAVE_OMAP_IH2_MIR, -#if defined(CONFIG_ARCH_OMAP15XX) - MPUI1510_SLEEP_SAVE_SIZE -#else - MPUI1510_SLEEP_SAVE_SIZE = 0 -#endif -}; - -enum mpui730_save_state { - MPUI730_SLEEP_SAVE_START = 0, - /* - * MPUI registers 32 bits - */ - MPUI730_SLEEP_SAVE_MPUI_CTRL, - MPUI730_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, - MPUI730_SLEEP_SAVE_MPUI_DSP_API_CONFIG, - MPUI730_SLEEP_SAVE_MPUI_DSP_STATUS, - MPUI730_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, - MPUI730_SLEEP_SAVE_EMIFS_CONFIG, - MPUI730_SLEEP_SAVE_OMAP_IH1_MIR, - MPUI730_SLEEP_SAVE_OMAP_IH2_0_MIR, - MPUI730_SLEEP_SAVE_OMAP_IH2_1_MIR, -#if defined(CONFIG_ARCH_OMAP730) - MPUI730_SLEEP_SAVE_SIZE -#else - MPUI730_SLEEP_SAVE_SIZE = 0 -#endif -}; - -enum mpui1610_save_state { - MPUI1610_SLEEP_SAVE_START = 0, - /* - * MPUI registers 32 bits - */ - MPUI1610_SLEEP_SAVE_MPUI_CTRL, - MPUI1610_SLEEP_SAVE_MPUI_DSP_BOOT_CONFIG, - MPUI1610_SLEEP_SAVE_MPUI_DSP_API_CONFIG, - MPUI1610_SLEEP_SAVE_MPUI_DSP_STATUS, - MPUI1610_SLEEP_SAVE_EMIFF_SDRAM_CONFIG, - MPUI1610_SLEEP_SAVE_EMIFS_CONFIG, - MPUI1610_SLEEP_SAVE_OMAP_IH1_MIR, - MPUI1610_SLEEP_SAVE_OMAP_IH2_0_MIR, - MPUI1610_SLEEP_SAVE_OMAP_IH2_1_MIR, - MPUI1610_SLEEP_SAVE_OMAP_IH2_2_MIR, - MPUI1610_SLEEP_SAVE_OMAP_IH2_3_MIR, -#if defined(CONFIG_ARCH_OMAP16XX) - MPUI1610_SLEEP_SAVE_SIZE -#else - MPUI1610_SLEEP_SAVE_SIZE = 0 -#endif -}; - -enum omap24xx_save_state { - OMAP24XX_SLEEP_SAVE_START = 0, - OMAP24XX_SLEEP_SAVE_INTC_MIR0, - OMAP24XX_SLEEP_SAVE_INTC_MIR1, - OMAP24XX_SLEEP_SAVE_INTC_MIR2, - - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MPU, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_CORE, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_GFX, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_DSP, - OMAP24XX_SLEEP_SAVE_CM_CLKSTCTRL_MDM, - - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MPU, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_CORE, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_GFX, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_DSP, - OMAP24XX_SLEEP_SAVE_PM_PWSTCTRL_MDM, - - OMAP24XX_SLEEP_SAVE_CM_IDLEST1_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST2_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST3_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST4_CORE, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_GFX, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_WKUP, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_CKGEN, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_DSP, - OMAP24XX_SLEEP_SAVE_CM_IDLEST_MDM, - - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE1_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE2_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE3_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE4_CORE, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_WKUP, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_PLL, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_DSP, - OMAP24XX_SLEEP_SAVE_CM_AUTOIDLE_MDM, - - OMAP24XX_SLEEP_SAVE_CM_FCLKEN1_CORE, - OMAP24XX_SLEEP_SAVE_CM_FCLKEN2_CORE, - OMAP24XX_SLEEP_SAVE_CM_ICLKEN1_CORE, - OMAP24XX_SLEEP_SAVE_CM_ICLKEN2_CORE, - OMAP24XX_SLEEP_SAVE_CM_ICLKEN3_CORE, - OMAP24XX_SLEEP_SAVE_CM_ICLKEN4_CORE, - OMAP24XX_SLEEP_SAVE_GPIO1_IRQENABLE1, - OMAP24XX_SLEEP_SAVE_GPIO2_IRQENABLE1, - OMAP24XX_SLEEP_SAVE_GPIO3_IRQENABLE1, - OMAP24XX_SLEEP_SAVE_GPIO4_IRQENABLE1, - OMAP24XX_SLEEP_SAVE_GPIO3_OE, - OMAP24XX_SLEEP_SAVE_GPIO4_OE, - OMAP24XX_SLEEP_SAVE_GPIO3_RISINGDETECT, - OMAP24XX_SLEEP_SAVE_GPIO3_FALLINGDETECT, - OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SPI1_NCS2, - OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_MCBSP1_DX, - OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SSI1_FLAG_TX, - OMAP24XX_SLEEP_SAVE_CONTROL_PADCONF_SYS_NIRQW0, - OMAP24XX_SLEEP_SAVE_SIZE -}; - -#endif /* ASSEMBLER */ -#endif /* __ASM_ARCH_OMAP_PM_H */ diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c index f2e9de1414d..6391e3dc800 100644 --- a/drivers/mtd/onenand/omap2.c +++ b/drivers/mtd/onenand/omap2.c @@ -39,7 +39,6 @@ #include #include #include -#include #include -- cgit v1.2.3-70-g09d2 From 94434535bd36ca010a81e1199f954beef2c4de64 Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Tue, 3 Feb 2009 15:49:04 -0800 Subject: OMAP: Add new function to check wether there is irq pending Add common omap2/3 function to check wether there is irq pending. Switch to use it in omap2 pm code instead of its own. Signed-off-by: Jouni Hogander Signed-off-by: Tony Lindgren Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/irq.c | 17 ++++++++++++++++- arch/arm/mach-omap2/pm24xx.c | 19 +++---------------- arch/arm/plat-omap/include/mach/irqs.h | 1 + 3 files changed, 20 insertions(+), 17 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/irq.c b/arch/arm/mach-omap2/irq.c index 08a3b99abe6..b82863887f1 100644 --- a/arch/arm/mach-omap2/irq.c +++ b/arch/arm/mach-omap2/irq.c @@ -28,7 +28,6 @@ #define INTC_MIR_CLEAR0 0x0088 #define INTC_MIR_SET0 0x008c #define INTC_PENDING_IRQ0 0x0098 - /* Number of IRQ state bits in each MIR register */ #define IRQ_BITS_PER_REG 32 @@ -156,6 +155,22 @@ static void __init omap_irq_bank_init_one(struct omap_irq_bank *bank) intc_bank_write_reg(1 << 0, bank, INTC_SYSCONFIG); } +int omap_irq_pending(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(irq_banks); i++) { + struct omap_irq_bank *bank = irq_banks + i; + int irq; + + for (irq = 0; irq < bank->nr_irqs; irq += 32) + if (intc_bank_read_reg(bank, INTC_PENDING_IRQ0 + + ((irq >> 5) << 5))) + return 1; + } + return 0; +} + void __init omap_init_irq(void) { unsigned long nr_of_irqs = 0; diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index 232b9f6032e..d38f3121dde 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -76,19 +76,6 @@ static int omap2_fclks_active(void) return 0; } -static int omap2_irq_pending(void) -{ - u32 pending_reg = 0x480fe098; - int i; - - for (i = 0; i < 4; i++) { - if (omap_readl(pending_reg)) - return 1; - pending_reg += 0x20; - } - return 0; -} - static void omap2_enter_full_retention(void) { u32 l; @@ -127,7 +114,7 @@ static void omap2_enter_full_retention(void) /* One last check for pending IRQs to avoid extra latency due * to sleeping unnecessarily. */ - if (omap2_irq_pending()) + if (omap_irq_pending()) goto no_sleep; /* Jump to SRAM suspend code */ @@ -262,13 +249,13 @@ static void omap2_pm_idle(void) local_fiq_disable(); if (!omap2_can_sleep()) { - if (omap2_irq_pending()) + if (omap_irq_pending()) goto out; omap2_enter_mpu_retention(); goto out; } - if (omap2_irq_pending()) + if (omap_irq_pending()) goto out; omap2_enter_full_retention(); diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index 7f57ee66f36..f5f7c928b53 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -467,6 +467,7 @@ #ifndef __ASSEMBLY__ extern void omap_init_irq(void); +extern int omap_irq_pending(void); #endif #include -- cgit v1.2.3-70-g09d2 From 1155e426b7365f7909f5a32612feff7361aa0f4c Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 25 Nov 2008 11:48:24 -0800 Subject: OMAP3: PM: Force IVA2 into idle during bootup Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm34xx.c | 50 +++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/control.h | 5 ++++ 2 files changed, 55 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 4474947ddd6..b2a8730771e 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -352,6 +352,54 @@ static struct platform_suspend_ops omap_pm_ops = { .valid = suspend_valid_only_mem, }; + +/** + * omap3_iva_idle(): ensure IVA is in idle so it can be put into + * retention + * + * In cases where IVA2 is activated by bootcode, it may prevent + * full-chip retention or off-mode because it is not idle. This + * function forces the IVA2 into idle state so it can go + * into retention/off and thus allow full-chip retention/off. + * + **/ +static void __init omap3_iva_idle(void) +{ + /* ensure IVA2 clock is disabled */ + cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN); + + /* if no clock activity, nothing else to do */ + if (!(cm_read_mod_reg(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSTST) & + OMAP3430_CLKACTIVITY_IVA2_MASK)) + return; + + /* Reset IVA2 */ + prm_write_mod_reg(OMAP3430_RST1_IVA2 | + OMAP3430_RST2_IVA2 | + OMAP3430_RST3_IVA2, + OMAP3430_IVA2_MOD, RM_RSTCTRL); + + /* Enable IVA2 clock */ + cm_write_mod_reg(OMAP3430_CM_FCLKEN_IVA2_EN_IVA2, + OMAP3430_IVA2_MOD, CM_FCLKEN); + + /* Set IVA2 boot mode to 'idle' */ + omap_ctrl_writel(OMAP3_IVA2_BOOTMOD_IDLE, + OMAP343X_CONTROL_IVA2_BOOTMOD); + + /* Un-reset IVA2 */ + prm_write_mod_reg(0, OMAP3430_IVA2_MOD, RM_RSTCTRL); + + /* Disable IVA2 clock */ + cm_write_mod_reg(0, OMAP3430_IVA2_MOD, CM_FCLKEN); + + /* Reset IVA2 */ + prm_write_mod_reg(OMAP3430_RST1_IVA2 | + OMAP3430_RST2_IVA2 | + OMAP3430_RST3_IVA2, + OMAP3430_IVA2_MOD, RM_RSTCTRL); +} + static void __init prcm_setup_regs(void) { /* reset modem */ @@ -511,6 +559,8 @@ static void __init prcm_setup_regs(void) * it is selected to mpu wakeup goup */ prm_write_mod_reg(OMAP3430_IO_EN | OMAP3430_WKUP_EN, OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); + + omap3_iva_idle(); } static int __init pwrdms_setup(struct powerdomain *pwrdm) diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index 269147f3836..d38697b603e 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -189,6 +189,11 @@ #define OMAP2_PBIASLITEPWRDNZ0 (1 << 1) #define OMAP2_PBIASLITEVMODE0 (1 << 0) +/* CONTROL_IVA2_BOOTMOD bits */ +#define OMAP3_IVA2_BOOTMOD_SHIFT 0 +#define OMAP3_IVA2_BOOTMOD_MASK (0xf << 0) +#define OMAP3_IVA2_BOOTMOD_IDLE (0x1 << 0) + #ifndef __ASSEMBLY__ #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) extern void __iomem *omap_ctrl_base_get(void); -- cgit v1.2.3-70-g09d2 From 5a1a5abdb2e9a301f1ac62feb37228f3f4d3117c Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Fri, 31 Oct 2008 11:08:42 -0700 Subject: OMAP3: PM: Add wake-up bit defintiions for CONTROL_PADCONF_X Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/mach/control.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index d38697b603e..a9f05e5bb2b 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -194,6 +194,10 @@ #define OMAP3_IVA2_BOOTMOD_MASK (0xf << 0) #define OMAP3_IVA2_BOOTMOD_IDLE (0x1 << 0) +/* CONTROL_PADCONF_X bits */ +#define OMAP3_PADCONF_WAKEUPEVENT0 (1 << 15) +#define OMAP3_PADCONF_WAKEUPENABLE0 (1 << 14) + #ifndef __ASSEMBLY__ #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) extern void __iomem *omap_ctrl_base_get(void); -- cgit v1.2.3-70-g09d2 From 4af4016c53f52b26461b8030211f8427a58fa5ed Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Wed, 4 Feb 2009 10:51:40 -0800 Subject: OMAP3: PM: UART: disable clocks when idle and off-mode support This patch allows the UART clocks to be disabled when the OMAP UARTs are inactive, thus permitting the chip to hit retention in idle. After the expiration of an activity timer, each UART is allowed to disable its clocks so the system can enter retention. The activity timer is (re)activated on any UART interrupt, UART wake event or any IO pad wakeup. The actual disable of the UART clocks is done in the 'prepare_idle' hook called from the OMAP idle loop. While the activity timer is active, the smart-idle mode of the UART is also disabled. This is due to a "feature" of the UART module that after a UART wakeup, the smart-idle mode may be entered before the UART has communicated the interrupt, or upon TX, an idle mode may be entered before the TX FIFOs are emptied. Upon suspend, the 'prepare_suspend' hook cancels any pending activity timers and allows the clocks to be disabled immediately. In addition, upon disabling clocks the UART state is saved in case of an off-mode transition while clocks are off. Special thanks to Tero Kristo for the initial ideas and first versions of UART idle support, and to Jouni Hogander for extra testing and bugfixes. Tested on OMAP3 (Beagle, RX51, SDP, EVM) and OMAP2 (n810) Cc: Tero Kristo Cc: Jouni Hogander Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/pm24xx.c | 16 +- arch/arm/mach-omap2/pm34xx.c | 15 ++ arch/arm/mach-omap2/serial.c | 390 +++++++++++++++++++++++++++++-- arch/arm/plat-omap/include/mach/common.h | 2 - arch/arm/plat-omap/include/mach/serial.h | 9 + 5 files changed, 405 insertions(+), 27 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c index d38f3121dde..db1025562fb 100644 --- a/arch/arm/mach-omap2/pm24xx.c +++ b/arch/arm/mach-omap2/pm24xx.c @@ -71,6 +71,11 @@ static int omap2_fclks_active(void) f1 = cm_read_mod_reg(CORE_MOD, CM_FCLKEN1); f2 = cm_read_mod_reg(CORE_MOD, OMAP24XX_CM_FCLKEN2); + + /* Ignore UART clocks. These are handled by UART core (serial.c) */ + f1 &= ~(OMAP24XX_EN_UART1 | OMAP24XX_EN_UART2); + f2 &= ~OMAP24XX_EN_UART3; + if (f1 | f2) return 1; return 0; @@ -117,12 +122,20 @@ static void omap2_enter_full_retention(void) if (omap_irq_pending()) goto no_sleep; + omap_uart_prepare_idle(0); + omap_uart_prepare_idle(1); + omap_uart_prepare_idle(2); + /* Jump to SRAM suspend code */ omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL), OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL), OMAP_SDRC_REGADDR(SDRC_POWER)); -no_sleep: + omap_uart_resume_idle(2); + omap_uart_resume_idle(1); + omap_uart_resume_idle(0); + +no_sleep: if (omap2_pm_debug) { unsigned long long tmp; @@ -283,6 +296,7 @@ static int omap2_pm_suspend(void) mir1 = omap_readl(0x480fe0a4); omap_writel(1 << 5, 0x480fe0ac); + omap_uart_prepare_suspend(); omap2_enter_full_retention(); omap_writel(mir1, 0x480fe0a4); diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index b2a8730771e..54876aca2d4 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "cm.h" #include "cm-regbits-34xx.h" @@ -168,10 +169,16 @@ static void omap_sram_idle(void) return; } omap2_gpio_prepare_for_retention(); + omap_uart_prepare_idle(0); + omap_uart_prepare_idle(1); + omap_uart_prepare_idle(2); _omap_sram_idle(NULL, save_state); cpu_init(); + omap_uart_resume_idle(2); + omap_uart_resume_idle(1); + omap_uart_resume_idle(0); omap2_gpio_resume_after_retention(); } @@ -204,6 +211,11 @@ static int omap3_fclks_active(void) CM_FCLKEN); fck_per = cm_read_mod_reg(OMAP3430_PER_MOD, CM_FCLKEN); + + /* Ignore UART clocks. These are handled by UART core (serial.c) */ + fck_core1 &= ~(OMAP3430_EN_UART1 | OMAP3430_EN_UART2); + fck_per &= ~OMAP3430_EN_UART3; + if (fck_core1 | fck_core3 | fck_sgx | fck_dss | fck_cam | fck_per | fck_usbhost) return 1; @@ -212,6 +224,8 @@ static int omap3_fclks_active(void) static int omap3_can_sleep(void) { + if (!omap_uart_can_sleep()) + return 0; if (omap3_fclks_active()) return 0; return 1; @@ -301,6 +315,7 @@ static int omap3_pm_suspend(void) goto restore; } + omap_uart_prepare_suspend(); omap_sram_idle(); restore: diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 4dcf39c285b..53cbe062028 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -6,6 +6,8 @@ * Copyright (C) 2005-2008 Nokia Corporation * Author: Paul Mundt * + * Major rework for PM support by Kevin Hilman + * * Based off of arch/arm/mach-omap/omap1/serial.c * * This file is subject to the terms and conditions of the GNU General Public @@ -21,9 +23,50 @@ #include #include +#include +#include + +#include "prm.h" +#include "pm.h" +#include "prm-regbits-34xx.h" + +#define UART_OMAP_WER 0x17 /* Wake-up enable register */ + +#define DEFAULT_TIMEOUT (2 * HZ) + +struct omap_uart_state { + int num; + int can_sleep; + struct timer_list timer; + u32 timeout; + + void __iomem *wk_st; + void __iomem *wk_en; + u32 wk_mask; + u32 padconf; + + struct clk *ick; + struct clk *fck; + int clocked; + + struct plat_serial8250_port *p; + struct list_head node; -static struct clk *uart_ick[OMAP_MAX_NR_PORTS]; -static struct clk *uart_fck[OMAP_MAX_NR_PORTS]; +#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) + int context_valid; + + /* Registers to be saved/restored for OFF-mode */ + u16 dll; + u16 dlh; + u16 ier; + u16 sysc; + u16 scr; + u16 wer; +#endif +}; + +static struct omap_uart_state omap_uart[OMAP_MAX_NR_PORTS]; +static LIST_HEAD(uart_list); static struct plat_serial8250_port serial_platform_data[] = { { @@ -74,30 +117,320 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset, * properly. Note that the TX watermark initialization may not be needed * once the 8250.c watermark handling code is merged. */ -static inline void __init omap_serial_reset(struct plat_serial8250_port *p) +static inline void __init omap_uart_reset(struct omap_uart_state *uart) { + struct plat_serial8250_port *p = uart->p; + serial_write_reg(p, UART_OMAP_MDR1, 0x07); serial_write_reg(p, UART_OMAP_SCR, 0x08); serial_write_reg(p, UART_OMAP_MDR1, 0x00); serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0)); } -void omap_serial_enable_clocks(int enable) +#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) + +static int enable_off_mode; /* to be removed by full off-mode patches */ + +static void omap_uart_save_context(struct omap_uart_state *uart) { - int i; - for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { - if (uart_ick[i] && uart_fck[i]) { - if (enable) { - clk_enable(uart_ick[i]); - clk_enable(uart_fck[i]); - } else { - clk_disable(uart_ick[i]); - clk_disable(uart_fck[i]); + u16 lcr = 0; + struct plat_serial8250_port *p = uart->p; + + if (!enable_off_mode) + return; + + lcr = serial_read_reg(p, UART_LCR); + serial_write_reg(p, UART_LCR, 0xBF); + uart->dll = serial_read_reg(p, UART_DLL); + uart->dlh = serial_read_reg(p, UART_DLM); + serial_write_reg(p, UART_LCR, lcr); + uart->ier = serial_read_reg(p, UART_IER); + uart->sysc = serial_read_reg(p, UART_OMAP_SYSC); + uart->scr = serial_read_reg(p, UART_OMAP_SCR); + uart->wer = serial_read_reg(p, UART_OMAP_WER); + + uart->context_valid = 1; +} + +static void omap_uart_restore_context(struct omap_uart_state *uart) +{ + u16 efr = 0; + struct plat_serial8250_port *p = uart->p; + + if (!enable_off_mode) + return; + + if (!uart->context_valid) + return; + + uart->context_valid = 0; + + serial_write_reg(p, UART_OMAP_MDR1, 0x7); + serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ + efr = serial_read_reg(p, UART_EFR); + serial_write_reg(p, UART_EFR, UART_EFR_ECB); + serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ + serial_write_reg(p, UART_IER, 0x0); + serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ + serial_write_reg(p, UART_DLL, uart->dll); + serial_write_reg(p, UART_DLM, uart->dlh); + serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */ + serial_write_reg(p, UART_IER, uart->ier); + serial_write_reg(p, UART_FCR, 0xA1); + serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */ + serial_write_reg(p, UART_EFR, efr); + serial_write_reg(p, UART_LCR, UART_LCR_WLEN8); + serial_write_reg(p, UART_OMAP_SCR, uart->scr); + serial_write_reg(p, UART_OMAP_WER, uart->wer); + serial_write_reg(p, UART_OMAP_SYSC, uart->sysc); + serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */ +} +#else +static inline void omap_uart_save_context(struct omap_uart_state *uart) {} +static inline void omap_uart_restore_context(struct omap_uart_state *uart) {} +#endif /* CONFIG_PM && CONFIG_ARCH_OMAP3 */ + +static inline void omap_uart_enable_clocks(struct omap_uart_state *uart) +{ + if (uart->clocked) + return; + + clk_enable(uart->ick); + clk_enable(uart->fck); + uart->clocked = 1; + omap_uart_restore_context(uart); +} + +#ifdef CONFIG_PM + +static inline void omap_uart_disable_clocks(struct omap_uart_state *uart) +{ + if (!uart->clocked) + return; + + omap_uart_save_context(uart); + uart->clocked = 0; + clk_disable(uart->ick); + clk_disable(uart->fck); +} + +static void omap_uart_smart_idle_enable(struct omap_uart_state *uart, + int enable) +{ + struct plat_serial8250_port *p = uart->p; + u16 sysc; + + sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7; + if (enable) + sysc |= 0x2 << 3; + else + sysc |= 0x1 << 3; + + serial_write_reg(p, UART_OMAP_SYSC, sysc); +} + +static void omap_uart_block_sleep(struct omap_uart_state *uart) +{ + omap_uart_enable_clocks(uart); + + omap_uart_smart_idle_enable(uart, 0); + uart->can_sleep = 0; + mod_timer(&uart->timer, jiffies + uart->timeout); +} + +static void omap_uart_allow_sleep(struct omap_uart_state *uart) +{ + if (!uart->clocked) + return; + + omap_uart_smart_idle_enable(uart, 1); + uart->can_sleep = 1; + del_timer(&uart->timer); +} + +static void omap_uart_idle_timer(unsigned long data) +{ + struct omap_uart_state *uart = (struct omap_uart_state *)data; + + omap_uart_allow_sleep(uart); +} + +void omap_uart_prepare_idle(int num) +{ + struct omap_uart_state *uart; + + list_for_each_entry(uart, &uart_list, node) { + if (num == uart->num && uart->can_sleep) { + omap_uart_disable_clocks(uart); + return; + } + } +} + +void omap_uart_resume_idle(int num) +{ + struct omap_uart_state *uart; + + list_for_each_entry(uart, &uart_list, node) { + if (num == uart->num) { + omap_uart_enable_clocks(uart); + + /* Check for IO pad wakeup */ + if (cpu_is_omap34xx() && uart->padconf) { + u16 p = omap_ctrl_readw(uart->padconf); + + if (p & OMAP3_PADCONF_WAKEUPEVENT0) + omap_uart_block_sleep(uart); } + + /* Check for normal UART wakeup */ + if (__raw_readl(uart->wk_st) & uart->wk_mask) + omap_uart_block_sleep(uart); + + return; + } + } +} + +void omap_uart_prepare_suspend(void) +{ + struct omap_uart_state *uart; + + list_for_each_entry(uart, &uart_list, node) { + omap_uart_allow_sleep(uart); + } +} + +int omap_uart_can_sleep(void) +{ + struct omap_uart_state *uart; + int can_sleep = 1; + + list_for_each_entry(uart, &uart_list, node) { + if (!uart->clocked) + continue; + + if (!uart->can_sleep) { + can_sleep = 0; + continue; } + + /* This UART can now safely sleep. */ + omap_uart_allow_sleep(uart); } + + return can_sleep; } +/** + * omap_uart_interrupt() + * + * This handler is used only to detect that *any* UART interrupt has + * occurred. It does _nothing_ to handle the interrupt. Rather, + * any UART interrupt will trigger the inactivity timer so the + * UART will not idle or sleep for its timeout period. + * + **/ +static irqreturn_t omap_uart_interrupt(int irq, void *dev_id) +{ + struct omap_uart_state *uart = dev_id; + + omap_uart_block_sleep(uart); + + return IRQ_NONE; +} + +static void omap_uart_idle_init(struct omap_uart_state *uart) +{ + u32 v; + struct plat_serial8250_port *p = uart->p; + int ret; + + uart->can_sleep = 0; + uart->timeout = DEFAULT_TIMEOUT; + setup_timer(&uart->timer, omap_uart_idle_timer, + (unsigned long) uart); + mod_timer(&uart->timer, jiffies + uart->timeout); + omap_uart_smart_idle_enable(uart, 0); + + if (cpu_is_omap34xx()) { + u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD; + u32 wk_mask = 0; + u32 padconf = 0; + + uart->wk_en = OMAP34XX_PRM_REGADDR(mod, PM_WKEN1); + uart->wk_st = OMAP34XX_PRM_REGADDR(mod, PM_WKST1); + switch (uart->num) { + case 0: + wk_mask = OMAP3430_ST_UART1_MASK; + padconf = 0x182; + break; + case 1: + wk_mask = OMAP3430_ST_UART2_MASK; + padconf = 0x17a; + break; + case 2: + wk_mask = OMAP3430_ST_UART3_MASK; + padconf = 0x19e; + break; + } + uart->wk_mask = wk_mask; + uart->padconf = padconf; + } else if (cpu_is_omap24xx()) { + u32 wk_mask = 0; + + if (cpu_is_omap2430()) { + uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1); + uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1); + } else if (cpu_is_omap2420()) { + uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1); + uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1); + } + switch (uart->num) { + case 0: + wk_mask = OMAP24XX_ST_UART1_MASK; + break; + case 1: + wk_mask = OMAP24XX_ST_UART2_MASK; + break; + case 2: + wk_mask = OMAP24XX_ST_UART3_MASK; + break; + } + uart->wk_mask = wk_mask; + } else { + uart->wk_en = 0; + uart->wk_st = 0; + uart->wk_mask = 0; + uart->padconf = 0; + } + + /* Set wake-enable bit */ + if (uart->wk_en && uart->wk_mask) { + v = __raw_readl(uart->wk_en); + v |= uart->wk_mask; + __raw_writel(v, uart->wk_en); + } + + /* Ensure IOPAD wake-enables are set */ + if (cpu_is_omap34xx() && uart->padconf) { + u16 v; + + v = omap_ctrl_readw(uart->padconf); + v |= OMAP3_PADCONF_WAKEUPENABLE0; + omap_ctrl_writew(v, uart->padconf); + } + + p->flags |= UPF_SHARE_IRQ; + ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED, + "serial idle", (void *)uart); + WARN_ON(ret); +} + +#else +static inline void omap_uart_idle_init(struct omap_uart_state *uart) {} +#endif /* CONFIG_PM */ + void __init omap_serial_init(void) { int i; @@ -117,6 +450,7 @@ void __init omap_serial_init(void) for (i = 0; i < OMAP_MAX_NR_PORTS; i++) { struct plat_serial8250_port *p = serial_platform_data + i; + struct omap_uart_state *uart = &omap_uart[i]; if (!(info->enabled_uarts & (1 << i))) { p->membase = NULL; @@ -125,22 +459,30 @@ void __init omap_serial_init(void) } sprintf(name, "uart%d_ick", i+1); - uart_ick[i] = clk_get(NULL, name); - if (IS_ERR(uart_ick[i])) { + uart->ick = clk_get(NULL, name); + if (IS_ERR(uart->ick)) { printk(KERN_ERR "Could not get uart%d_ick\n", i+1); - uart_ick[i] = NULL; - } else - clk_enable(uart_ick[i]); + uart->ick = NULL; + } sprintf(name, "uart%d_fck", i+1); - uart_fck[i] = clk_get(NULL, name); - if (IS_ERR(uart_fck[i])) { + uart->fck = clk_get(NULL, name); + if (IS_ERR(uart->fck)) { printk(KERN_ERR "Could not get uart%d_fck\n", i+1); - uart_fck[i] = NULL; - } else - clk_enable(uart_fck[i]); + uart->fck = NULL; + } + + if (!uart->ick || !uart->fck) + continue; + + uart->num = i; + p->private_data = uart; + uart->p = p; + list_add(&uart->node, &uart_list); - omap_serial_reset(p); + omap_uart_enable_clocks(uart); + omap_uart_reset(uart); + omap_uart_idle_init(uart); } } diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index 0ecf36deb17..834f0b3aad1 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h @@ -33,8 +33,6 @@ struct sys_timer; extern void omap_map_common_io(void); extern struct sys_timer omap_timer; -extern void omap_serial_init(void); -extern void omap_serial_enable_clocks(int enable); #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) extern int omap_register_i2c_bus(int bus_id, u32 clkrate, struct i2c_board_info const *info, diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h index 8a676a04be4..8e895858b3e 100644 --- a/arch/arm/plat-omap/include/mach/serial.h +++ b/arch/arm/plat-omap/include/mach/serial.h @@ -40,4 +40,13 @@ __ret; \ }) +#ifndef __ASSEMBLER__ +extern void omap_serial_init(void); +extern int omap_uart_can_sleep(void); +extern void omap_uart_check_wakeup(void); +extern void omap_uart_prepare_suspend(void); +extern void omap_uart_prepare_idle(int num); +extern void omap_uart_resume_idle(int num); +#endif + #endif -- cgit v1.2.3-70-g09d2 From 8111b221a275cbc974eba26059dc764680ded9a9 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 28 Apr 2009 15:27:44 -0700 Subject: OMAP3: PM: Add D2D clocks and auto-idle setup to PRCM init Add D2D clocks (modem_fck, sad2d_ick, mad2d_ick) to clock framework and ensure that auto-idle bits are set for these clocks during PRCM init. Also add omap3_d2d_idle() function called durint PRCM setup which ensures D2D pins are MUX'd correctly to enable retention for standalone (no-modem) devices. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/clock34xx.c | 3 +++ arch/arm/mach-omap2/clock34xx.h | 33 +++++++++++++++++++++++++++++-- arch/arm/mach-omap2/cm-regbits-34xx.h | 14 +++++++++++++ arch/arm/mach-omap2/pm34xx.c | 25 +++++++++++++++++++++-- arch/arm/plat-omap/include/mach/control.h | 4 ++++ 5 files changed, 75 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c index 62021397e5f..9e43fe5209d 100644 --- a/arch/arm/mach-omap2/clock34xx.c +++ b/arch/arm/mach-omap2/clock34xx.c @@ -129,6 +129,9 @@ static struct omap_clk omap34xx_clks[] = { CLK(NULL, "sgx_fck", &sgx_fck, CK_3430ES2), CLK(NULL, "sgx_ick", &sgx_ick, CK_3430ES2), CLK(NULL, "d2d_26m_fck", &d2d_26m_fck, CK_3430ES1), + CLK(NULL, "modem_fck", &modem_fck, CK_343X), + CLK(NULL, "sad2d_ick", &sad2d_ick, CK_343X), + CLK(NULL, "mad2d_ick", &mad2d_ick, CK_343X), CLK(NULL, "gpt10_fck", &gpt10_fck, CK_343X), CLK(NULL, "gpt11_fck", &gpt11_fck, CK_343X), CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2), diff --git a/arch/arm/mach-omap2/clock34xx.h b/arch/arm/mach-omap2/clock34xx.h index 496f0e9caeb..e433aec4efd 100644 --- a/arch/arm/mach-omap2/clock34xx.h +++ b/arch/arm/mach-omap2/clock34xx.h @@ -1230,6 +1230,37 @@ static struct clk d2d_26m_fck = { .recalc = &followparent_recalc, }; +static struct clk modem_fck = { + .name = "modem_fck", + .ops = &clkops_omap2_dflt_wait, + .parent = &sys_ck, + .init = &omap2_init_clk_clkdm, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1), + .enable_bit = OMAP3430_EN_MODEM_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk sad2d_ick = { + .name = "sad2d_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1), + .enable_bit = OMAP3430_EN_SAD2D_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + +static struct clk mad2d_ick = { + .name = "mad2d_ick", + .ops = &clkops_omap2_dflt_wait, + .parent = &l3_ick, + .enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3), + .enable_bit = OMAP3430_EN_MAD2D_SHIFT, + .clkdm_name = "d2d_clkdm", + .recalc = &followparent_recalc, +}; + static const struct clksel omap343x_gpt_clksel[] = { { .parent = &omap_32k_fck, .rates = gpt_32k_rates }, { .parent = &sys_ck, .rates = gpt_sys_rates }, @@ -1947,8 +1978,6 @@ static struct clk usb_l4_ick = { .recalc = &omap2_clksel_recalc, }; -/* XXX MDM_INTC_ICK, SAD2D_ICK ?? */ - /* SECURITY_L4_ICK2 based clocks */ static struct clk security_l4_ick2 = { diff --git a/arch/arm/mach-omap2/cm-regbits-34xx.h b/arch/arm/mach-omap2/cm-regbits-34xx.h index 6f3f5a36aae..6923deb98a2 100644 --- a/arch/arm/mach-omap2/cm-regbits-34xx.h +++ b/arch/arm/mach-omap2/cm-regbits-34xx.h @@ -145,6 +145,8 @@ #define OMAP3430_CLKACTIVITY_MPU_MASK (1 << 0) /* CM_FCLKEN1_CORE specific bits */ +#define OMAP3430_EN_MODEM (1 << 31) +#define OMAP3430_EN_MODEM_SHIFT 31 /* CM_ICLKEN1_CORE specific bits */ #define OMAP3430_EN_ICR (1 << 29) @@ -161,6 +163,8 @@ #define OMAP3430_EN_MAILBOXES_SHIFT 7 #define OMAP3430_EN_OMAPCTRL (1 << 6) #define OMAP3430_EN_OMAPCTRL_SHIFT 6 +#define OMAP3430_EN_SAD2D (1 << 3) +#define OMAP3430_EN_SAD2D_SHIFT 3 #define OMAP3430_EN_SDRC (1 << 1) #define OMAP3430_EN_SDRC_SHIFT 1 @@ -176,6 +180,10 @@ #define OMAP3430_EN_DES1 (1 << 0) #define OMAP3430_EN_DES1_SHIFT 0 +/* CM_ICLKEN3_CORE */ +#define OMAP3430_EN_MAD2D_SHIFT 3 +#define OMAP3430_EN_MAD2D (1 << 3) + /* CM_FCLKEN3_CORE specific bits */ #define OMAP3430ES2_EN_TS_SHIFT 1 #define OMAP3430ES2_EN_TS_MASK (1 << 1) @@ -231,6 +239,8 @@ #define OMAP3430ES2_ST_CPEFUSE_MASK (1 << 0) /* CM_AUTOIDLE1_CORE */ +#define OMAP3430_AUTO_MODEM (1 << 31) +#define OMAP3430_AUTO_MODEM_SHIFT 31 #define OMAP3430ES2_AUTO_MMC3 (1 << 30) #define OMAP3430ES2_AUTO_MMC3_SHIFT 30 #define OMAP3430ES2_AUTO_ICR (1 << 29) @@ -287,6 +297,8 @@ #define OMAP3430_AUTO_HSOTGUSB_SHIFT 4 #define OMAP3430ES1_AUTO_D2D (1 << 3) #define OMAP3430ES1_AUTO_D2D_SHIFT 3 +#define OMAP3430_AUTO_SAD2D (1 << 3) +#define OMAP3430_AUTO_SAD2D_SHIFT 3 #define OMAP3430_AUTO_SSI (1 << 0) #define OMAP3430_AUTO_SSI_SHIFT 0 @@ -308,6 +320,8 @@ #define OMAP3430ES2_AUTO_USBTLL (1 << 2) #define OMAP3430ES2_AUTO_USBTLL_SHIFT 2 #define OMAP3430ES2_AUTO_USBTLL_MASK (1 << 2) +#define OMAP3430_AUTO_MAD2D_SHIFT 3 +#define OMAP3430_AUTO_MAD2D (1 << 3) /* CM_CLKSEL_CORE */ #define OMAP3430_CLKSEL_SSI_SHIFT 8 diff --git a/arch/arm/mach-omap2/pm34xx.c b/arch/arm/mach-omap2/pm34xx.c index 54876aca2d4..f72e2546542 100644 --- a/arch/arm/mach-omap2/pm34xx.c +++ b/arch/arm/mach-omap2/pm34xx.c @@ -415,14 +415,32 @@ static void __init omap3_iva_idle(void) OMAP3430_IVA2_MOD, RM_RSTCTRL); } -static void __init prcm_setup_regs(void) +static void __init omap3_d2d_idle(void) { + u16 mask, padconf; + + /* In a stand alone OMAP3430 where there is not a stacked + * modem for the D2D Idle Ack and D2D MStandby must be pulled + * high. S CONTROL_PADCONF_SAD2D_IDLEACK and + * CONTROL_PADCONF_SAD2D_MSTDBY to have a pull up. */ + mask = (1 << 4) | (1 << 3); /* pull-up, enabled */ + padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_MSTANDBY); + padconf |= mask; + omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_MSTANDBY); + + padconf = omap_ctrl_readw(OMAP3_PADCONF_SAD2D_IDLEACK); + padconf |= mask; + omap_ctrl_writew(padconf, OMAP3_PADCONF_SAD2D_IDLEACK); + /* reset modem */ prm_write_mod_reg(OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RSTPWRON | OMAP3430_RM_RSTCTRL_CORE_MODEM_SW_RST, CORE_MOD, RM_RSTCTRL); prm_write_mod_reg(0, CORE_MOD, RM_RSTCTRL); +} +static void __init prcm_setup_regs(void) +{ /* XXX Reset all wkdeps. This should be done when initializing * powerdomains */ prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP); @@ -442,6 +460,7 @@ static void __init prcm_setup_regs(void) * Note that in the long run this should be done by clockfw */ cm_write_mod_reg( + OMAP3430_AUTO_MODEM | OMAP3430ES2_AUTO_MMC3 | OMAP3430ES2_AUTO_ICR | OMAP3430_AUTO_AES2 | @@ -469,7 +488,7 @@ static void __init prcm_setup_regs(void) OMAP3430_AUTO_OMAPCTRL | OMAP3430ES1_AUTO_FSHOSTUSB | OMAP3430_AUTO_HSOTGUSB | - OMAP3430ES1_AUTO_D2D | /* This is es1 only */ + OMAP3430_AUTO_SAD2D | OMAP3430_AUTO_SSI, CORE_MOD, CM_AUTOIDLE1); @@ -483,6 +502,7 @@ static void __init prcm_setup_regs(void) if (omap_rev() > OMAP3430_REV_ES1_0) { cm_write_mod_reg( + OMAP3430_AUTO_MAD2D | OMAP3430ES2_AUTO_USBTLL, CORE_MOD, CM_AUTOIDLE3); } @@ -576,6 +596,7 @@ static void __init prcm_setup_regs(void) OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET); omap3_iva_idle(); + omap3_d2d_idle(); } static int __init pwrdms_setup(struct powerdomain *pwrdm) diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index a9f05e5bb2b..fcc5a9b7697 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -144,6 +144,10 @@ #define OMAP343X_CONTROL_PBIAS_LITE (OMAP2_CONTROL_GENERAL + 0x02b0) #define OMAP343X_CONTROL_TEMP_SENSOR (OMAP2_CONTROL_GENERAL + 0x02b4) +/* 34xx D2D idle-related pins, handled by PM core */ +#define OMAP3_PADCONF_SAD2D_MSTANDBY 0x250 +#define OMAP3_PADCONF_SAD2D_IDLEACK 0x254 + /* * REVISIT: This list of registers is not comprehensive - there are more * that should be added. -- cgit v1.2.3-70-g09d2 From 94a3ef6f2888ae995a8d112e277ed8465a9457fb Mon Sep 17 00:00:00 2001 From: Peter 'p2' De Schrijver Date: Mon, 19 Jan 2009 19:09:22 +0200 Subject: OMAP3: PM: Ensure MUSB block can idle when driver not loaded Otherwise, bootloaders may leave MUSB in a state which prevents retention. Signed-off-by: Kevin Hilman --- arch/arm/mach-omap2/Makefile | 2 -- arch/arm/mach-omap2/usb-musb.c | 20 ++++++++++++++++++++ arch/arm/plat-omap/include/mach/usb.h | 6 ------ 3 files changed, 20 insertions(+), 8 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 6fd1c1f7739..3935a359e7e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -57,6 +57,4 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ mmc-twl4030.o # Platform specific device init code -ifeq ($(CONFIG_USB_MUSB_SOC),y) obj-y += usb-musb.o -endif diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 215d463b70e..d85296dc896 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -31,6 +31,17 @@ #include #include +#define OTG_SYSCONFIG (OMAP34XX_HSUSB_OTG_BASE + 0x404) + +static void __init usb_musb_pm_init(void) +{ + /* Ensure force-idle mode for OTG controller */ + if (cpu_is_omap34xx()) + omap_writel(0, OTG_SYSCONFIG); +} + +#ifdef CONFIG_USB_MUSB_SOC + static struct resource musb_resources[] = { [0] = { /* start and end set dynamically */ .flags = IORESOURCE_MEM, @@ -183,4 +194,13 @@ void __init usb_musb_init(void) printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n"); return; } + + usb_musb_pm_init(); +} + +#else +void __init usb_musb_init(void) +{ + usb_musb_pm_init(); } +#endif /* CONFIG_USB_MUSB_SOC */ diff --git a/arch/arm/plat-omap/include/mach/usb.h b/arch/arm/plat-omap/include/mach/usb.h index 69f0ceed500..f337e1761e2 100644 --- a/arch/arm/plat-omap/include/mach/usb.h +++ b/arch/arm/plat-omap/include/mach/usb.h @@ -27,13 +27,7 @@ #define UDC_BASE OMAP2_UDC_BASE #define OMAP_OHCI_BASE OMAP2_OHCI_BASE -#ifdef CONFIG_USB_MUSB_SOC extern void usb_musb_init(void); -#else -static inline void usb_musb_init(void) -{ -} -#endif #endif -- cgit v1.2.3-70-g09d2 From 0815f8eaae6d11b9dae6c2ff0202d7945f8d7cd2 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 28 May 2009 13:23:51 -0700 Subject: ARM: OMAP2/3: DMA: implement trans copy and const fill Implement transparent copy and constant fill features for OMAP2/3. Signed-off-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 77 ++++++++++++++++++++++------------- arch/arm/plat-omap/include/mach/dma.h | 1 + 2 files changed, 50 insertions(+), 28 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 7fc8c045ad5..58d98ad981e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -310,41 +310,62 @@ EXPORT_SYMBOL(omap_set_dma_transfer_params); void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) { - u16 w; - BUG_ON(omap_dma_in_1510_mode()); - if (cpu_class_is_omap2()) { - REVISIT_24XX(); - return; - } + if (cpu_class_is_omap1()) { + u16 w; - w = dma_read(CCR2(lch)); - w &= ~0x03; + w = dma_read(CCR2(lch)); + w &= ~0x03; - switch (mode) { - case OMAP_DMA_CONSTANT_FILL: - w |= 0x01; - break; - case OMAP_DMA_TRANSPARENT_COPY: - w |= 0x02; - break; - case OMAP_DMA_COLOR_DIS: - break; - default: - BUG(); + switch (mode) { + case OMAP_DMA_CONSTANT_FILL: + w |= 0x01; + break; + case OMAP_DMA_TRANSPARENT_COPY: + w |= 0x02; + break; + case OMAP_DMA_COLOR_DIS: + break; + default: + BUG(); + } + dma_write(w, CCR2(lch)); + + w = dma_read(LCH_CTRL(lch)); + w &= ~0x0f; + /* Default is channel type 2D */ + if (mode) { + dma_write((u16)color, COLOR_L(lch)); + dma_write((u16)(color >> 16), COLOR_U(lch)); + w |= 1; /* Channel type G */ + } + dma_write(w, LCH_CTRL(lch)); } - dma_write(w, CCR2(lch)); - w = dma_read(LCH_CTRL(lch)); - w &= ~0x0f; - /* Default is channel type 2D */ - if (mode) { - dma_write((u16)color, COLOR_L(lch)); - dma_write((u16)(color >> 16), COLOR_U(lch)); - w |= 1; /* Channel type G */ + if (cpu_class_is_omap2()) { + u32 val; + + val = dma_read(CCR(lch)); + val &= ~((1 << 17) | (1 << 16)); + + switch (mode) { + case OMAP_DMA_CONSTANT_FILL: + val |= 1 << 16; + break; + case OMAP_DMA_TRANSPARENT_COPY: + val |= 1 << 17; + break; + case OMAP_DMA_COLOR_DIS: + break; + default: + BUG(); + } + dma_write(val, CCR(lch)); + + color &= 0xffffff; + dma_write(color, COLOR(lch)); } - dma_write(w, LCH_CTRL(lch)); } EXPORT_SYMBOL(omap_set_dma_color_mode); diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 54fe9665b18..35fefdb0b79 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -144,6 +144,7 @@ #define OMAP_DMA4_CSSA_U(n) 0 #define OMAP_DMA4_CDSA_L(n) 0 #define OMAP_DMA4_CDSA_U(n) 0 +#define OMAP1_DMA_COLOR(n) 0 /*----------------------------------------------------------------------------*/ -- cgit v1.2.3-70-g09d2 From 279b918d726a66c61c9dc7aec8b1fb035d40fdfc Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 28 May 2009 13:23:52 -0700 Subject: ARM: OMAP2/3: sDMA: Correct omap_request_dma_chain(), v2 Original OMAP DMA chaining design had chain_id as one of the callback parameters. Patch 538528de0cb256f65716ab2e9613d9e920f97fe2 changed it to use logical channel instead. Correct the naming for callback to also use logical channel number instead of the chain_id. More details are on this email thread: http://marc.info/?l=linux-omap&m=122961071931459&w=2 Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 2 +- arch/arm/plat-omap/include/mach/dma.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 58d98ad981e..06e9cbe8b8e 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -1220,7 +1220,7 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) * Failure: -EINVAL/-ENOMEM */ int omap_request_dma_chain(int dev_id, const char *dev_name, - void (*callback) (int chain_id, u16 ch_status, + void (*callback) (int lch, u16 ch_status, void *data), int *chain_id, int no_of_chans, int chain_mode, struct omap_dma_channel_params params) diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 35fefdb0b79..19df76f97ab 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -532,7 +532,7 @@ extern int omap_get_dma_index(int lch, int *ei, int *fi); /* Chaining APIs */ #ifndef CONFIG_ARCH_OMAP1 extern int omap_request_dma_chain(int dev_id, const char *dev_name, - void (*callback) (int chain_id, u16 ch_status, + void (*callback) (int lch, u16 ch_status, void *data), int *chain_id, int no_of_chans, int chain_mode, -- cgit v1.2.3-70-g09d2 From aa62e90fe0700c037675926fff9f75b0b1c00d78 Mon Sep 17 00:00:00 2001 From: Juha Yrjola Date: Thu, 28 May 2009 13:23:52 -0700 Subject: ARM: OMAP2/3: Add generic onenand support when connected to GPMC Add generic onenand support when connected to GPMC and make the boards to use it. The patch has been modified to make it more generic to support all the boards with GPMC. The patch also remove unused prototype for omap2_onenand_rephase(void). Note that board-apollon.c is currently using the MTD_ONENAND_GENERIC and setting the GPMC timings in the bootloader. Setting the GPMC timings in the bootloader will not allow supporting frequency scaling for the onenand source clock. Signed-off-by: Tony Lindgren --- arch/arm/configs/rx51_defconfig | 2 +- arch/arm/mach-omap2/Makefile | 3 + arch/arm/mach-omap2/board-rx51-peripherals.c | 58 +++++ arch/arm/mach-omap2/gpmc-onenand.c | 330 +++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/onenand.h | 22 +- 5 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-omap2/gpmc-onenand.c (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/configs/rx51_defconfig b/arch/arm/configs/rx51_defconfig index 593102da8cd..eb2cb31825c 100644 --- a/arch/arm/configs/rx51_defconfig +++ b/arch/arm/configs/rx51_defconfig @@ -282,7 +282,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs rw console=ttyMTD5" +CONFIG_CMDLINE="init=/sbin/preinit ubi.mtd=rootfs root=ubi0:rootfs rootfstype=ubifs rootflags=bulk_read,no_chk_data_crc rw console=ttyMTD,log console=tty0" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index bf3827ae2c5..11f7f660879 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -58,3 +58,6 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ ifeq ($(CONFIG_USB_MUSB_SOC),y) obj-y += usb-musb.o endif + +onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o +obj-y += $(onenand-m) $(onenand-y) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index a7381729645..ca18ae94185 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -408,6 +409,62 @@ static int __init rx51_i2c_init(void) return 0; } +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ + defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) + +static struct mtd_partition onenand_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 0x20000, + .mask_flags = MTD_WRITEABLE, /* Force read-only */ + }, + { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = 0x60000, + }, + { + .name = "log", + .offset = MTDPART_OFS_APPEND, + .size = 0x40000, + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 0x200000, + }, + { + .name = "initfs", + .offset = MTDPART_OFS_APPEND, + .size = 0x200000, + }, + { + .name = "rootfs", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +static struct omap_onenand_platform_data board_onenand_data = { + .cs = 0, + .gpio_irq = 65, + .parts = onenand_partitions, + .nr_parts = ARRAY_SIZE(onenand_partitions), +}; + +static void __init board_onenand_init(void) +{ + gpmc_onenand_init(&board_onenand_data); +} + +#else + +static inline void board_onenand_init(void) +{ +} + +#endif void __init rx51_peripherals_init(void) { @@ -415,5 +472,6 @@ void __init rx51_peripherals_init(void) ARRAY_SIZE(rx51_peripherals_devices)); rx51_i2c_init(); rx51_init_smc91x(); + board_onenand_init(); } diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c new file mode 100644 index 00000000000..2fd22f9c5f0 --- /dev/null +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -0,0 +1,330 @@ +/* + * linux/arch/arm/mach-omap2/gpmc-onenand.c + * + * Copyright (C) 2006 - 2009 Nokia Corporation + * Contacts: Juha Yrjola + * Tony Lindgren + * + * 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 +#include +#include +#include + +#include + +#include +#include +#include + +static struct omap_onenand_platform_data *gpmc_onenand_data; + +static struct platform_device gpmc_onenand_device = { + .name = "omap2-onenand", + .id = -1, +}; + +static int omap2_onenand_set_async_mode(int cs, void __iomem *onenand_base) +{ + struct gpmc_timings t; + + const int t_cer = 15; + const int t_avdp = 12; + const int t_aavdh = 7; + const int t_ce = 76; + const int t_aa = 76; + const int t_oe = 20; + const int t_cez = 20; /* max of t_cez, t_oez */ + const int t_ds = 30; + const int t_wpl = 40; + const int t_wph = 30; + + memset(&t, 0, sizeof(t)); + t.sync_clk = 0; + t.cs_on = 0; + t.adv_on = 0; + + /* Read */ + t.adv_rd_off = gpmc_round_ns_to_ticks(max_t(int, t_avdp, t_cer)); + t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(t_aavdh); + t.access = t.adv_on + gpmc_round_ns_to_ticks(t_aa); + t.access = max_t(int, t.access, t.cs_on + gpmc_round_ns_to_ticks(t_ce)); + t.access = max_t(int, t.access, t.oe_on + gpmc_round_ns_to_ticks(t_oe)); + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(t_cez); + + /* Write */ + t.adv_wr_off = t.adv_rd_off; + t.we_on = t.oe_on; + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = t.we_on; + t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); + } + t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + + /* Configure GPMC for asynchronous read */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_MUXADDDATA); + + return gpmc_cs_set_timings(cs, &t); +} + +static void set_onenand_cfg(void __iomem *onenand_base, int latency, + int sync_read, int sync_write, int hf) +{ + u32 reg; + + reg = readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); + reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | + ONENAND_SYS_CFG1_BL_16; + if (sync_read) + reg |= ONENAND_SYS_CFG1_SYNC_READ; + else + reg &= ~ONENAND_SYS_CFG1_SYNC_READ; + if (sync_write) + reg |= ONENAND_SYS_CFG1_SYNC_WRITE; + else + reg &= ~ONENAND_SYS_CFG1_SYNC_WRITE; + if (hf) + reg |= ONENAND_SYS_CFG1_HF; + else + reg &= ~ONENAND_SYS_CFG1_HF; + writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); +} + +static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, + void __iomem *onenand_base, + int freq) +{ + struct gpmc_timings t; + const int t_cer = 15; + const int t_avdp = 12; + const int t_cez = 20; /* max of t_cez, t_oez */ + const int t_ds = 30; + const int t_wpl = 40; + const int t_wph = 30; + int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo; + int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; + int first_time = 0, hf = 0, sync_read = 0, sync_write = 0; + int err, ticks_cez; + int cs = cfg->cs; + u32 reg; + + if (cfg->flags & ONENAND_SYNC_READ) { + sync_read = 1; + } else if (cfg->flags & ONENAND_SYNC_READWRITE) { + sync_read = 1; + sync_write = 1; + } + + if (!freq) { + /* Very first call freq is not known */ + err = omap2_onenand_set_async_mode(cs, onenand_base); + if (err) + return err; + reg = readw(onenand_base + ONENAND_REG_VERSION_ID); + switch ((reg >> 4) & 0xf) { + case 0: + freq = 40; + break; + case 1: + freq = 54; + break; + case 2: + freq = 66; + break; + case 3: + freq = 83; + break; + case 4: + freq = 104; + break; + default: + freq = 54; + break; + } + first_time = 1; + } + + switch (freq) { + case 83: + min_gpmc_clk_period = 12; /* 83 MHz */ + t_ces = 5; + t_avds = 4; + t_avdh = 2; + t_ach = 6; + t_aavdh = 6; + t_rdyo = 9; + break; + case 66: + min_gpmc_clk_period = 15; /* 66 MHz */ + t_ces = 6; + t_avds = 5; + t_avdh = 2; + t_ach = 6; + t_aavdh = 6; + t_rdyo = 11; + break; + default: + min_gpmc_clk_period = 18; /* 54 MHz */ + t_ces = 7; + t_avds = 7; + t_avdh = 7; + t_ach = 9; + t_aavdh = 7; + t_rdyo = 15; + sync_write = 0; + break; + } + + tick_ns = gpmc_ticks_to_ns(1); + div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + gpmc_clk_ns = gpmc_ticks_to_ns(div); + if (gpmc_clk_ns < 15) /* >66Mhz */ + hf = 1; + if (hf) + latency = 6; + else if (gpmc_clk_ns >= 25) /* 40 MHz*/ + latency = 3; + else + latency = 4; + + if (first_time) + set_onenand_cfg(onenand_base, latency, + sync_read, sync_write, hf); + + if (div == 1) { + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); + reg |= (1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); + reg |= (1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); + reg |= (1 << 7); + reg |= (1 << 23); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + } else { + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2); + reg &= ~(1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG2, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG3); + reg &= ~(1 << 7); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG3, reg); + reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG4); + reg &= ~(1 << 7); + reg &= ~(1 << 23); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG4, reg); + } + + /* Set synchronous read timings */ + memset(&t, 0, sizeof(t)); + t.sync_clk = min_gpmc_clk_period; + t.cs_on = 0; + t.adv_on = 0; + fclk_offset_ns = gpmc_round_ns_to_ticks(max_t(int, t_ces, t_avds)); + fclk_offset = gpmc_ns_to_ticks(fclk_offset_ns); + t.page_burst_access = gpmc_clk_ns; + + /* Read */ + t.adv_rd_off = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_avdh)); + t.oe_on = gpmc_ticks_to_ns(fclk_offset + gpmc_ns_to_ticks(t_ach)); + t.access = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div); + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + ticks_cez = ((gpmc_ns_to_ticks(t_cez) + div - 1) / div) * div; + t.rd_cycle = gpmc_ticks_to_ns(fclk_offset + (latency + 1) * div + + ticks_cez); + + /* Write */ + if (sync_write) { + t.adv_wr_off = t.adv_rd_off; + t.we_on = 0; + t.we_off = t.cs_rd_off; + t.cs_wr_off = t.cs_rd_off; + t.wr_cycle = t.rd_cycle; + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = gpmc_ticks_to_ns(fclk_offset + + gpmc_ns_to_ticks(min_gpmc_clk_period + + t_rdyo)); + t.wr_access = t.access; + } + } else { + t.adv_wr_off = gpmc_round_ns_to_ticks(max_t(int, + t_avdp, t_cer)); + t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(t_aavdh); + t.we_off = t.we_on + gpmc_round_ns_to_ticks(t_wpl); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(t_wph); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(t_cez); + if (cpu_is_omap34xx()) { + t.wr_data_mux_bus = t.we_on; + t.wr_access = t.we_on + gpmc_round_ns_to_ticks(t_ds); + } + } + + /* Configure GPMC for synchronous read */ + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_READMULTIPLE_SUPP | + (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) | + (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) | + (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) | + GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | + GPMC_CONFIG1_PAGE_LEN(2) | + (cpu_is_omap34xx() ? 0 : + (GPMC_CONFIG1_WAIT_READ_MON | + GPMC_CONFIG1_WAIT_PIN_SEL(0))) | + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_MUXADDDATA); + + err = gpmc_cs_set_timings(cs, &t); + if (err) + return err; + + set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf); + + return 0; +} + +static int gpmc_onenand_setup(void __iomem *onenand_base, int freq) +{ + struct device *dev = &gpmc_onenand_device.dev; + + /* Set sync timings in GPMC */ + if (omap2_onenand_set_sync_mode(gpmc_onenand_data, onenand_base, + freq) < 0) { + dev_err(dev, "Unable to set synchronous mode\n"); + return -EINVAL; + } + + return 0; +} + +void __init gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data) +{ + gpmc_onenand_data = _onenand_data; + gpmc_onenand_data->onenand_setup = gpmc_onenand_setup; + gpmc_onenand_device.dev.platform_data = gpmc_onenand_data; + + if (cpu_is_omap24xx() && + (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) { + printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n"); + gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE; + gpmc_onenand_data->flags |= ONENAND_SYNC_READ; + } + + if (platform_device_register(&gpmc_onenand_device) < 0) { + printk(KERN_ERR "Unable to register OneNAND device\n"); + return; + } +} diff --git a/arch/arm/plat-omap/include/mach/onenand.h b/arch/arm/plat-omap/include/mach/onenand.h index 4649d302c26..72f433d7d82 100644 --- a/arch/arm/plat-omap/include/mach/onenand.h +++ b/arch/arm/plat-omap/include/mach/onenand.h @@ -9,8 +9,12 @@ * published by the Free Software Foundation. */ +#include #include +#define ONENAND_SYNC_READ (1 << 0) +#define ONENAND_SYNC_READWRITE (1 << 1) + struct omap_onenand_platform_data { int cs; int gpio_irq; @@ -18,8 +22,22 @@ struct omap_onenand_platform_data { int nr_parts; int (*onenand_setup)(void __iomem *, int freq); int dma_channel; + u8 flags; }; -int omap2_onenand_rephase(void); - #define ONENAND_MAX_PARTITIONS 8 + +#if defined(CONFIG_MTD_ONENAND_OMAP2) || \ + defined(CONFIG_MTD_ONENAND_OMAP2_MODULE) + +extern void gpmc_onenand_init(struct omap_onenand_platform_data *d); + +#else + +#define board_onenand_data NULL + +static inline void gpmc_onenand_init(struct omap_onenand_platform_data *d) +{ +} + +#endif -- cgit v1.2.3-70-g09d2 From 1a48e1575188d4023b3428b623caeefe8c599e79 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 28 May 2009 13:23:52 -0700 Subject: ARM: OMAP2/3: Add generic smc91x support when connected to GPMC Convert the board-rx51 smc91x code to be generic and make the boards to use it. This allows future recalculation of the timings when the source clock gets scaled. Also correct the rx51 interrupt to be IORESOURCE_IRQ_HIGHLEVEL. Thanks to Paul Walmsley for better GPMC timing calculations. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Makefile | 3 + arch/arm/mach-omap2/board-2430sdp.c | 103 +++----------- arch/arm/mach-omap2/board-3430sdp.c | 84 ++++-------- arch/arm/mach-omap2/board-rx51-peripherals.c | 146 ++++---------------- arch/arm/mach-omap2/gpmc-smc91x.c | 189 ++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/gpmc-smc91x.h | 42 ++++++ 6 files changed, 313 insertions(+), 254 deletions(-) create mode 100644 arch/arm/mach-omap2/gpmc-smc91x.c create mode 100644 arch/arm/plat-omap/include/mach/gpmc-smc91x.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 11f7f660879..e4f6f61c40e 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -61,3 +61,6 @@ endif onenand-$(CONFIG_MTD_ONENAND_OMAP2) := gpmc-onenand.o obj-y += $(onenand-m) $(onenand-y) + +smc91x-$(CONFIG_SMC91X) := gpmc-smc91x.o +obj-y += $(smc91x-m) $(smc91x-y) diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 22143651037..ef70b79942c 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -36,14 +36,11 @@ #include #include #include +#include #include "mmc-twl4030.h" #define SDP2430_CS0_BASE 0x04000000 -#define SDP2430_FLASH_CS 0 -#define SDP2430_SMC91X_CS 5 - -#define SDP2430_ETHR_GPIO_IRQ 149 static struct mtd_partition sdp2430_partitions[] = { /* bootloader (U-Boot, etc) in first sector */ @@ -99,100 +96,43 @@ static struct platform_device sdp2430_flash_device = { .resource = &sdp2430_flash_resource, }; -static struct resource sdp2430_smc91x_resources[] = { - [0] = { - .start = SDP2430_CS0_BASE, - .end = SDP2430_CS0_BASE + SZ_64M - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ), - .end = OMAP_GPIO_IRQ(SDP2430_ETHR_GPIO_IRQ), - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, - }, -}; - -static struct platform_device sdp2430_smc91x_device = { - .name = "smc91x", - .id = -1, - .num_resources = ARRAY_SIZE(sdp2430_smc91x_resources), - .resource = sdp2430_smc91x_resources, -}; - static struct platform_device *sdp2430_devices[] __initdata = { - &sdp2430_smc91x_device, &sdp2430_flash_device, }; -static inline void __init sdp2430_init_smc91x(void) -{ - int eth_cs; - unsigned long cs_mem_base; - unsigned int rate; - struct clk *gpmc_fck; - - eth_cs = SDP2430_SMC91X_CS; +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE) - gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ - if (IS_ERR(gpmc_fck)) { - WARN_ON(1); - return; - } +static struct omap_smc91x_platform_data board_smc91x_data = { + .cs = 5, + .gpio_irq = 149, + .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 | + IORESOURCE_IRQ_LOWLEVEL, - clk_enable(gpmc_fck); - rate = clk_get_rate(gpmc_fck); - - /* Make sure CS1 timings are correct, for 2430 always muxed */ - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200); - - if (rate >= 160000000) { - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); - } else if (rate >= 130000000) { - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); - } else { /* rate = 100000000 */ - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F); - gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2); - } +}; - if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { - printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); - goto out; - } +static void __init board_smc91x_init(void) +{ + if (omap_rev() > OMAP3430_REV_ES1_0) + board_smc91x_data.gpio_irq = 6; + else + board_smc91x_data.gpio_irq = 29; - sdp2430_smc91x_resources[0].start = cs_mem_base + 0x300; - sdp2430_smc91x_resources[0].end = cs_mem_base + 0x30f; - udelay(100); + gpmc_smc91x_init(&board_smc91x_data); +} - if (gpio_request(SDP2430_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { - printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", - SDP2430_ETHR_GPIO_IRQ); - gpmc_cs_free(eth_cs); - goto out; - } - gpio_direction_input(SDP2430_ETHR_GPIO_IRQ); +#else -out: - clk_disable(gpmc_fck); - clk_put(gpmc_fck); +static inline void board_smc91x_init(void) +{ } +#endif + static void __init omap_2430sdp_init_irq(void) { omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); - sdp2430_init_smc91x(); } static struct omap_uart_config sdp2430_uart_config __initdata = { @@ -256,6 +196,7 @@ static void __init omap_2430sdp_init(void) omap_serial_init(); twl4030_mmc_init(mmc); usb_musb_init(); + board_smc91x_init(); } static void __init omap_2430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index ed927497212..0e636958395 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -39,15 +39,12 @@ #include #include +#include #include "mmc-twl4030.h" #define CONFIG_DISABLE_HFCLK 1 -#define SDP3430_ETHR_GPIO_IRQ_SDPV1 29 -#define SDP3430_ETHR_GPIO_IRQ_SDPV2 6 -#define SDP3430_SMC91X_CS 3 - #define SDP3430_TS_GPIO_IRQ_SDPV1 3 #define SDP3430_TS_GPIO_IRQ_SDPV2 2 @@ -56,24 +53,6 @@ #define TWL4030_MSECURE_GPIO 22 -static struct resource sdp3430_smc91x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = 0, - .end = 0, - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL, - }, -}; - -static struct platform_device sdp3430_smc91x_device = { - .name = "smc91x", - .id = -1, - .num_resources = ARRAY_SIZE(sdp3430_smc91x_resources), - .resource = sdp3430_smc91x_resources, -}; - static int sdp3430_keymap[] = { KEY(0, 0, KEY_LEFT), KEY(0, 1, KEY_RIGHT), @@ -184,48 +163,14 @@ static struct regulator_consumer_supply sdp3430_vdvi_supply = { }; static struct platform_device *sdp3430_devices[] __initdata = { - &sdp3430_smc91x_device, &sdp3430_lcd_device, }; -static inline void __init sdp3430_init_smc91x(void) -{ - int eth_cs; - unsigned long cs_mem_base; - int eth_gpio = 0; - - eth_cs = SDP3430_SMC91X_CS; - - if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { - printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); - return; - } - - sdp3430_smc91x_resources[0].start = cs_mem_base + 0x300; - sdp3430_smc91x_resources[0].end = cs_mem_base + 0x30f; - udelay(100); - - if (omap_rev() > OMAP3430_REV_ES1_0) - eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV2; - else - eth_gpio = SDP3430_ETHR_GPIO_IRQ_SDPV1; - - sdp3430_smc91x_resources[1].start = gpio_to_irq(eth_gpio); - - if (gpio_request(eth_gpio, "SMC91x irq") < 0) { - printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", - eth_gpio); - return; - } - gpio_direction_input(eth_gpio); -} - static void __init omap_3430sdp_init_irq(void) { omap2_init_common_hw(NULL); omap_init_irq(); omap_gpio_init(); - sdp3430_init_smc91x(); } static struct omap_uart_config sdp3430_uart_config __initdata = { @@ -506,6 +451,32 @@ static int __init omap3430_i2c_init(void) return 0; } +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) + +static struct omap_smc91x_platform_data board_smc91x_data = { + .cs = 3, + .flags = GPMC_MUX_ADD_DATA | GPMC_TIMINGS_SMC91C96 | + IORESOURCE_IRQ_LOWLEVEL, +}; + +static void __init board_smc91x_init(void) +{ + if (omap_rev() > OMAP3430_REV_ES1_0) + board_smc91x_data.gpio_irq = 6; + else + board_smc91x_data.gpio_irq = 29; + + gpmc_smc91x_init(&board_smc91x_data); +} + +#else + +static inline void board_smc91x_init(void) +{ +} + +#endif + static void __init omap_3430sdp_init(void) { omap3430_i2c_init(); @@ -522,6 +493,7 @@ static void __init omap_3430sdp_init(void) ads7846_dev_init(); omap_serial_init(); usb_musb_init(); + board_smc91x_init(); } static void __init omap_3430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index ca18ae94185..233c7454d84 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -28,31 +28,10 @@ #include #include #include +#include #include "mmc-twl4030.h" - -#define SMC91X_CS 1 -#define SMC91X_GPIO_IRQ 54 -#define SMC91X_GPIO_RESET 164 -#define SMC91X_GPIO_PWRDWN 86 - -static struct resource rx51_smc91x_resources[] = { - [0] = { - .flags = IORESOURCE_MEM, - }, - [1] = { - .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, - }, -}; - -static struct platform_device rx51_smc91x_device = { - .name = "smc91x", - .id = -1, - .num_resources = ARRAY_SIZE(rx51_smc91x_resources), - .resource = rx51_smc91x_resources, -}; - static int rx51_keymap[] = { KEY(0, 0, KEY_Q), KEY(0, 1, KEY_W), @@ -108,98 +87,6 @@ static struct twl4030_keypad_data rx51_kp_data = { .rep = 1, }; -static struct platform_device *rx51_peripherals_devices[] = { - &rx51_smc91x_device, -}; - -/* - * Timings are taken from smsc-lan91c96-ms.pdf - */ -static int smc91x_init_gpmc(int cs) -{ - struct gpmc_timings t; - const int t2_r = 45; /* t2 in Figure 12.10 */ - const int t2_w = 30; /* t2 in Figure 12.11 */ - const int t3 = 15; /* t3 in Figure 12.10 */ - const int t5_r = 0; /* t5 in Figure 12.10 */ - const int t6_r = 45; /* t6 in Figure 12.10 */ - const int t6_w = 0; /* t6 in Figure 12.11 */ - const int t7_w = 15; /* t7 in Figure 12.11 */ - const int t15 = 12; /* t15 in Figure 12.2 */ - const int t20 = 185; /* t20 in Figure 12.2 */ - - memset(&t, 0, sizeof(t)); - - t.cs_on = t15; - t.cs_rd_off = t3 + t2_r + t5_r; /* Figure 12.10 */ - t.cs_wr_off = t3 + t2_w + t6_w; /* Figure 12.11 */ - t.adv_on = t3; /* Figure 12.10 */ - t.adv_rd_off = t3 + t2_r; /* Figure 12.10 */ - t.adv_wr_off = t3 + t2_w; /* Figure 12.11 */ - t.oe_off = t3 + t2_r + t5_r; /* Figure 12.10 */ - t.oe_on = t.oe_off - t6_r; /* Figure 12.10 */ - t.we_off = t3 + t2_w + t6_w; /* Figure 12.11 */ - t.we_on = t.we_off - t7_w; /* Figure 12.11 */ - t.rd_cycle = t20; /* Figure 12.2 */ - t.wr_cycle = t20; /* Figure 12.4 */ - t.access = t3 + t2_r + t5_r; /* Figure 12.10 */ - t.wr_access = t3 + t2_w + t6_w; /* Figure 12.11 */ - - gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, GPMC_CONFIG1_DEVICESIZE_16); - - return gpmc_cs_set_timings(cs, &t); -} - -static void __init rx51_init_smc91x(void) -{ - unsigned long cs_mem_base; - int ret; - - omap_cfg_reg(U8_34XX_GPIO54_DOWN); - omap_cfg_reg(G25_34XX_GPIO86_OUT); - omap_cfg_reg(H19_34XX_GPIO164_OUT); - - if (gpmc_cs_request(SMC91X_CS, SZ_16M, &cs_mem_base) < 0) { - printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); - return; - } - - rx51_smc91x_resources[0].start = cs_mem_base + 0x300; - rx51_smc91x_resources[0].end = cs_mem_base + 0x30f; - - smc91x_init_gpmc(SMC91X_CS); - - if (gpio_request(SMC91X_GPIO_IRQ, "SMC91X irq") < 0) - goto free1; - - gpio_direction_input(SMC91X_GPIO_IRQ); - rx51_smc91x_resources[1].start = gpio_to_irq(SMC91X_GPIO_IRQ); - - ret = gpio_request(SMC91X_GPIO_PWRDWN, "SMC91X powerdown"); - if (ret) - goto free2; - gpio_direction_output(SMC91X_GPIO_PWRDWN, 0); - - ret = gpio_request(SMC91X_GPIO_RESET, "SMC91X reset"); - if (ret) - goto free3; - gpio_direction_output(SMC91X_GPIO_RESET, 0); - gpio_set_value(SMC91X_GPIO_RESET, 1); - msleep(100); - gpio_set_value(SMC91X_GPIO_RESET, 0); - - return; - -free3: - gpio_free(SMC91X_GPIO_PWRDWN); -free2: - gpio_free(SMC91X_GPIO_IRQ); -free1: - gpmc_cs_free(SMC91X_CS); - - printk(KERN_ERR "Could not initialize smc91x\n"); -} - static struct twl4030_madc_platform_data rx51_madc_data = { .irq_line = 1, }; @@ -466,12 +353,37 @@ static inline void board_onenand_init(void) #endif +#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91X_MODULE) + +static struct omap_smc91x_platform_data board_smc91x_data = { + .cs = 1, + .gpio_irq = 54, + .gpio_pwrdwn = 86, + .gpio_reset = 164, + .flags = GPMC_TIMINGS_SMC91C96 | IORESOURCE_IRQ_HIGHLEVEL, +}; + +static void __init board_smc91x_init(void) +{ + omap_cfg_reg(U8_34XX_GPIO54_DOWN); + omap_cfg_reg(G25_34XX_GPIO86_OUT); + omap_cfg_reg(H19_34XX_GPIO164_OUT); + + gpmc_smc91x_init(&board_smc91x_data); +} + +#else + +static inline void board_smc91x_init(void) +{ +} + +#endif + void __init rx51_peripherals_init(void) { - platform_add_devices(rx51_peripherals_devices, - ARRAY_SIZE(rx51_peripherals_devices)); rx51_i2c_init(); - rx51_init_smc91x(); board_onenand_init(); + board_smc91x_init(); } diff --git a/arch/arm/mach-omap2/gpmc-smc91x.c b/arch/arm/mach-omap2/gpmc-smc91x.c new file mode 100644 index 00000000000..df99d31d8b6 --- /dev/null +++ b/arch/arm/mach-omap2/gpmc-smc91x.c @@ -0,0 +1,189 @@ +/* + * linux/arch/arm/mach-omap2/gpmc-smc91x.c + * + * Copyright (C) 2009 Nokia Corporation + * Contact: Tony Lindgren + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +static struct omap_smc91x_platform_data *gpmc_cfg; + +static struct resource gpmc_smc91x_resources[] = { + [0] = { + .flags = IORESOURCE_MEM, + }, + [1] = { + .flags = IORESOURCE_IRQ, + }, +}; + +static struct smc91x_platdata gpmc_smc91x_info = { + .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_0, +}; + +static struct platform_device gpmc_smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(gpmc_smc91x_resources), + .resource = gpmc_smc91x_resources, + .dev = { + .platform_data = &gpmc_smc91x_info, + }, +}; + +/* + * Set the gpmc timings for smc91c96. The timings are taken + * from the data sheet available at: + * http://www.smsc.com/main/catalog/lan91c96.html + * REVISIT: Level shifters can add at least to the access latency. + */ +static int smc91c96_gpmc_retime(void) +{ + struct gpmc_timings t; + const int t3 = 10; /* Figure 12.2 read and 12.4 write */ + const int t4_r = 20; /* Figure 12.2 read */ + const int t4_w = 5; /* Figure 12.4 write */ + const int t5 = 25; /* Figure 12.2 read */ + const int t6 = 15; /* Figure 12.2 read */ + const int t7 = 5; /* Figure 12.4 write */ + const int t8 = 5; /* Figure 12.4 write */ + const int t20 = 185; /* Figure 12.2 read and 12.4 write */ + u32 l; + + memset(&t, 0, sizeof(t)); + + /* Read timings */ + t.cs_on = 0; + t.adv_on = t.cs_on; + t.oe_on = t.adv_on + t3; + t.access = t.oe_on + t5; + t.oe_off = t.access; + t.adv_rd_off = t.oe_off + max(t4_r, t6); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t20 - t.oe_on; + + /* Write timings */ + t.we_on = t.adv_on + t3; + + if (cpu_is_omap34xx() && (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)) { + t.wr_data_mux_bus = t.we_on; + t.we_off = t.wr_data_mux_bus + t7; + } else + t.we_off = t.we_on + t7; + if (cpu_is_omap34xx()) + t.wr_access = t.we_off; + t.adv_wr_off = t.we_off + max(t4_w, t8); + t.cs_wr_off = t.we_off + t4_w; + t.wr_cycle = t20 - t.we_on; + + l = GPMC_CONFIG1_DEVICESIZE_16; + if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) + l |= GPMC_CONFIG1_MUXADDDATA; + if (gpmc_cfg->flags & GPMC_READ_MON) + l |= GPMC_CONFIG1_WAIT_READ_MON; + if (gpmc_cfg->flags & GPMC_WRITE_MON) + l |= GPMC_CONFIG1_WAIT_WRITE_MON; + if (gpmc_cfg->wait_pin) + l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin); + gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l); + + /* + * FIXME: Calculate the address and data bus muxed timings. + * Note that at least adv_rd_off needs to be changed according + * to omap3430 TRM Figure 11-11. Are the sdp boards using the + * FPGA in between smc91x and omap as the timings are different + * from above? + */ + if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA) + return 0; + + return gpmc_cs_set_timings(gpmc_cfg->cs, &t); +} + +/* + * Initialize smc91x device connected to the GPMC. Note that we + * assume that pin multiplexing is done in the board-*.c file, + * or in the bootloader. + */ +void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data) +{ + unsigned long cs_mem_base; + int ret; + + gpmc_cfg = board_data; + + if (gpmc_cfg->flags & GPMC_TIMINGS_SMC91C96) + gpmc_cfg->retime = smc91c96_gpmc_retime; + + if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); + return; + } + + gpmc_smc91x_resources[0].start = cs_mem_base + 0x300; + gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f; + gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK); + + if (gpmc_cfg->retime) { + ret = gpmc_cfg->retime(); + if (ret != 0) + goto free1; + } + + if (gpio_request(gpmc_cfg->gpio_irq, "SMC91X irq") < 0) + goto free1; + + gpio_direction_input(gpmc_cfg->gpio_irq); + gpmc_smc91x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq); + + if (gpmc_cfg->gpio_pwrdwn) { + ret = gpio_request(gpmc_cfg->gpio_pwrdwn, "SMC91X powerdown"); + if (ret) + goto free2; + gpio_direction_output(gpmc_cfg->gpio_pwrdwn, 0); + } + + if (gpmc_cfg->gpio_reset) { + ret = gpio_request(gpmc_cfg->gpio_reset, "SMC91X reset"); + if (ret) + goto free3; + + gpio_direction_output(gpmc_cfg->gpio_reset, 0); + gpio_set_value(gpmc_cfg->gpio_reset, 1); + msleep(100); + gpio_set_value(gpmc_cfg->gpio_reset, 0); + } + + if (platform_device_register(&gpmc_smc91x_device) < 0) { + printk(KERN_ERR "Unable to register smc91x device\n"); + gpio_free(gpmc_cfg->gpio_reset); + goto free3; + } + + return; + +free3: + if (gpmc_cfg->gpio_pwrdwn) + gpio_free(gpmc_cfg->gpio_pwrdwn); +free2: + gpio_free(gpmc_cfg->gpio_irq); +free1: + gpmc_cs_free(gpmc_cfg->cs); + + printk(KERN_ERR "Could not initialize smc91x\n"); +} diff --git a/arch/arm/plat-omap/include/mach/gpmc-smc91x.h b/arch/arm/plat-omap/include/mach/gpmc-smc91x.h new file mode 100644 index 00000000000..b64fbee4d56 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/gpmc-smc91x.h @@ -0,0 +1,42 @@ +/* + * arch/arm/plat-omap/include/mach/gpmc-smc91x.h + * + * Copyright (C) 2009 Nokia Corporation + * + * 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. + */ + +#ifndef __ASM_ARCH_OMAP_GPMC_SMC91X_H__ + +#define GPMC_TIMINGS_SMC91C96 (1 << 4) +#define GPMC_MUX_ADD_DATA (1 << 5) /* GPMC_CONFIG1_MUXADDDATA */ +#define GPMC_READ_MON (1 << 6) /* GPMC_CONFIG1_WAIT_READ_MON */ +#define GPMC_WRITE_MON (1 << 7) /* GPMC_CONFIG1_WAIT_WRITE_MON */ + +struct omap_smc91x_platform_data { + int cs; + int gpio_irq; + int gpio_pwrdwn; + int gpio_reset; + int wait_pin; /* Optional GPMC_CONFIG1_WAITPINSELECT */ + u32 flags; + int (*retime)(void); +}; + +#if defined(CONFIG_SMC91X) || \ + defined(CONFIG_SMC91X_MODULE) + +extern void gpmc_smc91x_init(struct omap_smc91x_platform_data *d); + +#else + +#define board_smc91x_data NULL + +static inline void gpmc_smc91x_init(struct omap_smc91x_platform_data *d) +{ +} + +#endif +#endif -- cgit v1.2.3-70-g09d2 From 088962c243db42b9c608f30be3e3a05a5b696895 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 28 May 2009 14:03:31 -0700 Subject: ARM: OMAP1: Make 770 LCD work Make 770 LCD work by adding clk_add_alias(). Also remove the old unused functions. Note that the clk_add_alias() could probably be moved to arch/arm/clkdev.c later on. Cc: linux-fbdev-devel@lists.sourceforge.net Signed-off-by: Andrew de Quincey Signed-off-by: Imre Deak Signed-off-by: Tony Lindgren #include #include +#include #include #include #include +#include #define ADS7846_PENDOWN_GPIO 15 @@ -163,6 +165,15 @@ static struct spi_board_info nokia770_spi_board_info[] __initdata = { }, }; +static struct hwa742_platform_data nokia770_hwa742_platform_data = { + .te_connected = 1, +}; + +static void hwa742_dev_init(void) +{ + clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL); + omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data); +} /* assume no Mini-AB port */ @@ -371,6 +382,7 @@ static void __init omap_nokia770_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); omap_dsp_init(); + hwa742_dev_init(); ads7846_dev_init(); mipid_dev_init(); omap_usb_init(&nokia770_usb_config); diff --git a/arch/arm/plat-omap/include/mach/hwa742.h b/arch/arm/plat-omap/include/mach/hwa742.h index 577f492f2d3..886248d32b4 100644 --- a/arch/arm/plat-omap/include/mach/hwa742.h +++ b/arch/arm/plat-omap/include/mach/hwa742.h @@ -2,10 +2,6 @@ #define _HWA742_H struct hwa742_platform_data { - void (*power_up)(struct device *dev); - void (*power_down)(struct device *dev); - unsigned long (*get_clock_rate)(struct device *dev); - unsigned te_connected:1; }; diff --git a/drivers/video/omap/hwa742.c b/drivers/video/omap/hwa742.c index 8aa6e47202b..5d4f34887a2 100644 --- a/drivers/video/omap/hwa742.c +++ b/drivers/video/omap/hwa742.c @@ -133,8 +133,7 @@ struct { struct lcd_ctrl_extif *extif; struct lcd_ctrl *int_ctrl; - void (*power_up)(struct device *dev); - void (*power_down)(struct device *dev); + struct clk *sys_ck; } hwa742; struct lcd_ctrl hwa742_ctrl; @@ -915,14 +914,13 @@ static void hwa742_suspend(void) hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); /* Enable sleep mode */ hwa742_write_reg(HWA742_POWER_SAVE, 1 << 1); - if (hwa742.power_down != NULL) - hwa742.power_down(hwa742.fbdev->dev); + clk_disable(hwa742.sys_ck); } static void hwa742_resume(void) { - if (hwa742.power_up != NULL) - hwa742.power_up(hwa742.fbdev->dev); + clk_enable(hwa742.sys_ck); + /* Disable sleep mode */ hwa742_write_reg(HWA742_POWER_SAVE, 0); while (1) { @@ -955,14 +953,13 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, omapfb_conf = fbdev->dev->platform_data; ctrl_conf = omapfb_conf->ctrl_platform_data; - if (ctrl_conf == NULL || ctrl_conf->get_clock_rate == NULL) { + if (ctrl_conf == NULL) { dev_err(fbdev->dev, "HWA742: missing platform data\n"); r = -ENOENT; goto err1; } - hwa742.power_down = ctrl_conf->power_down; - hwa742.power_up = ctrl_conf->power_up; + hwa742.sys_ck = clk_get(NULL, "hwa_sys_ck"); spin_lock_init(&hwa742.req_lock); @@ -972,12 +969,11 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, if ((r = hwa742.extif->init(fbdev)) < 0) goto err2; - ext_clk = ctrl_conf->get_clock_rate(fbdev->dev); + ext_clk = clk_get_rate(hwa742.sys_ck); if ((r = calc_extif_timings(ext_clk, &extif_mem_div)) < 0) goto err3; hwa742.extif->set_timings(&hwa742.reg_timings); - if (hwa742.power_up != NULL) - hwa742.power_up(fbdev->dev); + clk_enable(hwa742.sys_ck); calc_hwa742_clk_rates(ext_clk, &sys_clk, &pix_clk); if ((r = calc_extif_timings(sys_clk, &extif_mem_div)) < 0) @@ -1040,8 +1036,7 @@ static int hwa742_init(struct omapfb_device *fbdev, int ext_mode, return 0; err4: - if (hwa742.power_down != NULL) - hwa742.power_down(fbdev->dev); + clk_disable(hwa742.sys_ck); err3: hwa742.extif->cleanup(); err2: @@ -1055,8 +1050,7 @@ static void hwa742_cleanup(void) hwa742_set_update_mode(OMAPFB_UPDATE_DISABLED); hwa742.extif->cleanup(); hwa742.int_ctrl->cleanup(); - if (hwa742.power_down != NULL) - hwa742.power_down(hwa742.fbdev->dev); + clk_disable(hwa742.sys_ck); } struct lcd_ctrl hwa742_ctrl = { -- cgit v1.2.3-70-g09d2 From f247de346f67db1e252e4ed6c29d029a6e592398 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 28 May 2009 14:03:58 -0700 Subject: ARM: OMAP2/3: Remove L4_WK_OMAP_BASE, L4_PER_OMAP_BASE, L4_EMU_BASE, L3_OMAP_BASE These are not being used right now, and the processor specific defines should be used instead by any code accessing these registers. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/mach/omap34xx.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/mach/omap34xx.h b/arch/arm/plat-omap/include/mach/omap34xx.h index cc2573330dc..f8d186a7371 100644 --- a/arch/arm/plat-omap/include/mach/omap34xx.h +++ b/arch/arm/plat-omap/include/mach/omap34xx.h @@ -31,13 +31,9 @@ #define L4_34XX_BASE 0x48000000 #define L4_WK_34XX_BASE 0x48300000 -#define L4_WK_OMAP_BASE L4_WK_34XX_BASE #define L4_PER_34XX_BASE 0x49000000 -#define L4_PER_OMAP_BASE L4_PER_34XX_BASE #define L4_EMU_34XX_BASE 0x54000000 -#define L4_EMU_BASE L4_EMU_34XX_BASE #define L3_34XX_BASE 0x68000000 -#define L3_OMAP_BASE L3_34XX_BASE #define OMAP3430_32KSYNCT_BASE 0x48320000 #define OMAP3430_CM_BASE 0x48004800 -- cgit v1.2.3-70-g09d2 From 4a899d5e93fd974952492cd4a09e98b209d1ad58 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 28 May 2009 14:04:00 -0700 Subject: ARM: OMAP3: Initialize more devices for LDP Based on an earlier patches by Stanley.Miao and Nishant Kamat . Note that at the ads7846 support still needs support for vaux_control for the touchscreen to work. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-ldp.c | 204 ++++++++++++++++++++++++++++++- arch/arm/plat-omap/include/mach/keypad.h | 4 + 2 files changed, 207 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 59ac8ed979e..d8bc0a7dcb8 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -16,11 +16,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -39,6 +41,7 @@ #include #include #include +#include #include "mmc-twl4030.h" @@ -77,6 +80,165 @@ static struct platform_device ldp_smsc911x_device = { }, }; +static int ldp_twl4030_keymap[] = { + KEY(0, 0, KEY_1), + KEY(1, 0, KEY_2), + KEY(2, 0, KEY_3), + KEY(0, 1, KEY_4), + KEY(1, 1, KEY_5), + KEY(2, 1, KEY_6), + KEY(3, 1, KEY_F5), + KEY(0, 2, KEY_7), + KEY(1, 2, KEY_8), + KEY(2, 2, KEY_9), + KEY(3, 2, KEY_F6), + KEY(0, 3, KEY_F7), + KEY(1, 3, KEY_0), + KEY(2, 3, KEY_F8), + PERSISTENT_KEY(4, 5), + KEY(4, 4, KEY_VOLUMEUP), + KEY(5, 5, KEY_VOLUMEDOWN), + 0 +}; + +static struct twl4030_keypad_data ldp_kp_twl4030_data = { + .rows = 6, + .cols = 6, + .keymap = ldp_twl4030_keymap, + .keymapsize = ARRAY_SIZE(ldp_twl4030_keymap), + .rep = 1, +}; + +static struct gpio_keys_button ldp_gpio_keys_buttons[] = { + [0] = { + .code = KEY_ENTER, + .gpio = 101, + .desc = "enter sw", + .active_low = 1, + .debounce_interval = 30, + }, + [1] = { + .code = KEY_F1, + .gpio = 102, + .desc = "func 1", + .active_low = 1, + .debounce_interval = 30, + }, + [2] = { + .code = KEY_F2, + .gpio = 103, + .desc = "func 2", + .active_low = 1, + .debounce_interval = 30, + }, + [3] = { + .code = KEY_F3, + .gpio = 104, + .desc = "func 3", + .active_low = 1, + .debounce_interval = 30, + }, + [4] = { + .code = KEY_F4, + .gpio = 105, + .desc = "func 4", + .active_low = 1, + .debounce_interval = 30, + }, + [5] = { + .code = KEY_LEFT, + .gpio = 106, + .desc = "left sw", + .active_low = 1, + .debounce_interval = 30, + }, + [6] = { + .code = KEY_RIGHT, + .gpio = 107, + .desc = "right sw", + .active_low = 1, + .debounce_interval = 30, + }, + [7] = { + .code = KEY_UP, + .gpio = 108, + .desc = "up sw", + .active_low = 1, + .debounce_interval = 30, + }, + [8] = { + .code = KEY_DOWN, + .gpio = 109, + .desc = "down sw", + .active_low = 1, + .debounce_interval = 30, + }, +}; + +static struct gpio_keys_platform_data ldp_gpio_keys = { + .buttons = ldp_gpio_keys_buttons, + .nbuttons = ARRAY_SIZE(ldp_gpio_keys_buttons), + .rep = 1, +}; + +static struct platform_device ldp_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &ldp_gpio_keys, + }, +}; + +static int ts_gpio; + +/** + * @brief ads7846_dev_init : Requests & sets GPIO line for pen-irq + * + * @return - void. If request gpio fails then Flag KERN_ERR. + */ +static void ads7846_dev_init(void) +{ + if (gpio_request(ts_gpio, "ads7846 irq") < 0) { + printk(KERN_ERR "can't get ads746 pen down GPIO\n"); + return; + } + + gpio_direction_input(ts_gpio); + omap_set_gpio_debounce(ts_gpio, 1); + omap_set_gpio_debounce_time(ts_gpio, 0xa); +} + +static int ads7846_get_pendown_state(void) +{ + return !gpio_get_value(ts_gpio); +} + +static struct ads7846_platform_data tsc2046_config __initdata = { + .get_pendown_state = ads7846_get_pendown_state, + .keep_vref_on = 1, +}; + +static struct omap2_mcspi_device_config tsc2046_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, /* 0: slave, 1: master */ +}; + +static struct spi_board_info ldp_spi_board_info[] __initdata = { + [0] = { + /* + * TSC2046 operates at a max freqency of 2MHz, so + * operate slightly below at 1.5MHz + */ + .modalias = "ads7846", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 1500000, + .controller_data = &tsc2046_mcspi_config, + .irq = 0, + .platform_data = &tsc2046_config, + }, +}; + static inline void __init ldp_init_smsc911x(void) { int eth_cs; @@ -132,18 +294,49 @@ static struct omap_board_config_kernel ldp_config[] __initdata = { { OMAP_TAG_LCD, &ldp_lcd_config }, }; +static struct twl4030_usb_data ldp_usb_data = { + .usb_mode = T2_USB_MODE_ULPI, +}; + static struct twl4030_gpio_platform_data ldp_gpio_data = { .gpio_base = OMAP_MAX_GPIO_LINES, .irq_base = TWL4030_GPIO_IRQ_BASE, .irq_end = TWL4030_GPIO_IRQ_END, }; +static struct twl4030_madc_platform_data ldp_madc_data = { + .irq_line = 1, +}; + +static struct regulator_consumer_supply ldp_vmmc1_supply = { + .supply = "vmmc", +}; + +/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */ +static struct regulator_init_data ldp_vmmc1 = { + .constraints = { + .min_uV = 1850000, + .max_uV = 3150000, + .valid_modes_mask = REGULATOR_MODE_NORMAL + | REGULATOR_MODE_STANDBY, + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE + | REGULATOR_CHANGE_MODE + | REGULATOR_CHANGE_STATUS, + }, + .num_consumer_supplies = 1, + .consumer_supplies = &ldp_vmmc1_supply, +}; + static struct twl4030_platform_data ldp_twldata = { .irq_base = TWL4030_IRQ_BASE, .irq_end = TWL4030_IRQ_END, /* platform_data for children goes here */ + .madc = &ldp_madc_data, + .usb = &ldp_usb_data, + .vmmc1 = &ldp_vmmc1, .gpio = &ldp_gpio_data, + .keypad = &ldp_kp_twl4030_data, }; static struct i2c_board_info __initdata ldp_i2c_boardinfo[] = { @@ -177,6 +370,7 @@ static struct twl4030_hsmmc_info mmc[] __initdata = { static struct platform_device *ldp_devices[] __initdata = { &ldp_smsc911x_device, &ldp_lcd_device, + &ldp_gpio_keys_device, }; static void __init omap_ldp_init(void) @@ -185,9 +379,17 @@ static void __init omap_ldp_init(void) platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices)); omap_board_config = ldp_config; omap_board_config_size = ARRAY_SIZE(ldp_config); + ts_gpio = 54; + ldp_spi_board_info[0].irq = gpio_to_irq(ts_gpio); + spi_register_board_info(ldp_spi_board_info, + ARRAY_SIZE(ldp_spi_board_info)); + ads7846_dev_init(); omap_serial_init(); - twl4030_mmc_init(mmc); usb_musb_init(); + + twl4030_mmc_init(mmc); + /* link regulators to MMC adapters */ + ldp_vmmc1_supply.dev = mmc[0].dev; } static void __init omap_ldp_map_io(void) diff --git a/arch/arm/plat-omap/include/mach/keypad.h b/arch/arm/plat-omap/include/mach/keypad.h index 232923aaf61..45ea3ae3c99 100644 --- a/arch/arm/plat-omap/include/mach/keypad.h +++ b/arch/arm/plat-omap/include/mach/keypad.h @@ -33,7 +33,11 @@ struct omap_kp_platform_data { #define GROUP_3 (3 << 16) #define GROUP_MASK GROUP_3 +#define KEY_PERSISTENT 0x00800000 +#define KEYNUM_MASK 0x00EFFFFF #define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val)) +#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \ + KEY_PERSISTENT) #endif -- cgit v1.2.3-70-g09d2 From 44169075e6eaa87bab6a296209d8d0610879b394 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 28 May 2009 14:16:04 -0700 Subject: ARM: OMAP4: Add minimal support for omap4 This patch adds the support for OMAP4. The platform and machine specific headers and sources updated for OMAP4430 SDP platform. OMAP4430 is Texas Instrument's SOC based on ARM Cortex-A9 SMP architecture. It's a dual core SOC with GIC used for interrupt handling and SCU for cache coherency. Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/gpmc.c | 6 ++ arch/arm/mach-omap2/id.c | 8 +- arch/arm/mach-omap2/io.c | 52 +++++++++- arch/arm/mach-omap2/serial.c | 7 ++ arch/arm/mach-omap2/timer-gp.c | 9 +- arch/arm/plat-omap/common.c | 31 ++++++ arch/arm/plat-omap/devices.c | 2 + arch/arm/plat-omap/dma.c | 23 ++++- arch/arm/plat-omap/dmtimer.c | 59 +++++++++++- arch/arm/plat-omap/gpio.c | 134 +++++++++++++++++++------- arch/arm/plat-omap/include/mach/clock.h | 8 +- arch/arm/plat-omap/include/mach/common.h | 1 + arch/arm/plat-omap/include/mach/control.h | 7 +- arch/arm/plat-omap/include/mach/cpu.h | 21 +++- arch/arm/plat-omap/include/mach/debug-macro.S | 2 +- arch/arm/plat-omap/include/mach/dma.h | 1 + arch/arm/plat-omap/include/mach/entry-macro.S | 46 ++++++++- arch/arm/plat-omap/include/mach/hardware.h | 1 + arch/arm/plat-omap/include/mach/io.h | 37 +++++++ arch/arm/plat-omap/include/mach/irqs.h | 89 +++++++++++++++++ arch/arm/plat-omap/include/mach/memory.h | 3 +- arch/arm/plat-omap/include/mach/omap44xx.h | 46 +++++++++ arch/arm/plat-omap/include/mach/serial.h | 16 ++- arch/arm/plat-omap/io.c | 29 +++++- arch/arm/plat-omap/mux.c | 3 + arch/arm/plat-omap/sram.c | 21 ++++ 26 files changed, 600 insertions(+), 62 deletions(-) create mode 100644 arch/arm/plat-omap/include/mach/omap44xx.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 2249049c1d5..f91934b2b09 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -5,6 +5,9 @@ * * Author: Juha Yrjola * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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. @@ -424,6 +427,9 @@ void __init gpmc_init(void) } else if (cpu_is_omap34xx()) { ck = "gpmc_fck"; l = OMAP34XX_GPMC_BASE; + } else if (cpu_is_omap44xx()) { + ck = "gpmc_fck"; + l = OMAP44XX_GPMC_BASE; } gpmc_l3_clk = clk_get(NULL, ck); diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 34b5914e0f8..458990e20c6 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -6,6 +6,9 @@ * Copyright (C) 2005 Nokia Corporation * Written by Tony Lindgren * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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. @@ -200,7 +203,10 @@ void __init omap2_check_revision(void) omap24xx_check_revision(); else if (cpu_is_omap34xx()) omap34xx_check_revision(); - else + else if (cpu_is_omap44xx()) { + printk(KERN_INFO "FIXME: CPU revision = OMAP4430\n"); + return; + } else pr_err("OMAP revision unknown, please fix!\n"); /* diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 916fcd3a232..32afd944821 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -4,12 +4,14 @@ * OMAP2 I/O mapping code * * Copyright (C) 2005 Nokia Corporation - * Copyright (C) 2007 Texas Instruments + * Copyright (C) 2007-2009 Texas Instruments * * Author: * Juha Yrjola * Syed Khasim * + * Added OMAP4 support - Santosh Shilimkar + * * 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. @@ -30,6 +32,7 @@ #include #include +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once clkdev is ready */ #include "clock.h" #include @@ -38,7 +41,7 @@ #include #include "clockdomains.h" - +#endif /* * The machine specific code may provide the extra mapping besides the * default mapping provided here. @@ -166,6 +169,46 @@ static struct map_desc omap34xx_io_desc[] __initdata = { }, }; #endif +#ifdef CONFIG_ARCH_OMAP4 +static struct map_desc omap44xx_io_desc[] __initdata = { + { + .virtual = L3_44XX_VIRT, + .pfn = __phys_to_pfn(L3_44XX_PHYS), + .length = L3_44XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_44XX_VIRT, + .pfn = __phys_to_pfn(L4_44XX_PHYS), + .length = L4_44XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_WK_44XX_VIRT, + .pfn = __phys_to_pfn(L4_WK_44XX_PHYS), + .length = L4_WK_44XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = OMAP44XX_GPMC_VIRT, + .pfn = __phys_to_pfn(OMAP44XX_GPMC_PHYS), + .length = OMAP44XX_GPMC_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_PER_44XX_VIRT, + .pfn = __phys_to_pfn(L4_PER_44XX_PHYS), + .length = L4_PER_44XX_SIZE, + .type = MT_DEVICE, + }, + { + .virtual = L4_EMU_44XX_VIRT, + .pfn = __phys_to_pfn(L4_EMU_44XX_PHYS), + .length = L4_EMU_44XX_SIZE, + .type = MT_DEVICE, + }, +}; +#endif void __init omap2_map_common_io(void) { @@ -183,6 +226,9 @@ void __init omap2_map_common_io(void) iotable_init(omap34xx_io_desc, ARRAY_SIZE(omap34xx_io_desc)); #endif +#if defined(CONFIG_ARCH_OMAP4) + iotable_init(omap44xx_io_desc, ARRAY_SIZE(omap44xx_io_desc)); +#endif /* Normally devicemaps_init() would flush caches and tlb after * mdesc->map_io(), but we must also do it here because of the CPU * revision check below. @@ -198,9 +244,11 @@ void __init omap2_map_common_io(void) void __init omap2_init_common_hw(struct omap_sdrc_params *sp) { omap2_mux_init(); +#ifndef CONFIG_ARCH_OMAP4 /* FIXME: Remove this once the clkdev is ready */ pwrdm_init(powerdomains_omap); clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps); omap2_clk_init(); omap2_sdrc_init(sp); +#endif gpmc_init(); } diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c index 3c2d325d3dc..29dc6f52905 100644 --- a/arch/arm/mach-omap2/serial.c +++ b/arch/arm/mach-omap2/serial.c @@ -8,6 +8,9 @@ * * Based off of arch/arm/mach-omap/omap1/serial.c * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -82,7 +83,8 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_PERIODIC: period = clk_get_rate(omap_dm_timer_get_fclk(gptimer)) / HZ; period -= 1; - + if (cpu_is_omap44xx()) + period = 0xff; /* FIXME: */ omap_dm_timer_set_load_start(gptimer, 1, 0xffffffff - period); break; case CLOCK_EVT_MODE_ONESHOT: @@ -145,6 +147,9 @@ static void __init omap2_gp_clockevent_init(void) "timer-gp: omap_dm_timer_set_source() failed\n"); tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer)); + if (cpu_is_omap44xx()) + /* Assuming 32kHz clk is driving GPT1 */ + tick_rate = 32768; /* FIXME: */ pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n", gptimer_id, tick_rate); diff --git a/arch/arm/plat-omap/common.c b/arch/arm/plat-omap/common.c index 70b68ef8320..66738c3854c 100644 --- a/arch/arm/plat-omap/common.c +++ b/arch/arm/plat-omap/common.c @@ -2,6 +2,10 @@ * linux/arch/arm/plat-omap/common.c * * Code common to all OMAP machines. + * The file is created by Tony Lindgren + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar * * 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 @@ -217,6 +221,15 @@ static cycle_t omap34xx_32k_read(struct clocksource *cs) #define omap34xx_32k_read NULL #endif +#ifdef CONFIG_ARCH_OMAP4 +static cycle_t omap44xx_32k_read(struct clocksource *cs) +{ + return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10); +} +#else +#define omap44xx_32k_read NULL +#endif + /* * Kernel assumes that sched_clock can be called early but may not have * things ready yet. @@ -264,6 +277,8 @@ static int __init omap_init_clocksource_32k(void) clocksource_32k.read = omap2430_32k_read; else if (cpu_is_omap34xx()) clocksource_32k.read = omap34xx_32k_read; + else if (cpu_is_omap44xx()) + clocksource_32k.read = omap44xx_32k_read; else return -ENODEV; @@ -351,3 +366,19 @@ void __init omap2_set_globals_343x(void) } #endif +#if defined(CONFIG_ARCH_OMAP4) +static struct omap_globals omap4_globals = { + .class = OMAP443X_CLASS, + .tap = OMAP2_IO_ADDRESS(0x4830a000), + .ctrl = OMAP2_IO_ADDRESS(OMAP443X_CTRL_BASE), + .prm = OMAP2_IO_ADDRESS(OMAP4430_PRM_BASE), + .cm = OMAP2_IO_ADDRESS(OMAP4430_CM_BASE), +}; + +void __init omap2_set_globals_443x(void) +{ + omap2_set_globals_tap(&omap4_globals); + omap2_set_globals_control(&omap4_globals); +} +#endif + diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index 87fb7ff4179..a64b692a1bf 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -311,6 +311,8 @@ static void omap_init_wdt(void) wdt_resources[0].start = 0x49016000; /* WDT2 */ else if (cpu_is_omap343x()) wdt_resources[0].start = 0x48314000; /* WDT2 */ + else if (cpu_is_omap44xx()) + wdt_resources[0].start = 0x4a314000; else return; diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 06e9cbe8b8e..def14ec265b 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -10,6 +10,9 @@ * Merged to support both OMAP1 and OMAP2 by Tony Lindgren * Some functions based on earlier dma-omap.c Copyright (C) 2001 RidgeRun, Inc. * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * Support functions for the OMAP internal DMA channels. * * This program is free software; you can redistribute it and/or modify @@ -872,7 +875,7 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, } l = dma_read(CCR(lch)); l &= ~((1 << 6) | (1 << 26)); - if (cpu_is_omap2430() || cpu_is_omap34xx()) + if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else l |= ((read_prio & 0x1) << 6); @@ -1844,7 +1847,8 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) #define omap1_dma_irq_handler NULL #endif -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) static int omap2_dma_handle_ch(int ch) { @@ -2339,6 +2343,9 @@ static int __init omap_init_dma(void) } else if (cpu_is_omap34xx()) { omap_dma_base = IO_ADDRESS(OMAP34XX_DMA4_BASE); dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; + } else if (cpu_is_omap44xx()) { + omap_dma_base = IO_ADDRESS(OMAP44XX_DMA4_BASE); + dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; } else { pr_err("DMA init failed for unsupported omap\n"); return -ENODEV; @@ -2437,12 +2444,18 @@ static int __init omap_init_dma(void) } } - if (cpu_is_omap2430() || cpu_is_omap34xx()) + if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, DMA_DEFAULT_FIFO_DEPTH, 0); - if (cpu_class_is_omap2()) - setup_irq(INT_24XX_SDMA_IRQ0, &omap24xx_dma_irq); + if (cpu_class_is_omap2()) { + int irq; + if (cpu_is_omap44xx()) + irq = INT_44XX_SDMA_IRQ0; + else + irq = INT_24XX_SDMA_IRQ0; + setup_irq(irq, &omap24xx_dma_irq); + } /* FIXME: Update LCD DMA to work on 24xx */ if (cpu_class_is_omap1()) { diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index ee206122f50..7f50b6103de 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -7,6 +7,9 @@ * OMAP2 support by Juha Yrjola * API improvements and OMAP2 clock framework support by Timo Teras * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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 of the License, or (at your @@ -150,7 +153,8 @@ struct omap_dm_timer { unsigned long phys_base; int irq; -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) struct clk *iclk, *fclk; #endif void __iomem *io_base; @@ -169,6 +173,9 @@ struct omap_dm_timer { #define omap3_dm_timers NULL #define omap3_dm_source_names NULL #define omap3_dm_source_clocks NULL +#define omap4_dm_timers NULL +#define omap4_dm_source_names NULL +#define omap4_dm_source_clocks NULL static struct omap_dm_timer omap1_dm_timers[] = { { .phys_base = 0xfffb1400, .irq = INT_1610_GPTIMER1 }, @@ -191,6 +198,9 @@ static const int dm_timer_count = ARRAY_SIZE(omap1_dm_timers); #define omap3_dm_timers NULL #define omap3_dm_source_names NULL #define omap3_dm_source_clocks NULL +#define omap4_dm_timers NULL +#define omap4_dm_source_names NULL +#define omap4_dm_source_clocks NULL static struct omap_dm_timer omap2_dm_timers[] = { { .phys_base = 0x48028000, .irq = INT_24XX_GPTIMER1 }, @@ -225,6 +235,9 @@ static const int dm_timer_count = ARRAY_SIZE(omap2_dm_timers); #define omap2_dm_timers NULL #define omap2_dm_source_names NULL #define omap2_dm_source_clocks NULL +#define omap4_dm_timers NULL +#define omap4_dm_source_names NULL +#define omap4_dm_source_clocks NULL static struct omap_dm_timer omap3_dm_timers[] = { { .phys_base = 0x48318000, .irq = INT_24XX_GPTIMER1 }, @@ -250,6 +263,40 @@ static const char *omap3_dm_source_names[] __initdata = { static struct clk *omap3_dm_source_clocks[2]; static const int dm_timer_count = ARRAY_SIZE(omap3_dm_timers); +#elif defined(CONFIG_ARCH_OMAP4) + +#define omap_dm_clk_enable(x) clk_enable(x) +#define omap_dm_clk_disable(x) clk_disable(x) +#define omap1_dm_timers NULL +#define omap2_dm_timers NULL +#define omap2_dm_source_names NULL +#define omap2_dm_source_clocks NULL +#define omap3_dm_timers NULL +#define omap3_dm_source_names NULL +#define omap3_dm_source_clocks NULL + +static struct omap_dm_timer omap4_dm_timers[] = { + { .phys_base = 0x4a318000, .irq = INT_44XX_GPTIMER1 }, + { .phys_base = 0x48032000, .irq = INT_44XX_GPTIMER2 }, + { .phys_base = 0x48034000, .irq = INT_44XX_GPTIMER3 }, + { .phys_base = 0x48036000, .irq = INT_44XX_GPTIMER4 }, + { .phys_base = 0x40138000, .irq = INT_44XX_GPTIMER5 }, + { .phys_base = 0x4013a000, .irq = INT_44XX_GPTIMER6 }, + { .phys_base = 0x4013a000, .irq = INT_44XX_GPTIMER7 }, + { .phys_base = 0x4013e000, .irq = INT_44XX_GPTIMER8 }, + { .phys_base = 0x4803e000, .irq = INT_44XX_GPTIMER9 }, + { .phys_base = 0x48086000, .irq = INT_44XX_GPTIMER10 }, + { .phys_base = 0x48088000, .irq = INT_44XX_GPTIMER11 }, + { .phys_base = 0x4a320000, .irq = INT_44XX_GPTIMER12 }, +}; +static const char *omap4_dm_source_names[] __initdata = { + "sys_ck", + "omap_32k_fck", + NULL +}; +static struct clk *omap4_dm_source_clocks[2]; +static const int dm_timer_count = ARRAY_SIZE(omap4_dm_timers); + #else #error OMAP architecture not supported! @@ -459,7 +506,8 @@ __u32 omap_dm_timer_modify_idlect_mask(__u32 inputmask) } EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask); -#elif defined(CONFIG_ARCH_OMAP2) || defined (CONFIG_ARCH_OMAP3) +#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer) { @@ -711,6 +759,10 @@ int __init omap_dm_timer_init(void) dm_timers = omap3_dm_timers; dm_source_names = omap3_dm_source_names; dm_source_clocks = omap3_dm_source_clocks; + } else if (cpu_is_omap44xx()) { + dm_timers = omap4_dm_timers; + dm_source_names = omap4_dm_source_names; + dm_source_clocks = omap4_dm_source_clocks; } if (cpu_class_is_omap2()) @@ -723,7 +775,8 @@ int __init omap_dm_timer_init(void) for (i = 0; i < dm_timer_count; i++) { timer = &dm_timers[i]; timer->io_base = IO_ADDRESS(timer->phys_base); -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) if (cpu_class_is_omap2()) { char clk_name[16]; sprintf(clk_name, "gpt%d_ick", i + 1); diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index ee0b21f5b09..7fd89ba8d3b 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -6,6 +6,9 @@ * Copyright (C) 2003-2005 Nokia Corporation * Written by Juha Yrjölä * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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. @@ -146,6 +149,16 @@ #define OMAP34XX_GPIO5_BASE IO_ADDRESS(0x49056000) #define OMAP34XX_GPIO6_BASE IO_ADDRESS(0x49058000) +/* + * OMAP44XX specific GPIO registers + */ +#define OMAP44XX_GPIO1_BASE IO_ADDRESS(0x4a310000) +#define OMAP44XX_GPIO2_BASE IO_ADDRESS(0x48055000) +#define OMAP44XX_GPIO3_BASE IO_ADDRESS(0x48057000) +#define OMAP44XX_GPIO4_BASE IO_ADDRESS(0x48059000) +#define OMAP44XX_GPIO5_BASE IO_ADDRESS(0x4805B000) +#define OMAP44XX_GPIO6_BASE IO_ADDRESS(0x4805D000) + #define OMAP_MPUIO_VBASE IO_ADDRESS(OMAP_MPUIO_BASE) struct gpio_bank { @@ -153,11 +166,13 @@ struct gpio_bank { u16 irq; u16 virtual_irq_start; int method; -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \ + defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) u32 suspend_wakeup; u32 saved_wakeup; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; @@ -251,6 +266,24 @@ static struct gpio_bank gpio_bank_34xx[6] = { #endif +#ifdef CONFIG_ARCH_OMAP4 +static struct gpio_bank gpio_bank_44xx[6] = { + { OMAP44XX_GPIO1_BASE, INT_44XX_GPIO_BANK1, IH_GPIO_BASE, \ + METHOD_GPIO_24XX }, + { OMAP44XX_GPIO2_BASE, INT_44XX_GPIO_BANK2, IH_GPIO_BASE + 32, \ + METHOD_GPIO_24XX }, + { OMAP44XX_GPIO3_BASE, INT_44XX_GPIO_BANK3, IH_GPIO_BASE + 64, \ + METHOD_GPIO_24XX }, + { OMAP44XX_GPIO4_BASE, INT_44XX_GPIO_BANK4, IH_GPIO_BASE + 96, \ + METHOD_GPIO_24XX }, + { OMAP44XX_GPIO5_BASE, INT_44XX_GPIO_BANK5, IH_GPIO_BASE + 128, \ + METHOD_GPIO_24XX }, + { OMAP44XX_GPIO6_BASE, INT_44XX_GPIO_BANK6, IH_GPIO_BASE + 160, \ + METHOD_GPIO_24XX }, +}; + +#endif + static struct gpio_bank *gpio_bank; static int gpio_bank_count; @@ -273,7 +306,7 @@ static inline struct gpio_bank *get_gpio_bank(int gpio) } if (cpu_is_omap24xx()) return &gpio_bank[gpio >> 5]; - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx() || cpu_is_omap44xx()) return &gpio_bank[gpio >> 5]; BUG(); return NULL; @@ -285,7 +318,7 @@ static inline int get_gpio_index(int gpio) return gpio & 0x1f; if (cpu_is_omap24xx()) return gpio & 0x1f; - if (cpu_is_omap34xx()) + if (cpu_is_omap34xx() || cpu_is_omap44xx()) return gpio & 0x1f; return gpio & 0x0f; } @@ -307,7 +340,7 @@ static inline int gpio_valid(int gpio) return 0; if (cpu_is_omap24xx() && gpio < 128) return 0; - if (cpu_is_omap34xx() && gpio < 192) + if ((cpu_is_omap34xx() || cpu_is_omap44xx()) && gpio < 192) return 0; return -1; } @@ -353,7 +386,8 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) reg += OMAP850_GPIO_DIR_CONTROL; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_OE; break; @@ -425,7 +459,8 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) l &= ~(1 << gpio); break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: if (enable) reg += OMAP24XX_GPIO_SETDATAOUT; @@ -476,7 +511,8 @@ static int __omap_get_gpio_datain(int gpio) reg += OMAP850_GPIO_DATA_INPUT; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_DATAIN; break; @@ -520,7 +556,7 @@ void omap_set_gpio_debounce(int gpio, int enable) else goto done; - if (cpu_is_omap34xx()) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { if (enable) clk_enable(bank->dbck); else @@ -550,7 +586,8 @@ void omap_set_gpio_debounce_time(int gpio, int enc_time) } EXPORT_SYMBOL(omap_set_gpio_debounce_time); -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) { @@ -660,7 +697,8 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) goto bad; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: set_24xx_gpio_triggering(bank, gpio, trigger); break; @@ -745,7 +783,8 @@ static void _clear_gpio_irqbank(struct gpio_bank *bank, int gpio_mask) reg += OMAP850_GPIO_INT_STATUS; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQSTATUS1; break; @@ -814,7 +853,8 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) inv = 1; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: reg += OMAP24XX_GPIO_IRQENABLE1; mask = 0xffffffff; @@ -887,7 +927,8 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab l |= gpio_mask; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: if (enable) reg += OMAP24XX_GPIO_SETIRQENABLE1; @@ -932,7 +973,8 @@ static int _set_gpio_wakeup(struct gpio_bank *bank, int gpio, int enable) spin_unlock_irqrestore(&bank->lock, flags); return 0; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: if (bank->non_wakeup_gpios & (1 << gpio)) { printk(KERN_ERR "Unable to modify wakeup on " @@ -1017,7 +1059,8 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) __raw_writel(1 << offset, reg); } #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) if (bank->method == METHOD_GPIO_24XX) { /* Disable wake-up during idle for dynamic tick */ void __iomem *reg = bank->base + OMAP24XX_GPIO_CLEARWKUENA; @@ -1069,7 +1112,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (bank->method == METHOD_GPIO_850) isr_reg = bank->base + OMAP850_GPIO_INT_STATUS; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) if (bank->method == METHOD_GPIO_24XX) isr_reg = bank->base + OMAP24XX_GPIO_IRQSTATUS1; #endif @@ -1346,7 +1390,7 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset) /*---------------------------------------------------------------------*/ static int initialized; -#if !defined(CONFIG_ARCH_OMAP3) +#if !(defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)) static struct clk * gpio_ick; #endif @@ -1359,7 +1403,7 @@ static struct clk * gpio5_ick; static struct clk * gpio5_fck; #endif -#if defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; #endif @@ -1419,8 +1463,8 @@ static int __init _omap_gpio_init(void) } #endif -#if defined(CONFIG_ARCH_OMAP3) - if (cpu_is_omap34xx()) { +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { for (i = 0; i < OMAP34XX_NR_GPIOS; i++) { sprintf(clk_name, "gpio%d_ick", i + 1); gpio_iclks[i] = clk_get(NULL, clk_name); @@ -1496,6 +1540,17 @@ static int __init _omap_gpio_init(void) printk(KERN_INFO "OMAP34xx GPIO hardware version %d.%d\n", (rev >> 4) & 0x0f, rev & 0x0f); } +#endif +#ifdef CONFIG_ARCH_OMAP4 + if (cpu_is_omap44xx()) { + int rev; + + gpio_bank_count = OMAP34XX_NR_GPIOS; + gpio_bank = gpio_bank_44xx; + rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); + printk(KERN_INFO "OMAP44xx GPIO hardware version %d.%d\n", + (rev >> 4) & 0x0f, rev & 0x0f); + } #endif for (i = 0; i < gpio_bank_count; i++) { int j, gpio_count = 16; @@ -1520,7 +1575,8 @@ static int __init _omap_gpio_init(void) gpio_count = 32; /* 730 has 32-bit GPIOs */ } -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) if (bank->method == METHOD_GPIO_24XX) { static const u32 non_wakeup_gpios[] = { 0xe203ffc0, 0x08700040 @@ -1577,7 +1633,7 @@ static int __init _omap_gpio_init(void) set_irq_chained_handler(bank->irq, gpio_irq_handler); set_irq_data(bank->irq, bank); - if (cpu_is_omap34xx()) { + if (cpu_is_omap34xx() || cpu_is_omap44xx()) { sprintf(clk_name, "gpio%d_dbck", i + 1); bank->dbck = clk_get(NULL, clk_name); if (IS_ERR(bank->dbck)) @@ -1599,7 +1655,8 @@ static int __init _omap_gpio_init(void) return 0; } -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \ + defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) { int i; @@ -1622,7 +1679,8 @@ static int omap_gpio_suspend(struct sys_device *dev, pm_message_t mesg) wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: wake_status = bank->base + OMAP24XX_GPIO_WAKE_EN; wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; @@ -1663,7 +1721,8 @@ static int omap_gpio_resume(struct sys_device *dev) wake_set = bank->base + OMAP1610_GPIO_SET_WAKEUPENA; break; #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) case METHOD_GPIO_24XX: wake_clear = bank->base + OMAP24XX_GPIO_CLEARWKUENA; wake_set = bank->base + OMAP24XX_GPIO_SETWKUENA; @@ -1695,7 +1754,8 @@ static struct sys_device omap_gpio_device = { #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) static int workaround_enabled; @@ -1711,7 +1771,8 @@ void omap2_gpio_prepare_for_retention(void) if (!(bank->enabled_non_wakeup_gpios)) continue; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) bank->saved_datain = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); l1 = __raw_readl(bank->base + OMAP24XX_GPIO_FALLINGDETECT); l2 = __raw_readl(bank->base + OMAP24XX_GPIO_RISINGDETECT); @@ -1720,7 +1781,8 @@ void omap2_gpio_prepare_for_retention(void) bank->saved_risingdetect = l2; l1 &= ~bank->enabled_non_wakeup_gpios; l2 &= ~bank->enabled_non_wakeup_gpios; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) __raw_writel(l1, bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_writel(l2, bank->base + OMAP24XX_GPIO_RISINGDETECT); #endif @@ -1745,7 +1807,8 @@ void omap2_gpio_resume_after_retention(void) if (!(bank->enabled_non_wakeup_gpios)) continue; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) __raw_writel(bank->saved_fallingdetect, bank->base + OMAP24XX_GPIO_FALLINGDETECT); __raw_writel(bank->saved_risingdetect, @@ -1755,14 +1818,16 @@ void omap2_gpio_resume_after_retention(void) * state. If so, generate an IRQ by software. This is * horribly racy, but it's the best we can do to work around * this silicon bug. */ -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) l = __raw_readl(bank->base + OMAP24XX_GPIO_DATAIN); #endif l ^= bank->saved_datain; l &= bank->non_wakeup_gpios; if (l) { u32 old0, old1; -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) old0 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT0); old1 = __raw_readl(bank->base + OMAP24XX_GPIO_LEVELDETECT1); __raw_writel(old0 | l, bank->base + OMAP24XX_GPIO_LEVELDETECT0); @@ -1798,7 +1863,8 @@ static int __init omap_gpio_sysinit(void) mpuio_init(); -#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \ + defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) if (cpu_is_omap16xx() || cpu_class_is_omap2()) { if (ret == 0) { ret = sysdev_class_register(&omap_gpio_sysclass); @@ -1887,7 +1953,7 @@ static int dbg_gpio_show(struct seq_file *s, void *unused) irqstat = irq_desc[irq].status; #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP24XX) || \ - defined(CONFIG_ARCH_OMAP34XX) + defined(CONFIG_ARCH_OMAP34XX) || defined(CONFIG_ARCH_OMAP4) if (is_in && ((bank->suspend_wakeup & mask) || irqstat & IRQ_TYPE_SENSE_MASK)) { char *trigger = NULL; diff --git a/arch/arm/plat-omap/include/mach/clock.h b/arch/arm/plat-omap/include/mach/clock.h index 073a2c5569f..c20e02ec303 100644 --- a/arch/arm/plat-omap/include/mach/clock.h +++ b/arch/arm/plat-omap/include/mach/clock.h @@ -22,7 +22,8 @@ struct clkops { void (*disable)(struct clk *); }; -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) struct clksel_rate { u32 val; @@ -51,7 +52,7 @@ struct dpll_data { u8 max_divider; u32 max_tolerance; u16 max_multiplier; -# if defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) u8 modes; void __iomem *autoidle_reg; void __iomem *idlest_reg; @@ -83,7 +84,8 @@ struct clk { void (*init)(struct clk *); __u8 enable_bit; __s8 usecount; -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) u8 fixed_div; void __iomem *clksel_reg; u32 clksel_mask; diff --git a/arch/arm/plat-omap/include/mach/common.h b/arch/arm/plat-omap/include/mach/common.h index 0ecf36deb17..4b188334c66 100644 --- a/arch/arm/plat-omap/include/mach/common.h +++ b/arch/arm/plat-omap/include/mach/common.h @@ -62,6 +62,7 @@ struct omap_globals { void omap2_set_globals_242x(void); void omap2_set_globals_243x(void); void omap2_set_globals_343x(void); +void omap2_set_globals_443x(void); /* These get called from omap2_set_globals_xxxx(), do not call these */ void omap2_set_globals_tap(struct omap_globals *); diff --git a/arch/arm/plat-omap/include/mach/control.h b/arch/arm/plat-omap/include/mach/control.h index 269147f3836..f45ec621da9 100644 --- a/arch/arm/plat-omap/include/mach/control.h +++ b/arch/arm/plat-omap/include/mach/control.h @@ -1,9 +1,9 @@ /* * arch/arm/plat-omap/include/mach/control.h * - * OMAP2/3 System Control Module definitions + * OMAP2/3/4 System Control Module definitions * - * Copyright (C) 2007-2008 Texas Instruments, Inc. + * Copyright (C) 2007-2009 Texas Instruments, Inc. * Copyright (C) 2007-2008 Nokia Corporation * * Written by Paul Walmsley @@ -190,7 +190,8 @@ #define OMAP2_PBIASLITEVMODE0 (1 << 0) #ifndef __ASSEMBLY__ -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) extern void __iomem *omap_ctrl_base_get(void); extern u8 omap_ctrl_readb(u16 offset); extern u16 omap_ctrl_readw(u16 offset); diff --git a/arch/arm/plat-omap/include/mach/cpu.h b/arch/arm/plat-omap/include/mach/cpu.h index 98b14425236..fc60c4ebcc2 100644 --- a/arch/arm/plat-omap/include/mach/cpu.h +++ b/arch/arm/plat-omap/include/mach/cpu.h @@ -5,8 +5,12 @@ * * Copyright (C) 2004, 2008 Nokia Corporation * + * Copyright (C) 2009 Texas Instruments. + * * Written by Tony Lindgren * + * Added OMAP4 specific defines - Santosh Shilimkar + * * 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 of the License, or @@ -155,6 +159,8 @@ IS_OMAP_SUBCLASS(343x, 0x343) #define cpu_is_omap243x() 0 #define cpu_is_omap34xx() 0 #define cpu_is_omap343x() 0 +#define cpu_is_omap44xx() 0 +#define cpu_is_omap443x() 0 #if defined(MULTI_OMAP1) # if defined(CONFIG_ARCH_OMAP730) @@ -348,12 +354,21 @@ IS_OMAP_TYPE(3430, 0x3430) # define cpu_is_omap3430() is_omap3430() #endif +# if defined(CONFIG_ARCH_OMAP4) +# undef cpu_is_omap44xx +# undef cpu_is_omap443x +# define cpu_is_omap44xx() 1 +# define cpu_is_omap443x() 1 +# endif + /* Macros to detect if we have OMAP1 or OMAP2 */ #define cpu_class_is_omap1() (cpu_is_omap7xx() || cpu_is_omap15xx() || \ cpu_is_omap16xx()) -#define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx()) +#define cpu_class_is_omap2() (cpu_is_omap24xx() || cpu_is_omap34xx() || \ + cpu_is_omap44xx()) -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) /* Various silicon revisions for omap2 */ #define OMAP242X_CLASS 0x24200024 @@ -370,6 +385,8 @@ IS_OMAP_TYPE(3430, 0x3430) #define OMAP3430_REV_ES3_0 0x34303034 #define OMAP3430_REV_ES3_1 0x34304034 +#define OMAP443X_CLASS 0x44300034 + /* * omap_chip bits * diff --git a/arch/arm/plat-omap/include/mach/debug-macro.S b/arch/arm/plat-omap/include/mach/debug-macro.S index 1b11f5c6a2d..ac24050e341 100644 --- a/arch/arm/plat-omap/include/mach/debug-macro.S +++ b/arch/arm/plat-omap/include/mach/debug-macro.S @@ -36,7 +36,7 @@ add \rx, \rx, #0x00004000 @ UART 3 #endif -#elif CONFIG_ARCH_OMAP3 +#elif defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) moveq \rx, #0x48000000 @ physical base address movne \rx, #0xd8000000 @ virtual base orr \rx, \rx, #0x0006a000 diff --git a/arch/arm/plat-omap/include/mach/dma.h b/arch/arm/plat-omap/include/mach/dma.h index 19df76f97ab..8c1eae88737 100644 --- a/arch/arm/plat-omap/include/mach/dma.h +++ b/arch/arm/plat-omap/include/mach/dma.h @@ -48,6 +48,7 @@ /* Hardware registers for omap2 and omap3 */ #define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000) #define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000) +#define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000) #define OMAP_DMA4_REVISION 0x00 #define OMAP_DMA4_GCR 0x78 diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S index 33256a0e9a2..00f45c01390 100644 --- a/arch/arm/plat-omap/include/mach/entry-macro.S +++ b/arch/arm/plat-omap/include/mach/entry-macro.S @@ -3,6 +3,9 @@ * * Low-level IRQ helper macros for OMAP-based platforms * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any * warranty of any kind, whether express or implied. @@ -10,6 +13,7 @@ #include #include #include +#include #if defined(CONFIG_ARCH_OMAP1) @@ -56,7 +60,8 @@ .endm #endif -#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) +#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) || \ + defined(CONFIG_ARCH_OMAP4) #include #include @@ -67,7 +72,9 @@ #elif defined(CONFIG_ARCH_OMAP34XX) #define OMAP2_VA_IC_BASE IO_ADDRESS(OMAP34XX_IC_BASE) #endif - +#if defined(CONFIG_ARCH_OMAP4) +#include +#endif #define INTCPS_SIR_IRQ_OFFSET 0x0040 /* Active interrupt offset */ #define ACTIVEIRQ_MASK 0x7f /* Active interrupt bits */ @@ -80,6 +87,7 @@ .macro arch_ret_to_user, tmp1, tmp2 .endm +#ifndef CONFIG_ARCH_OMAP4 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \base, =OMAP2_VA_IC_BASE ldr \irqnr, [\base, #0x98] /* IRQ pending reg 1 */ @@ -95,6 +103,40 @@ and \irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */ .endm +#else + /* + * The interrupt numbering scheme is defined in the + * interrupt controller spec. To wit: + * + * Interrupts 0-15 are IPI + * 16-28 are reserved + * 29-31 are local. We allow 30 to be used for the watchdog. + * 32-1020 are global + * 1021-1022 are reserved + * 1023 is "spurious" (no interrupt) + * + * For now, we ignore all local interrupts so only return an + * interrupt if it's between 30 and 1020. The test_for_ipi + * routine below will pick up on IPIs. + * A simple read from the controller will tell us the number + * of the highest priority enabled interrupt. + * We then just need to check whether it is in the + * valid range for an IRQ (30-1020 inclusive). + */ + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp + ldr \base, =OMAP44XX_VA_GIC_CPU_BASE + ldr \irqstat, [\base, #GIC_CPU_INTACK] + + ldr \tmp, =1021 + + bic \irqnr, \irqstat, #0x1c00 + + cmp \irqnr, #29 + cmpcc \irqnr, \irqnr + cmpne \irqnr, \tmp + cmpcs \irqnr, \irqnr + .endm +#endif .macro irq_prio_table .endm diff --git a/arch/arm/plat-omap/include/mach/hardware.h b/arch/arm/plat-omap/include/mach/hardware.h index 3dc423ed3e8..26c1fbff08a 100644 --- a/arch/arm/plat-omap/include/mach/hardware.h +++ b/arch/arm/plat-omap/include/mach/hardware.h @@ -285,5 +285,6 @@ #include "omap16xx.h" #include "omap24xx.h" #include "omap34xx.h" +#include "omap44xx.h" #endif /* __ASM_ARCH_OMAP_HARDWARE_H */ diff --git a/arch/arm/plat-omap/include/mach/io.h b/arch/arm/plat-omap/include/mach/io.h index 0610d7e2b3d..3b281472056 100644 --- a/arch/arm/plat-omap/include/mach/io.h +++ b/arch/arm/plat-omap/include/mach/io.h @@ -6,6 +6,9 @@ * Copied from arch/arm/mach-sa1100/include/mach/io.h * Copyright (C) 1997-1999 Russell King * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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 of the License, or (at your @@ -157,6 +160,40 @@ #define DSP_MMU_34XX_VIRT 0xe2000000 #define DSP_MMU_34XX_SIZE SZ_4K + +#elif defined(CONFIG_ARCH_OMAP4) +/* We map both L3 and L4 on OMAP4 */ +#define L3_44XX_PHYS L3_44XX_BASE +#define L3_44XX_VIRT 0xd4000000 +#define L3_44XX_SIZE SZ_1M + +#define L4_44XX_PHYS L4_44XX_BASE +#define L4_44XX_VIRT 0xda000000 +#define L4_44XX_SIZE SZ_4M + + +#define L4_WK_44XX_PHYS L4_WK_44XX_BASE +#define L4_WK_44XX_VIRT 0xda300000 +#define L4_WK_44XX_SIZE SZ_1M + +#define L4_PER_44XX_PHYS L4_PER_44XX_BASE +#define L4_PER_44XX_VIRT 0xd8000000 +#define L4_PER_44XX_SIZE SZ_4M + +#define L4_EMU_44XX_PHYS L4_EMU_44XX_BASE +#define L4_EMU_44XX_VIRT 0xe4000000 +#define L4_EMU_44XX_SIZE SZ_64M + +#define OMAP44XX_GPMC_PHYS OMAP44XX_GPMC_BASE +#define OMAP44XX_GPMC_VIRT 0xe0000000 +#define OMAP44XX_GPMC_SIZE SZ_1M + + +#define IO_OFFSET 0x90000000 +#define __IO_ADDRESS(pa) ((pa) + IO_OFFSET)/* Works for L3 and L4 */ +#define __OMAP2_IO_ADDRESS(pa) ((pa) + IO_OFFSET)/* Works for L3 and L4 */ +#define io_v2p(va) ((va) - IO_OFFSET)/* Works for L3 and L4 */ + #endif #define IO_ADDRESS(pa) IOMEM(__IO_ADDRESS(pa)) diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index 7f57ee66f36..5bc331e93cf 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -4,6 +4,9 @@ * Copyright (C) Greg Lonnon 2001 * Updated for OMAP-1610 by Tony Lindgren * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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 of the License, or @@ -422,6 +425,92 @@ #define INT_34XX_BENCH_MPU_EMUL 3 + +#define IRQ_GIC_START 32 + +#define INT_44XX_BENCH_MPU_EMUL (3 + IRQ_GIC_START) +#define INT_44XX_SSM_ABORT_IRQ (6 + IRQ_GIC_START) +#define INT_44XX_SYS_NIRQ (7 + IRQ_GIC_START) +#define INT_44XX_D2D_FW_IRQ (8 + IRQ_GIC_START) +#define INT_44XX_PRCM_MPU_IRQ (11 + IRQ_GIC_START) +#define INT_44XX_SDMA_IRQ0 (12 + IRQ_GIC_START) +#define INT_44XX_SDMA_IRQ1 (13 + IRQ_GIC_START) +#define INT_44XX_SDMA_IRQ2 (14 + IRQ_GIC_START) +#define INT_44XX_SDMA_IRQ3 (15 + IRQ_GIC_START) +#define INT_44XX_ISS_IRQ (24 + IRQ_GIC_START) +#define INT_44XX_DSS_IRQ (25 + IRQ_GIC_START) +#define INT_44XX_MAIL_U0_MPU (26 + IRQ_GIC_START) +#define INT_44XX_DSP_MMU (28 + IRQ_GIC_START) +#define INT_44XX_GPTIMER1 (37 + IRQ_GIC_START) +#define INT_44XX_GPTIMER2 (38 + IRQ_GIC_START) +#define INT_44XX_GPTIMER3 (39 + IRQ_GIC_START) +#define INT_44XX_GPTIMER4 (40 + IRQ_GIC_START) +#define INT_44XX_GPTIMER5 (41 + IRQ_GIC_START) +#define INT_44XX_GPTIMER6 (42 + IRQ_GIC_START) +#define INT_44XX_GPTIMER7 (43 + IRQ_GIC_START) +#define INT_44XX_GPTIMER8 (44 + IRQ_GIC_START) +#define INT_44XX_GPTIMER9 (45 + IRQ_GIC_START) +#define INT_44XX_GPTIMER10 (46 + IRQ_GIC_START) +#define INT_44XX_GPTIMER11 (47 + IRQ_GIC_START) +#define INT_44XX_GPTIMER12 (95 + IRQ_GIC_START) +#define INT_44XX_SHA1MD5 (51 + IRQ_GIC_START) +#define INT_44XX_I2C1_IRQ (56 + IRQ_GIC_START) +#define INT_44XX_I2C2_IRQ (57 + IRQ_GIC_START) +#define INT_44XX_HDQ_IRQ (58 + IRQ_GIC_START) +#define INT_44XX_SPI1_IRQ (65 + IRQ_GIC_START) +#define INT_44XX_SPI2_IRQ (66 + IRQ_GIC_START) +#define INT_44XX_HSI_1_IRQ0 (67 + IRQ_GIC_START) +#define INT_44XX_HSI_2_IRQ1 (68 + IRQ_GIC_START) +#define INT_44XX_HSI_1_DMAIRQ (71 + IRQ_GIC_START) +#define INT_44XX_UART1_IRQ (72 + IRQ_GIC_START) +#define INT_44XX_UART2_IRQ (73 + IRQ_GIC_START) +#define INT_44XX_UART3_IRQ (74 + IRQ_GIC_START) +#define INT_44XX_UART4_IRQ (70 + IRQ_GIC_START) +#define INT_44XX_USB_IRQ_NISO (76 + IRQ_GIC_START) +#define INT_44XX_USB_IRQ_ISO (77 + IRQ_GIC_START) +#define INT_44XX_USB_IRQ_HGEN (78 + IRQ_GIC_START) +#define INT_44XX_USB_IRQ_HSOF (79 + IRQ_GIC_START) +#define INT_44XX_USB_IRQ_OTG (80 + IRQ_GIC_START) +#define INT_44XX_MCBSP4_IRQ_TX (81 + IRQ_GIC_START) +#define INT_44XX_MCBSP4_IRQ_RX (82 + IRQ_GIC_START) +#define INT_44XX_MMC_IRQ (83 + IRQ_GIC_START) +#define INT_44XX_MMC2_IRQ (86 + IRQ_GIC_START) +#define INT_44XX_MCBSP2_IRQ_TX (89 + IRQ_GIC_START) +#define INT_44XX_MCBSP2_IRQ_RX (90 + IRQ_GIC_START) +#define INT_44XX_SPI3_IRQ (91 + IRQ_GIC_START) +#define INT_44XX_SPI5_IRQ (69 + IRQ_GIC_START) + +#define INT_44XX_MCBSP5_IRQ (16 + IRQ_GIC_START) +#define INT_44xX_MCBSP1_IRQ (17 + IRQ_GIC_START) +#define INT_44XX_MCBSP2_IRQ (22 + IRQ_GIC_START) +#define INT_44XX_MCBSP3_IRQ (23 + IRQ_GIC_START) +#define INT_44XX_MCBSP4_IRQ (27 + IRQ_GIC_START) +#define INT_44XX_HS_USB_MC (92 + IRQ_GIC_START) +#define INT_44XX_HS_USB_DMA (93 + IRQ_GIC_START) + +#define INT_44XX_GPIO_BANK1 (29 + IRQ_GIC_START) +#define INT_44XX_GPIO_BANK2 (30 + IRQ_GIC_START) +#define INT_44XX_GPIO_BANK3 (31 + IRQ_GIC_START) +#define INT_44XX_GPIO_BANK4 (32 + IRQ_GIC_START) +#define INT_44XX_GPIO_BANK5 (33 + IRQ_GIC_START) +#define INT_44XX_GPIO_BANK6 (34 + IRQ_GIC_START) +#define INT_44XX_USIM_IRQ (35 + IRQ_GIC_START) +#define INT_44XX_WDT3_IRQ (36 + IRQ_GIC_START) +#define INT_44XX_SPI4_IRQ (48 + IRQ_GIC_START) +#define INT_44XX_SHA1MD52_IRQ (49 + IRQ_GIC_START) +#define INT_44XX_FPKA_READY_IRQ (50 + IRQ_GIC_START) +#define INT_44XX_SHA1MD51_IRQ (51 + IRQ_GIC_START) +#define INT_44XX_RNG_IRQ (52 + IRQ_GIC_START) +#define INT_44XX_I2C3_IRQ (61 + IRQ_GIC_START) +#define INT_44XX_FPKA_ERROR_IRQ (64 + IRQ_GIC_START) +#define INT_44XX_PBIAS_IRQ (75 + IRQ_GIC_START) +#define INT_44XX_OHCI_IRQ (76 + IRQ_GIC_START) +#define INT_44XX_EHCI_IRQ (77 + IRQ_GIC_START) +#define INT_44XX_TLL_IRQ (78 + IRQ_GIC_START) +#define INT_44XX_PARTHASH_IRQ (79 + IRQ_GIC_START) +#define INT_44XX_MMC3_IRQ (94 + IRQ_GIC_START) + + /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and * 16 MPUIO lines */ #define OMAP_MAX_GPIO_LINES 192 diff --git a/arch/arm/plat-omap/include/mach/memory.h b/arch/arm/plat-omap/include/mach/memory.h index 99ed564d927..9ad41dc484c 100644 --- a/arch/arm/plat-omap/include/mach/memory.h +++ b/arch/arm/plat-omap/include/mach/memory.h @@ -38,7 +38,8 @@ */ #if defined(CONFIG_ARCH_OMAP1) #define PHYS_OFFSET UL(0x10000000) -#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) +#elif defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) || \ + defined(CONFIG_ARCH_OMAP4) #define PHYS_OFFSET UL(0x80000000) #endif diff --git a/arch/arm/plat-omap/include/mach/omap44xx.h b/arch/arm/plat-omap/include/mach/omap44xx.h new file mode 100644 index 00000000000..15dec7f1c7c --- /dev/null +++ b/arch/arm/plat-omap/include/mach/omap44xx.h @@ -0,0 +1,46 @@ +/*: + * Address mappings and base address for OMAP4 interconnects + * and peripherals. + * + * Copyright (C) 2009 Texas Instruments + * + * Author: Santosh Shilimkar + * + * 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. + */ +#ifndef __ASM_ARCH_OMAP44XX_H +#define __ASM_ARCH_OMAP44XX_H + +/* + * Please place only base defines here and put the rest in device + * specific headers. + */ +#define L4_44XX_BASE 0x4a000000 +#define L4_WK_44XX_BASE 0x4a300000 +#define L4_PER_44XX_BASE 0x48000000 +#define L4_EMU_44XX_BASE 0x54000000 +#define L3_44XX_BASE 0x44000000 +#define OMAP4430_32KSYNCT_BASE 0x4a304000 +#define OMAP4430_CM_BASE 0x4a004000 +#define OMAP4430_PRM_BASE 0x48306000 +#define OMAP44XX_GPMC_BASE 0x50000000 +#define OMAP443X_SCM_BASE 0x4a002000 +#define OMAP443X_CTRL_BASE OMAP443X_SCM_BASE +#define OMAP44XX_IC_BASE 0x48200000 +#define OMAP44XX_IVA_INTC_BASE 0x40000000 +#define IRQ_SIR_IRQ 0x0040 +#define OMAP44XX_GIC_DIST_BASE 0x48241000 +#define OMAP44XX_GIC_CPU_BASE 0x48240100 +#define OMAP44XX_VA_GIC_CPU_BASE IO_ADDRESS(OMAP44XX_GIC_CPU_BASE) +#define OMAP44XX_SCU_BASE 0x48240000 +#define OMAP44XX_VA_SCU_BASE IO_ADDRESS(OMAP44XX_SCU_BASE) +#define OMAP44XX_LOCAL_TWD_BASE 0x48240600 +#define OMAP44XX_VA_LOCAL_TWD_BASE IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE) +#define OMAP44XX_LOCAL_TWD_SIZE 0x00000100 +#define OMAP44XX_WKUPGEN_BASE 0x48281000 +#define OMAP44XX_VA_WKUPGEN_BASE IO_ADDRESS(OMAP44XX_WKUPGEN_BASE) + +#endif /* __ASM_ARCH_OMAP44XX_H */ + diff --git a/arch/arm/plat-omap/include/mach/serial.h b/arch/arm/plat-omap/include/mach/serial.h index 8a676a04be4..e37894e423b 100644 --- a/arch/arm/plat-omap/include/mach/serial.h +++ b/arch/arm/plat-omap/include/mach/serial.h @@ -1,5 +1,8 @@ /* - * arch/arm/plat-omap/include/mach/serial.h + * arch/arm/plat-omap/include/mach/serial.h + * + * Copyright (C) 2009 Texas Instruments + * Addded OMAP4 support- Santosh Shilimkar * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -15,19 +18,28 @@ #define OMAP_UART1_BASE 0xfffb0000 #define OMAP_UART2_BASE 0xfffb0800 #define OMAP_UART3_BASE 0xfffb9800 +#define OMAP_MAX_NR_PORTS 3 #elif defined(CONFIG_ARCH_OMAP2) /* OMAP2 serial ports */ #define OMAP_UART1_BASE 0x4806a000 #define OMAP_UART2_BASE 0x4806c000 #define OMAP_UART3_BASE 0x4806e000 +#define OMAP_MAX_NR_PORTS 3 #elif defined(CONFIG_ARCH_OMAP3) /* OMAP3 serial ports */ #define OMAP_UART1_BASE 0x4806a000 #define OMAP_UART2_BASE 0x4806c000 #define OMAP_UART3_BASE 0x49020000 +#define OMAP_MAX_NR_PORTS 3 +#elif defined(CONFIG_ARCH_OMAP4) +/* OMAP4 serial ports */ +#define OMAP_UART1_BASE 0x4806a000 +#define OMAP_UART2_BASE 0x4806c000 +#define OMAP_UART3_BASE 0x48020000 +#define OMAP_UART4_BASE 0x4806e000 +#define OMAP_MAX_NR_PORTS 4 #endif -#define OMAP_MAX_NR_PORTS 3 #define OMAP1510_BASE_BAUD (12000000/16) #define OMAP16XX_BASE_BAUD (48000000/16) #define OMAP24XX_BASE_BAUD (48000000/16) diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c index af326efc1ad..9b42d72d96c 100644 --- a/arch/arm/plat-omap/io.c +++ b/arch/arm/plat-omap/io.c @@ -1,3 +1,14 @@ +/* + * Common io.c file + * This file is created by Russell King + * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * + * 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 #include #include @@ -7,6 +18,7 @@ #include #include #include +#include #define BETWEEN(p,st,sz) ((p) >= (st) && (p) < ((st) + (sz))) #define XLATE(p,pst,vst) ((void __iomem *)((p) - (pst) + (vst))) @@ -92,7 +104,22 @@ void __iomem *omap_ioremap(unsigned long p, size_t size, unsigned int type) return XLATE(p, L4_EMU_34XX_PHYS, L4_EMU_34XX_VIRT); } #endif - +#ifdef CONFIG_ARCH_OMAP4 + if (cpu_is_omap44xx()) { + if (BETWEEN(p, L3_44XX_PHYS, L3_44XX_SIZE)) + return XLATE(p, L3_44XX_PHYS, L3_44XX_VIRT); + if (BETWEEN(p, L4_44XX_PHYS, L4_44XX_SIZE)) + return XLATE(p, L4_44XX_PHYS, L4_44XX_VIRT); + if (BETWEEN(p, L4_WK_44XX_PHYS, L4_WK_44XX_SIZE)) + return XLATE(p, L4_WK_44XX_PHYS, L4_WK_44XX_VIRT); + if (BETWEEN(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_SIZE)) + return XLATE(p, OMAP44XX_GPMC_PHYS, OMAP44XX_GPMC_VIRT); + if (BETWEEN(p, L4_PER_44XX_PHYS, L4_PER_44XX_SIZE)) + return XLATE(p, L4_PER_44XX_PHYS, L4_PER_44XX_VIRT); + if (BETWEEN(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_SIZE)) + return XLATE(p, L4_EMU_44XX_PHYS, L4_EMU_44XX_VIRT); + } +#endif return __arm_ioremap(p, size, type); } EXPORT_SYMBOL(omap_ioremap); diff --git a/arch/arm/plat-omap/mux.c b/arch/arm/plat-omap/mux.c index 80b040fd5ca..8d329fb2074 100644 --- a/arch/arm/plat-omap/mux.c +++ b/arch/arm/plat-omap/mux.c @@ -54,6 +54,9 @@ int __init_or_module omap_cfg_reg(const unsigned long index) { struct pin_config *reg; + if (cpu_is_omap44xx()) + return 0; + if (mux_cfg == NULL) { printk(KERN_ERR "Pin mux table not initialized\n"); return -ENODEV; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 102c9f71a3c..67a90708b68 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -6,6 +6,9 @@ * Copyright (C) 2005 Nokia Corporation * Written by Tony Lindgren * + * Copyright (C) 2009 Texas Instruments + * Added OMAP4 support - Santosh Shilimkar + * * 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. @@ -44,6 +47,8 @@ #define OMAP3_SRAM_VA 0xd7000000 #define OMAP3_SRAM_PUB_PA 0x40208000 #define OMAP3_SRAM_PUB_VA 0xd7008000 +#define OMAP4_SRAM_PA 0x40200000 /*0x402f0000*/ +#define OMAP4_SRAM_VA 0xd7000000 /*0xd70f0000*/ #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) #define SRAM_BOOTLOADER_SZ 0x00 @@ -87,6 +92,10 @@ static int is_sram_locked(void) { int type = 0; + if (cpu_is_omap44xx()) + /* Not yet supported */ + return 0; + if (cpu_is_omap242x()) type = omap_rev() & OMAP2_DEVICETYPE_MASK; @@ -135,6 +144,10 @@ void __init omap_detect_sram(void) omap_sram_base = OMAP3_SRAM_VA; omap_sram_start = OMAP3_SRAM_PA; omap_sram_size = 0x10000; /* 64K */ + } else if (cpu_is_omap44xx()) { + omap_sram_base = OMAP4_SRAM_VA; + omap_sram_start = OMAP4_SRAM_PA; + omap_sram_size = 0x8000; /* 32K */ } else { omap_sram_base = OMAP2_SRAM_VA; omap_sram_start = OMAP2_SRAM_PA; @@ -203,6 +216,12 @@ void __init omap_map_sram(void) omap_sram_io_desc[0].pfn = __phys_to_pfn(base); } + if (cpu_is_omap44xx()) { + omap_sram_io_desc[0].virtual = OMAP4_SRAM_VA; + base = OMAP4_SRAM_PA; + base = ROUND_DOWN(base, PAGE_SIZE); + omap_sram_io_desc[0].pfn = __phys_to_pfn(base); + } omap_sram_io_desc[0].length = 1024 * 1024; /* Use section desc */ iotable_init(omap_sram_io_desc, ARRAY_SIZE(omap_sram_io_desc)); @@ -391,6 +410,8 @@ int __init omap_sram_init(void) omap243x_sram_init(); else if (cpu_is_omap34xx()) omap34xx_sram_init(); + else if (cpu_is_omap44xx()) + omap34xx_sram_init(); /* FIXME: */ return 0; } -- cgit v1.2.3-70-g09d2 From 748303850d589038f8ff9f5c7014afb006210b1f Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 28 May 2009 14:16:04 -0700 Subject: ARM: OMAP4: Clock stubs since CLKDEV not in yet. This patch update the common clock.c file for OMAP4. The clk_get() and clk_put() functions are moved to common place in arch/arm/common/clkdev.c Since on current OMAP4 platform clk management is still not supported, the platform file is stubbed with those functions. Once the framework is ready, this WILL be replaced with a full clkdev implementation. Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/clock.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c index 29efc279287..0fcfcd68709 100644 --- a/arch/arm/plat-omap/clock.c +++ b/arch/arm/plat-omap/clock.c @@ -36,10 +36,40 @@ static struct clk_functions *arch_clock; * Standard clock functions defined in include/linux/clk.h *-------------------------------------------------------------------------*/ +/* This functions is moved to arch/arm/common/clkdev.c. For OMAP4 since + * clock framework is not up , it is defined here to avoid rework in + * every driver. Also dummy prcm reset function is added */ + +/* Dummy hooks only for OMAP4.For rest OMAPs, common clkdev is used */ +#if defined(CONFIG_ARCH_OMAP4) +struct clk *clk_get(struct device *dev, const char *id) +{ + return NULL; +} +EXPORT_SYMBOL(clk_get); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); + +void omap2_clk_prepare_for_reboot(void) +{ +} +EXPORT_SYMBOL(omap2_clk_prepare_for_reboot); + +void omap_prcm_arch_reset(char mode) +{ +} +EXPORT_SYMBOL(omap_prcm_arch_reset); +#endif int clk_enable(struct clk *clk) { unsigned long flags; int ret = 0; + if (cpu_is_omap44xx()) + /* OMAP4 clk framework not supported yet */ + return 0; if (clk == NULL || IS_ERR(clk)) return -EINVAL; @@ -140,6 +170,9 @@ int clk_set_parent(struct clk *clk, struct clk *parent) unsigned long flags; int ret = -EINVAL; + if (cpu_is_omap44xx()) + /* OMAP4 clk framework not supported yet */ + return 0; if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent)) return ret; -- cgit v1.2.3-70-g09d2 From 46ba0abfe1ac2bd9608d0fc9e914379be695aa5b Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Thu, 28 May 2009 14:16:05 -0700 Subject: ARM: OMAP4: Add support for 4430 SDP This patch updates the Makefile and Kconfig entries for OMAP4. The OMAP4430 SDP board file supports only minimal set of drivers. Signed-off-by: Santosh Shilimkar Signed-off-by: Tony Lindgren --- arch/arm/Makefile | 1 + arch/arm/mach-omap2/Kconfig | 6 ++- arch/arm/mach-omap2/Makefile | 3 ++ arch/arm/mach-omap2/board-4430sdp.c | 94 +++++++++++++++++++++++++++++++++++++ arch/arm/plat-omap/Kconfig | 11 +++-- 5 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 arch/arm/mach-omap2/board-4430sdp.c (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e84729bf13d..676d10d028b 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -127,6 +127,7 @@ endif machine-$(CONFIG_ARCH_OMAP1) := omap1 machine-$(CONFIG_ARCH_OMAP2) := omap2 machine-$(CONFIG_ARCH_OMAP3) := omap2 + machine-$(CONFIG_ARCH_OMAP4) := omap2 plat-$(CONFIG_ARCH_OMAP) := omap machine-$(CONFIG_ARCH_S3C2410) := s3c2410 s3c2400 s3c2412 s3c2440 s3c2442 s3c2443 machine-$(CONFIG_ARCH_S3C24A0) := s3c24a0 diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index b5c9088a6a4..a755eb5e236 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -25,7 +25,7 @@ config ARCH_OMAP3430 select ARCH_OMAP_OTG comment "OMAP Board Type" - depends on ARCH_OMAP2 || ARCH_OMAP3 + depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4 config MACH_OMAP_GENERIC bool "Generic OMAP board" @@ -75,3 +75,7 @@ config MACH_NOKIA_RX51 config MACH_OMAP_ZOOM2 bool "OMAP3 Zoom2 board" depends on ARCH_OMAP3 && ARCH_OMAP34XX + +config MACH_OMAP_4430SDP + bool "OMAP 4430 SDP board" + depends on ARCH_OMAP4 diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile index 10e7c29ac1d..09fb3ad5249 100644 --- a/arch/arm/mach-omap2/Makefile +++ b/arch/arm/mach-omap2/Makefile @@ -58,6 +58,9 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \ obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \ mmc-twl4030.o \ board-zoom-debugboard.o + +obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o + # Platform specific device init code ifeq ($(CONFIG_USB_MUSB_SOC),y) obj-y += usb-musb.o diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c new file mode 100644 index 00000000000..57e477bd89c --- /dev/null +++ b/arch/arm/mach-omap2/board-4430sdp.c @@ -0,0 +1,94 @@ +/* + * Board support file for OMAP4430 SDP. + * + * Copyright (C) 2009 Texas Instruments + * + * Author: Santosh Shilimkar + * + * Based on mach-omap2/board-3430sdp.c + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static struct platform_device sdp4430_lcd_device = { + .name = "sdp4430_lcd", + .id = -1, +}; + +static struct platform_device *sdp4430_devices[] __initdata = { + &sdp4430_lcd_device, +}; + +static struct omap_uart_config sdp4430_uart_config __initdata = { + .enabled_uarts = (1 << 0) | (1 << 1) | (1 << 2), +}; + +static struct omap_lcd_config sdp4430_lcd_config __initdata = { + .ctrl_name = "internal", +}; + +static struct omap_board_config_kernel sdp4430_config[] __initdata = { + { OMAP_TAG_UART, &sdp4430_uart_config }, + { OMAP_TAG_LCD, &sdp4430_lcd_config }, +}; + +static void __init gic_init_irq(void) +{ + gic_dist_init(0, IO_ADDRESS(OMAP44XX_GIC_DIST_BASE), 29); + gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE)); +} + +static void __init omap_4430sdp_init_irq(void) +{ + omap2_init_common_hw(NULL); +#ifdef CONFIG_OMAP_32K_TIMER + omap2_gp_clockevent_set_gptimer(1); +#endif + gic_init_irq(); + omap_gpio_init(); +} + + +static void __init omap_4430sdp_init(void) +{ + platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices)); + omap_board_config = sdp4430_config; + omap_board_config_size = ARRAY_SIZE(sdp4430_config); + omap_serial_init(); +} + +static void __init omap_4430sdp_map_io(void) +{ + omap2_set_globals_443x(); + omap2_map_common_io(); +} + +MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board") + /* Maintainer: Santosh Shilimkar - Texas Instruments Inc */ + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = omap_4430sdp_map_io, + .init_irq = omap_4430sdp_init_irq, + .init_machine = omap_4430sdp_init, + .timer = &omap_timer, +MACHINE_END diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9dd68fafb37..89499e67b67 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -23,6 +23,11 @@ config ARCH_OMAP3 select CPU_V7 select COMMON_CLKDEV +config ARCH_OMAP4 + bool "TI OMAP4" + select CPU_V7 + select ARM_GIC + endchoice comment "OMAP Feature Selections" @@ -128,13 +133,13 @@ config OMAP_MPU_TIMER config OMAP_32K_TIMER bool "Use 32KHz timer" - depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX + depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4 help Select this option if you want to enable the OMAP 32KHz timer. This timer saves power compared to the OMAP_MPU_TIMER, and has support for no tick during idle. The 32KHz timer provides less intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is - currently only available for OMAP16XX, 24XX and 34XX. + currently only available for OMAP16XX, 24XX, 34XX and OMAP4. endchoice @@ -149,7 +154,7 @@ config OMAP_32K_TIMER_HZ config OMAP_DM_TIMER bool "Use dual-mode timer" - depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX + depends on ARCH_OMAP16XX || ARCH_OMAP24XX || ARCH_OMAP34XX || ARCH_OMAP4 help Select this option if you want to use OMAP Dual-Mode timers. -- cgit v1.2.3-70-g09d2 From a22f277bba321474a01691ae66d5952926459f44 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 31 May 2009 15:02:58 +0100 Subject: [ARM] Kconfig: remove 'default n' Kconfig entries default to n, so there's no need for this to be explicitly specified. Signed-off-by: Russell King --- arch/arm/Kconfig | 7 ------- arch/arm/mach-davinci/Kconfig | 4 ---- arch/arm/mach-mx3/Kconfig | 4 ---- arch/arm/mach-realview/Kconfig | 1 - arch/arm/mm/Kconfig | 3 --- arch/arm/plat-omap/Kconfig | 3 --- 6 files changed, 22 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 65bf774a26f..65778839d38 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -34,15 +34,12 @@ config SYS_SUPPORTS_APM_EMULATION config GENERIC_GPIO bool - default n config GENERIC_TIME bool - default n config GENERIC_CLOCKEVENTS bool - default n config GENERIC_CLOCKEVENTS_BROADCAST bool @@ -55,7 +52,6 @@ config MMU config NO_IOPORT bool - default n config EISA bool @@ -126,11 +122,9 @@ config RWSEM_XCHGADD_ALGORITHM config ARCH_HAS_ILOG2_U32 bool - default n config ARCH_HAS_ILOG2_U64 bool - default n config GENERIC_HWEIGHT bool @@ -969,7 +963,6 @@ config OABI_COMPAT config ARCH_HAS_HOLES_MEMORYMODEL bool - default n # Discontigmem is deprecated config ARCH_DISCONTIGMEM_ENABLE diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 76408670554..be747f5c6cd 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -34,7 +34,6 @@ config MACH_DAVINCI_EVM config MACH_SFFSDR bool "Lyrtech SFFSDR" - default n depends on ARCH_DAVINCI_DM644x help Say Y here to select the Lyrtech Small Form Factor @@ -42,7 +41,6 @@ config MACH_SFFSDR config MACH_DAVINCI_DM355_EVM bool "TI DM355 EVM" - default n depends on ARCH_DAVINCI_DM355 help Configure this option to specify the whether the board used @@ -50,7 +48,6 @@ config MACH_DAVINCI_DM355_EVM config MACH_DM355_LEOPARD bool "DM355 Leopard board" - default n depends on ARCH_DAVINCI_DM355 help Configure this option to specify the whether the board used @@ -58,7 +55,6 @@ config MACH_DM355_LEOPARD config MACH_DAVINCI_DM6467_EVM bool "TI DM6467 EVM" - default n depends on ARCH_DAVINCI_DM646x help Configure this option to specify the whether the board used diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig index 32e45155089..229fb3e71fa 100644 --- a/arch/arm/mach-mx3/Kconfig +++ b/arch/arm/mach-mx3/Kconfig @@ -39,7 +39,6 @@ config MACH_PCM037 config MACH_MX31LITE bool "Support MX31 LITEKIT (LogicPD)" select ARCH_MX31 - default n help Include support for MX31 LITEKIT platform. This includes specific configurations for the board and its peripherals. @@ -47,7 +46,6 @@ config MACH_MX31LITE config MACH_MX31_3DS bool "Support MX31PDK (3DS)" select ARCH_MX31 - default n help Include support for MX31PDK (3DS) platform. This includes specific configurations for the board and its peripherals. @@ -55,7 +53,6 @@ config MACH_MX31_3DS config MACH_MX31MOBOARD bool "Support mx31moboard platforms (EPFL Mobots group)" select ARCH_MX31 - default n help Include support for mx31moboard platform. This includes specific configurations for the board and its peripherals. @@ -63,7 +60,6 @@ config MACH_MX31MOBOARD config MACH_QONG bool "Support Dave/DENX QongEVB-LITE platform" select ARCH_MX31 - default n help Include support for Dave/DENX QongEVB-LITE platform. This includes specific configurations for the board and its peripherals. diff --git a/arch/arm/mach-realview/Kconfig b/arch/arm/mach-realview/Kconfig index b6ec1062777..bf35cfd89f3 100644 --- a/arch/arm/mach-realview/Kconfig +++ b/arch/arm/mach-realview/Kconfig @@ -24,7 +24,6 @@ config REALVIEW_EB_ARM11MP config REALVIEW_EB_ARM11MP_REVB bool "Support ARM11MPCore RevB tile" depends on REALVIEW_EB_ARM11MP - default n help Enable support for the ARM11MPCore RevB tile on the Realview platform. Since there are device address differences, a diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig index 20979564e7e..b9bd481a0ec 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -642,7 +642,6 @@ config CPU_BIG_ENDIAN config CPU_HIGH_VECTOR depends on !MMU && CPU_CP15 && !CPU_ARM740T bool "Select the High exception vector" - default n help Say Y here to select high exception vector(0xFFFF0000~). The exception vector can be vary depending on the platform @@ -726,7 +725,6 @@ config NEEDS_SYSCALL_FOR_CMPXCHG config OUTER_CACHE bool - default n config CACHE_FEROCEON_L2 bool "Enable the Feroceon L2 cache controller" @@ -739,7 +737,6 @@ config CACHE_FEROCEON_L2 config CACHE_FEROCEON_L2_WRITETHROUGH bool "Force Feroceon L2 cache write through" depends on CACHE_FEROCEON_L2 - default n help Say Y here to use the Feroceon L2 cache in writethrough mode. Unless you specifically require this, say N for writeback mode. diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 9a6ecc7159b..efe85d09519 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -45,7 +45,6 @@ config OMAP_DEBUG_LEDS config OMAP_DEBUG_POWERDOMAIN bool "Emit debug messages from powerdomain layer" depends on ARCH_OMAP2 || ARCH_OMAP3 - default n help Say Y here if you want to compile in powerdomain layer debugging messages for OMAP2/3. These messages can @@ -57,7 +56,6 @@ config OMAP_DEBUG_POWERDOMAIN config OMAP_DEBUG_CLOCKDOMAIN bool "Emit debug messages from clockdomain layer" depends on ARCH_OMAP2 || ARCH_OMAP3 - default n help Say Y here if you want to compile in clockdomain layer debugging messages for OMAP2/3. These messages can @@ -115,7 +113,6 @@ config OMAP_MCBSP config OMAP_MBOX_FWK tristate "Mailbox framework support" depends on ARCH_OMAP - default n help Say Y here if you want to use OMAP Mailbox framework support for DSP, IVA1.0 and IVA2 in OMAP1/2/3. -- cgit v1.2.3-70-g09d2 From 367cd31ee0cbc948fe3b83960b1dbf931e2eaa90 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Tue, 28 Apr 2009 20:51:52 +0530 Subject: ARM: OMAP4: SMP: Add OMAP4430 SMP board files This patch adds SMP platform files support for OMAP4430SDP. TI's OMAP4430 SOC is based on ARM Cortex-A9 SMP architecture. It's a dual core SOC with GIC used for interrupt handling and SCU for cache coherency. Signed-off-by: Santosh Shilimkar --- arch/arm/mach-omap2/omap-headsmp.S | 46 +++++++++ arch/arm/mach-omap2/omap-smp.c | 178 ++++++++++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/smp.h | 51 ++++++++++ 3 files changed, 275 insertions(+) create mode 100644 arch/arm/mach-omap2/omap-headsmp.S create mode 100644 arch/arm/mach-omap2/omap-smp.c create mode 100644 arch/arm/plat-omap/include/mach/smp.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/omap-headsmp.S b/arch/arm/mach-omap2/omap-headsmp.S new file mode 100644 index 00000000000..4afadba0947 --- /dev/null +++ b/arch/arm/mach-omap2/omap-headsmp.S @@ -0,0 +1,46 @@ +/* + * Secondary CPU startup routine source file. + * + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Author: + * Santosh Shilimkar + * + * Interface functions needed for the SMP. This file is based on arm + * realview smp platform. + * Copyright (c) 2003 ARM Limited. + * + * 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 +#include + +/* Physical address needed since MMU not enabled yet on secondary core */ +#define OMAP4_AUX_CORE_BOOT1_PA 0x48281804 + + __INIT + +/* + * OMAP4 specific entry point for secondary CPU to jump from ROM + * code. This routine also provides a holding flag into which + * secondary core is held until we're ready for it to initialise. + * The primary core will update the this flag using a hardware + * register AuxCoreBoot1. + */ +ENTRY(omap_secondary_startup) + mrc p15, 0, r0, c0, c0, 5 + and r0, r0, #0x0f +hold: ldr r1, =OMAP4_AUX_CORE_BOOT1_PA @ read from AuxCoreBoot1 + ldr r2, [r1] + cmp r2, r0 + bne hold + + /* + * we've been released from the cpu_release,secondary_stack + * should now contain the SVC stack for this core + */ + b secondary_startup + diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c new file mode 100644 index 00000000000..8fe8d230f21 --- /dev/null +++ b/arch/arm/mach-omap2/omap-smp.c @@ -0,0 +1,178 @@ +/* + * OMAP4 SMP source file. It contains platform specific fucntions + * needed for the linux smp kernel. + * + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Author: + * Santosh Shilimkar + * + * Platform file needed for the OMAP4 SMP. This file is based on arm + * realview smp platform. + * * Copyright (c) 2002 ARM Limited. + * + * 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 +#include +#include +#include +#include + +#include +#include +#include + +/* Registers used for communicating startup information */ +#define OMAP4_AUXCOREBOOT_REG0 (OMAP44XX_VA_WKUPGEN_BASE + 0x800) +#define OMAP4_AUXCOREBOOT_REG1 (OMAP44XX_VA_WKUPGEN_BASE + 0x804) + +/* SCU base address */ +static void __iomem *scu_base = OMAP44XX_VA_SCU_BASE; + +/* + * Use SCU config register to count number of cores + */ +static inline unsigned int get_core_count(void) +{ + if (scu_base) + return scu_get_core_count(scu_base); + return 1; +} + +static DEFINE_SPINLOCK(boot_lock); + +void __cpuinit platform_secondary_init(unsigned int cpu) +{ + trace_hardirqs_off(); + + /* + * If any interrupts are already enabled for the primary + * core (e.g. timer irq), then they will not have been enabled + * for us: do so + */ + + gic_cpu_init(0, IO_ADDRESS(OMAP44XX_GIC_CPU_BASE)); + + /* + * Synchronise with the boot thread. + */ + spin_lock(&boot_lock); + spin_unlock(&boot_lock); +} + +int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +{ + unsigned long timeout; + + /* + * Set synchronisation state between this boot processor + * and the secondary one + */ + spin_lock(&boot_lock); + + /* + * Update the AuxCoreBoot1 with boot state for secondary core. + * omap_secondary_startup() routine will hold the secondary core till + * the AuxCoreBoot1 register is updated with cpu state + * A barrier is added to ensure that write buffer is drained + */ + __raw_writel(cpu, OMAP4_AUXCOREBOOT_REG1); + smp_wmb(); + + timeout = jiffies + (1 * HZ); + while (time_before(jiffies, timeout)) + ; + + /* + * Now the secondary core is starting up let it run its + * calibrations, then wait for it to finish + */ + spin_unlock(&boot_lock); + + return 0; +} + +static void __init wakeup_secondary(void) +{ + /* + * Write the address of secondary startup routine into the + * AuxCoreBoot0 where ROM code will jump and start executing + * on secondary core once out of WFE + * A barrier is added to ensure that write buffer is drained + */ + __raw_writel(virt_to_phys(omap_secondary_startup), \ + OMAP4_AUXCOREBOOT_REG0); + smp_wmb(); + + /* + * Send a 'sev' to wake the secondary core from WFE. + */ + set_event(); + mb(); +} + +/* + * Initialise the CPU possible map early - this describes the CPUs + * which may be present or become present in the system. + */ +void __init smp_init_cpus(void) +{ + unsigned int i, ncores = get_core_count(); + + for (i = 0; i < ncores; i++) + set_cpu_possible(i, true); +} + +void __init smp_prepare_cpus(unsigned int max_cpus) +{ + unsigned int ncores = get_core_count(); + unsigned int cpu = smp_processor_id(); + int i; + + /* sanity check */ + if (ncores == 0) { + printk(KERN_ERR + "OMAP4: strange core count of 0? Default to 1\n"); + ncores = 1; + } + + if (ncores > NR_CPUS) { + printk(KERN_WARNING + "OMAP4: no. of cores (%d) greater than configured " + "maximum of %d - clipping\n", + ncores, NR_CPUS); + ncores = NR_CPUS; + } + smp_store_cpu_info(cpu); + + /* + * are we trying to boot more cores than exist? + */ + if (max_cpus > ncores) + max_cpus = ncores; + + /* + * Initialise the present map, which describes the set of CPUs + * actually populated at the present time. + */ + for (i = 0; i < max_cpus; i++) + set_cpu_present(i, true); + + if (max_cpus > 1) { + /* + * Enable the local timer or broadcast device for the + * boot CPU, but only if we have more than one CPU. + */ + percpu_timer_setup(); + + /* + * Initialise the SCU and wake up the secondary core using + * wakeup_secondary(). + */ + scu_enable(scu_base); + wakeup_secondary(); + } +} diff --git a/arch/arm/plat-omap/include/mach/smp.h b/arch/arm/plat-omap/include/mach/smp.h new file mode 100644 index 00000000000..dcaa8fde706 --- /dev/null +++ b/arch/arm/plat-omap/include/mach/smp.h @@ -0,0 +1,51 @@ +/* + * OMAP4 machine specific smp.h + * + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Author: + * Santosh Shilimkar + * + * Interface functions needed for the SMP. This file is based on arm + * realview smp platform. + * Copyright (c) 2003 ARM Limited. + * + * 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. + */ +#ifndef OMAP_ARCH_SMP_H +#define OMAP_ARCH_SMP_H + +#include + +/* + * set_event() is used to wake up secondary core from wfe using sev. ROM + * code puts the second core into wfe(standby). + * + */ +#define set_event() __asm__ __volatile__ ("sev" : : : "memory") + +/* Needed for secondary core boot */ +extern void omap_secondary_startup(void); + +/* + * We use Soft IRQ1 as the IPI + */ +static inline void smp_cross_call(const struct cpumask *mask) +{ + gic_raise_softirq(mask, 1); +} + +/* + * Read MPIDR: Multiprocessor affinity register + */ +#define hard_smp_processor_id() \ + ({ \ + unsigned int cpunum; \ + __asm__("mrc p15, 0, %0, c0, c0, 5" \ + : "=r" (cpunum)); \ + cpunum &= 0x0F; \ + }) + +#endif -- cgit v1.2.3-70-g09d2 From 39e1d4c18f34190c739f765ae56bfaa9cbbc6fdb Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Tue, 28 Apr 2009 20:52:00 +0530 Subject: ARM: OMAP4: SMP: Add mpu timer support for OMAP4430 This patch adds SMP platform specific parts for local(mpu) timer support for OMAP4430 platform. Each Cortex-a9 core has it's own local timer in the MPU domain. These timers are not in wakeup domain. Signed-off-by: Santosh Shilimkar --- arch/arm/mach-omap2/timer-gp.c | 4 ++++ arch/arm/mach-omap2/timer-mpu.c | 34 +++++++++++++++++++++++++++ arch/arm/plat-omap/include/mach/entry-macro.S | 28 ++++++++++++++++++++++ arch/arm/plat-omap/include/mach/irqs.h | 2 ++ 4 files changed, 68 insertions(+) create mode 100644 arch/arm/mach-omap2/timer-mpu.c (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/mach-omap2/timer-gp.c b/arch/arm/mach-omap2/timer-gp.c index 2ce474a9d2b..97eeeebcb06 100644 --- a/arch/arm/mach-omap2/timer-gp.c +++ b/arch/arm/mach-omap2/timer-gp.c @@ -38,6 +38,7 @@ #include #include +#include /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */ #define MAX_GPTIMER_ID 12 @@ -229,6 +230,9 @@ static void __init omap2_gp_clocksource_init(void) static void __init omap2_gp_timer_init(void) { +#ifdef CONFIG_LOCAL_TIMERS + twd_base = IO_ADDRESS(OMAP44XX_LOCAL_TWD_BASE); +#endif omap_dm_timer_init(); omap2_gp_clockevent_init(); diff --git a/arch/arm/mach-omap2/timer-mpu.c b/arch/arm/mach-omap2/timer-mpu.c new file mode 100644 index 00000000000..c1a650a9910 --- /dev/null +++ b/arch/arm/mach-omap2/timer-mpu.c @@ -0,0 +1,34 @@ +/* + * The MPU local timer source file. In OMAP4, both cortex-a9 cores have + * own timer in it's MPU domain. These timers will be driving the + * linux kernel SMP tick framework when active. These timers are not + * part of the wake up domain. + * + * Copyright (C) 2009 Texas Instruments, Inc. + * + * Author: + * Santosh Shilimkar + * + * This file is based on arm realview smp platform file. + * Copyright (C) 2002 ARM Ltd. + * + * 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 +#include +#include +#include +#include +#include + +/* + * Setup the local clock events for a CPU. + */ +void __cpuinit local_timer_setup(struct clock_event_device *evt) +{ + evt->irq = INT_44XX_LOCALTIMER_IRQ; + twd_timer_setup(evt); +} + diff --git a/arch/arm/plat-omap/include/mach/entry-macro.S b/arch/arm/plat-omap/include/mach/entry-macro.S index 00f45c01390..56426ed45ef 100644 --- a/arch/arm/plat-omap/include/mach/entry-macro.S +++ b/arch/arm/plat-omap/include/mach/entry-macro.S @@ -136,6 +136,34 @@ cmpne \irqnr, \tmp cmpcs \irqnr, \irqnr .endm + + /* We assume that irqstat (the raw value of the IRQ acknowledge + * register) is preserved from the macro above. + * If there is an IPI, we immediately signal end of interrupt + * on the controller, since this requires the original irqstat + * value which we won't easily be able to recreate later. + */ + + .macro test_for_ipi, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + cmp \irqnr, #16 + it cc + strcc \irqstat, [\base, #GIC_CPU_EOI] + it cs + cmpcs \irqnr, \irqnr + .endm + + /* As above, this assumes that irqstat and base are preserved */ + + .macro test_for_ltirq, irqnr, irqstat, base, tmp + bic \irqnr, \irqstat, #0x1c00 + mov \tmp, #0 + cmp \irqnr, #29 + itt eq + moveq \tmp, #1 + streq \irqstat, [\base, #GIC_CPU_EOI] + cmp \tmp, #0 + .endm #endif .macro irq_prio_table diff --git a/arch/arm/plat-omap/include/mach/irqs.h b/arch/arm/plat-omap/include/mach/irqs.h index 8015fe27c8b..fb7cb772399 100644 --- a/arch/arm/plat-omap/include/mach/irqs.h +++ b/arch/arm/plat-omap/include/mach/irqs.h @@ -427,6 +427,8 @@ #define IRQ_GIC_START 32 +#define INT_44XX_LOCALTIMER_IRQ 29 +#define INT_44XX_LOCALWDT_IRQ 30 #define INT_44XX_BENCH_MPU_EMUL (3 + IRQ_GIC_START) #define INT_44XX_SSM_ABORT_IRQ (6 + IRQ_GIC_START) -- cgit v1.2.3-70-g09d2