From: gregory.clement@free-electrons.com (Gregory CLEMENT)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 2/2] arm: mvebu: Add hardware I/O Coherency support
Date: Wed, 24 Oct 2012 10:13:07 +0200 [thread overview]
Message-ID: <5087A313.7080306@free-electrons.com> (raw)
In-Reply-To: <2E2747FC8980BB40958FB06A958ED3550144C25FAD4F@IL-MB01.marvell.com>
On 10/24/2012 10:11 AM, Yehuda Yitschak wrote:
>
>
>> -----Original Message-----
>> From: Gregory CLEMENT [mailto:gregory.clement at free-electrons.com]
>> Sent: Wednesday, October 24, 2012 10:04 AM
>> To: Jason Cooper; Andrew Lunn; Gregory Clement
>> Cc: linux-arm-kernel at lists.infradead.org; Arnd Bergmann; Olof Johansson;
>> Russell King; Rob Herring; Ben Dooks; Ian Molton; Nicolas Pitre; Lior
>> Amsalem; Maen Suleiman; Tawfik Bayouk; Shadi Ammouri; Eran Ben-Avi;
>> Yehuda Yitschak; Nadav Haklai; Ike Pan; Jani Monoses; Chris Van Hoof; Dan
>> Frazier; Thomas Petazzoni; Leif Lindholm; Jon Masters; David Marlin;
>> Sebastian Hesselbarth; linux-kernel at vger.kernel.org
>> Subject: [PATCH 2/2] arm: mvebu: Add hardware I/O Coherency support
>>
>> Armada 370 and XP come with an unit called coherency fabric. This unit
>> allows to use the Armada XP as a nearly coherent architecture. The
>> coherency mechanism uses snoop filters to ensure the coherency between
>> caches, DRAM and devices. This mechanism needs a synchronization barrier
>> which guarantees that all memory write initiated by the devices has
>> reached their target and do not reside in intermediate write buffers. That's
>> why the architecture is not totally coherent and we need to provide our
>> own functions for some DMA operations.
>>
>> Beside the use of the coherency fabric, the device units will have to set the
>> attribute flag to select the accurate coherency process for the memory
>> transaction. This is done each device driver programs the DRAM address
>> windows. The value of the attribute set by the driver is retrieved through
>> the orion_addr_map_cfg struct filled during the early initialization of the
>> platform.
>>
>> Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
>> Reviewed-by: Yehuda Yitschak <yehuday@marvell.com>
>> ---
>> arch/arm/boot/dts/armada-370-xp.dtsi | 3 +-
>> arch/arm/mach-mvebu/addr-map.c | 3 ++
>> arch/arm/mach-mvebu/armada-370-xp.c | 1 +
>> arch/arm/mach-mvebu/coherency.c | 87
>> ++++++++++++++++++++++++++++++++++
>> arch/arm/mach-mvebu/common.h | 2 +
>> 5 files changed, 95 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi
>> b/arch/arm/boot/dts/armada-370-xp.dtsi
>> index 18ba60b..af22e53 100644
>> --- a/arch/arm/boot/dts/armada-370-xp.dtsi
>> +++ b/arch/arm/boot/dts/armada-370-xp.dtsi
>> @@ -38,7 +38,8 @@
>>
>> coherency-fabric at d0020200 {
>> compatible = "marvell,coherency-fabric";
>> - reg = <0xd0020200 0xb0>;
>> + reg = <0xd0020200 0xb0>,
>> + <0xd0021010 0x1c>;
>> };
>>
>> soc {
>> diff --git a/arch/arm/mach-mvebu/addr-map.c b/arch/arm/mach-
>> mvebu/addr-map.c index fe454a4..595f6b7 100644
>> --- a/arch/arm/mach-mvebu/addr-map.c
>> +++ b/arch/arm/mach-mvebu/addr-map.c
>> @@ -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.
>> */
>> diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-
>> mvebu/armada-370-xp.c
>> index 41431a1..3517f7d 100644
>> --- a/arch/arm/mach-mvebu/armada-370-xp.c
>> +++ b/arch/arm/mach-mvebu/armada-370-xp.c
>> @@ -49,6 +49,7 @@ struct sys_timer armada_370_xp_timer = {
>>
>> static void __init armada_370_xp_dt_init(void) {
>> + armada_370_xp_coherency_iocache_init();
>> of_platform_populate(NULL, of_default_bus_match_table, NULL,
>> NULL); }
>>
>> diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-
>> mvebu/coherency.c index 71e27ba..a596ca9 100644
>> --- a/arch/arm/mach-mvebu/coherency.c
>> +++ b/arch/arm/mach-mvebu/coherency.c
>> @@ -22,6 +22,10 @@
>> #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"
>>
>> /* Some functions in this file are called very early during SMP @@ -31,16
>> +35,53 @@
>> * value matching its virtual mapping
>> */
>> static void __iomem *coherency_base = ARMADA_370_XP_REGS_VIRT_BASE
>> + 0x20200;
>> +static void __iomem *coherency_cpu_base;
>> +
>> +struct dma_map_ops armada_xp_dma_ops;
>>
>> /* Coherency fabric registers */
>> #define COHERENCY_FABRIC_CTL_OFFSET 0x0
>> #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 */ },
>> };
>>
>> +static inline void armada_xp_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);
>> +}
>> +
>> +dma_addr_t armada_xp_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)
>> + armada_xp_sync_io_barrier();
>> + return pfn_to_dma(dev, page_to_pfn(page)) + offset; }
>> +
>> +
>> +void armada_xp_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)
>> + armada_xp_sync_io_barrier();
>> +}
>> +
>> +void armada_xp_dma_sync(struct device *dev, dma_addr_t dma_handle,
>> + size_t size, enum dma_data_direction dir) {
>> + if (dir != DMA_TO_DEVICE)
>> + armada_xp_sync_io_barrier();
>> +}
>> +
>
> Shouldn't all the 4 functions above start with armada_370_xp and not armada_xp ?
>
Yes good catch!
>
>> int armada_xp_get_cpu_count(void)
>
> This function can be limited to CONFIG_SP
>
Right
>> {
>> int reg, cnt;
>> @@ -74,6 +115,42 @@ int armada_370_xp_set_cpu_coherent(unsigned int
>> hw_cpu_id, int smp_group_id)
>> return 0;
>> }
>>
>> +static int armada_xp_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, &armada_xp_dma_ops);
>> +
>> + return NOTIFY_OK;
>> +}
>> +
>> +static struct notifier_block armada_xp_platform_nb = {
>> + .notifier_call = armada_xp_platform_notifier, };
>> +
>> +void __init armada_370_xp_coherency_iocache_init(void)
>> +{
>> + /* When the coherency fabric is available, the Armada XP and
>> + * Aramada 370 are close to a coherent architecture, so we based
>> + * our dma ops on the coherent one, and just changes the
>> + * operations which need a arch io sync */
>> + if (of_find_compatible_node(NULL, NULL, "marvell,coherency-
>> fabric")) {
>> + struct dma_map_ops *dma_ops = &armada_xp_dma_ops;
>> + memcpy(dma_ops, &arm_coherent_dma_ops,
>> sizeof(*dma_ops));
>> + dma_ops->map_page = armada_xp_dma_map_page;
>> + dma_ops->unmap_page = armada_xp_dma_unmap_page;
>> + dma_ops->unmap_sg = arm_dma_ops.unmap_sg;
>> + dma_ops->sync_single_for_cpu = armada_xp_dma_sync;
>> + dma_ops->sync_single_for_device = armada_xp_dma_sync;
>> + dma_ops->sync_sg_for_cpu =
>> arm_dma_ops.sync_sg_for_cpu;
>> + dma_ops->sync_sg_for_device =
>> arm_dma_ops.sync_sg_for_device;
>> + }
>> + bus_register_notifier(&platform_bus_type,
>> &armada_xp_platform_nb); }
>> +
>> int __init armada_370_xp_coherency_init(void)
>> {
>> struct device_node *np;
>> @@ -82,7 +159,17 @@ int __init armada_370_xp_coherency_init(void)
>> if (np) {
>> pr_info("Initializing Coherency fabric\n");
>> coherency_base = of_iomap(np, 0);
>> + coherency_cpu_base = of_iomap(np, 1);
>> + }
>> +#ifndef CONFIG_SMP
>> + if (coherency_base) {
>> + /* In UP case, cpu coherency is enabled here, in SMP case
>> cpu
>> + * coherency is enabled for each CPU by
>> + * armada_xp_smp_prepare_cpus() in platsmp.c */
>> + int hw_cpuid = cpu_logical_map(smp_processor_id());
>> + armada_370_xp_set_cpu_coherent(hw_cpuid, 0);
>> }
>> +#endif
>>
>> return 0;
>> }
>> diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-
>> mvebu/common.h index 86484bb..fff952e 100644
>> --- a/arch/arm/mach-mvebu/common.h
>> +++ b/arch/arm/mach-mvebu/common.h
>> @@ -23,6 +23,8 @@ void armada_370_xp_handle_irq(struct pt_regs *regs);
>>
>> void armada_xp_cpu_die(unsigned int cpu);
>>
>> +void armada_370_xp_coherency_iocache_init(void);
>> +
>> int armada_370_xp_coherency_init(void);
>> int armada_370_xp_pmsu_init(void);
>> void armada_xp_secondary_startup(void);
>> --
>> 1.7.9.5
>
--
Gregory Clement, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com
next prev parent reply other threads:[~2012-10-24 8:13 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-24 8:03 [PATCH 0/2] Add hardware I/O coherency support for Armada 370/XP Gregory CLEMENT
2012-10-24 8:03 ` Gregory CLEMENT
2012-10-24 8:04 ` [PATCH 1/2] arm: plat-orion: Add coherency attribute when setup mbus target Gregory CLEMENT
2012-10-24 8:04 ` Gregory CLEMENT
2012-10-24 11:55 ` Thomas Petazzoni
2012-10-24 11:55 ` Thomas Petazzoni
2012-10-24 8:04 ` [PATCH 2/2] arm: mvebu: Add hardware I/O Coherency support Gregory CLEMENT
2012-10-24 8:04 ` Gregory CLEMENT
2012-10-24 8:11 ` Yehuda Yitschak
2012-10-24 8:11 ` Yehuda Yitschak
2012-10-24 8:13 ` Gregory CLEMENT [this message]
2012-10-24 8:25 ` Andrew Lunn
2012-10-24 11:50 ` Gregory CLEMENT
2012-10-24 11:50 ` Gregory CLEMENT
2012-10-24 11:36 ` Arnd Bergmann
2012-10-24 11:36 ` Arnd Bergmann
2012-10-24 11:48 ` Gregory CLEMENT
2012-10-24 11:48 ` Gregory CLEMENT
2012-10-24 11:53 ` Gregory CLEMENT
2012-10-24 11:53 ` Gregory CLEMENT
2012-10-24 12:24 ` Arnd Bergmann
2012-10-24 12:24 ` Arnd Bergmann
2012-10-24 13:56 ` Gregory CLEMENT
2012-10-24 13:56 ` Gregory CLEMENT
2012-10-24 20:30 ` Arnd Bergmann
2012-10-24 20:30 ` Arnd Bergmann
2012-10-24 12:27 ` Thomas Petazzoni
2012-10-24 12:27 ` Thomas Petazzoni
2012-10-24 14:39 ` Gregory CLEMENT
2012-10-24 14:39 ` Gregory CLEMENT
2012-10-24 14:56 ` Thomas Petazzoni
2012-10-24 14:56 ` Thomas Petazzoni
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5087A313.7080306@free-electrons.com \
--to=gregory.clement@free-electrons.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.