Commit 6f3cafce authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm

* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (21 commits)
  [ARM] 3629/1: S3C24XX: fix missing bracket in regs-dsc.h
  [ARM] 3537/1: Rework DMA-bounce locking for finer granularity
  [ARM] 3601/1: i.MX/MX1 DMA error handling for signaled channels only
  [ARM] 3597/1: ixp4xx/nslu2: Board support for new LED subsystem
  [ARM] 3595/1: ixp4xx/nas100d: Board support for new LED subsystem
  [ARM] 3626/1: ARM EABI: fix syscall restarting
  [ARM] 3628/1: S3C24XX: add get_rate call to struct clk
  [ARM] 3627/1: S3C24XX: split s3c2410 clocks from core clocks
  [ARM] 3613/1: S3C2410: Add sysdev and sysclass
  [ARM] 3624/1: Report true modem control line states
  [ARM] 3620/2: ixp23xx: add uengine loader support
  [ARM] 3618/1: add defconfig for logicpd pxa270 card engine
  [ARM] 3617/1: ep93xx: fix slightly incorrect timer tick rate
  [ARM] 3616/1: fix timer handler wrap logic for a number of platforms
  [ARM] 3615/1: ixp23xx: use platform devices for physmap flash
  [ARM] 3614/1: ep93xx: use platform devices for physmap flash
  [ARM] 3621/1: fix compilation breakage for pnx4008
  [ARM] 3623/1: pnx4008: move GPIO-related defines to gpio.h
  [ARM] 3622/1: pnx4008: remove clk_use/clk_unuse
  [ARM] Enable VFP to be built when non-VFP capable CPUs are selected
  ...
parents 0c97f524 02916526
...@@ -16,3 +16,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o ...@@ -16,3 +16,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o obj-$(CONFIG_SHARPSL_PM) += sharpsl_pm.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o obj-$(CONFIG_SHARP_SCOOP) += scoop.o
obj-$(CONFIG_ARCH_IXP2000) += uengine.o obj-$(CONFIG_ARCH_IXP2000) += uengine.o
obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
...@@ -77,6 +77,8 @@ struct dmabounce_device_info { ...@@ -77,6 +77,8 @@ struct dmabounce_device_info {
#endif #endif
struct dmabounce_pool small; struct dmabounce_pool small;
struct dmabounce_pool large; struct dmabounce_pool large;
rwlock_t lock;
}; };
static LIST_HEAD(dmabounce_devs); static LIST_HEAD(dmabounce_devs);
...@@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, ...@@ -116,6 +118,7 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
struct safe_buffer *buf; struct safe_buffer *buf;
struct dmabounce_pool *pool; struct dmabounce_pool *pool;
struct device *dev = device_info->dev; struct device *dev = device_info->dev;
unsigned long flags;
dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n",
__func__, ptr, size, dir); __func__, ptr, size, dir);
...@@ -163,8 +166,12 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, ...@@ -163,8 +166,12 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
print_alloc_stats(device_info); print_alloc_stats(device_info);
#endif #endif
write_lock_irqsave(&device_info->lock, flags);
list_add(&buf->node, &device_info->safe_buffers); list_add(&buf->node, &device_info->safe_buffers);
write_unlock_irqrestore(&device_info->lock, flags);
return buf; return buf;
} }
...@@ -172,22 +179,32 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, ...@@ -172,22 +179,32 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
static inline struct safe_buffer * static inline struct safe_buffer *
find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr) find_safe_buffer(struct dmabounce_device_info *device_info, dma_addr_t safe_dma_addr)
{ {
struct safe_buffer *b; struct safe_buffer *b = NULL;
unsigned long flags;
read_lock_irqsave(&device_info->lock, flags);
list_for_each_entry(b, &device_info->safe_buffers, node) list_for_each_entry(b, &device_info->safe_buffers, node)
if (b->safe_dma_addr == safe_dma_addr) if (b->safe_dma_addr == safe_dma_addr)
return b; break;
return NULL; read_unlock_irqrestore(&device_info->lock, flags);
return b;
} }
static inline void static inline void
free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf) free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *buf)
{ {
unsigned long flags;
dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf); dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
write_lock_irqsave(&device_info->lock, flags);
list_del(&buf->node); list_del(&buf->node);
write_unlock_irqrestore(&device_info->lock, flags);
if (buf->pool) if (buf->pool)
dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr); dma_pool_free(buf->pool->pool, buf->safe, buf->safe_dma_addr);
else else
...@@ -396,7 +413,6 @@ dma_addr_t ...@@ -396,7 +413,6 @@ dma_addr_t
dma_map_single(struct device *dev, void *ptr, size_t size, dma_map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
dma_addr_t dma_addr; dma_addr_t dma_addr;
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
...@@ -404,12 +420,8 @@ dma_map_single(struct device *dev, void *ptr, size_t size, ...@@ -404,12 +420,8 @@ dma_map_single(struct device *dev, void *ptr, size_t size,
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
dma_addr = map_single(dev, ptr, size, dir); dma_addr = map_single(dev, ptr, size, dir);
local_irq_restore(flags);
return dma_addr; return dma_addr;
} }
...@@ -424,25 +436,18 @@ void ...@@ -424,25 +436,18 @@ void
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir); __func__, (void *) dma_addr, size, dir);
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
unmap_single(dev, dma_addr, size, dir); unmap_single(dev, dma_addr, size, dir);
local_irq_restore(flags);
} }
int int
dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
int i; int i;
dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
...@@ -450,8 +455,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -450,8 +455,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
for (i = 0; i < nents; i++, sg++) { for (i = 0; i < nents; i++, sg++) {
struct page *page = sg->page; struct page *page = sg->page;
unsigned int offset = sg->offset; unsigned int offset = sg->offset;
...@@ -462,8 +465,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -462,8 +465,6 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
map_single(dev, ptr, length, dir); map_single(dev, ptr, length, dir);
} }
local_irq_restore(flags);
return nents; return nents;
} }
...@@ -471,7 +472,6 @@ void ...@@ -471,7 +472,6 @@ void
dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
int i; int i;
dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
...@@ -479,55 +479,38 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents, ...@@ -479,55 +479,38 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
for (i = 0; i < nents; i++, sg++) { for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address; dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length; unsigned int length = sg->length;
unmap_single(dev, dma_addr, length, dir); unmap_single(dev, dma_addr, length, dir);
} }
local_irq_restore(flags);
} }
void void
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size, dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir); __func__, (void *) dma_addr, size, dir);
local_irq_save(flags);
sync_single(dev, dma_addr, size, dir); sync_single(dev, dma_addr, size, dir);
local_irq_restore(flags);
} }
void void
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size, dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir); __func__, (void *) dma_addr, size, dir);
local_irq_save(flags);
sync_single(dev, dma_addr, size, dir); sync_single(dev, dma_addr, size, dir);
local_irq_restore(flags);
} }
void void
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
int i; int i;
dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
...@@ -535,23 +518,18 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents, ...@@ -535,23 +518,18 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
for (i = 0; i < nents; i++, sg++) { for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address; dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length; unsigned int length = sg->length;
sync_single(dev, dma_addr, length, dir); sync_single(dev, dma_addr, length, dir);
} }
local_irq_restore(flags);
} }
void void
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir) enum dma_data_direction dir)
{ {
unsigned long flags;
int i; int i;
dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n",
...@@ -559,16 +537,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents, ...@@ -559,16 +537,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
BUG_ON(dir == DMA_NONE); BUG_ON(dir == DMA_NONE);
local_irq_save(flags);
for (i = 0; i < nents; i++, sg++) { for (i = 0; i < nents; i++, sg++) {
dma_addr_t dma_addr = sg->dma_address; dma_addr_t dma_addr = sg->dma_address;
unsigned int length = sg->length; unsigned int length = sg->length;
sync_single(dev, dma_addr, length, dir); sync_single(dev, dma_addr, length, dir);
} }
local_irq_restore(flags);
} }
static int static int
...@@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, ...@@ -622,6 +596,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->dev = dev; device_info->dev = dev;
INIT_LIST_HEAD(&device_info->safe_buffers); INIT_LIST_HEAD(&device_info->safe_buffers);
rwlock_init(&device_info->lock);
#ifdef STATS #ifdef STATS
device_info->total_allocs = 0; device_info->total_allocs = 0;
......
...@@ -18,10 +18,26 @@ ...@@ -18,10 +18,26 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/arch/ixp2000-regs.h> #include <asm/arch/hardware.h>
#include <asm/hardware/uengine.h> #include <asm/hardware/uengine.h>
#include <asm/io.h> #include <asm/io.h>
#if defined(CONFIG_ARCH_IXP2000)
#define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE
#define IXP_PRODUCT_ID IXP2000_PRODUCT_ID
#define IXP_MISC_CONTROL IXP2000_MISC_CONTROL
#define IXP_RESET1 IXP2000_RESET1
#else
#if defined(CONFIG_ARCH_IXP23XX)
#define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE
#define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID
#define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL
#define IXP_RESET1 IXP23XX_RESET1
#else
#error unknown platform
#endif
#endif
#define USTORE_ADDRESS 0x000 #define USTORE_ADDRESS 0x000
#define USTORE_DATA_LOWER 0x004 #define USTORE_DATA_LOWER 0x004
#define USTORE_DATA_UPPER 0x008 #define USTORE_DATA_UPPER 0x008
...@@ -43,7 +59,7 @@ u32 ixp2000_uengine_mask; ...@@ -43,7 +59,7 @@ u32 ixp2000_uengine_mask;
static void *ixp2000_uengine_csr_area(int uengine) static void *ixp2000_uengine_csr_area(int uengine)
{ {
return ((void *)IXP2000_UENGINE_CSR_VIRT_BASE) + (uengine << 10); return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
} }
/* /*
...@@ -91,8 +107,13 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write); ...@@ -91,8 +107,13 @@ EXPORT_SYMBOL(ixp2000_uengine_csr_write);
void ixp2000_uengine_reset(u32 uengine_mask) void ixp2000_uengine_reset(u32 uengine_mask)
{ {
ixp2000_reg_wrb(IXP2000_RESET1, uengine_mask & ixp2000_uengine_mask); u32 value;
ixp2000_reg_wrb(IXP2000_RESET1, 0);
value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
uengine_mask &= ixp2000_uengine_mask;
ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
ixp2000_reg_wrb(IXP_RESET1, value);
} }
EXPORT_SYMBOL(ixp2000_uengine_reset); EXPORT_SYMBOL(ixp2000_uengine_reset);
...@@ -235,11 +256,12 @@ static int check_ixp_type(struct ixp2000_uengine_code *c) ...@@ -235,11 +256,12 @@ static int check_ixp_type(struct ixp2000_uengine_code *c)
u32 product_id; u32 product_id;
u32 rev; u32 rev;
product_id = ixp2000_reg_read(IXP2000_PRODUCT_ID); product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
if (((product_id >> 16) & 0x1f) != 0) if (((product_id >> 16) & 0x1f) != 0)
return 0; return 0;
switch ((product_id >> 8) & 0xff) { switch ((product_id >> 8) & 0xff) {
#ifdef CONFIG_ARCH_IXP2000
case 0: /* IXP2800 */ case 0: /* IXP2800 */
if (!(c->cpu_model_bitmask & 4)) if (!(c->cpu_model_bitmask & 4))
return 0; return 0;
...@@ -254,6 +276,14 @@ static int check_ixp_type(struct ixp2000_uengine_code *c) ...@@ -254,6 +276,14 @@ static int check_ixp_type(struct ixp2000_uengine_code *c)
if (!(c->cpu_model_bitmask & 2)) if (!(c->cpu_model_bitmask & 2))
return 0; return 0;
break; break;
#endif
#ifdef CONFIG_ARCH_IXP23XX
case 4: /* IXP23xx */
if (!(c->cpu_model_bitmask & 0x3f0))
return 0;
break;
#endif
default: default:
return 0; return 0;
...@@ -432,7 +462,8 @@ static int __init ixp2000_uengine_init(void) ...@@ -432,7 +462,8 @@ static int __init ixp2000_uengine_init(void)
/* /*
* Determine number of microengines present. * Determine number of microengines present.
*/ */
switch ((ixp2000_reg_read(IXP2000_PRODUCT_ID) >> 8) & 0x1fff) { switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
#ifdef CONFIG_ARCH_IXP2000
case 0: /* IXP2800 */ case 0: /* IXP2800 */
case 1: /* IXP2850 */ case 1: /* IXP2850 */
ixp2000_uengine_mask = 0x00ff00ff; ixp2000_uengine_mask = 0x00ff00ff;
...@@ -441,10 +472,17 @@ static int __init ixp2000_uengine_init(void) ...@@ -441,10 +472,17 @@ static int __init ixp2000_uengine_init(void)
case 2: /* IXP2400 */ case 2: /* IXP2400 */
ixp2000_uengine_mask = 0x000f000f; ixp2000_uengine_mask = 0x000f000f;
break; break;
#endif
#ifdef CONFIG_ARCH_IXP23XX
case 4: /* IXP23xx */
ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
break;
#endif
default: default:
printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n", printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
(unsigned int)ixp2000_reg_read(IXP2000_PRODUCT_ID)); (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
ixp2000_uengine_mask = 0x00000000; ixp2000_uengine_mask = 0x00000000;
break; break;
} }
...@@ -457,15 +495,15 @@ static int __init ixp2000_uengine_init(void) ...@@ -457,15 +495,15 @@ static int __init ixp2000_uengine_init(void)
/* /*
* Synchronise timestamp counters across all microengines. * Synchronise timestamp counters across all microengines.
*/ */
value = ixp2000_reg_read(IXP2000_MISC_CONTROL); value = ixp2000_reg_read(IXP_MISC_CONTROL);
ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value & ~0x80); ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
for (uengine = 0; uengine < 32; uengine++) { for (uengine = 0; uengine < 32; uengine++) {
if (ixp2000_uengine_mask & (1 << uengine)) { if (ixp2000_uengine_mask & (1 << uengine)) {
ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0); ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0); ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
} }
} }
ixp2000_reg_wrb(IXP2000_MISC_CONTROL, value | 0x80); ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <asm/glue.h> #include <asm/glue.h>
#include <asm/vfpmacros.h> #include <asm/vfpmacros.h>
#include <asm/arch/entry-macro.S> #include <asm/arch/entry-macro.S>
#include <asm/thread_notify.h>
#include "entry-header.S" #include "entry-header.S"
...@@ -560,10 +561,8 @@ ENTRY(__switch_to) ...@@ -560,10 +561,8 @@ ENTRY(__switch_to)
add ip, r1, #TI_CPU_SAVE add ip, r1, #TI_CPU_SAVE
ldr r3, [r2, #TI_TP_VALUE] ldr r3, [r2, #TI_TP_VALUE]
stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
#ifndef CONFIG_MMU #ifdef CONFIG_MMU
add r2, r2, #TI_CPU_DOMAIN ldr r6, [r2, #TI_CPU_DOMAIN]
#else
ldr r6, [r2, #TI_CPU_DOMAIN]!
#endif #endif
#if __LINUX_ARM_ARCH__ >= 6 #if __LINUX_ARM_ARCH__ >= 6
#ifdef CONFIG_CPU_32v6K #ifdef CONFIG_CPU_32v6K
...@@ -585,21 +584,20 @@ ENTRY(__switch_to) ...@@ -585,21 +584,20 @@ ENTRY(__switch_to)
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
mcr p15, 0, r6, c3, c0, 0 @ Set domain register mcr p15, 0, r6, c3, c0, 0 @ Set domain register
#endif #endif
#ifdef CONFIG_VFP
@ Always disable VFP so we can lazily save/restore the old
@ state. This occurs in the context of the previous thread.
VFPFMRX r4, FPEXC
bic r4, r4, #FPEXC_ENABLE
VFPFMXR FPEXC, r4
#endif
#if defined(CONFIG_IWMMXT) #if defined(CONFIG_IWMMXT)
bl iwmmxt_task_switch bl iwmmxt_task_switch
#elif defined(CONFIG_CPU_XSCALE) #elif defined(CONFIG_CPU_XSCALE)
add r4, r2, #40 @ cpu_context_save->extra add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra
ldmib r4, {r4, r5} ldmib r4, {r4, r5}
mar acc0, r4, r5 mar acc0, r4, r5
#endif #endif
ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously mov r5, r0
add r4, r2, #TI_CPU_SAVE
ldr r0, =thread_notify_head
mov r1, #THREAD_NOTIFY_SWITCH
bl atomic_notifier_call_chain
mov r0, r5
ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
__INIT __INIT
......
...@@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch) ...@@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch)
bne 1f @ yes: block them for next task bne 1f @ yes: block them for next task
ldr r5, =concan_owner ldr r5, =concan_owner
add r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area
ldr r5, [r5] @ get current Concan owner ldr r5, [r5] @ get current Concan owner
teq r5, r6 @ next task owns it? teq r5, r6 @ next task owns it?
movne pc, lr @ no: leave Concan disabled movne pc, lr @ no: leave Concan disabled
......
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <asm/leds.h> #include <asm/leds.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/thread_notify.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/mach/time.h> #include <asm/mach/time.h>
...@@ -338,13 +339,9 @@ void exit_thread(void) ...@@ -338,13 +339,9 @@ void exit_thread(void)
{ {
} }
static void default_fp_init(union fp_state *fp) ATOMIC_NOTIFIER_HEAD(thread_notify_head);
{
memset(fp, 0, sizeof(union fp_state));
}
void (*fp_init)(union fp_state *) = default_fp_init; EXPORT_SYMBOL_GPL(thread_notify_head);
EXPORT_SYMBOL(fp_init);
void flush_thread(void) void flush_thread(void)
{ {
...@@ -353,22 +350,21 @@ void flush_thread(void) ...@@ -353,22 +350,21 @@ void flush_thread(void)
memset(thread->used_cp, 0, sizeof(thread->used_cp)); memset(thread->used_cp, 0, sizeof(thread->used_cp));
memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
memset(&thread->fpstate, 0, sizeof(union fp_state));
thread_notify(THREAD_NOTIFY_FLUSH, thread);
#if defined(CONFIG_IWMMXT) #if defined(CONFIG_IWMMXT)
iwmmxt_task_release(thread); iwmmxt_task_release(thread);
#endif
fp_init(&thread->fpstate);
#if defined(CONFIG_VFP)
vfp_flush_thread(&thread->vfpstate);
#endif #endif
} }
void release_thread(struct task_struct *dead_task) void release_thread(struct task_struct *dead_task)
{ {
#if defined(CONFIG_VFP) struct thread_info *thread = task_thread_info(dead_task);
vfp_release_thread(&task_thread_info(dead_task)->vfpstate);
#endif thread_notify(THREAD_NOTIFY_RELEASE, thread);
#if defined(CONFIG_IWMMXT) #if defined(CONFIG_IWMMXT)
iwmmxt_task_release(task_thread_info(dead_task)); iwmmxt_task_release(thread);
#endif #endif
} }
......
...@@ -665,17 +665,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) ...@@ -665,17 +665,33 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (syscall) { if (syscall) {
if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) { if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
if (thumb_mode(regs)) { if (thumb_mode(regs)) {
regs->ARM_r7 = __NR_restart_syscall; regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
regs->ARM_pc -= 2; regs->ARM_pc -= 2;
} else { } else {
#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)
regs->ARM_r7 = __NR_restart_syscall;
regs->ARM_pc -= 4;
#else
u32 __user *usp; u32 __user *usp;
u32 swival = __NR_restart_syscall;
regs->ARM_sp -= 12; regs->ARM_sp -= 12;
usp = (u32 __user *)regs->ARM_sp; usp = (u32 __user *)regs->ARM_sp;
/*
* Either we supports OABI only, or we have
* EABI with the OABI compat layer enabled.
* In the later case we don't know if user
* space is EABI or not, and if not we must
* not clobber r7. Always using the OABI
* syscall solves that issue and works for
* all those cases.
*/
swival = swival - __NR_SYSCAll_BASE + __NR_OABI_SYSCALL_BASE;
put_user(regs->ARM_pc, &usp[0]); put_user(regs->ARM_pc, &usp[0]);
/* swi __NR_restart_syscall */ /* swi __NR_restart_syscall */
put_user(0xef000000 | __NR_restart_syscall, &usp[1]); put_user(0xef000000 | swival, &usp[1]);
/* ldr pc, [sp], #12 */ /* ldr pc, [sp], #12 */
put_user(0xe49df00c, &usp[2]); put_user(0xe49df00c, &usp[2]);
...@@ -683,6 +699,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall) ...@@ -683,6 +699,7 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
(unsigned long)(usp + 3)); (unsigned long)(usp + 3));
regs->ARM_pc = regs->ARM_sp + 4; regs->ARM_pc = regs->ARM_sp + 4;
#endif
} }
} }
if (regs->ARM_r0 == -ERESTARTNOHAND || if (regs->ARM_r0 == -ERESTARTNOHAND ||
......
...@@ -103,7 +103,8 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -103,7 +103,8 @@ static int ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
write_seqlock(&xtime_lock); write_seqlock(&xtime_lock);
__raw_writel(1, EP93XX_TIMER1_CLEAR); __raw_writel(1, EP93XX_TIMER1_CLEAR);
while (__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time while ((signed long)
(__raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time)
>= TIMER4_TICKS_PER_JIFFY) { >= TIMER4_TICKS_PER_JIFFY) {
last_jiffy_time += TIMER4_TICKS_PER_JIFFY; last_jiffy_time += TIMER4_TICKS_PER_JIFFY;
timer_tick(regs); timer_tick(regs);
...@@ -124,7 +125,7 @@ static void __init ep93xx_timer_init(void) ...@@ -124,7 +125,7 @@ static void __init ep93xx_timer_init(void)
{ {
/* Enable periodic HZ timer. */ /* Enable periodic HZ timer. */
__raw_writel(0x48, EP93XX_TIMER1_CONTROL); __raw_writel(0x48, EP93XX_TIMER1_CONTROL);
__raw_writel((508000 / HZ) - 1, EP93XX_TIMER1_LOAD); __raw_writel((508469 / HZ) - 1, EP93XX_TIMER1_LOAD);
__raw_writel(0xc8, EP93XX_TIMER1_CONTROL); __raw_writel(0xc8, EP93XX_TIMER1_CONTROL);
/* Enable lost jiffy timer. */ /* Enable lost jiffy timer. */
......
...@@ -16,16 +16,38 @@ ...@@ -16,16 +16,38 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
#include <asm/io.h> #include <asm/io.h>
#include <asm/hardware.h> #include <asm/hardware.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
static struct physmap_flash_data gesbc9312_flash_data = {
.width = 4,
};
static struct resource gesbc9312_flash_resource = {
.start = 0x60000000,
.end = 0x60800000,
.flags = IORESOURCE_MEM,
};
static struct platform_device gesbc9312_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &gesbc9312_flash_data,
},
.num_resources = 1,
.resource = &gesbc9312_flash_resource,
};
static void __init gesbc9312_init_machine(void) static void __init gesbc9312_init_machine(void)
{ {
ep93xx_init_devices(); ep93xx_init_devices();
physmap_configure(0x60000000, 0x00800000, 4, NULL); platform_device_register(&gesbc9312_flash);
} }
MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx") MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/mtd/physmap.h> #include <linux/mtd/physmap.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/m48t86.h> #include <linux/m48t86.h>
...@@ -111,6 +112,26 @@ static void __init ts72xx_map_io(void) ...@@ -111,6 +112,26 @@ static void __init ts72xx_map_io(void)
} }
} }
static struct physmap_flash_data ts72xx_flash_data = {
.width = 1,
};
static struct resource ts72xx_flash_resource = {
.start = TS72XX_NOR_PHYS_BASE,
.end = TS72XX_NOR_PHYS_BASE + 0x01000000,
.flags = IORESOURCE_MEM,
};
static struct platform_device ts72xx_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &ts72xx_flash_data,
},
.num_resources = 1,
.resource = &ts72xx_flash_resource,
};
static unsigned char ts72xx_rtc_readbyte(unsigned long addr) static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
{ {
__raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE); __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
...@@ -141,7 +162,7 @@ static void __init ts72xx_init_machine(void) ...@@ -141,7 +162,7 @@ static void __init ts72xx_init_machine(void)
{ {
ep93xx_init_devices(); ep93xx_init_devices();
if (board_is_ts7200()) if (board_is_ts7200())
physmap_configure(TS72XX_NOR_PHYS_BASE, 0x01000000, 1, NULL); platform_device_register(&ts72xx_flash);
platform_device_register(&ts72xx_rtc_device); platform_device_register(&ts72xx_rtc_device);
} }
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
* Changed to support scatter gather DMA * Changed to support scatter gather DMA
* by taking Russell's code from RiscPC * by taking Russell's code from RiscPC
* *
* 2006-05-31 Pavel Pisa <pisa@cmp.felk.cvut.cz>
* Corrected error handling code.
*
*/ */
#undef DEBUG #undef DEBUG
...@@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch, ...@@ -277,7 +280,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
int int
imx_dma_setup_handlers(imx_dmach_t dma_ch, imx_dma_setup_handlers(imx_dmach_t dma_ch,
void (*irq_handler) (int, void *, struct pt_regs *), void (*irq_handler) (int, void *, struct pt_regs *),
void (*err_handler) (int, void *, struct pt_regs *), void (*err_handler) (int, void *, struct pt_regs *, int),
void *data) void *data)
{ {
struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch]; struct imx_dma_channel *imxdma = &imx_dma_channels[dma_ch];
...@@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs) ...@@ -463,43 +466,53 @@ static irqreturn_t dma_err_handler(int irq, void *dev_id, struct pt_regs *regs)
int i, disr = DISR; int i, disr = DISR;
struct imx_dma_channel *channel; struct imx_dma_channel *channel;
unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR; unsigned int err_mask = DBTOSR | DRTOSR | DSESR | DBOSR;
int errcode;
DISR = disr; DISR = disr & err_mask;
for (i = 0; i < IMX_DMA_CHANNELS; i++) { for (i = 0; i < IMX_DMA_CHANNELS; i++) {
channel = &imx_dma_channels[i]; if(!(err_mask & (1 << i)))
if ((err_mask & 1 << i) && channel->name
&& channel->err_handler) {
channel->err_handler(i, channel->data, regs);
continue; continue;
} channel = &imx_dma_channels[i];
errcode = 0;
imx_dma_channels[i].sg = NULL;
if (DBTOSR & (1 << i)) { if (DBTOSR & (1 << i)) {
printk(KERN_WARNING DBTOSR = (1 << i);
"Burst timeout on channel %d (%s)\n", errcode |= IMX_DMA_ERR_BURST;
i, channel->name);
DBTOSR |= (1 << i);
} }
if (DRTOSR & (1 << i)) { if (DRTOSR & (1 << i)) {
printk(KERN_WARNING DRTOSR = (1 << i);
"Request timeout on channel %d (%s)\n", errcode |= IMX_DMA_ERR_REQUEST;
i, channel->name);
DRTOSR |= (1 << i);
} }
if (DSESR & (1 << i)) { if (DSESR & (1 << i)) {
printk(KERN_WARNING DSESR = (1 << i);
"Transfer timeout on channel %d (%s)\n", errcode |= IMX_DMA_ERR_TRANSFER;
i, channel->name);
DSESR |= (1 << i);
} }
if (DBOSR & (1 << i)) { if (DBOSR & (1 << i)) {
printk(KERN_WARNING DBOSR = (1 << i);
"Buffer overflow timeout on channel %d (%s)\n", errcode |= IMX_DMA_ERR_BUFFER;
i, channel->name);
DBOSR |= (1 << i);
} }
/*
* The cleaning of @sg field would be questionable
* there, because its value can help to compute
* remaining/transfered bytes count in the handler
*/
/*imx_dma_channels[i].sg = NULL;*/
if (channel->name && channel->err_handler) {
channel->err_handler(i, channel->data, regs, errcode);
continue;
}
imx_dma_channels[i].sg = NULL;
printk(KERN_WARNING
"DMA timeout on channel %d (%s) -%s%s%s%s\n",
i, channel->name,
errcode&IMX_DMA_ERR_BURST? " burst":"",
errcode&IMX_DMA_ERR_REQUEST? " request":"",
errcode&IMX_DMA_ERR_TRANSFER? " transfer":"",
errcode&IMX_DMA_ERR_BUFFER? " buffer":"");
} }
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -211,7 +211,8 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -211,7 +211,8 @@ static int ixp2000_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* clear timer 1 */ /* clear timer 1 */
ixp2000_reg_wrb(IXP2000_T1_CLR, 1); ixp2000_reg_wrb(IXP2000_T1_CLR, 1);
while ((next_jiffy_time - *missing_jiffy_timer_csr) > ticks_per_jiffy) { while ((signed long)(next_jiffy_time - *missing_jiffy_timer_csr)
>= ticks_per_jiffy) {
timer_tick(regs); timer_tick(regs);
next_jiffy_time -= ticks_per_jiffy; next_jiffy_time -= ticks_per_jiffy;
} }
......
...@@ -334,7 +334,7 @@ void __init ixp23xx_init_irq(void) ...@@ -334,7 +334,7 @@ void __init ixp23xx_init_irq(void)
/************************************************************************* /*************************************************************************
* Timer-tick functions for IXP23xx * Timer-tick functions for IXP23xx
*************************************************************************/ *************************************************************************/
#define CLOCK_TICKS_PER_USEC CLOCK_TICK_RATE / (USEC_PER_SEC) #define CLOCK_TICKS_PER_USEC (CLOCK_TICK_RATE / USEC_PER_SEC)
static unsigned long next_jiffy_time; static unsigned long next_jiffy_time;
...@@ -353,7 +353,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -353,7 +353,7 @@ ixp23xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{ {
/* Clear Pending Interrupt by writing '1' to it */ /* Clear Pending Interrupt by writing '1' to it */
*IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND; *IXP23XX_TIMER_STATUS = IXP23XX_TIMER1_INT_PEND;
while ((*IXP23XX_TIMER_CONT - next_jiffy_time) > LATCH) { while ((signed long)(*IXP23XX_TIMER_CONT - next_jiffy_time) >= LATCH) {
timer_tick(regs); timer_tick(regs);
next_jiffy_time += LATCH; next_jiffy_time += LATCH;
} }
...@@ -439,5 +439,6 @@ static struct platform_device *ixp23xx_devices[] __initdata = { ...@@ -439,5 +439,6 @@ static struct platform_device *ixp23xx_devices[] __initdata = {
void __init ixp23xx_sys_init(void) void __init ixp23xx_sys_init(void)
{ {
*IXP23XX_EXP_UNIT_FUSE |= 0xf;
platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices)); platform_add_devices(ixp23xx_devices, ARRAY_SIZE(ixp23xx_devices));
} }
...@@ -53,9 +53,29 @@ static int __init espresso_pci_init(void) ...@@ -53,9 +53,29 @@ static int __init espresso_pci_init(void)
}; };
subsys_initcall(espresso_pci_init); subsys_initcall(espresso_pci_init);
static struct physmap_flash_data espresso_flash_data = {
.width = 2,
};
static struct resource espresso_flash_resource = {
.start = 0x90000000,
.end = 0x92000000,
.flags = IORESOURCE_MEM,
};
static struct platform_device espresso_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &espresso_flash_data,
},
.num_resources = 1,
.resource = &espresso_flash_resource,
};
static void __init espresso_init(void) static void __init espresso_init(void)
{ {
physmap_configure(0x90000000, 0x02000000, 2, NULL); platform_device_register(&espresso_flash);
/* /*
* Mark flash as writeable. * Mark flash as writeable.
......
...@@ -298,9 +298,29 @@ static void __init ixdp2351_map_io(void) ...@@ -298,9 +298,29 @@ static void __init ixdp2351_map_io(void)
iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc)); iotable_init(ixdp2351_io_desc, ARRAY_SIZE(ixdp2351_io_desc));
} }
static struct physmap_flash_data ixdp2351_flash_data = {
.width = 1,
};
static struct resource ixdp2351_flash_resource = {
.start = 0x90000000,
.end = 0x94000000,
.flags = IORESOURCE_MEM,
};
static struct platform_device ixdp2351_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &ixdp2351_flash_data,
},
.num_resources = 1,
.resource = &ixdp2351_flash_resource,
};
static void __init ixdp2351_init(void) static void __init ixdp2351_init(void)
{ {
physmap_configure(0x90000000, 0x04000000, 1, NULL); platform_device_register(&ixdp2351_flash);
/* /*
* Mark flash as writeable * Mark flash as writeable
......
...@@ -137,9 +137,29 @@ static int __init roadrunner_pci_init(void) ...@@ -137,9 +137,29 @@ static int __init roadrunner_pci_init(void)
subsys_initcall(roadrunner_pci_init); subsys_initcall(roadrunner_pci_init);
static struct physmap_flash_data roadrunner_flash_data = {
.width = 2,
};
static struct resource roadrunner_flash_resource = {
.start = 0x90000000,
.end = 0x94000000,
.flags = IORESOURCE_MEM,
};
static struct platform_device roadrunner_flash = {
.name = "physmap-flash",
.id = 0,
.dev = {
.platform_data = &roadrunner_flash_data,
},
.num_resources = 1,
.resource = &roadrunner_flash_resource,
};
static void __init roadrunner_init(void) static void __init roadrunner_init(void)
{ {
physmap_configure(0x90000000, 0x04000000, 2, NULL); platform_device_register(&roadrunner_flash);
/* /*
* Mark flash as writeable * Mark flash as writeable
......
...@@ -276,7 +276,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs ...@@ -276,7 +276,7 @@ static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id, struct pt_regs
/* /*
* Catch up with the real idea of time * Catch up with the real idea of time
*/ */
while ((*IXP4XX_OSTS - last_jiffy_time) > LATCH) { while ((signed long)(*IXP4XX_OSTS - last_jiffy_time) >= LATCH) {
timer_tick(regs); timer_tick(regs);
last_jiffy_time += LATCH; last_jiffy_time += LATCH;
} }
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/leds.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -37,6 +38,36 @@ static struct platform_device nas100d_flash = { ...@@ -37,6 +38,36 @@ static struct platform_device nas100d_flash = {
.resource = &nas100d_flash_resource, .resource = &nas100d_flash_resource,
}; };
#ifdef CONFIG_LEDS_IXP4XX
static struct resource nas100d_led_resources[] = {
{
.name = "wlan", /* green led */
.start = 0,
.end = 0,
.flags = IXP4XX_GPIO_LOW,
},
{
.name = "ready", /* blue power led (off is flashing!) */
.start = 15,
.end = 15,
.flags = IXP4XX_GPIO_LOW,
},
{
.name = "disk", /* yellow led */
.start = 3,
.end = 3,
.flags = IXP4XX_GPIO_LOW,
},
};
static struct platform_device nas100d_leds = {
.name = "IXP4XX-GPIO-LED",
.id = -1,
.num_resources = ARRAY_SIZE(nas100d_led_resources),
.resource = nas100d_led_resources,
};
#endif
static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = { static struct ixp4xx_i2c_pins nas100d_i2c_gpio_pins = {
.sda_pin = NAS100D_SDA_PIN, .sda_pin = NAS100D_SDA_PIN,
.scl_pin = NAS100D_SCL_PIN, .scl_pin = NAS100D_SCL_PIN,
...@@ -95,7 +126,9 @@ static struct platform_device nas100d_uart = { ...@@ -95,7 +126,9 @@ static struct platform_device nas100d_uart = {
static struct platform_device *nas100d_devices[] __initdata = { static struct platform_device *nas100d_devices[] __initdata = {
&nas100d_i2c_controller, &nas100d_i2c_controller,
&nas100d_flash, &nas100d_flash,
&nas100d_uart, #ifdef CONFIG_LEDS_IXP4XX
&nas100d_leds,
#endif
}; };
static void nas100d_power_off(void) static void nas100d_power_off(void)
...@@ -122,6 +155,12 @@ static void __init nas100d_init(void) ...@@ -122,6 +155,12 @@ static void __init nas100d_init(void)
pm_power_off = nas100d_power_off; pm_power_off = nas100d_power_off;
/* This is only useful on a modified machine, but it is valuable
* to have it first in order to see debug messages, and so that
* it does *not* get removed if platform_add_devices fails!
*/
(void)platform_device_register(&nas100d_uart);
platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices)); platform_add_devices(nas100d_devices, ARRAY_SIZE(nas100d_devices));
} }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Copyright (C) 2003-2004 MontaVista Software, Inc. * Copyright (C) 2003-2004 MontaVista Software, Inc.
* *
* Author: Mark Rakes <mrakes at mac.com> * Author: Mark Rakes <mrakes at mac.com>
* Author: Rod Whitby <rod@whitby.id.au>
* Maintainers: http://www.nslu2-linux.org/ * Maintainers: http://www.nslu2-linux.org/
* *
* Fixed missing init_time in MACHINE_START kas11 10/22/04 * Fixed missing init_time in MACHINE_START kas11 10/22/04
...@@ -16,6 +17,7 @@ ...@@ -16,6 +17,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/serial_8250.h> #include <linux/serial_8250.h>
#include <linux/leds.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -43,6 +45,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = { ...@@ -43,6 +45,42 @@ static struct ixp4xx_i2c_pins nslu2_i2c_gpio_pins = {
.scl_pin = NSLU2_SCL_PIN, .scl_pin = NSLU2_SCL_PIN,
}; };
#ifdef CONFIG_LEDS_IXP4XX
static struct resource nslu2_led_resources[] = {
{
.name = "ready", /* green led */
.start = NSLU2_LED_GRN,
.end = NSLU2_LED_GRN,
.flags = IXP4XX_GPIO_HIGH,
},
{
.name = "status", /* red led */
.start = NSLU2_LED_RED,
.end = NSLU2_LED_RED,
.flags = IXP4XX_GPIO_HIGH,
},
{
.name = "disk-1",
.start = NSLU2_LED_DISK1,
.end = NSLU2_LED_DISK1,
.flags = IXP4XX_GPIO_LOW,
},
{
.name = "disk-2",
.start = NSLU2_LED_DISK2,
.end = NSLU2_LED_DISK2,
.flags = IXP4XX_GPIO_LOW,
},
};
static struct platform_device nslu2_leds = {
.name = "IXP4XX-GPIO-LED",
.id = -1,
.num_resources = ARRAY_SIZE(nslu2_led_resources),
.resource = nslu2_led_resources,
};
#endif
static struct platform_device nslu2_i2c_controller = { static struct platform_device nslu2_i2c_controller = {
.name = "IXP4XX-I2C", .name = "IXP4XX-I2C",
.id = 0, .id = 0,
...@@ -102,8 +140,10 @@ static struct platform_device nslu2_uart = { ...@@ -102,8 +140,10 @@ static struct platform_device nslu2_uart = {
static struct platform_device *nslu2_devices[] __initdata = { static struct platform_device *nslu2_devices[] __initdata = {
&nslu2_i2c_controller, &nslu2_i2c_controller,
&nslu2_flash, &nslu2_flash,
&nslu2_uart,
&nslu2_beeper, &nslu2_beeper,
#ifdef CONFIG_LEDS_IXP4XX
&nslu2_leds,
#endif
}; };
static void nslu2_power_off(void) static void nslu2_power_off(void)
...@@ -127,6 +167,12 @@ static void __init nslu2_init(void) ...@@ -127,6 +167,12 @@ static void __init nslu2_init(void)
pm_power_off = nslu2_power_off; pm_power_off = nslu2_power_off;
/* This is only useful on a modified machine, but it is valuable
* to have it first in order to see debug messages, and so that
* it does *not* get removed if platform_add_devices fails!
*/
(void)platform_device_register(&nslu2_uart);
platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices)); platform_add_devices(nslu2_devices, ARRAY_SIZE(nslu2_devices));
} }
......
...@@ -767,6 +767,54 @@ static struct clk *onchip_clks[] = { ...@@ -767,6 +767,54 @@ static struct clk *onchip_clks[] = {
&uart6_ck, &uart6_ck,
}; };
static int local_clk_enable(struct clk *clk)
{
int ret = 0;
if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
&& clk->user_rate)
ret = clk->set_rate(clk, clk->user_rate);
return ret;
}
static void local_clk_disable(struct clk *clk)
{
if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
clk->set_rate(clk, 0);
}
static void local_clk_unuse(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
local_clk_disable(clk);
if (clk->parent)
local_clk_unuse(clk->parent);
}
}
static int local_clk_use(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (clk->parent)
ret = local_clk_use(clk->parent);
if (ret != 0) {
clk->usecount--;
goto out;
}
ret = local_clk_enable(clk);
if (ret != 0 && clk->parent) {
local_clk_unuse(clk->parent);
clk->usecount--;
}
}
out:
return ret;
}
static int local_set_rate(struct clk *clk, u32 rate) static int local_set_rate(struct clk *clk, u32 rate)
{ {
int ret = -EINVAL; int ret = -EINVAL;
...@@ -847,28 +895,12 @@ unsigned long clk_get_rate(struct clk *clk) ...@@ -847,28 +895,12 @@ unsigned long clk_get_rate(struct clk *clk)
} }
EXPORT_SYMBOL(clk_get_rate); EXPORT_SYMBOL(clk_get_rate);
static int local_clk_enable(struct clk *clk)
{
int ret = 0;
if (!(clk->flags & FIXED_RATE) && !clk->rate && clk->set_rate
&& clk->user_rate)
ret = clk->set_rate(clk, clk->user_rate);
return ret;
}
static void local_clk_disable(struct clk *clk)
{
if (!(clk->flags & FIXED_RATE) && clk->rate && clk->set_rate)
clk->set_rate(clk, 0);
}
int clk_enable(struct clk *clk) int clk_enable(struct clk *clk)
{ {
int ret = 0; int ret = 0;
clock_lock(); clock_lock();
ret = local_clk_enable(clk); ret = local_clk_use(clk);
clock_unlock(); clock_unlock();
return ret; return ret;
} }
...@@ -877,71 +909,12 @@ EXPORT_SYMBOL(clk_enable); ...@@ -877,71 +909,12 @@ EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk) void clk_disable(struct clk *clk)
{ {
clock_lock();
local_clk_disable(clk);
clock_unlock();
}
EXPORT_SYMBOL(clk_disable);
static void local_clk_unuse(struct clk *clk)
{
if (clk->usecount > 0 && !(--clk->usecount)) {
local_clk_disable(clk);
if (clk->parent)
local_clk_unuse(clk->parent);
}
}
static int local_clk_use(struct clk *clk)
{
int ret = 0;
if (clk->usecount++ == 0) {
if (clk->parent)
ret = local_clk_use(clk->parent);
if (ret != 0) {
clk->usecount--;
goto out;
}
ret = local_clk_enable(clk);
if (ret != 0 && clk->parent) {
local_clk_unuse(clk->parent);
clk->usecount--;
}
}
out:
return ret;
}
/* The main purpose of clk_use ans clk_unuse functions
* is to control switching 13MHz oscillator and PLL1 (13'MHz),
* so that they are disabled whenever none of PLL2-5 is using them.
* Although in theory these functions should work with any clock,
* please use them only on PLL2 - PLL5 to avoid confusion.
*/
int clk_use(struct clk *clk)
{
int ret = 0;
clock_lock();
ret = local_clk_use(clk);
clock_unlock();
return ret;
}
EXPORT_SYMBOL(clk_use);
void clk_unuse(struct clk *clk)
{
clock_lock(); clock_lock();
local_clk_unuse(clk); local_clk_unuse(clk);
clock_unlock(); clock_unlock();
} }
EXPORT_SYMBOL(clk_unuse); EXPORT_SYMBOL(clk_disable);
long clk_round_rate(struct clk *clk, unsigned long rate) long clk_round_rate(struct clk *clk, unsigned long rate)
{ {
...@@ -995,7 +968,7 @@ static int __init clk_init(void) ...@@ -995,7 +968,7 @@ static int __init clk_init(void)
__FUNCTION__, (*clkp)->name, (*clkp)->rate); __FUNCTION__, (*clkp)->name, (*clkp)->rate);
} }
clk_use(&ck_pll4); local_clk_use(&ck_pll4);
/* if ck_13MHz is not used, disable it. */ /* if ck_13MHz is not used, disable it. */
if (ck_13MHz.usecount == 0) if (ck_13MHz.usecount == 0)
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial_reg.h> #include <linux/serial_reg.h>
#include <asm/arch/pm.h> #include <asm/arch/gpio.h>
#include <asm/arch/clock.h> #include <asm/arch/clock.h>
......
...@@ -114,9 +114,15 @@ config MACH_NEXCODER_2440 ...@@ -114,9 +114,15 @@ config MACH_NEXCODER_2440
endmenu endmenu
config S3C2410_CLOCK
bool
help
Clock code for the S3C2410, and similar processors
config CPU_S3C2410 config CPU_S3C2410
bool bool
depends on ARCH_S3C2410 depends on ARCH_S3C2410
select S3C2410_CLOCK
help help
Support for S3C2410 and S3C2410A family from the S3C24XX line Support for S3C2410 and S3C2410A family from the S3C24XX line
of Samsung Mobile CPUs. of Samsung Mobile CPUs.
...@@ -130,6 +136,7 @@ config CPU_S3C244X ...@@ -130,6 +136,7 @@ config CPU_S3C244X
config CPU_S3C2440 config CPU_S3C2440
bool bool
depends on ARCH_S3C2410 depends on ARCH_S3C2410
select S3C2410_CLOCK
select CPU_S3C244X select CPU_S3C244X
help help
Support for S3C2440 Samsung Mobile CPU based systems. Support for S3C2440 Samsung Mobile CPU based systems.
...@@ -137,6 +144,7 @@ config CPU_S3C2440 ...@@ -137,6 +144,7 @@ config CPU_S3C2440
config CPU_S3C2442 config CPU_S3C2442
bool bool
depends on ARCH_S3C2420 depends on ARCH_S3C2420
select S3C2410_CLOCK
select CPU_S3C244X select CPU_S3C244X
help help
Support for S3C2442 Samsung Mobile CPU based systems. Support for S3C2442 Samsung Mobile CPU based systems.
......
...@@ -29,6 +29,10 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o ...@@ -29,6 +29,10 @@ obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
obj-$(CONFIG_CPU_S3C244X) += s3c244x.o obj-$(CONFIG_CPU_S3C244X) += s3c244x.o
obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o obj-$(CONFIG_CPU_S3C244X) += s3c244x-irq.o
# Clock control
obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
# S3C2440 support # S3C2440 support
obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o obj-$(CONFIG_CPU_S3C2440) += s3c2440.o s3c2440-dsc.o
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Copyright (c) 2004-2005 Simtec Electronics * Copyright (c) 2004-2005 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk> * Ben Dooks <ben@simtec.co.uk>
* *
* S3C2410 Clock control support * S3C24XX Core clock control support
* *
* Based on, and code from linux/arch/arm/mach-versatile/clock.c * Based on, and code from linux/arch/arm/mach-versatile/clock.c
** **
...@@ -56,25 +56,6 @@ static LIST_HEAD(clocks); ...@@ -56,25 +56,6 @@ static LIST_HEAD(clocks);
DEFINE_MUTEX(clocks_mutex); DEFINE_MUTEX(clocks_mutex);
/* old functions */
void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
{
unsigned long clkcon;
clkcon = __raw_readl(S3C2410_CLKCON);
if (enable)
clkcon |= clocks;
else
clkcon &= ~clocks;
/* ensure none of the special function bits set */
clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER | 3);
__raw_writel(clkcon, S3C2410_CLKCON);
}
/* enable and disable calls for use with the clk struct */ /* enable and disable calls for use with the clk struct */
static int clk_null_enable(struct clk *clk, int enable) static int clk_null_enable(struct clk *clk, int enable)
...@@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *clk, int enable) ...@@ -82,12 +63,6 @@ static int clk_null_enable(struct clk *clk, int enable)
return 0; return 0;
} }
int s3c24xx_clkcon_enable(struct clk *clk, int enable)
{
s3c24xx_clk_enable(clk->ctrlbit, enable);
return 0;
}
/* Clock API calls */ /* Clock API calls */
struct clk *clk_get(struct device *dev, const char *id) struct clk *clk_get(struct device *dev, const char *id)
...@@ -173,8 +148,11 @@ unsigned long clk_get_rate(struct clk *clk) ...@@ -173,8 +148,11 @@ unsigned long clk_get_rate(struct clk *clk)
if (clk->rate != 0) if (clk->rate != 0)
return clk->rate; return clk->rate;
while (clk->parent != NULL && clk->rate == 0) if (clk->get_rate != NULL)
clk = clk->parent; return (clk->get_rate)(clk);
if (clk->parent != NULL)
return clk_get_rate(clk->parent);
return clk->rate; return clk->rate;
} }
...@@ -233,28 +211,6 @@ EXPORT_SYMBOL(clk_set_rate); ...@@ -233,28 +211,6 @@ EXPORT_SYMBOL(clk_set_rate);
EXPORT_SYMBOL(clk_get_parent); EXPORT_SYMBOL(clk_get_parent);
EXPORT_SYMBOL(clk_set_parent); EXPORT_SYMBOL(clk_set_parent);
/* base clock enable */
static int s3c24xx_upll_enable(struct clk *clk, int enable)
{
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
unsigned long orig = clkslow;
if (enable)
clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
else
clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
__raw_writel(clkslow, S3C2410_CLKSLOW);
/* if we started the UPLL, then allow to settle */
if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
udelay(200);
return 0;
}
/* base clocks */ /* base clocks */
static struct clk clk_xtal = { static struct clk clk_xtal = {
...@@ -265,15 +221,14 @@ static struct clk clk_xtal = { ...@@ -265,15 +221,14 @@ static struct clk clk_xtal = {
.ctrlbit = 0, .ctrlbit = 0,
}; };
static struct clk clk_upll = { struct clk clk_upll = {
.name = "upll", .name = "upll",
.id = -1, .id = -1,
.parent = NULL, .parent = NULL,
.enable = s3c24xx_upll_enable,
.ctrlbit = 0, .ctrlbit = 0,
}; };
static struct clk clk_f = { struct clk clk_f = {
.name = "fclk", .name = "fclk",
.id = -1, .id = -1,
.rate = 0, .rate = 0,
...@@ -281,7 +236,7 @@ static struct clk clk_f = { ...@@ -281,7 +236,7 @@ static struct clk clk_f = {
.ctrlbit = 0, .ctrlbit = 0,
}; };
static struct clk clk_h = { struct clk clk_h = {
.name = "hclk", .name = "hclk",
.id = -1, .id = -1,
.rate = 0, .rate = 0,
...@@ -289,7 +244,7 @@ static struct clk clk_h = { ...@@ -289,7 +244,7 @@ static struct clk clk_h = {
.ctrlbit = 0, .ctrlbit = 0,
}; };
static struct clk clk_p = { struct clk clk_p = {
.name = "pclk", .name = "pclk",
.id = -1, .id = -1,
.rate = 0, .rate = 0,
...@@ -426,108 +381,6 @@ struct clk s3c24xx_uclk = { ...@@ -426,108 +381,6 @@ struct clk s3c24xx_uclk = {
.id = -1, .id = -1,
}; };
/* standard clock definitions */
static struct clk init_clocks[] = {
{
.name = "nand",
.id = -1,
.parent = &clk_h,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_NAND,
}, {
.name = "lcd",
.id = -1,
.parent = &clk_h,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_LCDC,
}, {
.name = "usb-host",
.id = -1,
.parent = &clk_h,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBH,
}, {
.name = "usb-device",
.id = -1,
.parent = &clk_h,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBD,
}, {
.name = "timers",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_PWMT,
}, {
.name = "sdi",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SDI,
}, {
.name = "uart",
.id = 0,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART0,
}, {
.name = "uart",
.id = 1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART1,
}, {
.name = "uart",
.id = 2,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART2,
}, {
.name = "gpio",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_GPIO,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_RTC,
}, {
.name = "adc",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_ADC,
}, {
.name = "i2c",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIC,
}, {
.name = "iis",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIS,
}, {
.name = "spi",
.id = -1,
.parent = &clk_p,
.enable = s3c24xx_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SPI,
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}
};
/* initialise the clock system */ /* initialise the clock system */
int s3c24xx_register_clock(struct clk *clk) int s3c24xx_register_clock(struct clk *clk)
...@@ -537,14 +390,6 @@ int s3c24xx_register_clock(struct clk *clk) ...@@ -537,14 +390,6 @@ int s3c24xx_register_clock(struct clk *clk)
if (clk->enable == NULL) if (clk->enable == NULL)
clk->enable = clk_null_enable; clk->enable = clk_null_enable;
/* if this is a standard clock, set the usage state */
if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) {
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0;
}
/* add to the list of available clocks */ /* add to the list of available clocks */
mutex_lock(&clocks_mutex); mutex_lock(&clocks_mutex);
...@@ -561,44 +406,17 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, ...@@ -561,44 +406,17 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
unsigned long hclk, unsigned long hclk,
unsigned long pclk) unsigned long pclk)
{ {
unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
struct clk *clkp = init_clocks;
int ptr;
int ret;
printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
/* initialise the main system clocks */ /* initialise the main system clocks */
clk_xtal.rate = xtal; clk_xtal.rate = xtal;
clk_upll.rate = s3c2410_get_pll(upllcon, xtal); clk_upll.rate = s3c2410_get_pll(__raw_readl(S3C2410_UPLLCON), xtal);
clk_h.rate = hclk; clk_h.rate = hclk;
clk_p.rate = pclk; clk_p.rate = pclk;
clk_f.rate = fclk; clk_f.rate = fclk;
/* We must be careful disabling the clocks we are not intending to
* be using at boot time, as subsytems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
* Disabling the LCD clock if the LCD is active is very dangerous,
* and therefore the bootloader should be careful to not enable
* the LCD clock if it is not needed.
*/
mutex_lock(&clocks_mutex);
s3c24xx_clk_enable(S3C2410_CLKCON_NAND, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_USBH, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_USBD, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_ADC, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_IIC, 0);
s3c24xx_clk_enable(S3C2410_CLKCON_SPI, 0);
mutex_unlock(&clocks_mutex);
/* assume uart clocks are correctly setup */ /* assume uart clocks are correctly setup */
/* register our clocks */ /* register our clocks */
...@@ -618,27 +436,5 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, ...@@ -618,27 +436,5 @@ int __init s3c24xx_setup_clocks(unsigned long xtal,
if (s3c24xx_register_clock(&clk_p) < 0) if (s3c24xx_register_clock(&clk_p) < 0)
printk(KERN_ERR "failed to register cpu pclk\n"); printk(KERN_ERR "failed to register cpu pclk\n");
if (s3c24xx_register_clock(&clk_usb_bus) < 0)
printk(KERN_ERR "failed to register usb bus clock\n");
/* register clocks from clock array */
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
/* show the clock-slow value */
printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
print_mhz(xtal / ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
(clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
(clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
(clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
return 0; return 0;
} }
...@@ -22,6 +22,7 @@ struct clk { ...@@ -22,6 +22,7 @@ struct clk {
int (*enable)(struct clk *, int enable); int (*enable)(struct clk *, int enable);
int (*set_rate)(struct clk *c, unsigned long rate); int (*set_rate)(struct clk *c, unsigned long rate);
unsigned long (*get_rate)(struct clk *c);
unsigned long (*round_rate)(struct clk *c, unsigned long rate); unsigned long (*round_rate)(struct clk *c, unsigned long rate);
int (*set_parent)(struct clk *c, struct clk *parent); int (*set_parent)(struct clk *c, struct clk *parent);
}; };
...@@ -36,6 +37,13 @@ extern struct clk s3c24xx_uclk; ...@@ -36,6 +37,13 @@ extern struct clk s3c24xx_uclk;
extern struct clk clk_usb_bus; extern struct clk clk_usb_bus;
/* core clock support */
extern struct clk clk_f;
extern struct clk clk_h;
extern struct clk clk_p;
extern struct clk clk_upll;
/* exports for arch/arm/mach-s3c2410 /* exports for arch/arm/mach-s3c2410
* *
* Please DO NOT use these outside of arch/arm/mach-s3c2410 * Please DO NOT use these outside of arch/arm/mach-s3c2410
...@@ -43,7 +51,8 @@ extern struct clk clk_usb_bus; ...@@ -43,7 +51,8 @@ extern struct clk clk_usb_bus;
extern struct mutex clocks_mutex; extern struct mutex clocks_mutex;
extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); extern int s3c2410_clkcon_enable(struct clk *clk, int enable);
extern int s3c24xx_register_clock(struct clk *clk); extern int s3c24xx_register_clock(struct clk *clk);
extern int s3c24xx_setup_clocks(unsigned long xtal, extern int s3c24xx_setup_clocks(unsigned long xtal,
......
...@@ -73,5 +73,6 @@ extern struct sys_timer s3c24xx_timer; ...@@ -73,5 +73,6 @@ extern struct sys_timer s3c24xx_timer;
/* system device classes */ /* system device classes */
extern struct sysdev_class s3c2410_sysclass;
extern struct sysdev_class s3c2440_sysclass; extern struct sysdev_class s3c2440_sysclass;
extern struct sysdev_class s3c2442_sysclass; extern struct sysdev_class s3c2442_sysclass;
/* linux/arch/arm/mach-s3c2410/clock.c
*
* Copyright (c) 2006 Simtec Electronics
* Ben Dooks <ben@simtec.co.uk>
*
* S3C2410,S3C2440,S3C2442 Clock control support
*
* 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 <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/sysdev.h>
#include <linux/clk.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/arch/regs-clock.h>
#include <asm/arch/regs-gpio.h>
#include "clock.h"
#include "cpu.h"
int s3c2410_clkcon_enable(struct clk *clk, int enable)
{
unsigned int clocks = clk->ctrlbit;
unsigned long clkcon;
clkcon = __raw_readl(S3C2410_CLKCON);
if (enable)
clkcon |= clocks;
else
clkcon &= ~clocks;
/* ensure none of the special function bits set */
clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);
__raw_writel(clkcon, S3C2410_CLKCON);
return 0;
}
static int s3c2410_upll_enable(struct clk *clk, int enable)
{
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
unsigned long orig = clkslow;
if (enable)
clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF;
else
clkslow |= S3C2410_CLKSLOW_UCLK_OFF;
__raw_writel(clkslow, S3C2410_CLKSLOW);
/* if we started the UPLL, then allow to settle */
if (enable && (orig & S3C2410_CLKSLOW_UCLK_OFF))
udelay(200);
return 0;
}
/* standard clock definitions */
static struct clk init_clocks_disable[] = {
{
.name = "nand",
.id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_NAND,
}, {
.name = "sdi",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SDI,
}, {
.name = "adc",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_ADC,
}, {
.name = "i2c",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIC,
}, {
.name = "iis",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_IIS,
}, {
.name = "spi",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_SPI,
}
};
static struct clk init_clocks[] = {
{
.name = "lcd",
.id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_LCDC,
}, {
.name = "gpio",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_GPIO,
}, {
.name = "usb-host",
.id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBH,
}, {
.name = "usb-device",
.id = -1,
.parent = &clk_h,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_USBD,
}, {
.name = "timers",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_PWMT,
}, {
.name = "uart",
.id = 0,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART0,
}, {
.name = "uart",
.id = 1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART1,
}, {
.name = "uart",
.id = 2,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_UART2,
}, {
.name = "rtc",
.id = -1,
.parent = &clk_p,
.enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2410_CLKCON_RTC,
}, {
.name = "watchdog",
.id = -1,
.parent = &clk_p,
.ctrlbit = 0,
}
};
/* s3c2410_baseclk_add()
*
* Add all the clocks used by the s3c2410 or compatible CPUs
* such as the S3C2440 and S3C2442.
*
* We cannot use a system device as we are needed before any
* of the init-calls that initialise the devices are actually
* done.
*/
int __init s3c2410_baseclk_add(void)
{
unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);
unsigned long clkcon = __raw_readl(S3C2410_CLKCON);
struct clk *clkp;
struct clk *xtal;
int ret;
int ptr;
clk_upll.enable = s3c2410_upll_enable;
if (s3c24xx_register_clock(&clk_usb_bus) < 0)
printk(KERN_ERR "failed to register usb bus clock\n");
/* register clocks from clock array */
clkp = init_clocks;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
/* ensure that we note the clock state */
clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
}
/* We must be careful disabling the clocks we are not intending to
* be using at boot time, as subsytems such as the LCD which do
* their own DMA requests to the bus can cause the system to lockup
* if they where in the middle of requesting bus access.
*
* Disabling the LCD clock if the LCD is active is very dangerous,
* and therefore the bootloader should be careful to not enable
* the LCD clock if it is not needed.
*/
/* install (and disable) the clocks we do not need immediately */
clkp = init_clocks_disable;
for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
ret = s3c24xx_register_clock(clkp);
if (ret < 0) {
printk(KERN_ERR "Failed to register clock %s (%d)\n",
clkp->name, ret);
}
s3c2410_clkcon_enable(clkp, 0);
}
/* show the clock-slow value */
xtal = clk_get(NULL, "xtal");
printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",
print_mhz(clk_get_rate(xtal) /
( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),
(clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",
(clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",
(clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");
return 0;
}
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sysdev.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -108,11 +109,33 @@ void __init s3c2410_init_clocks(int xtal) ...@@ -108,11 +109,33 @@ void __init s3c2410_init_clocks(int xtal)
*/ */
s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
s3c2410_baseclk_add();
} }
struct sysdev_class s3c2410_sysclass = {
set_kset_name("s3c2410-core"),
};
static struct sys_device s3c2410_sysdev = {
.cls = &s3c2410_sysclass,
};
/* need to register class before we actually register the device, and
* we also need to ensure that it has been initialised before any of the
* drivers even try to use it (even if not on an s3c2440 based system)
* as a driver which may support both 2410 and 2440 may try and use it.
*/
static int __init s3c2410_core_init(void)
{
return sysdev_class_register(&s3c2410_sysclass);
}
core_initcall(s3c2410_core_init);
int __init s3c2410_init(void) int __init s3c2410_init(void)
{ {
printk("S3C2410: Initialising architecture\n"); printk("S3C2410: Initialising architecture\n");
return 0; return sysdev_register(&s3c2410_sysdev);
} }
...@@ -29,6 +29,8 @@ extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no); ...@@ -29,6 +29,8 @@ extern void s3c2410_init_uarts(struct s3c2410_uartcfg *cfg, int no);
extern void s3c2410_init_clocks(int xtal); extern void s3c2410_init_clocks(int xtal);
extern int s3c2410_baseclk_add(void);
#else #else
#define s3c2410_init_clocks NULL #define s3c2410_init_clocks NULL
#define s3c2410_init_uarts NULL #define s3c2410_init_uarts NULL
......
...@@ -91,7 +91,7 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate) ...@@ -91,7 +91,7 @@ static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate)
static struct clk s3c2440_clk_cam = { static struct clk s3c2440_clk_cam = {
.name = "camif", .name = "camif",
.id = -1, .id = -1,
.enable = s3c24xx_clkcon_enable, .enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA, .ctrlbit = S3C2440_CLKCON_CAMERA,
}; };
...@@ -105,7 +105,7 @@ static struct clk s3c2440_clk_cam_upll = { ...@@ -105,7 +105,7 @@ static struct clk s3c2440_clk_cam_upll = {
static struct clk s3c2440_clk_ac97 = { static struct clk s3c2440_clk_ac97 = {
.name = "ac97", .name = "ac97",
.id = -1, .id = -1,
.enable = s3c24xx_clkcon_enable, .enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA, .ctrlbit = S3C2440_CLKCON_CAMERA,
}; };
......
...@@ -102,7 +102,7 @@ static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate) ...@@ -102,7 +102,7 @@ static int s3c2442_camif_upll_setrate(struct clk *clk, unsigned long rate)
static struct clk s3c2442_clk_cam = { static struct clk s3c2442_clk_cam = {
.name = "camif", .name = "camif",
.id = -1, .id = -1,
.enable = s3c24xx_clkcon_enable, .enable = s3c2410_clkcon_enable,
.ctrlbit = S3C2440_CLKCON_CAMERA, .ctrlbit = S3C2440_CLKCON_CAMERA,
}; };
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <asm/arch/regs-gpioj.h> #include <asm/arch/regs-gpioj.h>
#include <asm/arch/regs-dsc.h> #include <asm/arch/regs-dsc.h>
#include "s3c2410.h"
#include "s3c2440.h" #include "s3c2440.h"
#include "s3c244x.h" #include "s3c244x.h"
#include "clock.h" #include "clock.h"
...@@ -118,6 +119,7 @@ void __init s3c244x_init_clocks(int xtal) ...@@ -118,6 +119,7 @@ void __init s3c244x_init_clocks(int xtal)
*/ */
s3c24xx_setup_clocks(xtal, fclk, hclk, pclk); s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
s3c2410_baseclk_add();
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
......
...@@ -33,7 +33,8 @@ ...@@ -33,7 +33,8 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h> #include <linux/init.h>
/* XXX */
#include <asm/thread_notify.h>
#include "softfloat.h" #include "softfloat.h"
#include "fpopcode.h" #include "fpopcode.h"
...@@ -56,16 +57,28 @@ void fp_send_sig(unsigned long sig, struct task_struct *p, int priv); ...@@ -56,16 +57,28 @@ void fp_send_sig(unsigned long sig, struct task_struct *p, int priv);
extern char fpe_type[]; extern char fpe_type[];
#endif #endif
static int nwfpe_notify(struct notifier_block *self, unsigned long cmd, void *v)
{
struct thread_info *thread = v;
if (cmd == THREAD_NOTIFY_FLUSH)
nwfpe_init_fpa(&thread->fpstate);
return NOTIFY_DONE;
}
static struct notifier_block nwfpe_notifier_block = {
.notifier_call = nwfpe_notify,
};
/* kernel function prototypes required */ /* kernel function prototypes required */
void fp_setup(void); void fp_setup(void);
/* external declarations for saved kernel symbols */ /* external declarations for saved kernel symbols */
extern void (*kern_fp_enter)(void); extern void (*kern_fp_enter)(void);
extern void (*fp_init)(union fp_state *);
/* Original value of fp_enter from kernel before patched by fpe_init. */ /* Original value of fp_enter from kernel before patched by fpe_init. */
static void (*orig_fp_enter)(void); static void (*orig_fp_enter)(void);
static void (*orig_fp_init)(union fp_state *);
/* forward declarations */ /* forward declarations */
extern void nwfpe_enter(void); extern void nwfpe_enter(void);
...@@ -88,20 +101,20 @@ static int __init fpe_init(void) ...@@ -88,20 +101,20 @@ static int __init fpe_init(void)
printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 (" printk(KERN_WARNING "NetWinder Floating Point Emulator V0.97 ("
NWFPE_BITS " precision)\n"); NWFPE_BITS " precision)\n");
thread_register_notifier(&nwfpe_notifier_block);
/* Save pointer to the old FP handler and then patch ourselves in */ /* Save pointer to the old FP handler and then patch ourselves in */
orig_fp_enter = kern_fp_enter; orig_fp_enter = kern_fp_enter;
orig_fp_init = fp_init;
kern_fp_enter = nwfpe_enter; kern_fp_enter = nwfpe_enter;
fp_init = nwfpe_init_fpa;
return 0; return 0;
} }
static void __exit fpe_exit(void) static void __exit fpe_exit(void)
{ {
thread_unregister_notifier(&nwfpe_notifier_block);
/* Restore the values we saved earlier. */ /* Restore the values we saved earlier. */
kern_fp_enter = orig_fp_enter; kern_fp_enter = orig_fp_enter;
fp_init = orig_fp_init;
} }
/* /*
......
...@@ -210,7 +210,8 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, ...@@ -210,7 +210,8 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
now = omap_32k_sync_timer_read(); now = omap_32k_sync_timer_read();
while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { while ((signed long)(now - omap_32k_last_tick)
>= OMAP_32K_TICKS_PER_HZ) {
omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
timer_tick(regs); timer_tick(regs);
} }
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
# EXTRA_CFLAGS := -DDEBUG # EXTRA_CFLAGS := -DDEBUG
# EXTRA_AFLAGS := -DDEBUG # EXTRA_AFLAGS := -DDEBUG
AFLAGS :=$(AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
LDFLAGS +=--no-warn-mismatch
obj-y += vfp.o obj-y += vfp.o
vfp-$(CONFIG_VFP) += entry.o vfpmodule.o vfphw.o vfpsingle.o vfpdouble.o vfp-$(CONFIG_VFP) += vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o
...@@ -192,7 +192,7 @@ vfp_get_double: ...@@ -192,7 +192,7 @@ vfp_get_double:
add pc, pc, r0, lsl #3 add pc, pc, r0, lsl #3
mov r0, r0 mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
mrrc p11, 1, r0, r1, c\dr @ fmrrd r0, r1, d\dr fmrrd r0, r1, d\dr
mov pc, lr mov pc, lr
.endr .endr
...@@ -206,6 +206,6 @@ vfp_put_double: ...@@ -206,6 +206,6 @@ vfp_put_double:
add pc, pc, r0, lsl #3 add pc, pc, r0, lsl #3
mov r0, r0 mov r0, r0
.irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
mcrr p11, 1, r1, r2, c\dr @ fmdrr r1, r2, d\dr fmdrr d\dr, r1, r2
mov pc, lr mov pc, lr
.endr .endr
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/init.h> #include <linux/init.h>
#include <asm/thread_notify.h>
#include <asm/vfp.h> #include <asm/vfp.h>
#include "vfpinstr.h" #include "vfpinstr.h"
...@@ -36,11 +38,16 @@ union vfp_state *last_VFP_context; ...@@ -36,11 +38,16 @@ union vfp_state *last_VFP_context;
*/ */
unsigned int VFP_arch; unsigned int VFP_arch;
/* static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{
struct thread_info *thread = v;
union vfp_state *vfp = &thread->vfpstate;
switch (cmd) {
case THREAD_NOTIFY_FLUSH:
/*
* Per-thread VFP initialisation. * Per-thread VFP initialisation.
*/ */
void vfp_flush_thread(union vfp_state *vfp)
{
memset(vfp, 0, sizeof(union vfp_state)); memset(vfp, 0, sizeof(union vfp_state));
vfp->hard.fpexc = FPEXC_ENABLE; vfp->hard.fpexc = FPEXC_ENABLE;
...@@ -52,22 +59,34 @@ void vfp_flush_thread(union vfp_state *vfp) ...@@ -52,22 +59,34 @@ void vfp_flush_thread(union vfp_state *vfp)
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE); fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
/* /*
* Ensure we don't try to overwrite our newly initialised * FALLTHROUGH: Ensure we don't try to overwrite our newly
* state information on the first fault. * initialised state information on the first fault.
*/ */
if (last_VFP_context == vfp)
last_VFP_context = NULL;
}
/* case THREAD_NOTIFY_RELEASE:
/*
* Per-thread VFP cleanup. * Per-thread VFP cleanup.
*/ */
void vfp_release_thread(union vfp_state *vfp)
{
if (last_VFP_context == vfp) if (last_VFP_context == vfp)
last_VFP_context = NULL; last_VFP_context = NULL;
break;
case THREAD_NOTIFY_SWITCH:
/*
* Always disable VFP so we can lazily save/restore the
* old state.
*/
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_ENABLE);
break;
}
return NOTIFY_DONE;
} }
static struct notifier_block vfp_notifier_block = {
.notifier_call = vfp_notifier,
};
/* /*
* Raise a SIGFPE for the current process. * Raise a SIGFPE for the current process.
* sicode describes the signal being raised. * sicode describes the signal being raised.
...@@ -281,6 +300,8 @@ static int __init vfp_init(void) ...@@ -281,6 +300,8 @@ static int __init vfp_init(void)
(vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT, (vfpsid & FPSID_VARIANT_MASK) >> FPSID_VARIANT_BIT,
(vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT); (vfpsid & FPSID_REV_MASK) >> FPSID_REV_BIT);
vfp_vector = vfp_support_entry; vfp_vector = vfp_support_entry;
thread_register_notifier(&vfp_notifier_block);
} }
return 0; return 0;
} }
......
...@@ -269,7 +269,6 @@ static unsigned int serial_pxa_get_mctrl(struct uart_port *port) ...@@ -269,7 +269,6 @@ static unsigned int serial_pxa_get_mctrl(struct uart_port *port)
unsigned char status; unsigned char status;
unsigned int ret; unsigned int ret;
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
status = serial_in(up, UART_MSR); status = serial_in(up, UART_MSR);
ret = 0; ret = 0;
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
struct imx_dma_channel { struct imx_dma_channel {
const char *name; const char *name;
void (*irq_handler) (int, void *, struct pt_regs *); void (*irq_handler) (int, void *, struct pt_regs *);
void (*err_handler) (int, void *, struct pt_regs *); void (*err_handler) (int, void *, struct pt_regs *, int errcode);
void *data; void *data;
dmamode_t dma_mode; dmamode_t dma_mode;
struct scatterlist *sg; struct scatterlist *sg;
...@@ -58,6 +58,10 @@ struct imx_dma_channel { ...@@ -58,6 +58,10 @@ struct imx_dma_channel {
extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS]; extern struct imx_dma_channel imx_dma_channels[IMX_DMA_CHANNELS];
#define IMX_DMA_ERR_BURST 1
#define IMX_DMA_ERR_REQUEST 2
#define IMX_DMA_ERR_TRANSFER 4
#define IMX_DMA_ERR_BUFFER 8
/* The type to distinguish channel numbers parameter from ordinal int type */ /* The type to distinguish channel numbers parameter from ordinal int type */
typedef int imx_dmach_t; typedef int imx_dmach_t;
...@@ -74,7 +78,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch, ...@@ -74,7 +78,7 @@ imx_dma_setup_sg(imx_dmach_t dma_ch,
int int
imx_dma_setup_handlers(imx_dmach_t dma_ch, imx_dma_setup_handlers(imx_dmach_t dma_ch,
void (*irq_handler) (int, void *, struct pt_regs *), void (*irq_handler) (int, void *, struct pt_regs *),
void (*err_handler) (int, void *, struct pt_regs *), void *data); void (*err_handler) (int, void *, struct pt_regs *, int), void *data);
void imx_dma_enable(imx_dmach_t dma_ch); void imx_dma_enable(imx_dmach_t dma_ch);
......
...@@ -124,6 +124,7 @@ ...@@ -124,6 +124,7 @@
#define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28) #define IXP23XX_EXP_UNIT_FUSE IXP23XX_EXP_CFG_REG(0x28)
#define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30) #define IXP23XX_EXP_MSF_MUX IXP23XX_EXP_CFG_REG(0x30)
#define IXP23XX_EXP_CFG_FUSE IXP23XX_EXP_CFG_REG(0x34)
#define IXP23XX_EXP_BUS_PHYS 0x90000000 #define IXP23XX_EXP_BUS_PHYS 0x90000000
#define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000 #define IXP23XX_EXP_BUS_WINDOW_SIZE 0x01000000
...@@ -265,6 +266,8 @@ ...@@ -265,6 +266,8 @@
#define IXP23XX_PCI_UNIT_RESET (1 << 1) #define IXP23XX_PCI_UNIT_RESET (1 << 1)
#define IXP23XX_XSCALE_RESET (1 << 0) #define IXP23XX_XSCALE_RESET (1 << 0)
#define IXP23XX_UENGINE_CSR_VIRT_BASE (IXP23XX_CAP_CSR_VIRT + 0x18000)
/**************************************************************************** /****************************************************************************
* PCI CSRs. * PCI CSRs.
......
...@@ -14,6 +14,21 @@ ...@@ -14,6 +14,21 @@
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
extern inline unsigned long ixp2000_reg_read(volatile void *reg)
{
return *((volatile unsigned long *)reg);
}
extern inline void ixp2000_reg_write(volatile void *reg, unsigned long val)
{
*((volatile unsigned long *)reg) = val;
}
extern inline void ixp2000_reg_wrb(volatile void *reg, unsigned long val)
{
*((volatile unsigned long *)reg) = val;
}
struct pci_sys_data; struct pci_sys_data;
void ixp23xx_map_io(void); void ixp23xx_map_io(void);
......
...@@ -19,9 +19,5 @@ ...@@ -19,9 +19,5 @@
addne \rx, \rx, #0xf4000000 addne \rx, \rx, #0xf4000000
.endm .endm
.macro senduart,rd,rx
strb \rd, [\rx, #0x0]
.endm
#define UART_SHIFT 2 #define UART_SHIFT 2
#include <asm/hardware/debug-8250.S> #include <asm/hardware/debug-8250.S>
...@@ -127,6 +127,79 @@ ...@@ -127,6 +127,79 @@
#define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK)) #define GPIO_ISOUT(K) ((GPIO_TYPE_MASK(K) == GPIO_OUT) && (GPIO_BIT(K) & GPIO_OUT_MASK))
#define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK)) #define GPIO_ISIN(K) ((GPIO_TYPE_MASK(K) == GPIO_IN) && (GPIO_BIT(K) & GPIO_IN_MASK))
/* Start Enable Pin Interrupts - table 58 page 66 */
#define SE_PIN_BASE_INT 32
#define SE_U7_RX_INT 63
#define SE_U7_HCTS_INT 62
#define SE_BT_CLKREQ_INT 61
#define SE_U6_IRRX_INT 60
/*59 unused*/
#define SE_U5_RX_INT 58
#define SE_GPI_11_INT 57
#define SE_U3_RX_INT 56
#define SE_U2_HCTS_INT 55
#define SE_U2_RX_INT 54
#define SE_U1_RX_INT 53
#define SE_DISP_SYNC_INT 52
/*51 unused*/
#define SE_SDIO_INT_N 50
#define SE_MSDIO_START_INT 49
#define SE_GPI_06_INT 48
#define SE_GPI_05_INT 47
#define SE_GPI_04_INT 46
#define SE_GPI_03_INT 45
#define SE_GPI_02_INT 44
#define SE_GPI_01_INT 43
#define SE_GPI_00_INT 42
#define SE_SYSCLKEN_PIN_INT 41
#define SE_SPI1_DATAIN_INT 40
#define SE_GPI_07_INT 39
#define SE_SPI2_DATAIN_INT 38
#define SE_GPI_10_INT 37
#define SE_GPI_09_INT 36
#define SE_GPI_08_INT 35
/*34-32 unused*/
/* Start Enable Internal Interrupts - table 57 page 65 */
#define SE_INT_BASE_INT 0
#define SE_TS_IRQ 31
#define SE_TS_P_INT 30
#define SE_TS_AUX_INT 29
/*27-28 unused*/
#define SE_USB_AHB_NEED_CLK_INT 26
#define SE_MSTIMER_INT 25
#define SE_RTC_INT 24
#define SE_USB_NEED_CLK_INT 23
#define SE_USB_INT 22
#define SE_USB_I2C_INT 21
#define SE_USB_OTG_TIMER_INT 20
#define SE_USB_OTG_ATX_INT_N 19
/*18 unused*/
#define SE_DSP_GPIO4_INT 17
#define SE_KEY_IRQ 16
#define SE_DSP_SLAVEPORT_INT 15
#define SE_DSP_GPIO1_INT 14
#define SE_DSP_GPIO0_INT 13
#define SE_DSP_AHB_INT 12
/*11-6 unused*/
#define SE_GPIO_05_INT 5
#define SE_GPIO_04_INT 4
#define SE_GPIO_03_INT 3
#define SE_GPIO_02_INT 2
#define SE_GPIO_01_INT 1
#define SE_GPIO_00_INT 0
#define START_INT_REG_BIT(irq) (1<<((irq)&0x1F))
#define START_INT_ER_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x20 + (((irq)&(0x1<<5))>>1)))
#define START_INT_RSR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x24 + (((irq)&(0x1<<5))>>1)))
#define START_INT_SR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x28 + (((irq)&(0x1<<5))>>1)))
#define START_INT_APR_REG(irq) IO_ADDRESS((PNX4008_PWRMAN_BASE + 0x2C + (((irq)&(0x1<<5))>>1)))
extern int pnx4008_gpio_register_pin(unsigned short pin); extern int pnx4008_gpio_register_pin(unsigned short pin);
extern int pnx4008_gpio_unregister_pin(unsigned short pin); extern int pnx4008_gpio_unregister_pin(unsigned short pin);
extern unsigned long pnx4008_gpio_read_pin(unsigned short pin); extern unsigned long pnx4008_gpio_read_pin(unsigned short pin);
...@@ -136,4 +209,33 @@ extern int pnx4008_gpio_read_pin_direction(unsigned short pin); ...@@ -136,4 +209,33 @@ extern int pnx4008_gpio_read_pin_direction(unsigned short pin);
extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output); extern int pnx4008_gpio_set_pin_mux(unsigned short pin, int output);
extern int pnx4008_gpio_read_pin_mux(unsigned short pin); extern int pnx4008_gpio_read_pin_mux(unsigned short pin);
static inline void start_int_umask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_mask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_ack(u8 irq)
{
__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
}
static inline void start_int_set_falling_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
static inline void start_int_set_rising_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
#endif /* _PNX4008_GPIO_H_ */ #endif /* _PNX4008_GPIO_H_ */
...@@ -29,34 +29,5 @@ extern void pnx4008_cpu_standby(void); ...@@ -29,34 +29,5 @@ extern void pnx4008_cpu_standby(void);
extern int pnx4008_startup_pll(struct clk *); extern int pnx4008_startup_pll(struct clk *);
extern int pnx4008_shutdown_pll(struct clk *); extern int pnx4008_shutdown_pll(struct clk *);
static inline void start_int_umask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_mask(u8 irq)
{
__raw_writel(__raw_readl(START_INT_ER_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_ER_REG(irq));
}
static inline void start_int_ack(u8 irq)
{
__raw_writel(START_INT_REG_BIT(irq), START_INT_RSR_REG(irq));
}
static inline void start_int_set_falling_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) &
~START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
static inline void start_int_set_rising_edge(u8 irq)
{
__raw_writel(__raw_readl(START_INT_APR_REG(irq)) |
START_INT_REG_BIT(irq), START_INT_APR_REG(irq));
}
#endif /* ASSEMBLER */ #endif /* ASSEMBLER */
#endif /* __ASM_ARCH_PNX4008_PM_H */ #endif /* __ASM_ARCH_PNX4008_PM_H */
...@@ -170,7 +170,7 @@ ...@@ -170,7 +170,7 @@
#define S3C2440_DSC1_CS1_4mA (3<<2) #define S3C2440_DSC1_CS1_4mA (3<<2)
#define S3C2440_DSC1_CS1_MASK (3<<2) #define S3C2440_DSC1_CS1_MASK (3<<2)
#define S3C2440_DSC1_CS0 (S3C2440_SELECT_DSC1 | 0 #define S3C2440_DSC1_CS0 (S3C2440_SELECT_DSC1 | 0)
#define S3C2440_DSC1_CS0_10mA (0<<0) #define S3C2440_DSC1_CS0_10mA (0<<0)
#define S3C2440_DSC1_CS0_8mA (1<<0) #define S3C2440_DSC1_CS0_8mA (1<<0)
#define S3C2440_DSC1_CS0_6mA (2<<0) #define S3C2440_DSC1_CS0_6mA (2<<0)
......
/*
* linux/include/asm-arm/thread_notify.h
*
* Copyright (C) 2006 Russell King.
*
* 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 ASMARM_THREAD_NOTIFY_H
#define ASMARM_THREAD_NOTIFY_H
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
#include <linux/notifier.h>
#include <asm/thread_info.h>
static inline int thread_register_notifier(struct notifier_block *n)
{
extern struct atomic_notifier_head thread_notify_head;
return atomic_notifier_chain_register(&thread_notify_head, n);
}
static inline void thread_unregister_notifier(struct notifier_block *n)
{
extern struct atomic_notifier_head thread_notify_head;
atomic_notifier_chain_unregister(&thread_notify_head, n);
}
static inline void thread_notify(unsigned long rc, struct thread_info *thread)
{
extern struct atomic_notifier_head thread_notify_head;
atomic_notifier_call_chain(&thread_notify_head, rc, thread);
}
#endif
/*
* These are the reason codes for the thread notifier.
*/
#define THREAD_NOTIFY_FLUSH 0
#define THREAD_NOTIFY_RELEASE 1
#define THREAD_NOTIFY_SWITCH 2
#endif
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment