[PATCH v2 1/4] ARM: CSR: add rtc i/o bridge interface for SiRFprimaII
Barry Song
21cnbao at gmail.com
Tue Aug 23 05:33:39 EDT 2011
Hi Jamie,
Thanks.
2011/8/23 Jamie Iles <jamie at jamieiles.com>:
> Hi Barry,
>
> On Mon, Aug 22, 2011 at 11:15:49PM -0700, Barry Song wrote:
>> From: Zhiwu Song <zhiwu.song at csr.com>
>>
>> The module is a bridge between the RTC clock domain and the CPU interface
>> clock domain. ARM access the register of SYSRTC, GPSRTC and PWRC through
>> this module.
>>
>> Signed-off-by: Zhiwu Song <zhiwu.song at csr.com>
>> Signed-off-by: Barry Song <Baohua.Song at csr.com>
>
> A couple of minor nits inline (sorry if I didn't pick them up last
> time). Feel free to add a:
>
> Reviewed-by: Jamie Iles <jamie at jamieiles.com>
>
> if you choose to make those changes.
yes, i will.
>
> Jamie
>
>> ---
>> -v2:
>> handle feedback from Jamie Iles <jamie at jamieiles.com>
>> make rtciobrg become a device driver
>> make devices behind rtciobrg not be compatible with simple-bus
>> replace EXPORT_SYMBOL by EXPORT_SYMBOL_GPL
>>
>> arch/arm/boot/dts/prima2-cb.dts | 2 +-
>> arch/arm/mach-prima2/Makefile | 1 +
>> arch/arm/mach-prima2/rtciobrg.c | 136 ++++++++++++++++++++++++++++++++++
>> include/linux/rtc/sirfsoc_rtciobrg.h | 18 +++++
>> 4 files changed, 156 insertions(+), 1 deletions(-)
>> create mode 100644 arch/arm/mach-prima2/rtciobrg.c
>> create mode 100644 include/linux/rtc/sirfsoc_rtciobrg.h
>>
>> diff --git a/arch/arm/boot/dts/prima2-cb.dts b/arch/arm/boot/dts/prima2-cb.dts
>> index 6fecc88..e5e9bc6 100644
>> --- a/arch/arm/boot/dts/prima2-cb.dts
>> +++ b/arch/arm/boot/dts/prima2-cb.dts
>> @@ -358,7 +358,7 @@
>> };
>>
>> rtc-iobg {
>> - compatible = "sirf,prima2-rtciobg", "simple-bus";
>> + compatible = "sirf,prima2-rtciobg", "sirf-prima2-rtciobg-bus";
>> #address-cells = <1>;
>> #size-cells = <1>;
>> reg = <0x80030000 0x10000>;
>> diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
>> index 7af7fc0..f49d70b 100644
>> --- a/arch/arm/mach-prima2/Makefile
>> +++ b/arch/arm/mach-prima2/Makefile
>> @@ -3,5 +3,6 @@ obj-y += irq.o
>> obj-y += clock.o
>> obj-y += rstc.o
>> obj-y += prima2.o
>> +obj-y += rtciobrg.o
>> obj-$(CONFIG_DEBUG_LL) += lluart.o
>> obj-$(CONFIG_CACHE_L2X0) += l2x0.o
>> diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
>> new file mode 100644
>> index 0000000..1163e2c
>> --- /dev/null
>> +++ b/arch/arm/mach-prima2/rtciobrg.c
>> @@ -0,0 +1,136 @@
>> +/*
>> + * RTC I/O Bridge interfaces for CSR SiRFprimaII
>> + * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
>> + *
>> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
>> + *
>> + * Licensed under GPLv2 or later.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_device.h>
>> +#include <linux/of_platform.h>
>> +
>> +#define SIRFSOC_CPUIOBRG_CTRL 0x00
>> +#define SIRFSOC_CPUIOBRG_WRBE 0x04
>> +#define SIRFSOC_CPUIOBRG_ADDR 0x08
>> +#define SIRFSOC_CPUIOBRG_DATA 0x0c
>> +
>> +void __iomem *sirfsoc_rtciobrg_base;
>> +static DEFINE_SPINLOCK(rtciobrg_lock);
>> +
>> +void sirfsoc_rtc_iobrg_wait_sync(void)
>> +{
>> + while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL))
>> + continue;
>
> It might be worth using cpu_relax() here as it includes a memory barrier
> that's what many busy wait loops do.
yes. generically people add a cpu_relax() in busy wait and that makes
lots of senses. it seems readl_relaxed() can keep the execution
sequence even without the barrier?
Then there are:
static inline void cache_wait_way(void __iomem *reg, unsigned long mask)
{
/* wait for cache operation by line or way to complete */
while (readl_relaxed(reg) & mask)
;
}
static inline void ux500_cache_wait(void __iomem *reg, unsigned long mask)
{
/* wait for the operation to complete */
while (readl_relaxed(reg) & mask)
;
}
>
>> +}
>> +
>> +void sirfsoc_rtc_iobrg_besyncing(void)
>> +{
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&rtciobrg_lock, flags);
>> +
>> + sirfsoc_rtc_iobrg_wait_sync();
>> +
>> + spin_unlock_irqrestore(&rtciobrg_lock, flags);
>> +}
>> +EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing);
>> +
>> +u32 __sirfsoc_rtc_iobrg_readl(u32 addr)
>> +{
>> + unsigned long val;
>> +
>> + sirfsoc_rtc_iobrg_wait_sync();
>> +
>> + writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
>> + writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
>> + writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
>> +
>> + sirfsoc_rtc_iobrg_wait_sync();
>> +
>> + val = readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
>> +
>> + return val;
>
> I don't think this needs the temporary 'val', but that's not a big
> problem.
i think it can be "return readl_relaxed(sirfsoc_rtciobrg_base +
SIRFSOC_CPUIOBRG_DATA);"
>
>> +}
>> +
>> +u32 sirfsoc_rtc_iobrg_readl(u32 addr)
>> +{
>> + unsigned long flags, val;
>> +
>> + spin_lock_irqsave(&rtciobrg_lock, flags);
>> +
>> + val = __sirfsoc_rtc_iobrg_readl(addr);
>> +
>> + spin_unlock_irqrestore(&rtciobrg_lock, flags);
>> +
>> + return val;
>> +}
>> +EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl);
>> +
>> +void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr)
>> +{
>> + sirfsoc_rtc_iobrg_wait_sync();
>> +
>> + writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE);
>> + writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR);
>> +
>> + writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA);
>> +}
>> +
>> +void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr)
>> +{
>> + unsigned long flags;
>> +
>> + spin_lock_irqsave(&rtciobrg_lock, flags);
>> +
>> + sirfsoc_rtc_iobrg_pre_writel(val, addr);
>> +
>> + writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL);
>> +
>> + sirfsoc_rtc_iobrg_wait_sync();
>> +
>> + spin_unlock_irqrestore(&rtciobrg_lock, flags);
>> +}
>> +EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel);
>> +
>> +static struct of_device_id rtciobrg_ids[] = {
>
> const?
true.
>
>> + { .compatible = "sirf,prima2-rtciobg" },
>> + {}
>> +};
>> +
>> +static int __devinit sirfsoc_rtciobrg_probe(struct platform_device *op)
>> +{
>> + struct device_node *np = op->dev.of_node;
>> +
>> + sirfsoc_rtciobrg_base = of_iomap(np, 0);
>> + if (!sirfsoc_rtciobrg_base)
>> + panic("unable to map rtc iobrg registers\n");
>> +
>> + return 0;
>> +}
>> +
>> +static struct platform_driver sirfsoc_rtciobrg_driver = {
>> + .probe = sirfsoc_rtciobrg_probe,
>> + .driver = {
>> + .name = "sirfsoc-rtciobrg",
>> + .owner = THIS_MODULE,
>> + .of_match_table = rtciobrg_ids,
>> + },
>> +};
>> +
>> +static int __init sirfsoc_rtciobrg_init(void)
>> +{
>> + return platform_driver_register(&sirfsoc_rtciobrg_driver);
>> +}
>> +postcore_initcall(sirfsoc_rtciobrg_init);
>> +
>> +MODULE_AUTHOR("Zhiwu Song <zhiwu.song at csr.com>, "
>> + "Barry Song <baohua.song at csr.com>");
>> +MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge");
>> +MODULE_LICENSE("GPL");
>> +
>> diff --git a/include/linux/rtc/sirfsoc_rtciobrg.h b/include/linux/rtc/sirfsoc_rtciobrg.h
>> new file mode 100644
>> index 0000000..2c92e1c
>> --- /dev/null
>> +++ b/include/linux/rtc/sirfsoc_rtciobrg.h
>> @@ -0,0 +1,18 @@
>> +/*
>> + * RTC I/O Bridge interfaces for CSR SiRFprimaII
>> + * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module
>> + *
>> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
>> + *
>> + * Licensed under GPLv2 or later.
>> + */
>> +#ifndef _SIRFSOC_RTC_IOBRG_H_
>> +#define _SIRFSOC_RTC_IOBRG_H_
>> +
>> +extern void sirfsoc_rtc_iobrg_besyncing(void);
>> +
>> +extern u32 sirfsoc_rtc_iobrg_readl(u32 addr);
>> +
>> +extern void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr);
>> +
>> +#endif
>> --
>> 1.7.1
-barry
More information about the linux-arm-kernel
mailing list