Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 48994
b: refs/heads/master
c: 8213084
h: refs/heads/master
v: v3
  • Loading branch information
Russell King authored and Russell King committed Feb 18, 2007
1 parent e1f92f1 commit ef6d7d7
Show file tree
Hide file tree
Showing 256 changed files with 12,848 additions and 5,660 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b77bfa84c419e3ec8b8e3fd4b4579e5761b7c943
refs/heads/master: 8213084125eed3c5efbc5e13739b93dfedb88590
46 changes: 46 additions & 0 deletions trunk/Documentation/arm/Samsung-S3C24XX/DMA.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
S3C2410 DMA
===========

Introduction
------------

The kernel provides an interface to manage DMA transfers
using the DMA channels in the cpu, so that the central
duty of managing channel mappings, and programming the
channel generators is in one place.


DMA Channel Ordering
--------------------

Many of the range do not have connections for the DMA
channels to all sources, which means that some devices
have a restricted number of channels that can be used.

To allow flexibilty for each cpu type and board, the
dma code can be given an dma ordering structure which
allows the order of channel search to be specified, as
well as allowing the prohibition of certain claims.

struct s3c24xx_dma_order has a list of channels, and
each channel within has a slot for a list of dma
channel numbers. The slots are searched in order, for
the presence of a dma channel number with DMA_CH_VALID
orred in.

If the order has the flag DMA_CH_NEVER set, then after
checking the channel list, the system will return no
found channel, thus denying the request.

A board support file can call s3c24xx_dma_order_set()
to register an complete ordering set. The routine will
copy the data, so the original can be discared with
__initdata.


Authour
-------

Ben Dooks,
Copyright (c) 2007 Ben Dooks, Simtec Electronics
Licensed under the GPL v2
21 changes: 17 additions & 4 deletions trunk/Documentation/arm/Samsung-S3C24XX/Overview.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ Introduction

The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
by the 's3c2410' architecture of ARM Linux. Currently the S3C2410,
S3C2440 and S3C2442 devices are supported.
S3C2412, S3C2413, S3C2440 and S3C2442 devices are supported.

Support for the S3C2400 series is in progress.

Support for the S3C2412 and S3C2413 CPUs is being merged.


Configuration
-------------

Expand All @@ -26,6 +23,22 @@ Configuration
please check the machine specific documentation.


Layout
------

The core support files are located in the platform code contained in
arch/arm/plat-s3c24xx with headers in include/asm-arm/plat-s3c24xx.
This directory should be kept to items shared between the platform
code (arch/arm/plat-s3c24xx) and the arch/arm/mach-s3c24* code.

Each cpu has a directory with the support files for it, and the
machines that carry the device. For example S3C2410 is contained
in arch/arm/mach-s3c2410 and S3C2440 in arch/arm/mach-s3c2440

Register, kernel and platform data definitions are held in the
include/asm-arm/arch-s3c2410 directory.


Machines
--------

Expand Down
28 changes: 26 additions & 2 deletions trunk/arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ config ARCH_PXA
bool "PXA2xx-based"
depends on MMU
select ARCH_MTD_XIP
select GENERIC_TIME
help
Support for Intel's PXA2XX processor line.

Expand All @@ -311,7 +312,7 @@ config ARCH_SA1100
Support for StrongARM 11x0 based boards.

config ARCH_S3C2410
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442"
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
Expand Down Expand Up @@ -371,7 +372,16 @@ source "arch/arm/mach-omap1/Kconfig"

source "arch/arm/mach-omap2/Kconfig"

source "arch/arm/plat-s3c24xx/Kconfig"

if ARCH_S3C2410
source "arch/arm/mach-s3c2400/Kconfig"
source "arch/arm/mach-s3c2410/Kconfig"
source "arch/arm/mach-s3c2412/Kconfig"
source "arch/arm/mach-s3c2440/Kconfig"
source "arch/arm/mach-s3c2442/Kconfig"
source "arch/arm/mach-s3c2443/Kconfig"
endif

source "arch/arm/mach-lh7a40x/Kconfig"

Expand All @@ -385,7 +395,7 @@ source "arch/arm/mach-aaec2000/Kconfig"

source "arch/arm/mach-realview/Kconfig"

source "arch/arm/mach-at91rm9200/Kconfig"
source "arch/arm/mach-at91/Kconfig"

source "arch/arm/mach-netx/Kconfig"

Expand Down Expand Up @@ -748,6 +758,20 @@ config XIP_PHYS_ADDR
be linked for and stored to. This address is dependent on your
own flash usage.

config KEXEC
bool "Kexec system call (EXPERIMENTAL)"
depends on EXPERIMENTAL
help
kexec is a system call that implements the ability to shutdown your
current kernel, and to start another kernel. It is like a reboot
but it is indepedent of the system firmware. And like a reboot
you can start any kernel with it, not just Linux.

It is an ongoing process to be certain the hardware in a machine
is properly shutdown, so do not be surprised if this code does not
initially work for you. It may help to enable device hotplugging
support.

endmenu

if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX )
Expand Down
8 changes: 7 additions & 1 deletion trunk/arch/arm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ MACHINE := arch/arm/mach-$(machine-y)/
else
MACHINE :=
endif

export TEXT_OFFSET GZFLAGS MMUEXT

# Do we have FASTFPE?
Expand All @@ -163,13 +163,19 @@ endif
# If we have a machine-specific directory, then include it in the build.
core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/
core-y += $(MACHINE)
core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2400/
core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2412/
core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2440/
core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2442/
core-$(CONFIG_ARCH_S3C2410) += arch/arm/mach-s3c2443/
core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/
core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ)
core-$(CONFIG_VFP) += arch/arm/vfp/

# If we have a common platform directory, then include it in the build.
core-$(CONFIG_PLAT_IOP) += arch/arm/plat-iop/
core-$(CONFIG_ARCH_OMAP) += arch/arm/plat-omap/
core-$(CONFIG_PLAT_S3C24XX) += arch/arm/plat-s3c24xx/

drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/
drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/arm/boot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Image
zImage
1 change: 1 addition & 0 deletions trunk/arch/arm/boot/compressed/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
piggy.gz
87 changes: 36 additions & 51 deletions trunk/arch/arm/common/dmabounce.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

#include <asm/cacheflush.h>

#undef DEBUG
#undef STATS

#ifdef STATS
Expand Down Expand Up @@ -66,48 +65,37 @@ struct dmabounce_pool {
};

struct dmabounce_device_info {
struct list_head node;

struct device *dev;
struct list_head safe_buffers;
#ifdef STATS
unsigned long total_allocs;
unsigned long map_op_count;
unsigned long bounce_count;
int attr_res;
#endif
struct dmabounce_pool small;
struct dmabounce_pool large;

rwlock_t lock;
};

static LIST_HEAD(dmabounce_devs);

#ifdef STATS
static void print_alloc_stats(struct dmabounce_device_info *device_info)
static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
printk(KERN_INFO
"%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
device_info->dev->bus_id,
device_info->small.allocs, device_info->large.allocs,
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
device_info->small.allocs,
device_info->large.allocs,
device_info->total_allocs - device_info->small.allocs -
device_info->large.allocs,
device_info->total_allocs);
device_info->total_allocs,
device_info->map_op_count,
device_info->bounce_count);
}
#endif

/* find the given device in the dmabounce device list */
static inline struct dmabounce_device_info *
find_dmabounce_dev(struct device *dev)
{
struct dmabounce_device_info *d;

list_for_each_entry(d, &dmabounce_devs, node)
if (d->dev == dev)
return d;

return NULL;
}
static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
#endif


/* allocate a 'safe' buffer and keep track of it */
Expand Down Expand Up @@ -162,8 +150,6 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr,
if (pool)
pool->allocs++;
device_info->total_allocs++;
if (device_info->total_allocs % 1000 == 0)
print_alloc_stats(device_info);
#endif

write_lock_irqsave(&device_info->lock, flags);
Expand Down Expand Up @@ -218,20 +204,11 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer *

/* ************************************************** */

#ifdef STATS
static void print_map_stats(struct dmabounce_device_info *device_info)
{
dev_info(device_info->dev,
"dmabounce: map_op_count=%lu, bounce_count=%lu\n",
device_info->map_op_count, device_info->bounce_count);
}
#endif

static inline dma_addr_t
map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
dma_addr_t dma_addr;
int needs_bounce = 0;

Expand Down Expand Up @@ -281,18 +258,22 @@ map_single(struct device *dev, void *ptr, size_t size,
ptr = buf->safe;

dma_addr = buf->safe_dma_addr;
} else {
/*
* We don't need to sync the DMA buffer since
* it was allocated via the coherent allocators.
*/
consistent_sync(ptr, size, dir);
}

consistent_sync(ptr, size, dir);

return dma_addr;
}

static inline void
unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
struct safe_buffer *buf = NULL;

/*
Expand All @@ -317,12 +298,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
DO_STATS ( device_info->bounce_count++ );

if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
unsigned long ptr;
void *ptr = buf->ptr;

dev_dbg(dev,
"%s: copy back safe %p to unsafe %p size %d\n",
__func__, buf->safe, buf->ptr, size);
memcpy(buf->ptr, buf->safe, size);
__func__, buf->safe, ptr, size);
memcpy(ptr, buf->safe, size);

/*
* DMA buffers must have the same cache properties
Expand All @@ -332,8 +313,8 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
* bidirectional case because we know the cache
* lines will be coherent with the data written.
*/
ptr = (unsigned long)buf->ptr;
dmac_clean_range(ptr, ptr + size);
outer_clean_range(__pa(ptr), __pa(ptr) + size);
}
free_safe_buffer(device_info, buf);
}
Expand All @@ -343,7 +324,7 @@ static inline void
sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
struct safe_buffer *buf = NULL;

if (device_info)
Expand Down Expand Up @@ -397,7 +378,10 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
default:
BUG();
}
consistent_sync(buf->safe, size, dir);
/*
* No need to sync the safe buffer - it was allocated
* via the coherent allocators.
*/
} else {
consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
}
Expand Down Expand Up @@ -604,9 +588,10 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->total_allocs = 0;
device_info->map_op_count = 0;
device_info->bounce_count = 0;
device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats);
#endif

list_add(&device_info->node, &dmabounce_devs);
dev->archdata.dmabounce = device_info;

printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
dev->bus_id, dev->bus->name);
Expand All @@ -623,7 +608,9 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
void
dmabounce_unregister_dev(struct device *dev)
{
struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;

dev->archdata.dmabounce = NULL;

if (!device_info) {
printk(KERN_WARNING
Expand All @@ -645,12 +632,10 @@ dmabounce_unregister_dev(struct device *dev)
dma_pool_destroy(device_info->large.pool);

#ifdef STATS
print_alloc_stats(device_info);
print_map_stats(device_info);
if (device_info->attr_res == 0)
device_remove_file(dev, &dev_attr_dmabounce_stats);
#endif

list_del(&device_info->node);

kfree(device_info);

printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
Expand Down
Loading

0 comments on commit ef6d7d7

Please sign in to comment.