[PATCH v2] ARM: CSR: Adding CSR SiRFprimaII board support
Barry Song
21cnbao at gmail.com
Tue Jul 5 18:34:05 EST 2011
Hi Arnd,
2011/7/1 Barry Song <21cnbao at gmail.com>:
> Hi Arnd,
>
> 2011/6/30 Arnd Bergmann <arnd at arndb.de>:
>> On Thursday 30 June 2011, Barry Song wrote:
>>
>>> > Is this really just one bus with a huge address space, or rather some
>>> > nested buses? I'd prefer to have the device tree representation as
>>> > close as possible to the actual layout.
>>>
>>> there are two AXI buses in prima2. AXI-1 connect to memory, AXI-2 is
>>> transferred to CSR self-defined IOBUS by CPUIF, then 1 intterupt
>>> controller and 9 IO bridges are connected to the IOBUS .
>>> The 9 IO bridges are SYSIOBG, PERIIOBG,CPURTCIOBG, UUSIOBG, GRAPHIOBG,
>>> MEDIAIOBG, DSPIOBG, DISPIOBG, MEMIOBG. Every iobrg connect to a group
>>> of controllers.
>>> For example, DISPIOBG connect to VPP and LCD, SYSIOBG connect to CLKC,
>>> RSTC, RSC and CPHIFBG, DSPIOBG connect to DSPIF, GPS and DSP.
>>> PERIIOBG connect to TIMER, NAND, AUDIO, UART0, UART1, UART2, USP0,
>>> USP1, USP2, SPI0, I2C0, I2C1, GPIO, *SYS2PCI* and so on. Then
>>> *SYS2PCI* connect to SD.
>>>
>>> The indendation descible the device hierarchy
>>> AXI-1
>>> Memory
>>> AXI-2
>>> interrupt controller
>>> IOBG...
>>> xxxx
>>> IOBG...
>>> xxxx
>>> IOBG...
>>> xxxx
>>> IOBG...
>>> xxxx
>>> IOBG...
>>> xxxx
>>> IOBG...
>>> SYS2PCI
>>> SD
>>>
>>> i have get the IC guy Weizeng involved, maybe he can explain better than me :-)
>>
>> I think it would be good to represent the IOBG devices in the device tree then.
>> You don't need to represent AXI-1 because memory is special anyway, and I would
>> not bother to list SYS2PCI if the intention of that block was to hide the fact
>> that it's PCI behind it. Properly instantiating it as a PCI bridge would be
>> a lot of work that is probably not worth it.
>>
>> My usual plea to hardware developers: Please make the registers
>> autodiscoverable from software! On an AMBA bus, please use the PrimeCell
>> register layout. If you always have an IOBG device behind, they should
>> all have the same identifier for that kind of bus bridge.
>>
>> For the IOBG, it would be ideal to have a similar way of finding and
>> configuring the connected hardware, including:
>>
>> * unique identifier for each distinct IP block
>> * revision of that block
>> * MMIO ranges and sizes, relative to the bus
>> * interrupt numbers, relative to a local interrupt controller
>> * location identifier (like PCI bus/device/fn number) that can be
>> referred to by other devices
>> * clock management for that device
>> * power management for that device
>>
>> If your IODB infrastructure already has this, you should create a new
>> bus-type for this in Linux, which will let you detect all devices
>> in a consistent manner without having to list them in the device tree.
>
> IO bridges in prima2 don't have that. Configuration is hardcoded now.
> but we have learned so much from you and hope to improve our future IC
> design.
i have tried to figure out the full DT:
/dts-v1/;
/ {
model = "SiRF Prima2 EVB";
compatible = "sirf,prima2-cb", "sirf,prima2";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
memory {
reg = <0x00000000 0x20000000>;
};
chosen {
bootargs = "mem=512M real_root=/dev/mmcblk0p2 console=ttyS0 panel=1
bootsplash=true bpp=16 androidboot.console=ttyS1";
linux,stdout-path = &uart1;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
ARM-CortexA9,SiRFprimaII at 0 {
device_type = "cpu";
reg = <0x0>;
d-cache-line-size = <32>;
i-cache-line-size = <32>;
d-cache-size = <32768>;
i-cache-size = <32768>;
/* from bootloader */
timebase-frequency = <0>;
bus-frequency = <0>;
clock-frequency = <0>;
};
};
axi {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x40000000 0x40000000 0x80000000>;
l2-cache-controller at 0x80040000 {
compatible = "arm,pl310-cache", "cache";
reg = <0x80040000 0x1000>;
interrupts = <59>;
};
sirfsoc-iobus {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x56000000 0x56000000 0x1b0000
0x80010000 0x80010000 0x30000
0x88000000 0x88000000 0x40040000>;
intc: interrupt-controller at 0x80020000 {
#interrupt-cells = <1>;
interrupt-controller;
compatible = "sirf,intc", "sirf,prima2-intc";
reg = <0x80020000 0x1000>;
};
sys-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x88000000 0x88000000 0x40000>;
clock-controller at 0x88000000 {
compatible = "sirf,clkc", "sirf,prima2-clkc";
reg = <0x88000000 0x1000>;
interrupts = <3>;
};
reset-controller at 0x88010000 {
compatible = "sirf,rstc", "sirf,prima2-rstc";
reg = <0x88010000 0x1000>;
};
};
mem-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x90000000 0x90000000 0x10000>;
memory-controller at 0x90000000 {
compatible = "sirf,memc", "sirf,prima2-memc";
reg = <0x90000000 0x10000>;
interrupts = <27>;
};
};
disp-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x90010000 0x90010000 0x30000>;
display at 0x90010000 {
compatible = "sirf,lcd", "sirf,prima2-lcd";
reg = <0x90010000 0x20000>;
interrupts = <30>;
};
vpp at 0x90020000 {
compatible = "sirf,vpp", "sirf,prima2-vpp";
reg = <0x90020000 0x10000>;
interrupts = <31>;
};
};
graphics-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x98000000 0x98000000 0x8000000>;
graphics at 0x98000000 {
compatible = "sirf,graphics", "sirf,prima2-graphics";
reg = <0x98000000 0x8000000>;
interrupts = <6>;
};
};
multimedia-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0xa0000000 0xa0000000 0x8000000>;
multimedia at 0xa0000000 {
compatible = "sirf,multimedia", "sirf,prima2-multimedia";
reg = <0xa0000000 0x8000000>;
interrupts = <5>;
};
};
dsp-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0xa8000000 0xa8000000 0x2000000>;
dspif at 0xa8000000 {
compatible = "sirf,dspif", "sirf,prima2-dspif";
reg = <0xa8000000 0x10000>;
interrupts = <9>;
};
gps at 0xa8010000 {
compatible = "sirf,gps", "sirf,prima2-gps";
reg = <0xa8010000 0x10000>;
interrupts = <7>;
};
dsp at 0xa9000000 {
compatible = "sirf,dsp", "sirf,prima2-dsp";
reg = <0xa9000000 0x1000000>;
interrupts = <8>;
};
};
peri-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0xb0000000 0xb0000000 0x180000>;
timer at 0xb0020000 {
compatible = "sirf,tick", "sirf,prima2-tick";
reg = <0xb0020000 0x1000>;
interrupts = <0>;
};
nand at 0xb0030000 {
compatible = "sirf,nand", "sirf,prima2-nand";
reg = <0xb0030000 0x10000>;
interrupts = <41>;
};
audio at 0xb0040000 {
compatible = "sirf,audio", "sirf,prima2-audio";
reg = <0xb0040000 0x10000>;
interrupts = <35>;
};
uart0: uart at 0xb0050000 {
cell-index = <0>;
compatible = "sirf,uart", "sirf,prima2-uart";
reg = <0xb0050000 0x10000>;
interrupts = <17>;
};
uart1: uart at 0xb0060000 {
cell-index = <1>;
compatible = "sirf,uart", "sirf,prima2-uart";
reg = <0xb0060000 0x10000>;
interrupts = <18>;
};
uart2: uart at 0xb0070000 {
cell-index = <2>;
compatible = "sirf,uart", "sirf,prima2-uart";
reg = <0xb0070000 0x10000>;
interrupts = <19>;
};
usp0: usp at 0xb0080000 {
cell-index = <0>;
compatible = "sirf,usp", "sirf,prima2-usp";
reg = <0xb0080000 0x10000>;
interrupts = <20>;
};
usp1: usp at 0xb0090000 {
cell-index = <1>;
compatible = "sirf,usp", "sirf,prima2-usp";
reg = <0xb0090000 0x10000>;
interrupts = <21>;
};
usp2: usp at 0xb00a0000 {
cell-index = <2>;
compatible = "sirf,usp", "sirf,prima2-usp";
reg = <0xb00a0000 0x10000>;
interrupts = <22>;
};
dmac0: dma-controller at 0xb00b0000 {
cell-index = <0>;
compatible = "sirf,dmac", "sirf,prima2-dmac";
reg = <0xb00b0000 0x10000>;
interrupts = <12>;
};
dmac1: dma-controller at 0xb0160000 {
cell-index = <1>;
compatible = "sirf,dmac", "sirf,prima2-dmac";
reg = <0xb0160000 0x10000>;
interrupts = <13>;
};
vip at 0xb00C0000 {
compatible = "sirf,vip", "sirf,prima2-vip";
reg = <0xb00C0000 0x10000>;
};
spi0: spi at 0xb00D0000 {
cell-index = <0>;
compatible = "sirf,spi", "sirf,prima2-spi";
reg = <0xb00D0000 0x10000>;
interrupts = <15>;
};
spi1: spi at 0xb0170000 {
cell-index = <1>;
compatible = "sirf,spi", "sirf,prima2-spi";
reg = <0xb0170000 0x10000>;
interrupts = <16>;
};
i2c0: i2c at 0xb00E0000 {
cell-index = <0>;
compatible = "sirf,i2c", "sirf,prima2-i2c";
reg = <0xb00E0000 0x10000>;
interrupts = <24>;
};
i2c1: i2c at 0xb00f0000 {
cell-index = <1>;
compatible = "sirf,i2c", "sirf,prima2-i2c";
reg = <0xb00f0000 0x10000>;
interrupts = <25>;
};
tsc at 0xb0110000 {
compatible = "sirf,tsc", "sirf,prima2-tsc";
reg = <0xb0110000 0x10000>;
interrupts = <33>;
};
gpio: gpio-controller at 0xb0120000 {
#gpio-cells = <2>;
#interrupt-cells = <2>;
compatible = "sirf,gpio", "sirf,prima2-gpio";
reg = <0xb0120000 0x10000>;
gpio-controller;
interrupt-controller;
};
pwm at 0xb0130000 {
compatible = "sirf,pwm", "sirf,prima2-pwm";
reg = <0xb0130000 0x10000>;
};
efusesys at 0xb0140000 {
compatible = "sirf,efuse", "sirf,prima2-efuse";
reg = <0xb0140000 0x10000>;
};
pulsec at 0xb0150000 {
compatible = "sirf,pulsec", "sirf,prima2-pulsec";
reg = <0xb0150000 0x10000>;
interrupts = <48>;
};
pci-iobg {
compatible = "sirf,pciiobg", "sirf,prima2-pciiobg", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x56000000 0x56000000 0x1b00000>;
sd0: sdhci at 0x56000000 {
cell-index = <0>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56000000 0x100000>;
interrupts = <38>;
};
sd1: sdhci at 0x56100000 {
cell-index = <1>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56100000 0x100000>;
interrupts = <38>;
};
sd2: sdhci at 0x56200000 {
cell-index = <2>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56200000 0x100000>;
interrupts = <23>;
};
sd3: sdhci at 0x56300000 {
cell-index = <3>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56300000 0x100000>;
interrupts = <23>;
};
sd4: sdhci at 0x56400000 {
cell-index = <4>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56400000 0x100000>;
interrupts = <39>;
};
sd5: sdhci at 0x56500000 {
cell-index = <5>;
compatible = "sirf,sdhc", "sirf,prima2-sdhc";
reg = <0x56500000 0x100000>;
interrupts = <39>;
};
pci-copy at 0x57900000 {
compatible = "sirf,pcicp", "sirf,prima2-pcicp";
reg = <0x57900000 0x100000>;
interrupts = <40>;
};
rom-interface at 0x57a00000 {
compatible = "sirf,romif", "sirf,prima2-romif";
reg = <0x57a00000 0x100000>;
};
};
};
rtc-iobg {
compatible = "sirf,rtciobg", "sirf,prima2-rtciobg", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x80030000 0x10000>;
gpsrtc at 0x1000 {
compatible = "sirf,gpsrtc", "sirf,prima2-gpsrtc";
reg = <0x1000 0x1000>;
interrupts = <55 56 57>;
};
sysrtc at 0x2000 {
compatible = "sirf,sysrtc", "sirf,prima2-sysrtc";
reg = <0x2000 0x1000>;
interrupts = <52 53 54>;
};
pwrc at 0x3000 {
compatible = "sirf,pwrc", "sirf,prima2-pwrc";
reg = <0x3000 0x1000>;
interrupts = <32>;
};
};
uus-iobg {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0xb8000000 0xb8000000 0x40000>;
usb0: usb at 0xb00E0000 {
compatible = "sirf,usb", "sirf,prima2-usb";
reg = <0xb8000000 0x10000>;
interrupts = <10>;
};
usb1: usb at 0xb00f0000 {
compatible = "sirf,usb", "sirf,prima2-usb";
reg = <0xb8010000 0x10000>;
interrupts = <11>;
};
sata at 0xb00f0000 {
compatible = "sirf,sata", "sirf,prima2-sata";
reg = <0xb8020000 0x10000>;
interrupts = <37>;
};
security at 0xb00f0000 {
compatible = "sirf,security", "sirf,prima2-security";
reg = <0xb8030000 0x10000>;
interrupts = <42>;
};
};
};
};
};
if it looks ok to you, i will send v3 including it and other changes
reviewed by you before.
>
>>
>>> > I think the namespace for the compatible values is supposed to start with
>>> > the stock ticker name of the company making the device as a unique
>>> > identifier. This means you'd have to use
>>> > "csrxf,sirf-intc", "csrxf,sirf-prima2-intc" as the value, instead
>>> > of starting with the product name. I don't know exactly how strictly
>>> > we apply that rule, but I've taken the devicetree-discuss at lists.ozlabs.org
>>> > mailing list on Cc, maybe someone can clarify.
>>>
>>> in fact, SiRF is a company name. it was merged into CSR 4 years ago.
>>> Due to history reason, now the SoC names are still headed by sirf.
>>> the logo in SiRFprimaII chip is CSR.
>>> So the "SiRF" of SiRFprimaII should mean two things: old company name,
>>> heritable CPU production-line. Anyway, "csr, sirf-intc" seems to make
>>> more senses than "sirf, intc".
>>>
>>> could we change "csrxf,sirf-intc", "csrxf,sirf-prima2-intc" to
>>> "csr,sirf-intc", "csr,sirf-prima2-intc"?
>>
>> Not sure how strict we interpret the rules about stock ticker symbols.
>> 'CSR' on wallstreet is 'China Security & Surveillance Tech. Inc'. If they
>> ever decide to produce embedded Linux machines, we'd get a conflict, unless
>> they also use "csst" (their .com domain name) as a prefix.
>>
>>> > better put these in a list with one file per line, like
>>> >
>>> > obj-y += timer.o
>>> > obj-y += irq.o
>>> >
>>> > That makes the list more consistent when you add conditional files.
>>>
>>> Then it could be:
>>> obj-y += timer.o
>>> obj-y += irq.o
>>> obj-y += clock.o
>>> obj-y += common.o
>>> obj-$(CONFIG_CACHE_L2X0) := l2x0.o
>
> Now it is changed to:
>
> +obj-y := timer.o
> +obj-y += irq.o
> +obj-y += clock.o
> +obj-y += rstc.o
> +obj-y += prima2.o
> +obj-$(CONFIG_CACHE_L2X0) += l2x0.o
> +obj-$(CONFIG_DEBUG_LL) += lluart.o
>
> For clock, i have moved the static mapping to clock.c:
>
> diff --git a/arch/arm/mach-prima2/clock.c b/arch/arm/mach-prima2/clock.c
> new file mode 100644
> index 0000000..f4676bc
> --- /dev/null
> +++ b/arch/arm/mach-prima2/clock.c
> ...
> +
> +static void __init sirfsoc_clk_init(void)
> +{
> + clkdev_add_table(onchip_clks, ARRAY_SIZE(onchip_clks));
> +}
> +
> +static struct of_device_id clkc_ids[] = {
> + { .compatible = "sirf,clkc" },
> +};
> +
> +void __init sirfsoc_of_clk_init(void)
> +{
> + struct device_node *np;
> + struct resource res;
> + struct map_desc sirfsoc_clkc_iodesc = {
> + .virtual = SIRFSOC_CLOCK_VA_BASE,
> + .type = MT_DEVICE,
> + };
> +
> + np = of_find_matching_node(NULL, clkc_ids);
> + if (!np)
> + panic("unable to find compatible clkc node in dtb\n");
> +
> + if (of_address_to_resource(np, 0, &res))
> + panic("unable to find clkc range in dtb");
> + of_node_put(np);
> +
> + sirfsoc_clkc_iodesc.pfn = __phys_to_pfn(res.start);
> + sirfsoc_clkc_iodesc.length = 1 + res.end - res.start;
> +
> + iotable_init(&sirfsoc_clkc_iodesc, 1);
> +
> + sirfsoc_clk_init();
> +}
>
> It looks like we can new a common function named as of_io_earlymap()
> or something in drivers/of/address.c. of_iomap() does ioremap,
> of_io_earlymap() does early static mapping?
> Then all SoCs can call this function to do early static mapping. if
> so, some lines can be deleted in sirfsoc_of_clk_init(). How do you
> think about newing the function in drivers/of/address.c?
>
> For DEBUG_LL uart, i have moved the static mapping to a new file named
> lluart.c too:
> +#include <linux/kernel.h>
> +#include <asm/page.h>
> +#include <asm/mach/map.h>
> +#include <mach/map.h>
> +#include <mach/uart.h>
> +
> +void __init sirfsoc_map_lluart(void)
> +{
> + struct map_desc sirfsoc_lluart_map = {
> + .virtual = SIRFSOC_UART1_VA_BASE,
> + .pfn = __phys_to_pfn(SIRFSOC_UART1_PA_BASE),
> + .length = SIRFSOC_UART1_SIZE,
> + .type = MT_DEVICE,
> + };
> +
> + iotable_init(&sirfsoc_lluart_map, 1);
> +}
> +
>
> only when DEBUG_LL is selected, this file will be compiled. Otherwise,
> an empty sirfsoc_map_lluart is used:
> --- /dev/null
> +++ b/arch/arm/mach-prima2/common.h
> @@ -0,0 +1,26 @@
> +/*
> + * This file contains common function prototypes to avoid externs in
> the c files.
> + *
> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
> + *
> + * Licensed under GPLv2 or later.
> + */
> +
> +#ifndef __MACH_PRIMA2_COMMON_H__
> +#define __MACH_PRIMA2_COMMON_H__
> +
> +#include <linux/init.h>
> +#include <asm/mach/time.h>
> +
> +extern struct sys_timer sirfsoc_timer;
> +
> +extern void __init sirfsoc_of_irq_init(void);
> +extern void __init sirfsoc_of_clk_init(void);
> +
> +#ifndef CONFIG_DEBUG_LL
> +static inline void sirfsoc_map_lluart(void) {}
> +#else
> +extern void __init sirfsoc_map_lluart(void);
> +#endif
> +
> +#endif
>
> For rstc, it is the reset controller in prima2, every bit can reset a
> special component in the SoC. i move the mapping to a new rstc.c file
> too. But APIs, which every driver will call to reset itself, in rstc
> is not full finished:
> +/*
> + * reset controller for CSR SiRFprimaII
> + *
> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
> + *
> + * Licensed under GPLv2 or later.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +
> +void __iomem *sirfsoc_rstc_base;
> +
> +static struct of_device_id rstc_ids[] = {
> + { .compatible = "sirf,rstc" },
> +};
> +
> +static int __init sirfsoc_of_rstc_init(void)
> +{
> + struct device_node *np;
> +
> + np = of_find_matching_node(NULL, rstc_ids);
> + if (!np)
> + panic("unable to find compatible rstc node in dtb\n");
> +
> + sirfsoc_rstc_base = of_iomap(np, 0);
> + if (!sirfsoc_rstc_base)
> + panic("unable to map rstc cpu registers\n");
> +
> + of_node_put(np);
> +
> + return 0;
> +}
> +early_initcall(sirfsoc_of_rstc_init);
> +
> +/* TODO:
> + * add APIs to control reset of every module
> + */
>
>>
>>
>> Right. Note that you have a := in there, which needs to be +=.
>>
>>
>>> > It probably makes sense to pick a new name for the combined file, too, but I
>>> > can't think of a good one. Maybe one of platform.c, prima2.c or core.c.
>>>
>>> i am not sure the original purpose of board_dt.c. and i am guessing
>>> whether Grant created that single board file to contain multiple
>>> boards. For example:
>>>
>>> MACHINE_START(PRIMA2_XXX, "prima2xxx")
>>> .boot_params = SIRFSOC_SDRAM_PA + 0x100,
>>> .init_early = sirfsoc_init_clk,
>>> .map_io = sirfsoc_map_io,
>>> .init_irq = sirfsoc_of_init_irq,
>>> .timer = &sirfsoc_timer,
>>> .init_machine = sirfsoc_mach_init,
>>> .dt_compat = prima2xxx_dt_match,
>>> MACHINE_END
>>>
>>> MACHINE_START(PRIMA2_YYY, "prima2yyy")
>>> .boot_params = SIRFSOC_SDRAM_PA + 0x100,
>>> .init_early = sirfsoc_init_clk,
>>> .map_io = sirfsoc_map_io,
>>> .init_irq = sirfsoc_of_init_irq,
>>> .timer = &sirfsoc_timer,
>>> .init_machine = sirfsoc_mach_init,
>>> .dt_compat = prima2yyy_dt_match,
>>> MACHINE_END
>>
>> No, this wouldn't make any sense when the only difference is the dt_compat
>> field: At that point you would just list all the possible boards in the
>> global dt_match table.
>
> Yes. i have rename common.c to prima2.c and now there is no any
> map_desc table due to the above changes, so it is now much shorter:
>
> diff --git a/arch/arm/mach-prima2/prima2.c b/arch/arm/mach-prima2/prima2.c
> new file mode 100644
> index 0000000..f6b04a1
> --- /dev/null
> +++ b/arch/arm/mach-prima2/prima2.c
> @@ -0,0 +1,40 @@
> +/*
> + * Defines machines for CSR SiRFprimaII
> + *
> + * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
> + *
> + * Licensed under GPLv2 or later.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/kernel.h>
> +#include <asm/mach-types.h>
> +#include <asm/mach/arch.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include "common.h"
> +
> +static struct of_device_id sirfsoc_of_bus_ids[] __initdata = {
> + { .compatible = "simple-bus", },
> + {},
> +};
> +
> +void __init sirfsoc_mach_init(void)
> +{
> + of_platform_bus_probe(NULL, sirfsoc_of_bus_ids, NULL);
> +}
> +
> +static const char *prima2cb_dt_match[] __initdata = {
> + "sirf,prima2-cb",
> + NULL
> +};
> +
> +MACHINE_START(PRIMA2_EVB, "prima2cb")
> + .boot_params = 0x00000100,
> + .init_early = sirfsoc_of_clk_init,
> + .map_io = sirfsoc_map_lluart,
> + .init_irq = sirfsoc_of_irq_init,
> + .timer = &sirfsoc_timer,
> + .init_machine = sirfsoc_mach_init,
> + .dt_compat = prima2cb_dt_match,
> +MACHINE_END
>
>>
>>> after creating a new file named mach-prima2/l2x0.c, it seems we only
>>> need to change Makefile to:
>>> obj-$(CONFIG_CACHE_L2X0) := l2x0.o
>>> the head file is not needed.
>>>
>>> Currently, rob's OF-based L2 cache is not merged yet. then i only
>>> write the following:
>>>
>>> static int __init sirfsoc_of_l2x_init(void)
>>> {
>>> struct device_node *np;
>>> void __iomem *sirfsoc_l2x_base;
>>>
>>> np = of_find_matching_node(NULL, l2x_ids);
>>> if (!np)
>>> panic("unable to find compatible intc node in dtb\n");
>>>
>>> sirfsoc_l2x_base = of_iomap(np, 0);
>>> if (!sirfsoc_l2x_base)
>>> panic("unable to map l2x cpu registers\n");
>>>
>>> of_node_put(np);
>>>
>>> if (!(readl_relaxed(sirfsoc_l2x_base + L2X0_CTRL) & 1)) {
>>> /*
>>> * set the physical memory windows L2 cache will cover
>>> */
>>> writel_relaxed(PLAT_PHYS_OFFSET + 1024 * 1024 * 1024,
>>> sirfsoc_l2x_base + L2X0_ADDR_FILTERING_END);
>>> writel_relaxed(PLAT_PHYS_OFFSET | 0x1,
>>> sirfsoc_l2x_base + L2X0_ADDR_FILTERING_START);
>>>
>>> writel_relaxed(0,
>>> sirfsoc_l2x_base + L2X0_TAG_LATENCY_CTRL);
>>> writel_relaxed(0,
>>> sirfsoc_l2x_base + L2X0_DATA_LATENCY_CTRL);
>>> }
>>> l2x0_init((void __iomem *)sirfsoc_l2x_base, 0x00040000,
>>> 0x00000000);
>>>
>>> return 0;
>>> }
>>> early_initcall(sirfsoc_of_l2x_init);
>>>
>>> After Rob's patch is merged, i think sirfsoc_of_l2x_init can be much simpler.
>>>
>> Yes. Rob/Olof, what's the status of that patch?
>>
>> Arnd
>>
>
> After we get aggrement on DT node name(csr/csrxf/csr.l ?), i will send
> patch v3 with all those all changes and full DT. Really thank you very
> much!
>
> -barry
>
-barry
More information about the devicetree-discuss
mailing list