Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204475
b: refs/heads/master
c: ca36c36
h: refs/heads/master
i:
  204473: ce50def
  204471: 7c78975
v: v3
  • Loading branch information
David VomLehn authored and Ralf Baechle committed Aug 5, 2010
1 parent 6d5138a commit cfb6704
Show file tree
Hide file tree
Showing 7 changed files with 530 additions and 143 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: 36f217d9df3e6bf8e6ae7647827b485b79dbaf8e
refs/heads/master: ca36c36b7821b573fe06ce6bc34db03b557f3ce4
8 changes: 4 additions & 4 deletions trunk/arch/mips/include/asm/mach-powertv/dma-coherence.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,21 @@ static inline dma_addr_t plat_map_dma_mem(struct device *dev, void *addr,
size_t size)
{
if (is_kseg2(addr))
return phys_to_bus(virt_to_phys_from_pte(addr));
return phys_to_dma(virt_to_phys_from_pte(addr));
else
return phys_to_bus(virt_to_phys(addr));
return phys_to_dma(virt_to_phys(addr));
}

static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
struct page *page)
{
return phys_to_bus(page_to_phys(page));
return phys_to_dma(page_to_phys(page));
}

static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
dma_addr_t dma_addr)
{
return bus_to_phys(dma_addr);
return dma_to_phys(dma_addr);
}

static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
Expand Down
165 changes: 121 additions & 44 deletions trunk/arch/mips/include/asm/mach-powertv/ioremap.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,101 @@
#define __ASM_MACH_POWERTV_IOREMAP_H

#include <linux/types.h>
#include <linux/log2.h>
#include <linux/compiler.h>

#define LOW_MEM_BOUNDARY_PHYS 0x20000000
#define LOW_MEM_BOUNDARY_MASK (~(LOW_MEM_BOUNDARY_PHYS - 1))
#include <asm/pgtable-bits.h>
#include <asm/addrspace.h>

/* We're going to mess with bits, so get sizes */
#define IOR_BPC 8 /* Bits per char */
#define IOR_PHYS_BITS (IOR_BPC * sizeof(phys_addr_t))
#define IOR_DMA_BITS (IOR_BPC * sizeof(dma_addr_t))

/*
* The bus addresses are different than the physical addresses that
* the processor sees by an offset. This offset varies by ASIC
* version. Define a variable to hold the offset and some macros to
* make the conversion simpler. */
extern unsigned long phys_to_bus_offset;

#ifdef CONFIG_HIGHMEM
#define MEM_GAP_PHYS 0x60000000
* Define the granularity of physical/DMA mapping in terms of the number
* of bits that defines the offset within a grain. These will be the
* least significant bits of the address. The rest of a physical or DMA
* address will be used to index into an appropriate table to find the
* offset to add to the address to yield the corresponding DMA or physical
* address, respectively.
*/
#define IOR_LSBITS 22 /* Bits in a grain */

/*
* TODO: We will use the hard code for conversion between physical and
* bus until the bootloader releases their device tree to us.
* Compute the number of most significant address bits after removing those
* used for the offset within a grain and then compute the number of table
* entries for the conversion.
*/
#define phys_to_bus(x) (((x) < LOW_MEM_BOUNDARY_PHYS) ? \
((x) + phys_to_bus_offset) : (x))
#define bus_to_phys(x) (((x) < MEM_GAP_PHYS_ADDR) ? \
((x) - phys_to_bus_offset) : (x))
#else
#define phys_to_bus(x) ((x) + phys_to_bus_offset)
#define bus_to_phys(x) ((x) - phys_to_bus_offset)
#endif
#define IOR_PHYS_MSBITS (IOR_PHYS_BITS - IOR_LSBITS)
#define IOR_NUM_PHYS_TO_DMA ((phys_addr_t) 1 << IOR_PHYS_MSBITS)

#define IOR_DMA_MSBITS (IOR_DMA_BITS - IOR_LSBITS)
#define IOR_NUM_DMA_TO_PHYS ((dma_addr_t) 1 << IOR_DMA_MSBITS)

/*
* Determine whether the address we are given is for an ASIC device
* Params: addr Address to check
* Returns: Zero if the address is not for ASIC devices, non-zero
* if it is.
* Define data structures used as elements in the arrays for the conversion
* between physical and DMA addresses. We do some slightly fancy math to
* compute the width of the offset element of the conversion tables so
* that we can have the smallest conversion tables. Next, round up the
* sizes to the next higher power of two, i.e. the offset element will have
* 8, 16, 32, 64, etc. bits. This eliminates the need to mask off any
* bits. Finally, we compute a shift value that puts the most significant
* bits of the offset into the most significant bits of the offset element.
* This makes it more efficient on processors without barrel shifters and
* easier to see the values if the conversion table is dumped in binary.
*/
static inline int asic_is_device_addr(phys_t addr)
#define _IOR_OFFSET_WIDTH(n) (1 << order_base_2(n))
#define IOR_OFFSET_WIDTH(n) \
(_IOR_OFFSET_WIDTH(n) < 8 ? 8 : _IOR_OFFSET_WIDTH(n))

#define IOR_PHYS_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_PHYS_MSBITS)
#define IOR_PHYS_SHIFT (IOR_PHYS_BITS - IOR_PHYS_OFFSET_BITS)

#define IOR_DMA_OFFSET_BITS IOR_OFFSET_WIDTH(IOR_DMA_MSBITS)
#define IOR_DMA_SHIFT (IOR_DMA_BITS - IOR_DMA_OFFSET_BITS)

struct ior_phys_to_dma {
dma_addr_t offset:IOR_DMA_OFFSET_BITS __packed
__aligned((IOR_DMA_OFFSET_BITS / IOR_BPC));
};

struct ior_dma_to_phys {
dma_addr_t offset:IOR_PHYS_OFFSET_BITS __packed
__aligned((IOR_PHYS_OFFSET_BITS / IOR_BPC));
};

extern struct ior_phys_to_dma _ior_phys_to_dma[IOR_NUM_PHYS_TO_DMA];
extern struct ior_dma_to_phys _ior_dma_to_phys[IOR_NUM_DMA_TO_PHYS];

static inline dma_addr_t _phys_to_dma_offset_raw(phys_addr_t phys)
{
return !((phys_t)addr & (phys_t) LOW_MEM_BOUNDARY_MASK);
return (dma_addr_t)_ior_phys_to_dma[phys >> IOR_LSBITS].offset;
}

/*
* Determine whether the address we are given is external RAM mappable
* into KSEG1.
* Params: addr Address to check
* Returns: Zero if the address is not for external RAM and
*/
static inline int asic_is_lowmem_ram_addr(phys_t addr)
static inline dma_addr_t _dma_to_phys_offset_raw(dma_addr_t dma)
{
/*
* The RAM always starts at the following address in the processor's
* physical address space
*/
static const phys_t phys_ram_base = 0x10000000;
phys_t bus_ram_base;
return (dma_addr_t)_ior_dma_to_phys[dma >> IOR_LSBITS].offset;
}

bus_ram_base = phys_to_bus_offset + phys_ram_base;
/* These are not portable and should not be used in drivers. Drivers should
* be using ioremap() and friends to map physical addreses to virtual
* addresses and dma_map*() and friends to map virtual addresses into DMA
* addresses and back.
*/
static inline dma_addr_t phys_to_dma(phys_addr_t phys)
{
return phys + (_phys_to_dma_offset_raw(phys) << IOR_PHYS_SHIFT);
}

return addr >= bus_ram_base &&
addr < (bus_ram_base + (LOW_MEM_BOUNDARY_PHYS - phys_ram_base));
static inline phys_addr_t dma_to_phys(dma_addr_t dma)
{
return dma + (_dma_to_phys_offset_raw(dma) << IOR_DMA_SHIFT);
}

extern void ioremap_add_map(dma_addr_t phys, phys_addr_t alias,
dma_addr_t size);

/*
* Allow physical addresses to be fixed up to help peripherals located
* outside the low 32-bit range -- generic pass-through version.
Expand All @@ -77,10 +114,50 @@ static inline phys_t fixup_bigphys_addr(phys_t phys_addr, phys_t size)
return phys_addr;
}

static inline void __iomem *plat_ioremap(phys_t offset, unsigned long size,
/*
* Handle the special case of addresses the area aliased into the first
* 512 MiB of the processor's physical address space. These turn into either
* kseg0 or kseg1 addresses, depending on flags.
*/
static inline void __iomem *plat_ioremap(phys_t start, unsigned long size,
unsigned long flags)
{
return NULL;
phys_addr_t start_offset;
void __iomem *result = NULL;

/* Start by checking to see whether this is an aliased address */
start_offset = _dma_to_phys_offset_raw(start);

/*
* If:
* o the memory is aliased into the first 512 MiB, and
* o the start and end are in the same RAM bank, and
* o we don't have a zero size or wrap around, and
* o we are supposed to create an uncached mapping,
* handle this is a kseg0 or kseg1 address
*/
if (start_offset != 0) {
phys_addr_t last;
dma_addr_t dma_to_phys_offset;

last = start + size - 1;
dma_to_phys_offset =
_dma_to_phys_offset_raw(last) << IOR_DMA_SHIFT;

if (dma_to_phys_offset == start_offset &&
size != 0 && start <= last) {
phys_t adjusted_start;
adjusted_start = start + start_offset;
if (flags == _CACHE_UNCACHED)
result = (void __iomem *) (unsigned long)
CKSEG1ADDR(adjusted_start);
else
result = (void __iomem *) (unsigned long)
CKSEG0ADDR(adjusted_start);
}
}

return result;
}

static inline int plat_iounmap(const volatile void __iomem *addr)
Expand Down
3 changes: 2 additions & 1 deletion trunk/arch/mips/powertv/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
# under Linux.
#

obj-y += init.o memory.o reset.o time.o powertv_setup.o asic/ pci/
obj-y += init.o ioremap.o memory.o powertv_setup.o reset.o time.o \
asic/ pci/

EXTRA_CFLAGS += -Wall -Werror
18 changes: 9 additions & 9 deletions trunk/arch/mips/powertv/asic/asic_devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ static bool usb_configured;
* Don't recommend to use it directly, it is usually used by kernel internally.
* Portable code should be using interfaces such as ioremp, dma_map_single, etc.
*/
unsigned long phys_to_bus_offset;
EXPORT_SYMBOL(phys_to_bus_offset);
unsigned long phys_to_dma_offset;
EXPORT_SYMBOL(phys_to_dma_offset);

/*
*
Expand Down Expand Up @@ -533,10 +533,10 @@ void __init configure_platform(void)

switch (asic) {
case ASIC_ZEUS:
phys_to_bus_offset = 0x30000000;
phys_to_dma_offset = 0x30000000;
break;
case ASIC_CALLIOPE:
phys_to_bus_offset = 0x10000000;
phys_to_dma_offset = 0x10000000;
break;
case ASIC_CRONUSLITE:
/* Fall through */
Expand All @@ -546,10 +546,10 @@ void __init configure_platform(void)
* 0x2XXXXXXX. If 0x10000000 aliases into 0x60000000-
* 0x6XXXXXXX, the offset should be 0x50000000, not 0x10000000.
*/
phys_to_bus_offset = 0x10000000;
phys_to_dma_offset = 0x10000000;
break;
default:
phys_to_bus_offset = 0x00000000;
phys_to_dma_offset = 0x00000000;
break;
}
}
Expand Down Expand Up @@ -603,7 +603,7 @@ void __init platform_alloc_bootmem(void)
int size = gp_resources[i].end - gp_resources[i].start + 1;
if ((gp_resources[i].start != 0) &&
((gp_resources[i].flags & IORESOURCE_MEM) != 0)) {
reserve_bootmem(bus_to_phys(gp_resources[i].start),
reserve_bootmem(dma_to_phys(gp_resources[i].start),
size, 0);
total += gp_resources[i].end -
gp_resources[i].start + 1;
Expand All @@ -627,7 +627,7 @@ void __init platform_alloc_bootmem(void)

else {
gp_resources[i].start =
phys_to_bus(virt_to_phys(mem));
phys_to_dma(virt_to_phys(mem));
gp_resources[i].end =
gp_resources[i].start + size - 1;
total += size;
Expand Down Expand Up @@ -691,7 +691,7 @@ static void __init pmem_setup_resource(void)
if (resource && pmemaddr && pmemlen) {
/* The address provided by bootloader is in kseg0. Convert to
* a bus address. */
resource->start = phys_to_bus(pmemaddr - 0x80000000);
resource->start = phys_to_dma(pmemaddr - 0x80000000);
resource->end = resource->start + pmemlen - 1;

pr_info("persistent memory: start=0x%x end=0x%x\n",
Expand Down
Loading

0 comments on commit cfb6704

Please sign in to comment.