Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 344333
b: refs/heads/master
c: 56580bb
h: refs/heads/master
i:
  344331: 374f3c2
v: v3
  • Loading branch information
Jason Cooper committed Nov 24, 2012
1 parent a1a131f commit 33d6375
Show file tree
Hide file tree
Showing 9 changed files with 94 additions and 7 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: 73d9cdca1ced6ab32be363b58699039bd82b062a
refs/heads/master: 56580bb422e5f542da19c057f348dd39634138e7
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ Available on Marvell SOCs: Armada 370 and Armada XP
Required properties:

- compatible: "marvell,coherency-fabric"
- reg: Should contain,coherency fabric registers location and length.

- reg: Should contain coherency fabric registers location and
length. First pair for the coherency fabric registers, second pair
for the per-CPU fabric registers registers.

Example:

coherency-fabric@d0020200 {
compatible = "marvell,coherency-fabric";
reg = <0xd0020200 0xb0>;
reg = <0xd0020200 0xb0>,
<0xd0021810 0x1c>;

};

3 changes: 2 additions & 1 deletion trunk/arch/arm/boot/dts/armada-370-xp.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@

coherency-fabric@d0020200 {
compatible = "marvell,coherency-fabric";
reg = <0xd0020200 0xb0>;
reg = <0xd0020200 0xb0>,
<0xd0021810 0x1c>;
};

soc {
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/arm/include/asm/dma-mapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ static inline void dma_free_noncoherent(struct device *dev, size_t size,

extern int dma_supported(struct device *dev, u64 mask);

extern int arm_dma_set_mask(struct device *dev, u64 dma_mask);

/**
* arm_dma_alloc - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
Expand Down
3 changes: 3 additions & 0 deletions trunk/arch/arm/mach-mvebu/addr-map.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ static int __init armada_setup_cpu_mbus(void)

addr_map_cfg.bridge_virt_base = mbus_unit_addr_decoding_base;

if (of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"))
addr_map_cfg.hw_io_coherency = 1;

/*
* Disable, clear and configure windows.
*/
Expand Down
73 changes: 73 additions & 0 deletions trunk/arch/arm/mach-mvebu/coherency.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/smp.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <asm/smp_plat.h>
#include "armada-370-xp.h"

Expand All @@ -33,10 +35,13 @@
* value matching its virtual mapping
*/
static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE + 0x20200;
static void __iomem *coherency_cpu_base;

/* Coherency fabric registers */
#define COHERENCY_FABRIC_CFG_OFFSET 0x4

#define IO_SYNC_BARRIER_CTL_OFFSET 0x0

static struct of_device_id of_coherency_table[] = {
{.compatible = "marvell,coherency-fabric"},
{ /* end of list */ },
Expand Down Expand Up @@ -68,6 +73,70 @@ int set_cpu_coherent(unsigned int hw_cpu_id, int smp_group_id)
return ll_set_cpu_coherent(coherency_base, hw_cpu_id);
}

static inline void mvebu_hwcc_sync_io_barrier(void)
{
writel(0x1, coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET);
while (readl(coherency_cpu_base + IO_SYNC_BARRIER_CTL_OFFSET) & 0x1);
}

static dma_addr_t mvebu_hwcc_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
struct dma_attrs *attrs)
{
if (dir != DMA_TO_DEVICE)
mvebu_hwcc_sync_io_barrier();
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
}


static void mvebu_hwcc_dma_unmap_page(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir,
struct dma_attrs *attrs)
{
if (dir != DMA_TO_DEVICE)
mvebu_hwcc_sync_io_barrier();
}

static void mvebu_hwcc_dma_sync(struct device *dev, dma_addr_t dma_handle,
size_t size, enum dma_data_direction dir)
{
if (dir != DMA_TO_DEVICE)
mvebu_hwcc_sync_io_barrier();
}

static struct dma_map_ops mvebu_hwcc_dma_ops = {
.alloc = arm_dma_alloc,
.free = arm_dma_free,
.mmap = arm_dma_mmap,
.map_page = mvebu_hwcc_dma_map_page,
.unmap_page = mvebu_hwcc_dma_unmap_page,
.get_sgtable = arm_dma_get_sgtable,
.map_sg = arm_dma_map_sg,
.unmap_sg = arm_dma_unmap_sg,
.sync_single_for_cpu = mvebu_hwcc_dma_sync,
.sync_single_for_device = mvebu_hwcc_dma_sync,
.sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
.sync_sg_for_device = arm_dma_sync_sg_for_device,
.set_dma_mask = arm_dma_set_mask,
};

static int mvebu_hwcc_platform_notifier(struct notifier_block *nb,
unsigned long event, void *__dev)
{
struct device *dev = __dev;

if (event != BUS_NOTIFY_ADD_DEVICE)
return NOTIFY_DONE;
set_dma_ops(dev, &mvebu_hwcc_dma_ops);

return NOTIFY_OK;
}

static struct notifier_block mvebu_hwcc_platform_nb = {
.notifier_call = mvebu_hwcc_platform_notifier,
};

int __init coherency_init(void)
{
struct device_node *np;
Expand All @@ -76,6 +145,10 @@ int __init coherency_init(void)
if (np) {
pr_info("Initializing Coherency fabric\n");
coherency_base = of_iomap(np, 0);
coherency_cpu_base = of_iomap(np, 1);
set_cpu_coherent(cpu_logical_map(smp_processor_id()), 0);
bus_register_notifier(&platform_bus_type,
&mvebu_hwcc_platform_nb);
}

return 0;
Expand Down
4 changes: 1 addition & 3 deletions trunk/arch/arm/mm/dma-mapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ static void arm_dma_sync_single_for_device(struct device *dev,
__dma_page_cpu_to_dev(page, offset, size, dir);
}

static int arm_dma_set_mask(struct device *dev, u64 dma_mask);

struct dma_map_ops arm_dma_ops = {
.alloc = arm_dma_alloc,
.free = arm_dma_free,
Expand Down Expand Up @@ -971,7 +969,7 @@ int dma_supported(struct device *dev, u64 mask)
}
EXPORT_SYMBOL(dma_supported);

static int arm_dma_set_mask(struct device *dev, u64 dma_mask)
int arm_dma_set_mask(struct device *dev, u64 dma_mask)
{
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
Expand Down
4 changes: 4 additions & 0 deletions trunk/arch/arm/plat-orion/addr-map.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ EXPORT_SYMBOL_GPL(mv_mbus_dram_info);
#define WIN_REMAP_LO_OFF 0x0008
#define WIN_REMAP_HI_OFF 0x000c

#define ATTR_HW_COHERENCY (0x1 << 4)

/*
* Default implementation
*/
Expand Down Expand Up @@ -163,6 +165,8 @@ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
w = &orion_mbus_dram_info.cs[cs++];
w->cs_index = i;
w->mbus_attr = 0xf & ~(1 << i);
if (cfg->hw_io_coherency)
w->mbus_attr |= ATTR_HW_COHERENCY;
w->base = base & 0xffff0000;
w->size = (size | 0x0000ffff) + 1;
}
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm/plat-orion/include/plat/addr-map.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct orion_addr_map_cfg {
const int num_wins; /* Total number of windows */
const int remappable_wins;
void __iomem *bridge_virt_base;
int hw_io_coherency;

/* If NULL, the default cpu_win_can_remap will be used, using
the value in remappable_wins */
Expand Down

0 comments on commit 33d6375

Please sign in to comment.