mirror of https://gitee.com/openkylin/linux.git
Merge branch 'next/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc
* 'next/soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/linux-arm-soc: MAINTAINERS: add maintainer of CSR SiRFprimaII machine ARM: CSR: initializing L2 cache ARM: CSR: mapping early DEBUG_LL uart ARM: CSR: Adding CSR SiRFprimaII board support OMAP4: clocks: Update the clock tree with 4460 clock nodes OMAP4: PRCM: OMAP4460 specific PRM and CM register bitshifts OMAP4: ID: add omap_has_feature for max freq supported OMAP: ID: introduce chip detection for OMAP4460 ARM: Xilinx: merge board file into main platform code ARM: Xilinx: Adding Xilinx board support Fix up conflicts in arch/arm/mach-omap2/cm-regbits-44xx.h
This commit is contained in:
commit
4b30b6f23a
|
@ -0,0 +1,3 @@
|
|||
prima2 "cb" evalutation board
|
||||
Required root node properties:
|
||||
- compatible = "sirf,prima2-cb", "sirf,prima2";
|
|
@ -0,0 +1,7 @@
|
|||
Xilinx Zynq EP107 Emulation Platform board
|
||||
|
||||
This board is an emulation platform for the Zynq product which is
|
||||
based on an ARM Cortex A9 processor.
|
||||
|
||||
Required root node properties:
|
||||
- compatible = "xlnx,zynq-ep107";
|
|
@ -734,6 +734,12 @@ T: git git://git.berlios.de/gemini-board
|
|||
S: Maintained
|
||||
F: arch/arm/mach-gemini/
|
||||
|
||||
ARM/CSR SIRFPRIMA2 MACHINE SUPPORT
|
||||
M: Barry Song <baohua.song@csr.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: arch/arm/mach-prima2/
|
||||
|
||||
ARM/EBSA110 MACHINE SUPPORT
|
||||
M: Russell King <linux@arm.linux.org.uk>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
|
|
|
@ -340,6 +340,19 @@ config ARCH_GEMINI
|
|||
help
|
||||
Support for the Cortina Systems Gemini family SoCs
|
||||
|
||||
config ARCH_PRIMA2
|
||||
bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
|
||||
select CPU_V7
|
||||
select GENERIC_TIME
|
||||
select NO_IOPORT
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select CLKDEV_LOOKUP
|
||||
select GENERIC_IRQ_CHIP
|
||||
select USE_OF
|
||||
select ZONE_DMA
|
||||
help
|
||||
Support for CSR SiRFSoC ARM Cortex A9 Platform
|
||||
|
||||
config ARCH_EBSA110
|
||||
bool "EBSA-110"
|
||||
select CPU_SA110
|
||||
|
@ -884,6 +897,19 @@ config ARCH_VT8500
|
|||
select HAVE_PWM
|
||||
help
|
||||
Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
|
||||
|
||||
config ARCH_ZYNQ
|
||||
bool "Xilinx Zynq ARM Cortex A9 Platform"
|
||||
select CPU_V7
|
||||
select GENERIC_TIME
|
||||
select GENERIC_CLOCKEVENTS
|
||||
select CLKDEV_LOOKUP
|
||||
select ARM_GIC
|
||||
select ARM_AMBA
|
||||
select ICST
|
||||
select USE_OF
|
||||
help
|
||||
Support for Xilinx Zynq ARM Cortex A9 Platform
|
||||
endchoice
|
||||
|
||||
#
|
||||
|
|
|
@ -168,6 +168,7 @@ machine-$(CONFIG_ARCH_OMAP3) := omap2
|
|||
machine-$(CONFIG_ARCH_OMAP4) := omap2
|
||||
machine-$(CONFIG_ARCH_ORION5X) := orion5x
|
||||
machine-$(CONFIG_ARCH_PNX4008) := pnx4008
|
||||
machine-$(CONFIG_ARCH_PRIMA2) := prima2
|
||||
machine-$(CONFIG_ARCH_PXA) := pxa
|
||||
machine-$(CONFIG_ARCH_REALVIEW) := realview
|
||||
machine-$(CONFIG_ARCH_RPC) := rpc
|
||||
|
@ -194,6 +195,7 @@ machine-$(CONFIG_MACH_SPEAR300) := spear3xx
|
|||
machine-$(CONFIG_MACH_SPEAR310) := spear3xx
|
||||
machine-$(CONFIG_MACH_SPEAR320) := spear3xx
|
||||
machine-$(CONFIG_MACH_SPEAR600) := spear6xx
|
||||
machine-$(CONFIG_ARCH_ZYNQ) := zynq
|
||||
|
||||
# Platform directory name. This list is sorted alphanumerically
|
||||
# by CONFIG_* macro name.
|
||||
|
@ -201,6 +203,7 @@ plat-$(CONFIG_ARCH_MXC) := mxc
|
|||
plat-$(CONFIG_ARCH_OMAP) := omap
|
||||
plat-$(CONFIG_ARCH_S3C64XX) := samsung
|
||||
plat-$(CONFIG_ARCH_TCC_926) := tcc
|
||||
plat-$(CONFIG_ARCH_ZYNQ) := versatile
|
||||
plat-$(CONFIG_PLAT_IOP) := iop
|
||||
plat-$(CONFIG_PLAT_NOMADIK) := nomadik
|
||||
plat-$(CONFIG_PLAT_ORION) := orion
|
||||
|
|
|
@ -0,0 +1,416 @@
|
|||
/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>;
|
||||
|
||||
cpu@0 {
|
||||
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@80040000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0x80040000 0x1000>;
|
||||
interrupts = <59>;
|
||||
};
|
||||
|
||||
intc: interrupt-controller@80020000 {
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
compatible = "sirf,prima2-intc";
|
||||
reg = <0x80020000 0x1000>;
|
||||
};
|
||||
|
||||
sys-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x88000000 0x88000000 0x40000>;
|
||||
|
||||
clock-controller@88000000 {
|
||||
compatible = "sirf,prima2-clkc";
|
||||
reg = <0x88000000 0x1000>;
|
||||
interrupts = <3>;
|
||||
};
|
||||
|
||||
reset-controller@88010000 {
|
||||
compatible = "sirf,prima2-rstc";
|
||||
reg = <0x88010000 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
mem-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x90000000 0x90000000 0x10000>;
|
||||
|
||||
memory-controller@90000000 {
|
||||
compatible = "sirf,prima2-memc";
|
||||
reg = <0x90000000 0x10000>;
|
||||
interrupts = <27>;
|
||||
};
|
||||
};
|
||||
|
||||
disp-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x90010000 0x90010000 0x30000>;
|
||||
|
||||
display@90010000 {
|
||||
compatible = "sirf,prima2-lcd";
|
||||
reg = <0x90010000 0x20000>;
|
||||
interrupts = <30>;
|
||||
};
|
||||
|
||||
vpp@90020000 {
|
||||
compatible = "sirf,prima2-vpp";
|
||||
reg = <0x90020000 0x10000>;
|
||||
interrupts = <31>;
|
||||
};
|
||||
};
|
||||
|
||||
graphics-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x98000000 0x98000000 0x8000000>;
|
||||
|
||||
graphics@98000000 {
|
||||
compatible = "powervr,sgx531";
|
||||
reg = <0x98000000 0x8000000>;
|
||||
interrupts = <6>;
|
||||
};
|
||||
};
|
||||
|
||||
multimedia-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0xa0000000 0xa0000000 0x8000000>;
|
||||
|
||||
multimedia@a0000000 {
|
||||
compatible = "sirf,prima2-video-codec";
|
||||
reg = <0xa0000000 0x8000000>;
|
||||
interrupts = <5>;
|
||||
};
|
||||
};
|
||||
|
||||
dsp-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0xa8000000 0xa8000000 0x2000000>;
|
||||
|
||||
dspif@a8000000 {
|
||||
compatible = "sirf,prima2-dspif";
|
||||
reg = <0xa8000000 0x10000>;
|
||||
interrupts = <9>;
|
||||
};
|
||||
|
||||
gps@a8010000 {
|
||||
compatible = "sirf,prima2-gps";
|
||||
reg = <0xa8010000 0x10000>;
|
||||
interrupts = <7>;
|
||||
};
|
||||
|
||||
dsp@a9000000 {
|
||||
compatible = "sirf,prima2-dsp";
|
||||
reg = <0xa9000000 0x1000000>;
|
||||
interrupts = <8>;
|
||||
};
|
||||
};
|
||||
|
||||
peri-iobg {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0xb0000000 0xb0000000 0x180000>;
|
||||
|
||||
timer@b0020000 {
|
||||
compatible = "sirf,prima2-tick";
|
||||
reg = <0xb0020000 0x1000>;
|
||||
interrupts = <0>;
|
||||
};
|
||||
|
||||
nand@b0030000 {
|
||||
compatible = "sirf,prima2-nand";
|
||||
reg = <0xb0030000 0x10000>;
|
||||
interrupts = <41>;
|
||||
};
|
||||
|
||||
audio@b0040000 {
|
||||
compatible = "sirf,prima2-audio";
|
||||
reg = <0xb0040000 0x10000>;
|
||||
interrupts = <35>;
|
||||
};
|
||||
|
||||
uart0: uart@b0050000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-uart";
|
||||
reg = <0xb0050000 0x10000>;
|
||||
interrupts = <17>;
|
||||
};
|
||||
|
||||
uart1: uart@b0060000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-uart";
|
||||
reg = <0xb0060000 0x10000>;
|
||||
interrupts = <18>;
|
||||
};
|
||||
|
||||
uart2: uart@b0070000 {
|
||||
cell-index = <2>;
|
||||
compatible = "sirf,prima2-uart";
|
||||
reg = <0xb0070000 0x10000>;
|
||||
interrupts = <19>;
|
||||
};
|
||||
|
||||
usp0: usp@b0080000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-usp";
|
||||
reg = <0xb0080000 0x10000>;
|
||||
interrupts = <20>;
|
||||
};
|
||||
|
||||
usp1: usp@b0090000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-usp";
|
||||
reg = <0xb0090000 0x10000>;
|
||||
interrupts = <21>;
|
||||
};
|
||||
|
||||
usp2: usp@b00a0000 {
|
||||
cell-index = <2>;
|
||||
compatible = "sirf,prima2-usp";
|
||||
reg = <0xb00a0000 0x10000>;
|
||||
interrupts = <22>;
|
||||
};
|
||||
|
||||
dmac0: dma-controller@b00b0000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-dmac";
|
||||
reg = <0xb00b0000 0x10000>;
|
||||
interrupts = <12>;
|
||||
};
|
||||
|
||||
dmac1: dma-controller@b0160000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-dmac";
|
||||
reg = <0xb0160000 0x10000>;
|
||||
interrupts = <13>;
|
||||
};
|
||||
|
||||
vip@b00C0000 {
|
||||
compatible = "sirf,prima2-vip";
|
||||
reg = <0xb00C0000 0x10000>;
|
||||
};
|
||||
|
||||
spi0: spi@b00d0000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-spi";
|
||||
reg = <0xb00d0000 0x10000>;
|
||||
interrupts = <15>;
|
||||
};
|
||||
|
||||
spi1: spi@b0170000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-spi";
|
||||
reg = <0xb0170000 0x10000>;
|
||||
interrupts = <16>;
|
||||
};
|
||||
|
||||
i2c0: i2c@b00e0000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-i2c";
|
||||
reg = <0xb00e0000 0x10000>;
|
||||
interrupts = <24>;
|
||||
};
|
||||
|
||||
i2c1: i2c@b00f0000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-i2c";
|
||||
reg = <0xb00f0000 0x10000>;
|
||||
interrupts = <25>;
|
||||
};
|
||||
|
||||
tsc@b0110000 {
|
||||
compatible = "sirf,prima2-tsc";
|
||||
reg = <0xb0110000 0x10000>;
|
||||
interrupts = <33>;
|
||||
};
|
||||
|
||||
gpio: gpio-controller@b0120000 {
|
||||
#gpio-cells = <2>;
|
||||
#interrupt-cells = <2>;
|
||||
compatible = "sirf,prima2-gpio";
|
||||
reg = <0xb0120000 0x10000>;
|
||||
gpio-controller;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
pwm@b0130000 {
|
||||
compatible = "sirf,prima2-pwm";
|
||||
reg = <0xb0130000 0x10000>;
|
||||
};
|
||||
|
||||
efusesys@b0140000 {
|
||||
compatible = "sirf,prima2-efuse";
|
||||
reg = <0xb0140000 0x10000>;
|
||||
};
|
||||
|
||||
pulsec@b0150000 {
|
||||
compatible = "sirf,prima2-pulsec";
|
||||
reg = <0xb0150000 0x10000>;
|
||||
interrupts = <48>;
|
||||
};
|
||||
|
||||
pci-iobg {
|
||||
compatible = "sirf,prima2-pciiobg", "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges = <0x56000000 0x56000000 0x1b00000>;
|
||||
|
||||
sd0: sdhci@56000000 {
|
||||
cell-index = <0>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56000000 0x100000>;
|
||||
interrupts = <38>;
|
||||
};
|
||||
|
||||
sd1: sdhci@56100000 {
|
||||
cell-index = <1>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56100000 0x100000>;
|
||||
interrupts = <38>;
|
||||
};
|
||||
|
||||
sd2: sdhci@56200000 {
|
||||
cell-index = <2>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56200000 0x100000>;
|
||||
interrupts = <23>;
|
||||
};
|
||||
|
||||
sd3: sdhci@56300000 {
|
||||
cell-index = <3>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56300000 0x100000>;
|
||||
interrupts = <23>;
|
||||
};
|
||||
|
||||
sd4: sdhci@56400000 {
|
||||
cell-index = <4>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56400000 0x100000>;
|
||||
interrupts = <39>;
|
||||
};
|
||||
|
||||
sd5: sdhci@56500000 {
|
||||
cell-index = <5>;
|
||||
compatible = "sirf,prima2-sdhc";
|
||||
reg = <0x56500000 0x100000>;
|
||||
interrupts = <39>;
|
||||
};
|
||||
|
||||
pci-copy@57900000 {
|
||||
compatible = "sirf,prima2-pcicp";
|
||||
reg = <0x57900000 0x100000>;
|
||||
interrupts = <40>;
|
||||
};
|
||||
|
||||
rom-interface@57a00000 {
|
||||
compatible = "sirf,prima2-romif";
|
||||
reg = <0x57a00000 0x100000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
rtc-iobg {
|
||||
compatible = "sirf,prima2-rtciobg", "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0x80030000 0x10000>;
|
||||
|
||||
gpsrtc@1000 {
|
||||
compatible = "sirf,prima2-gpsrtc";
|
||||
reg = <0x1000 0x1000>;
|
||||
interrupts = <55 56 57>;
|
||||
};
|
||||
|
||||
sysrtc@2000 {
|
||||
compatible = "sirf,prima2-sysrtc";
|
||||
reg = <0x2000 0x1000>;
|
||||
interrupts = <52 53 54>;
|
||||
};
|
||||
|
||||
pwrc@3000 {
|
||||
compatible = "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@b00e0000 {
|
||||
compatible = "chipidea,ci13611a-prima2";
|
||||
reg = <0xb8000000 0x10000>;
|
||||
interrupts = <10>;
|
||||
};
|
||||
|
||||
usb1: usb@b00f0000 {
|
||||
compatible = "chipidea,ci13611a-prima2";
|
||||
reg = <0xb8010000 0x10000>;
|
||||
interrupts = <11>;
|
||||
};
|
||||
|
||||
sata@b00f0000 {
|
||||
compatible = "synopsys,dwc-ahsata";
|
||||
reg = <0xb8020000 0x10000>;
|
||||
interrupts = <37>;
|
||||
};
|
||||
|
||||
security@b00f0000 {
|
||||
compatible = "sirf,prima2-security";
|
||||
reg = <0xb8030000 0x10000>;
|
||||
interrupts = <42>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/ {
|
||||
model = "Xilinx Zynq EP107";
|
||||
compatible = "xlnx,zynq-ep107";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x0 0x10000000>;
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "console=ttyPS0,9600 root=/dev/ram rw initrd=0x800000,8M earlyprintk";
|
||||
linux,stdout-path = &uart0;
|
||||
};
|
||||
|
||||
amba {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
intc: interrupt-controller@f8f01000 {
|
||||
interrupt-controller;
|
||||
compatible = "arm,gic";
|
||||
reg = <0xF8F01000 0x1000>;
|
||||
#interrupt-cells = <2>;
|
||||
};
|
||||
|
||||
uart0: uart@e0000000 {
|
||||
compatible = "xlnx,xuartps";
|
||||
reg = <0xE0000000 0x1000>;
|
||||
interrupts = <59 0>;
|
||||
clock = <50000000>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -1397,6 +1397,40 @@ static struct clk dss_dss_clk = {
|
|||
.recalc = &followparent_recalc,
|
||||
};
|
||||
|
||||
static const struct clksel_rate div3_8to32_rates[] = {
|
||||
{ .div = 8, .val = 0, .flags = RATE_IN_44XX },
|
||||
{ .div = 16, .val = 1, .flags = RATE_IN_44XX },
|
||||
{ .div = 32, .val = 2, .flags = RATE_IN_44XX },
|
||||
{ .div = 0 },
|
||||
};
|
||||
|
||||
static const struct clksel div_ts_div[] = {
|
||||
{ .parent = &l4_wkup_clk_mux_ck, .rates = div3_8to32_rates },
|
||||
{ .parent = NULL },
|
||||
};
|
||||
|
||||
static struct clk div_ts_ck = {
|
||||
.name = "div_ts_ck",
|
||||
.parent = &l4_wkup_clk_mux_ck,
|
||||
.clksel = div_ts_div,
|
||||
.clksel_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
|
||||
.clksel_mask = OMAP4430_CLKSEL_24_25_MASK,
|
||||
.ops = &clkops_null,
|
||||
.recalc = &omap2_clksel_recalc,
|
||||
.round_rate = &omap2_clksel_round_rate,
|
||||
.set_rate = &omap2_clksel_set_rate,
|
||||
};
|
||||
|
||||
static struct clk bandgap_ts_fclk = {
|
||||
.name = "bandgap_ts_fclk",
|
||||
.ops = &clkops_omap2_dflt,
|
||||
.enable_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
|
||||
.enable_bit = OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
|
||||
.clkdm_name = "l4_wkup_clkdm",
|
||||
.parent = &div_ts_ck,
|
||||
.recalc = &followparent_recalc,
|
||||
};
|
||||
|
||||
static struct clk dss_48mhz_clk = {
|
||||
.name = "dss_48mhz_clk",
|
||||
.ops = &clkops_omap2_dflt,
|
||||
|
@ -3028,7 +3062,9 @@ static struct omap_clk omap44xx_clks[] = {
|
|||
CLK(NULL, "aes2_fck", &aes2_fck, CK_443X),
|
||||
CLK(NULL, "aess_fck", &aess_fck, CK_443X),
|
||||
CLK(NULL, "bandgap_fclk", &bandgap_fclk, CK_443X),
|
||||
CLK(NULL, "bandgap_ts_fclk", &bandgap_ts_fclk, CK_446X),
|
||||
CLK(NULL, "des3des_fck", &des3des_fck, CK_443X),
|
||||
CLK(NULL, "div_ts_ck", &div_ts_ck, CK_446X),
|
||||
CLK(NULL, "dmic_sync_mux_ck", &dmic_sync_mux_ck, CK_443X),
|
||||
CLK(NULL, "dmic_fck", &dmic_fck, CK_443X),
|
||||
CLK(NULL, "dsp_fck", &dsp_fck, CK_443X),
|
||||
|
@ -3208,6 +3244,9 @@ int __init omap4xxx_clk_init(void)
|
|||
if (cpu_is_omap44xx()) {
|
||||
cpu_mask = RATE_IN_4430;
|
||||
cpu_clkflg = CK_443X;
|
||||
} else if (cpu_is_omap446x()) {
|
||||
cpu_mask = RATE_IN_4460;
|
||||
cpu_clkflg = CK_446X;
|
||||
}
|
||||
|
||||
clk_init(&omap2_clk_functions);
|
||||
|
|
|
@ -101,6 +101,10 @@
|
|||
#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT 9
|
||||
#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK (1 << 9)
|
||||
|
||||
/* Used by CM_L4CFG_CLKSTCTRL */
|
||||
#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_SHIFT 9
|
||||
#define OMAP4460_CLKACTIVITY_CORE_TS_GFCLK_MASK (1 << 9)
|
||||
|
||||
/* Used by CM_CEFUSE_CLKSTCTRL */
|
||||
#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT 9
|
||||
#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK (1 << 9)
|
||||
|
@ -413,6 +417,10 @@
|
|||
#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT 11
|
||||
#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK (1 << 11)
|
||||
|
||||
/* Used by CM_WKUP_CLKSTCTRL */
|
||||
#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_SHIFT 13
|
||||
#define OMAP4460_CLKACTIVITY_WKUP_TS_GFCLK_MASK (1 << 13)
|
||||
|
||||
/*
|
||||
* Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
|
||||
* CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
|
||||
|
@ -444,6 +452,10 @@
|
|||
#define OMAP4430_CLKSEL_60M_SHIFT 24
|
||||
#define OMAP4430_CLKSEL_60M_MASK (1 << 24)
|
||||
|
||||
/* Used by CM_MPU_MPU_CLKCTRL */
|
||||
#define OMAP4460_CLKSEL_ABE_DIV_MODE_SHIFT 25
|
||||
#define OMAP4460_CLKSEL_ABE_DIV_MODE_MASK (1 << 25)
|
||||
|
||||
/* Used by CM1_ABE_AESS_CLKCTRL */
|
||||
#define OMAP4430_CLKSEL_AESS_FCLK_SHIFT 24
|
||||
#define OMAP4430_CLKSEL_AESS_FCLK_MASK (1 << 24)
|
||||
|
@ -460,6 +472,10 @@
|
|||
#define OMAP4430_CLKSEL_DIV_SHIFT 24
|
||||
#define OMAP4430_CLKSEL_DIV_MASK (1 << 24)
|
||||
|
||||
/* Used by CM_MPU_MPU_CLKCTRL */
|
||||
#define OMAP4460_CLKSEL_EMIF_DIV_MODE_SHIFT 24
|
||||
#define OMAP4460_CLKSEL_EMIF_DIV_MODE_MASK (1 << 24)
|
||||
|
||||
/* Used by CM_CAM_FDIF_CLKCTRL */
|
||||
#define OMAP4430_CLKSEL_FCLK_SHIFT 24
|
||||
#define OMAP4430_CLKSEL_FCLK_MASK (0x3 << 24)
|
||||
|
@ -555,6 +571,14 @@
|
|||
#define OMAP4430_D2D_STATDEP_SHIFT 18
|
||||
#define OMAP4430_D2D_STATDEP_MASK (1 << 18)
|
||||
|
||||
/* Used by CM_CLKSEL_DPLL_MPU */
|
||||
#define OMAP4460_DCC_COUNT_MAX_SHIFT 24
|
||||
#define OMAP4460_DCC_COUNT_MAX_MASK (0xff << 24)
|
||||
|
||||
/* Used by CM_CLKSEL_DPLL_MPU */
|
||||
#define OMAP4460_DCC_EN_SHIFT 22
|
||||
#define OMAP4460_DCC_EN_MASK (1 << 22)
|
||||
|
||||
/*
|
||||
* Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
|
||||
* CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
|
||||
|
@ -564,6 +588,10 @@
|
|||
#define OMAP4430_DELTAMSTEP_SHIFT 0
|
||||
#define OMAP4430_DELTAMSTEP_MASK (0xfffff << 0)
|
||||
|
||||
/* Renamed from DELTAMSTEP Used by CM_SSC_DELTAMSTEP_DPLL_USB */
|
||||
#define OMAP4460_DELTAMSTEP_0_20_SHIFT 0
|
||||
#define OMAP4460_DELTAMSTEP_0_20_MASK (0x1fffff << 0)
|
||||
|
||||
/* Used by CM_DLL_CTRL */
|
||||
#define OMAP4430_DLL_OVERRIDE_SHIFT 0
|
||||
#define OMAP4430_DLL_OVERRIDE_MASK (1 << 0)
|
||||
|
@ -1106,6 +1134,10 @@
|
|||
#define OMAP4430_MODULEMODE_SHIFT 0
|
||||
#define OMAP4430_MODULEMODE_MASK (0x3 << 0)
|
||||
|
||||
/* Used by CM_L4CFG_DYNAMICDEP */
|
||||
#define OMAP4460_MPU_DYNDEP_SHIFT 19
|
||||
#define OMAP4460_MPU_DYNDEP_MASK (1 << 19)
|
||||
|
||||
/* Used by CM_DSS_DSS_CLKCTRL */
|
||||
#define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT 9
|
||||
#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK (1 << 9)
|
||||
|
@ -1198,6 +1230,10 @@
|
|||
#define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT 10
|
||||
#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK (1 << 10)
|
||||
|
||||
/* Used by CM_WKUP_BANDGAP_CLKCTRL */
|
||||
#define OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT 8
|
||||
#define OMAP4460_OPTFCLKEN_TS_FCLK_MASK (1 << 8)
|
||||
|
||||
/* Used by CM_DSS_DSS_CLKCTRL */
|
||||
#define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT 11
|
||||
#define OMAP4430_OPTFCLKEN_TV_CLK_MASK (1 << 11)
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
static struct omap_chip_id omap_chip;
|
||||
static unsigned int omap_revision;
|
||||
|
||||
u32 omap3_features;
|
||||
u32 omap_features;
|
||||
|
||||
unsigned int omap_rev(void)
|
||||
{
|
||||
|
@ -183,14 +183,14 @@ static void __init omap24xx_check_revision(void)
|
|||
#define OMAP3_CHECK_FEATURE(status,feat) \
|
||||
if (((status & OMAP3_ ##feat## _MASK) \
|
||||
>> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) { \
|
||||
omap3_features |= OMAP3_HAS_ ##feat; \
|
||||
omap_features |= OMAP3_HAS_ ##feat; \
|
||||
}
|
||||
|
||||
static void __init omap3_check_features(void)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
omap3_features = 0;
|
||||
omap_features = 0;
|
||||
|
||||
status = omap_ctrl_readl(OMAP3_CONTROL_OMAP_STATUS);
|
||||
|
||||
|
@ -200,11 +200,11 @@ static void __init omap3_check_features(void)
|
|||
OMAP3_CHECK_FEATURE(status, NEON);
|
||||
OMAP3_CHECK_FEATURE(status, ISP);
|
||||
if (cpu_is_omap3630())
|
||||
omap3_features |= OMAP3_HAS_192MHZ_CLK;
|
||||
omap_features |= OMAP3_HAS_192MHZ_CLK;
|
||||
if (!cpu_is_omap3505() && !cpu_is_omap3517())
|
||||
omap3_features |= OMAP3_HAS_IO_WAKEUP;
|
||||
omap_features |= OMAP3_HAS_IO_WAKEUP;
|
||||
|
||||
omap3_features |= OMAP3_HAS_SDRC;
|
||||
omap_features |= OMAP3_HAS_SDRC;
|
||||
|
||||
/*
|
||||
* TODO: Get additional info (where applicable)
|
||||
|
@ -212,9 +212,34 @@ static void __init omap3_check_features(void)
|
|||
*/
|
||||
}
|
||||
|
||||
static void __init omap4_check_features(void)
|
||||
{
|
||||
u32 si_type;
|
||||
|
||||
if (cpu_is_omap443x())
|
||||
omap_features |= OMAP4_HAS_MPU_1GHZ;
|
||||
|
||||
|
||||
if (cpu_is_omap446x()) {
|
||||
si_type =
|
||||
read_tap_reg(OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1);
|
||||
switch ((si_type & (3 << 16)) >> 16) {
|
||||
case 2:
|
||||
/* High performance device */
|
||||
omap_features |= OMAP4_HAS_MPU_1_5GHZ;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
/* Standard device */
|
||||
omap_features |= OMAP4_HAS_MPU_1_2GHZ;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void __init ti816x_check_features(void)
|
||||
{
|
||||
omap3_features = OMAP3_HAS_NEON;
|
||||
omap_features = OMAP3_HAS_NEON;
|
||||
}
|
||||
|
||||
static void __init omap3_check_revision(void)
|
||||
|
@ -344,10 +369,10 @@ static void __init omap4_check_revision(void)
|
|||
rev = (idcode >> 28) & 0xf;
|
||||
|
||||
/*
|
||||
* Few initial ES2.0 samples IDCODE is same as ES1.0
|
||||
* Few initial 4430 ES2.0 samples IDCODE is same as ES1.0
|
||||
* Use ARM register to detect the correct ES version
|
||||
*/
|
||||
if (!rev) {
|
||||
if (!rev && (hawkeye != 0xb94e)) {
|
||||
idcode = read_cpuid(CPUID_ID);
|
||||
rev = (idcode & 0xf) - 1;
|
||||
}
|
||||
|
@ -377,6 +402,15 @@ static void __init omap4_check_revision(void)
|
|||
omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
|
||||
}
|
||||
break;
|
||||
case 0xb94e:
|
||||
switch (rev) {
|
||||
case 0:
|
||||
default:
|
||||
omap_revision = OMAP4460_REV_ES1_0;
|
||||
omap_chip.oc |= CHIP_IS_OMAP4460ES1_0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Unknown default to latest silicon rev as default */
|
||||
omap_revision = OMAP4430_REV_ES2_2;
|
||||
|
@ -518,6 +552,7 @@ void __init omap2_check_revision(void)
|
|||
return;
|
||||
} else if (cpu_is_omap44xx()) {
|
||||
omap4_check_revision();
|
||||
omap4_check_features();
|
||||
return;
|
||||
} else {
|
||||
pr_err("OMAP revision unknown, please fix!\n");
|
||||
|
|
|
@ -283,6 +283,14 @@
|
|||
#define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT 10
|
||||
#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK (0x3 << 10)
|
||||
|
||||
/* Used by PRM_DEVICE_OFF_CTRL */
|
||||
#define OMAP4460_EMIF1_OFFWKUP_DISABLE_SHIFT 8
|
||||
#define OMAP4460_EMIF1_OFFWKUP_DISABLE_MASK (1 << 8)
|
||||
|
||||
/* Used by PRM_DEVICE_OFF_CTRL */
|
||||
#define OMAP4460_EMIF2_OFFWKUP_DISABLE_SHIFT 9
|
||||
#define OMAP4460_EMIF2_OFFWKUP_DISABLE_MASK (1 << 9)
|
||||
|
||||
/* Used by RM_MPU_RSTST */
|
||||
#define OMAP4430_EMULATION_RST_SHIFT 0
|
||||
#define OMAP4430_EMULATION_RST_MASK (1 << 0)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
obj-y := timer.o
|
||||
obj-y += irq.o
|
||||
obj-y += clock.o
|
||||
obj-y += rstc.o
|
||||
obj-y += prima2.o
|
||||
obj-$(CONFIG_DEBUG_LL) += lluart.o
|
||||
obj-$(CONFIG_CACHE_L2X0) += l2x0.o
|
|
@ -0,0 +1,3 @@
|
|||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
|
@ -0,0 +1,509 @@
|
|||
/*
|
||||
* Clock tree for CSR SiRFprimaII
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <mach/map.h>
|
||||
|
||||
#define SIRFSOC_CLKC_CLK_EN0 0x0000
|
||||
#define SIRFSOC_CLKC_CLK_EN1 0x0004
|
||||
#define SIRFSOC_CLKC_REF_CFG 0x0014
|
||||
#define SIRFSOC_CLKC_CPU_CFG 0x0018
|
||||
#define SIRFSOC_CLKC_MEM_CFG 0x001c
|
||||
#define SIRFSOC_CLKC_SYS_CFG 0x0020
|
||||
#define SIRFSOC_CLKC_IO_CFG 0x0024
|
||||
#define SIRFSOC_CLKC_DSP_CFG 0x0028
|
||||
#define SIRFSOC_CLKC_GFX_CFG 0x002c
|
||||
#define SIRFSOC_CLKC_MM_CFG 0x0030
|
||||
#define SIRFSOC_LKC_LCD_CFG 0x0034
|
||||
#define SIRFSOC_CLKC_MMC_CFG 0x0038
|
||||
#define SIRFSOC_CLKC_PLL1_CFG0 0x0040
|
||||
#define SIRFSOC_CLKC_PLL2_CFG0 0x0044
|
||||
#define SIRFSOC_CLKC_PLL3_CFG0 0x0048
|
||||
#define SIRFSOC_CLKC_PLL1_CFG1 0x004c
|
||||
#define SIRFSOC_CLKC_PLL2_CFG1 0x0050
|
||||
#define SIRFSOC_CLKC_PLL3_CFG1 0x0054
|
||||
#define SIRFSOC_CLKC_PLL1_CFG2 0x0058
|
||||
#define SIRFSOC_CLKC_PLL2_CFG2 0x005c
|
||||
#define SIRFSOC_CLKC_PLL3_CFG2 0x0060
|
||||
|
||||
#define SIRFSOC_CLOCK_VA_BASE SIRFSOC_VA(0x005000)
|
||||
|
||||
#define KHZ 1000
|
||||
#define MHZ (KHZ * KHZ)
|
||||
|
||||
struct clk_ops {
|
||||
unsigned long (*get_rate)(struct clk *clk);
|
||||
long (*round_rate)(struct clk *clk, unsigned long rate);
|
||||
int (*set_rate)(struct clk *clk, unsigned long rate);
|
||||
int (*enable)(struct clk *clk);
|
||||
int (*disable)(struct clk *clk);
|
||||
struct clk *(*get_parent)(struct clk *clk);
|
||||
int (*set_parent)(struct clk *clk, struct clk *parent);
|
||||
};
|
||||
|
||||
struct clk {
|
||||
struct clk *parent; /* parent clk */
|
||||
unsigned long rate; /* clock rate in Hz */
|
||||
signed char usage; /* clock enable count */
|
||||
signed char enable_bit; /* enable bit: 0 ~ 63 */
|
||||
unsigned short regofs; /* register offset */
|
||||
struct clk_ops *ops; /* clock operation */
|
||||
};
|
||||
|
||||
static DEFINE_SPINLOCK(clocks_lock);
|
||||
|
||||
static inline unsigned long clkc_readl(unsigned reg)
|
||||
{
|
||||
return readl(SIRFSOC_CLOCK_VA_BASE + reg);
|
||||
}
|
||||
|
||||
static inline void clkc_writel(u32 val, unsigned reg)
|
||||
{
|
||||
writel(val, SIRFSOC_CLOCK_VA_BASE + reg);
|
||||
}
|
||||
|
||||
/*
|
||||
* osc_rtc - real time oscillator - 32.768KHz
|
||||
* osc_sys - high speed oscillator - 26MHz
|
||||
*/
|
||||
|
||||
static struct clk clk_rtc = {
|
||||
.rate = 32768,
|
||||
};
|
||||
|
||||
static struct clk clk_osc = {
|
||||
.rate = 26 * MHZ,
|
||||
};
|
||||
|
||||
/*
|
||||
* std pll
|
||||
*/
|
||||
static unsigned long std_pll_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long fin = clk_get_rate(clk->parent);
|
||||
u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 -
|
||||
SIRFSOC_CLKC_PLL1_CFG0;
|
||||
|
||||
if (clkc_readl(regcfg2) & BIT(2)) {
|
||||
/* pll bypass mode */
|
||||
clk->rate = fin;
|
||||
} else {
|
||||
/* fout = fin * nf / nr / od */
|
||||
u32 cfg0 = clkc_readl(clk->regofs);
|
||||
u32 nf = (cfg0 & (BIT(13) - 1)) + 1;
|
||||
u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1;
|
||||
u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1;
|
||||
WARN_ON(fin % MHZ);
|
||||
clk->rate = fin / MHZ * nf / nr / od * MHZ;
|
||||
}
|
||||
|
||||
return clk->rate;
|
||||
}
|
||||
|
||||
static int std_pll_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long fin, nf, nr, od, reg;
|
||||
|
||||
/*
|
||||
* fout = fin * nf / (nr * od);
|
||||
* set od = 1, nr = fin/MHz, so fout = nf * MHz
|
||||
*/
|
||||
|
||||
nf = rate / MHZ;
|
||||
if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1))
|
||||
return -EINVAL;
|
||||
|
||||
fin = clk_get_rate(clk->parent);
|
||||
BUG_ON(fin < MHZ);
|
||||
|
||||
nr = fin / MHZ;
|
||||
BUG_ON((fin % MHZ) || nr > BIT(6));
|
||||
|
||||
od = 1;
|
||||
|
||||
reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19);
|
||||
clkc_writel(reg, clk->regofs);
|
||||
|
||||
reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0;
|
||||
clkc_writel((nf >> 1) - 1, reg);
|
||||
|
||||
reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0;
|
||||
while (!(clkc_readl(reg) & BIT(6)))
|
||||
cpu_relax();
|
||||
|
||||
clk->rate = 0; /* set to zero will force recalculation */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops std_pll_ops = {
|
||||
.get_rate = std_pll_get_rate,
|
||||
.set_rate = std_pll_set_rate,
|
||||
};
|
||||
|
||||
static struct clk clk_pll1 = {
|
||||
.parent = &clk_osc,
|
||||
.regofs = SIRFSOC_CLKC_PLL1_CFG0,
|
||||
.ops = &std_pll_ops,
|
||||
};
|
||||
|
||||
static struct clk clk_pll2 = {
|
||||
.parent = &clk_osc,
|
||||
.regofs = SIRFSOC_CLKC_PLL2_CFG0,
|
||||
.ops = &std_pll_ops,
|
||||
};
|
||||
|
||||
static struct clk clk_pll3 = {
|
||||
.parent = &clk_osc,
|
||||
.regofs = SIRFSOC_CLKC_PLL3_CFG0,
|
||||
.ops = &std_pll_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* clock domains - cpu, mem, sys/io
|
||||
*/
|
||||
|
||||
static struct clk clk_mem;
|
||||
|
||||
static struct clk *dmn_get_parent(struct clk *clk)
|
||||
{
|
||||
struct clk *clks[] = {
|
||||
&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
|
||||
};
|
||||
u32 cfg = clkc_readl(clk->regofs);
|
||||
WARN_ON((cfg & (BIT(3) - 1)) > 4);
|
||||
return clks[cfg & (BIT(3) - 1)];
|
||||
}
|
||||
|
||||
static int dmn_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
const struct clk *clks[] = {
|
||||
&clk_osc, &clk_rtc, &clk_pll1, &clk_pll2, &clk_pll3
|
||||
};
|
||||
u32 cfg = clkc_readl(clk->regofs);
|
||||
int i;
|
||||
for (i = 0; i < ARRAY_SIZE(clks); i++) {
|
||||
if (clks[i] == parent) {
|
||||
cfg &= ~(BIT(3) - 1);
|
||||
clkc_writel(cfg | i, clk->regofs);
|
||||
/* BIT(3) - switching status: 1 - busy, 0 - done */
|
||||
while (clkc_readl(clk->regofs) & BIT(3))
|
||||
cpu_relax();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static unsigned long dmn_get_rate(struct clk *clk)
|
||||
{
|
||||
unsigned long fin = clk_get_rate(clk->parent);
|
||||
u32 cfg = clkc_readl(clk->regofs);
|
||||
if (cfg & BIT(24)) {
|
||||
/* fcd bypass mode */
|
||||
clk->rate = fin;
|
||||
} else {
|
||||
/*
|
||||
* wait count: bit[19:16], hold count: bit[23:20]
|
||||
*/
|
||||
u32 wait = (cfg >> 16) & (BIT(4) - 1);
|
||||
u32 hold = (cfg >> 20) & (BIT(4) - 1);
|
||||
|
||||
clk->rate = fin / (wait + hold + 2);
|
||||
}
|
||||
|
||||
return clk->rate;
|
||||
}
|
||||
|
||||
static int dmn_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
unsigned long fin;
|
||||
unsigned ratio, wait, hold, reg;
|
||||
unsigned bits = (clk == &clk_mem) ? 3 : 4;
|
||||
|
||||
fin = clk_get_rate(clk->parent);
|
||||
ratio = fin / rate;
|
||||
|
||||
if (unlikely(ratio < 2 || ratio > BIT(bits + 1)))
|
||||
return -EINVAL;
|
||||
|
||||
WARN_ON(fin % rate);
|
||||
|
||||
wait = (ratio >> 1) - 1;
|
||||
hold = ratio - wait - 2;
|
||||
|
||||
reg = clkc_readl(clk->regofs);
|
||||
reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20));
|
||||
reg |= (wait << 16) | (hold << 20) | BIT(25);
|
||||
clkc_writel(reg, clk->regofs);
|
||||
|
||||
/* waiting FCD been effective */
|
||||
while (clkc_readl(clk->regofs) & BIT(25))
|
||||
cpu_relax();
|
||||
|
||||
clk->rate = 0; /* set to zero will force recalculation */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu clock has no FCD register in Prima2, can only change pll
|
||||
*/
|
||||
static int cpu_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
int ret1, ret2;
|
||||
struct clk *cur_parent, *tmp_parent;
|
||||
|
||||
cur_parent = dmn_get_parent(clk);
|
||||
BUG_ON(cur_parent == NULL || cur_parent->usage > 1);
|
||||
|
||||
/* switch to tmp pll before setting parent clock's rate */
|
||||
tmp_parent = cur_parent == &clk_pll1 ? &clk_pll2 : &clk_pll1;
|
||||
ret1 = dmn_set_parent(clk, tmp_parent);
|
||||
BUG_ON(ret1);
|
||||
|
||||
ret2 = clk_set_rate(cur_parent, rate);
|
||||
|
||||
ret1 = dmn_set_parent(clk, cur_parent);
|
||||
|
||||
clk->rate = 0; /* set to zero will force recalculation */
|
||||
|
||||
return ret2 ? ret2 : ret1;
|
||||
}
|
||||
|
||||
static struct clk_ops cpu_ops = {
|
||||
.get_parent = dmn_get_parent,
|
||||
.set_parent = dmn_set_parent,
|
||||
.set_rate = cpu_set_rate,
|
||||
};
|
||||
|
||||
static struct clk clk_cpu = {
|
||||
.parent = &clk_pll1,
|
||||
.regofs = SIRFSOC_CLKC_CPU_CFG,
|
||||
.ops = &cpu_ops,
|
||||
};
|
||||
|
||||
|
||||
static struct clk_ops msi_ops = {
|
||||
.set_rate = dmn_set_rate,
|
||||
.get_rate = dmn_get_rate,
|
||||
.set_parent = dmn_set_parent,
|
||||
.get_parent = dmn_get_parent,
|
||||
};
|
||||
|
||||
static struct clk clk_mem = {
|
||||
.parent = &clk_pll2,
|
||||
.regofs = SIRFSOC_CLKC_MEM_CFG,
|
||||
.ops = &msi_ops,
|
||||
};
|
||||
|
||||
static struct clk clk_sys = {
|
||||
.parent = &clk_pll3,
|
||||
.regofs = SIRFSOC_CLKC_SYS_CFG,
|
||||
.ops = &msi_ops,
|
||||
};
|
||||
|
||||
static struct clk clk_io = {
|
||||
.parent = &clk_pll3,
|
||||
.regofs = SIRFSOC_CLKC_IO_CFG,
|
||||
.ops = &msi_ops,
|
||||
};
|
||||
|
||||
/*
|
||||
* on-chip clock sets
|
||||
*/
|
||||
static struct clk_lookup onchip_clks[] = {
|
||||
{
|
||||
.dev_id = "rtc",
|
||||
.clk = &clk_rtc,
|
||||
}, {
|
||||
.dev_id = "osc",
|
||||
.clk = &clk_osc,
|
||||
}, {
|
||||
.dev_id = "pll1",
|
||||
.clk = &clk_pll1,
|
||||
}, {
|
||||
.dev_id = "pll2",
|
||||
.clk = &clk_pll2,
|
||||
}, {
|
||||
.dev_id = "pll3",
|
||||
.clk = &clk_pll3,
|
||||
}, {
|
||||
.dev_id = "cpu",
|
||||
.clk = &clk_cpu,
|
||||
}, {
|
||||
.dev_id = "mem",
|
||||
.clk = &clk_mem,
|
||||
}, {
|
||||
.dev_id = "sys",
|
||||
.clk = &clk_sys,
|
||||
}, {
|
||||
.dev_id = "io",
|
||||
.clk = &clk_io,
|
||||
},
|
||||
};
|
||||
|
||||
int clk_enable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return -EINVAL;
|
||||
|
||||
if (clk->parent)
|
||||
clk_enable(clk->parent);
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
if (!clk->usage++ && clk->ops && clk->ops->enable)
|
||||
clk->ops->enable(clk);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_enable);
|
||||
|
||||
void clk_disable(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return;
|
||||
|
||||
WARN_ON(!clk->usage);
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
if (--clk->usage == 0 && clk->ops && clk->ops->disable)
|
||||
clk->ops->disable(clk);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
|
||||
if (clk->parent)
|
||||
clk_disable(clk->parent);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_disable);
|
||||
|
||||
unsigned long clk_get_rate(struct clk *clk)
|
||||
{
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return 0;
|
||||
|
||||
if (clk->rate)
|
||||
return clk->rate;
|
||||
|
||||
if (clk->ops && clk->ops->get_rate)
|
||||
return clk->ops->get_rate(clk);
|
||||
|
||||
return clk_get_rate(clk->parent);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_rate);
|
||||
|
||||
long clk_round_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return 0;
|
||||
|
||||
if (clk->ops && clk->ops->round_rate)
|
||||
return clk->ops->round_rate(clk, rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_round_rate);
|
||||
|
||||
int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||
{
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!clk->ops || !clk->ops->set_rate)
|
||||
return -EINVAL;
|
||||
|
||||
return clk->ops->set_rate(clk, rate);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_rate);
|
||||
|
||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||
{
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return -EINVAL;
|
||||
|
||||
if (!clk->ops || !clk->ops->set_parent)
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
ret = clk->ops->set_parent(clk, parent);
|
||||
if (!ret) {
|
||||
parent->usage += clk->usage;
|
||||
clk->parent->usage -= clk->usage;
|
||||
BUG_ON(clk->parent->usage < 0);
|
||||
clk->parent = parent;
|
||||
}
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_set_parent);
|
||||
|
||||
struct clk *clk_get_parent(struct clk *clk)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(IS_ERR_OR_NULL(clk)))
|
||||
return NULL;
|
||||
|
||||
if (!clk->ops || !clk->ops->get_parent)
|
||||
return clk->parent;
|
||||
|
||||
spin_lock_irqsave(&clocks_lock, flags);
|
||||
clk->parent = clk->ops->get_parent(clk);
|
||||
spin_unlock_irqrestore(&clocks_lock, flags);
|
||||
return clk->parent;
|
||||
}
|
||||
EXPORT_SYMBOL(clk_get_parent);
|
||||
|
||||
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,prima2-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();
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/clkdev.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_CLKDEV_H
|
||||
#define __MACH_CLKDEV_H
|
||||
|
||||
#define __clk_get(clk) ({ 1; })
|
||||
#define __clk_put(clk) do { } while (0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/debug-macro.S
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/uart.h>
|
||||
|
||||
.macro addruart, rp, rv
|
||||
ldr \rp, =SIRFSOC_UART1_PA_BASE @ physical
|
||||
ldr \rv, =SIRFSOC_UART1_VA_BASE @ virtual
|
||||
.endm
|
||||
|
||||
.macro senduart,rd,rx
|
||||
str \rd, [\rx, #SIRFSOC_UART_TXFIFO_DATA]
|
||||
.endm
|
||||
|
||||
.macro busyuart,rd,rx
|
||||
.endm
|
||||
|
||||
.macro waituart,rd,rx
|
||||
1001: ldr \rd, [\rx, #SIRFSOC_UART_TXFIFO_STATUS]
|
||||
tst \rd, #SIRFSOC_UART1_TXFIFO_EMPTY
|
||||
beq 1001b
|
||||
.endm
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/entry-macro.S
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#define SIRFSOC_INT_ID 0x38
|
||||
|
||||
.macro get_irqnr_preamble, base, tmp
|
||||
ldr \base, =sirfsoc_intc_base
|
||||
ldr \base, [\base]
|
||||
.endm
|
||||
|
||||
.macro get_irqnr_and_base, irqnr, irqstat, base, tmp
|
||||
ldr \irqnr, [\base, #SIRFSOC_INT_ID] @ Get the highest priority irq
|
||||
cmp \irqnr, #0x40 @ the irq num can't be larger than 0x3f
|
||||
movges \irqnr, #0
|
||||
.endm
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/hardware.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_HARDWARE_H__
|
||||
#define __MACH_HARDWARE_H__
|
||||
|
||||
#include <asm/sizes.h>
|
||||
#include <mach/map.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/io.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_PRIMA2_IO_H
|
||||
#define __MACH_PRIMA2_IO_H
|
||||
|
||||
#define IO_SPACE_LIMIT ((resource_size_t)0)
|
||||
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/irqs.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_IRQS_H
|
||||
#define __ASM_ARCH_IRQS_H
|
||||
|
||||
#define SIRFSOC_INTENAL_IRQ_START 0
|
||||
#define SIRFSOC_INTENAL_IRQ_END 59
|
||||
|
||||
#define NR_IRQS 220
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* memory & I/O static mapping definitions for CSR SiRFprimaII
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_PRIMA2_MAP_H__
|
||||
#define __MACH_PRIMA2_MAP_H__
|
||||
|
||||
#include <mach/vmalloc.h>
|
||||
|
||||
#define SIRFSOC_VA(x) (VMALLOC_END + ((x) & 0x00FFF000))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/memory.h
|
||||
*
|
||||
* Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_MEMORY_H
|
||||
#define __ASM_ARCH_MEMORY_H
|
||||
|
||||
#define PLAT_PHYS_OFFSET UL(0x00000000)
|
||||
|
||||
/*
|
||||
* Restrict DMA-able region to workaround silicon limitation.
|
||||
* The limitation restricts buffers available for DMA to SD/MMC
|
||||
* hardware to be below 256MB
|
||||
*/
|
||||
#define ARM_DMA_ZONE_SIZE (SZ_256M)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/system.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_SYSTEM_H__
|
||||
#define __MACH_SYSTEM_H__
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#define SIRFSOC_SYS_RST_BIT BIT(31)
|
||||
|
||||
extern void __iomem *sirfsoc_rstc_base;
|
||||
|
||||
static inline void arch_idle(void)
|
||||
{
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
static inline void arch_reset(char mode, const char *cmd)
|
||||
{
|
||||
writel(SIRFSOC_SYS_RST_BIT, sirfsoc_rstc_base);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/timex.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_TIMEX_H__
|
||||
#define __MACH_TIMEX_H__
|
||||
|
||||
#define CLOCK_TICK_RATE 1000000
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/uart.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_PRIMA2_SIRFSOC_UART_H
|
||||
#define __MACH_PRIMA2_SIRFSOC_UART_H
|
||||
|
||||
/* UART-1: used as serial debug port */
|
||||
#define SIRFSOC_UART1_PA_BASE 0xb0060000
|
||||
#define SIRFSOC_UART1_VA_BASE SIRFSOC_VA(0x060000)
|
||||
#define SIRFSOC_UART1_SIZE SZ_4K
|
||||
|
||||
#define SIRFSOC_UART_TXFIFO_STATUS 0x0114
|
||||
#define SIRFSOC_UART_TXFIFO_DATA 0x0118
|
||||
|
||||
#define SIRFSOC_UART1_TXFIFO_FULL (1 << 5)
|
||||
#define SIRFSOC_UART1_TXFIFO_EMPTY (1 << 6)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* arch/arm/mach-prima2/include/mach/uncompress.h
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_UNCOMPRESS_H
|
||||
#define __ASM_ARCH_UNCOMPRESS_H
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/uart.h>
|
||||
|
||||
void arch_decomp_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
#define arch_decomp_wdog()
|
||||
|
||||
static __inline__ void putc(char c)
|
||||
{
|
||||
/*
|
||||
* during kernel decompression, all mappings are flat:
|
||||
* virt_addr == phys_addr
|
||||
*/
|
||||
while (__raw_readl(SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
|
||||
& SIRFSOC_UART1_TXFIFO_FULL)
|
||||
barrier();
|
||||
|
||||
__raw_writel(c, SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_DATA);
|
||||
}
|
||||
|
||||
static inline void flush(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* arch/arm/ach-prima2/include/mach/vmalloc.h
|
||||
*
|
||||
* Copyright (c) 2010 – 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_VMALLOC_H
|
||||
#define __MACH_VMALLOC_H
|
||||
|
||||
#include <linux/const.h>
|
||||
|
||||
#define VMALLOC_END _AC(0xFEC00000, UL)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* interrupt controller support 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/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#define SIRFSOC_INT_RISC_MASK0 0x0018
|
||||
#define SIRFSOC_INT_RISC_MASK1 0x001C
|
||||
#define SIRFSOC_INT_RISC_LEVEL0 0x0020
|
||||
#define SIRFSOC_INT_RISC_LEVEL1 0x0024
|
||||
|
||||
void __iomem *sirfsoc_intc_base;
|
||||
|
||||
static __init void
|
||||
sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num)
|
||||
{
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
|
||||
gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq);
|
||||
ct = gc->chip_types;
|
||||
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_set_bit;
|
||||
ct->regs.mask = SIRFSOC_INT_RISC_MASK0;
|
||||
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0);
|
||||
}
|
||||
|
||||
static __init void sirfsoc_irq_init(void)
|
||||
{
|
||||
sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32);
|
||||
sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32);
|
||||
|
||||
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0);
|
||||
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1);
|
||||
|
||||
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0);
|
||||
writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
|
||||
}
|
||||
|
||||
static struct of_device_id intc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-intc" },
|
||||
};
|
||||
|
||||
void __init sirfsoc_of_irq_init(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_matching_node(NULL, intc_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible intc node in dtb\n");
|
||||
|
||||
sirfsoc_intc_base = of_iomap(np, 0);
|
||||
if (!sirfsoc_intc_base)
|
||||
panic("unable to map intc cpu registers\n");
|
||||
|
||||
of_node_put(np);
|
||||
|
||||
sirfsoc_irq_init();
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* l2 cache initialization 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 <linux/io.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
#include <mach/memory.h>
|
||||
|
||||
#define L2X0_ADDR_FILTERING_START 0xC00
|
||||
#define L2X0_ADDR_FILTERING_END 0xC04
|
||||
|
||||
static struct of_device_id l2x_ids[] = {
|
||||
{ .compatible = "arm,pl310-cache" },
|
||||
};
|
||||
|
||||
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 l2x 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);
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* Static memory mapping for DEBUG_LL
|
||||
*
|
||||
* Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
|
||||
*
|
||||
* Licensed under GPLv2 or later.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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")
|
||||
/* Maintainer: Barry Song <baohua.song@csr.com> */
|
||||
.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
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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/mutex.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
void __iomem *sirfsoc_rstc_base;
|
||||
static DEFINE_MUTEX(rstc_lock);
|
||||
|
||||
static struct of_device_id rstc_ids[] = {
|
||||
{ .compatible = "sirf,prima2-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);
|
||||
|
||||
int sirfsoc_reset_device(struct device *dev)
|
||||
{
|
||||
const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
|
||||
unsigned int reset_bit;
|
||||
|
||||
if (!prop)
|
||||
return -ENODEV;
|
||||
|
||||
reset_bit = be32_to_cpup(prop);
|
||||
|
||||
mutex_lock(&rstc_lock);
|
||||
|
||||
/*
|
||||
* Writing 1 to this bit resets corresponding block. Writing 0 to this
|
||||
* bit de-asserts reset signal of the corresponding block.
|
||||
* datasheet doesn't require explicit delay between the set and clear
|
||||
* of reset bit. it could be shorter if tests pass.
|
||||
*/
|
||||
writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
|
||||
sirfsoc_rstc_base + (reset_bit / 32) * 4);
|
||||
msleep(10);
|
||||
writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
|
||||
sirfsoc_rstc_base + (reset_bit / 32) * 4);
|
||||
|
||||
mutex_unlock(&rstc_lock);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* System timer 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/interrupt.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <mach/map.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#define SIRFSOC_TIMER_COUNTER_LO 0x0000
|
||||
#define SIRFSOC_TIMER_COUNTER_HI 0x0004
|
||||
#define SIRFSOC_TIMER_MATCH_0 0x0008
|
||||
#define SIRFSOC_TIMER_MATCH_1 0x000C
|
||||
#define SIRFSOC_TIMER_MATCH_2 0x0010
|
||||
#define SIRFSOC_TIMER_MATCH_3 0x0014
|
||||
#define SIRFSOC_TIMER_MATCH_4 0x0018
|
||||
#define SIRFSOC_TIMER_MATCH_5 0x001C
|
||||
#define SIRFSOC_TIMER_STATUS 0x0020
|
||||
#define SIRFSOC_TIMER_INT_EN 0x0024
|
||||
#define SIRFSOC_TIMER_WATCHDOG_EN 0x0028
|
||||
#define SIRFSOC_TIMER_DIV 0x002C
|
||||
#define SIRFSOC_TIMER_LATCH 0x0030
|
||||
#define SIRFSOC_TIMER_LATCHED_LO 0x0034
|
||||
#define SIRFSOC_TIMER_LATCHED_HI 0x0038
|
||||
|
||||
#define SIRFSOC_TIMER_WDT_INDEX 5
|
||||
|
||||
#define SIRFSOC_TIMER_LATCH_BIT BIT(0)
|
||||
|
||||
static void __iomem *sirfsoc_timer_base;
|
||||
static void __init sirfsoc_of_timer_map(void);
|
||||
|
||||
/* timer0 interrupt handler */
|
||||
static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *ce = dev_id;
|
||||
|
||||
WARN_ON(!(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_STATUS) & BIT(0)));
|
||||
|
||||
/* clear timer0 interrupt */
|
||||
writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
|
||||
|
||||
ce->event_handler(ce);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/* read 64-bit timer counter */
|
||||
static cycle_t sirfsoc_timer_read(struct clocksource *cs)
|
||||
{
|
||||
u64 cycles;
|
||||
|
||||
/* latch the 64-bit timer counter */
|
||||
writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
|
||||
cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_HI);
|
||||
cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
|
||||
|
||||
return cycles;
|
||||
}
|
||||
|
||||
static int sirfsoc_timer_set_next_event(unsigned long delta,
|
||||
struct clock_event_device *ce)
|
||||
{
|
||||
unsigned long now, next;
|
||||
|
||||
writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
|
||||
now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
|
||||
next = now + delta;
|
||||
writel_relaxed(next, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0);
|
||||
writel_relaxed(SIRFSOC_TIMER_LATCH_BIT, sirfsoc_timer_base + SIRFSOC_TIMER_LATCH);
|
||||
now = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_LATCHED_LO);
|
||||
|
||||
return next - now > delta ? -ETIME : 0;
|
||||
}
|
||||
|
||||
static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *ce)
|
||||
{
|
||||
u32 val = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
writel_relaxed(val | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
writel_relaxed(val & ~BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_INT_EN);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct clock_event_device sirfsoc_clockevent = {
|
||||
.name = "sirfsoc_clockevent",
|
||||
.rating = 200,
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_mode = sirfsoc_timer_set_mode,
|
||||
.set_next_event = sirfsoc_timer_set_next_event,
|
||||
};
|
||||
|
||||
static struct clocksource sirfsoc_clocksource = {
|
||||
.name = "sirfsoc_clocksource",
|
||||
.rating = 200,
|
||||
.mask = CLOCKSOURCE_MASK(64),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.read = sirfsoc_timer_read,
|
||||
};
|
||||
|
||||
static struct irqaction sirfsoc_timer_irq = {
|
||||
.name = "sirfsoc_timer0",
|
||||
.flags = IRQF_TIMER,
|
||||
.irq = 0,
|
||||
.handler = sirfsoc_timer_interrupt,
|
||||
.dev_id = &sirfsoc_clockevent,
|
||||
};
|
||||
|
||||
/* Overwrite weak default sched_clock with more precise one */
|
||||
unsigned long long notrace sched_clock(void)
|
||||
{
|
||||
static int is_mapped = 0;
|
||||
|
||||
/*
|
||||
* sched_clock is called earlier than .init of sys_timer
|
||||
* if we map timer memory in .init of sys_timer, system
|
||||
* will panic due to illegal memory access
|
||||
*/
|
||||
if(!is_mapped) {
|
||||
sirfsoc_of_timer_map();
|
||||
is_mapped = 1;
|
||||
}
|
||||
|
||||
return sirfsoc_timer_read(NULL) * (NSEC_PER_SEC / CLOCK_TICK_RATE);
|
||||
}
|
||||
|
||||
static void __init sirfsoc_clockevent_init(void)
|
||||
{
|
||||
clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
|
||||
|
||||
sirfsoc_clockevent.max_delta_ns =
|
||||
clockevent_delta2ns(-2, &sirfsoc_clockevent);
|
||||
sirfsoc_clockevent.min_delta_ns =
|
||||
clockevent_delta2ns(2, &sirfsoc_clockevent);
|
||||
|
||||
sirfsoc_clockevent.cpumask = cpumask_of(0);
|
||||
clockevents_register_device(&sirfsoc_clockevent);
|
||||
}
|
||||
|
||||
/* initialize the kernel jiffy timer source */
|
||||
static void __init sirfsoc_timer_init(void)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
/* timer's input clock is io clock */
|
||||
struct clk *clk = clk_get_sys("io", NULL);
|
||||
|
||||
BUG_ON(IS_ERR(clk));
|
||||
|
||||
rate = clk_get_rate(clk);
|
||||
|
||||
BUG_ON(rate < CLOCK_TICK_RATE);
|
||||
BUG_ON(rate % CLOCK_TICK_RATE);
|
||||
|
||||
writel_relaxed(rate / CLOCK_TICK_RATE / 2 - 1, sirfsoc_timer_base + SIRFSOC_TIMER_DIV);
|
||||
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_LO);
|
||||
writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_HI);
|
||||
writel_relaxed(BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_STATUS);
|
||||
|
||||
BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
|
||||
|
||||
BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
|
||||
|
||||
sirfsoc_clockevent_init();
|
||||
}
|
||||
|
||||
static struct of_device_id timer_ids[] = {
|
||||
{ .compatible = "sirf,prima2-tick" },
|
||||
};
|
||||
|
||||
static void __init sirfsoc_of_timer_map(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
const unsigned int *intspec;
|
||||
|
||||
np = of_find_matching_node(NULL, timer_ids);
|
||||
if (!np)
|
||||
panic("unable to find compatible timer node in dtb\n");
|
||||
sirfsoc_timer_base = of_iomap(np, 0);
|
||||
if (!sirfsoc_timer_base)
|
||||
panic("unable to map timer cpu registers\n");
|
||||
|
||||
/* Get the interrupts property */
|
||||
intspec = of_get_property(np, "interrupts", NULL);
|
||||
BUG_ON(!intspec);
|
||||
sirfsoc_timer_irq.irq = be32_to_cpup(intspec);
|
||||
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
struct sys_timer sirfsoc_timer = {
|
||||
.init = sirfsoc_timer_init,
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
# Common support
|
||||
obj-y := common.o timer.o board_dt.o
|
|
@ -0,0 +1,3 @@
|
|||
zreladdr-y := 0x00008000
|
||||
params_phys-y := 0x00000100
|
||||
initrd_phys-y := 0x00800000
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* This file contains common code that is intended to be used across
|
||||
* boards so that it's not replicated.
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
|
||||
#include <mach/zynq_soc.h>
|
||||
#include <mach/clkdev.h>
|
||||
#include "common.h"
|
||||
|
||||
static struct of_device_id zynq_of_bus_ids[] __initdata = {
|
||||
{ .compatible = "simple-bus", },
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
* xilinx_init_machine() - System specific initialization, intended to be
|
||||
* called from board specific initialization.
|
||||
*/
|
||||
static void __init xilinx_init_machine(void)
|
||||
{
|
||||
#ifdef CONFIG_CACHE_L2X0
|
||||
/*
|
||||
* 64KB way size, 8-way associativity, parity disabled
|
||||
*/
|
||||
l2x0_init(PL310_L2CC_BASE, 0x02060000, 0xF0F0FFFF);
|
||||
#endif
|
||||
|
||||
of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* xilinx_irq_init() - Interrupt controller initialization for the GIC.
|
||||
*/
|
||||
static void __init xilinx_irq_init(void)
|
||||
{
|
||||
gic_init(0, 29, SCU_GIC_DIST_BASE, SCU_GIC_CPU_BASE);
|
||||
}
|
||||
|
||||
/* The minimum devices needed to be mapped before the VM system is up and
|
||||
* running include the GIC, UART and Timer Counter.
|
||||
*/
|
||||
|
||||
static struct map_desc io_desc[] __initdata = {
|
||||
{
|
||||
.virtual = TTC0_VIRT,
|
||||
.pfn = __phys_to_pfn(TTC0_PHYS),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = SCU_PERIPH_VIRT,
|
||||
.pfn = __phys_to_pfn(SCU_PERIPH_PHYS),
|
||||
.length = SZ_8K,
|
||||
.type = MT_DEVICE,
|
||||
}, {
|
||||
.virtual = PL310_L2CC_VIRT,
|
||||
.pfn = __phys_to_pfn(PL310_L2CC_PHYS),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
|
||||
#ifdef CONFIG_DEBUG_LL
|
||||
{
|
||||
.virtual = UART0_VIRT,
|
||||
.pfn = __phys_to_pfn(UART0_PHYS),
|
||||
.length = SZ_4K,
|
||||
.type = MT_DEVICE,
|
||||
},
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* xilinx_map_io() - Create memory mappings needed for early I/O.
|
||||
*/
|
||||
static void __init xilinx_map_io(void)
|
||||
{
|
||||
iotable_init(io_desc, ARRAY_SIZE(io_desc));
|
||||
}
|
||||
|
||||
static const char *xilinx_dt_match[] = {
|
||||
"xlnx,zynq-ep107",
|
||||
NULL
|
||||
};
|
||||
|
||||
MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
|
||||
.map_io = xilinx_map_io,
|
||||
.init_irq = xilinx_irq_init,
|
||||
.init_machine = xilinx_init_machine,
|
||||
.timer = &xttcpss_sys_timer,
|
||||
.dt_compat = xilinx_dt_match,
|
||||
MACHINE_END
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* This file contains common function prototypes to avoid externs
|
||||
* in the c files.
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_ZYNQ_COMMON_H__
|
||||
#define __MACH_ZYNQ_COMMON_H__
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
extern struct sys_timer xttcpss_sys_timer;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* arch/arm/mach-zynq/include/mach/clkdev.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MACH_CLKDEV_H__
|
||||
#define __MACH_CLKDEV_H__
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
struct clk {
|
||||
unsigned long rate;
|
||||
const struct clk_ops *ops;
|
||||
const struct icst_params *params;
|
||||
void __iomem *vcoreg;
|
||||
};
|
||||
|
||||
#define __clk_get(clk) ({ 1; })
|
||||
#define __clk_put(clk) do { } while (0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,36 @@
|
|||
/* arch/arm/mach-zynq/include/mach/debug-macro.S
|
||||
*
|
||||
* Debugging macro include header
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <mach/zynq_soc.h>
|
||||
#include <mach/uart.h>
|
||||
|
||||
.macro addruart, rp, rv
|
||||
ldr \rp, =LL_UART_PADDR @ physical
|
||||
ldr \rv, =LL_UART_VADDR @ virtual
|
||||
.endm
|
||||
|
||||
.macro senduart,rd,rx
|
||||
str \rd, [\rx, #UART_FIFO_OFFSET] @ TXDATA
|
||||
.endm
|
||||
|
||||
.macro waituart,rd,rx
|
||||
.endm
|
||||
|
||||
.macro busyuart,rd,rx
|
||||
1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register
|
||||
tst \rd, #UART_SR_TXFULL @
|
||||
bne 1002b @ wait if FIFO is full
|
||||
.endm
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* arch/arm/mach-zynq/include/mach/entry-macro.S
|
||||
*
|
||||
* Low-level IRQ helper macros
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* based on arch/plat-mxc/include/mach/entry-macro.S
|
||||
*
|
||||
* Copyright (C) 2007 Lennert Buytenhek <buytenh@wantstofly.org>
|
||||
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/hardware/entry-macro-gic.S>
|
||||
|
||||
.macro disable_fiq
|
||||
.endm
|
||||
|
||||
.macro arch_ret_to_user, tmp1, tmp2
|
||||
.endm
|
|
@ -0,0 +1,18 @@
|
|||
/* arch/arm/mach-zynq/include/mach/hardware.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_HARDWARE_H__
|
||||
#define __MACH_HARDWARE_H__
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/* arch/arm/mach-zynq/include/mach/io.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_IO_H__
|
||||
#define __MACH_IO_H__
|
||||
|
||||
/* Allow IO space to be anywhere in the memory */
|
||||
|
||||
#define IO_SPACE_LIMIT 0xffff
|
||||
|
||||
/* IO address mapping macros, nothing special at this time but required */
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#define IOMEM(x) (x)
|
||||
#else
|
||||
#define IOMEM(x) ((void __force __iomem *)(x))
|
||||
#endif
|
||||
|
||||
#define __io(a) __typesafe_io(a)
|
||||
#define __mem_pci(a) (a)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/* arch/arm/mach-zynq/include/mach/irqs.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_IRQS_H
|
||||
#define __MACH_IRQS_H
|
||||
|
||||
#define ARCH_NR_GPIOS 118
|
||||
#define NR_IRQS (128 + ARCH_NR_GPIOS)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/* arch/arm/mach-zynq/include/mach/memory.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_MEMORY_H__
|
||||
#define __MACH_MEMORY_H__
|
||||
|
||||
#include <asm/sizes.h>
|
||||
|
||||
#define PLAT_PHYS_OFFSET UL(0x0)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
/* arch/arm/mach-zynq/include/mach/system.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_SYSTEM_H__
|
||||
#define __MACH_SYSTEM_H__
|
||||
|
||||
static inline void arch_idle(void)
|
||||
{
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
static inline void arch_reset(char mode, const char *cmd)
|
||||
{
|
||||
/* Add architecture specific reset processing here */
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
/* arch/arm/mach-zynq/include/mach/timex.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_TIMEX_H__
|
||||
#define __MACH_TIMEX_H__
|
||||
|
||||
/* the following is needed for the system to build but will be removed
|
||||
in the future, the value is not important but won't hurt
|
||||
*/
|
||||
#define CLOCK_TICK_RATE (100 * HZ)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,25 @@
|
|||
/* arch/arm/mach-zynq/include/mach/uart.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_UART_H__
|
||||
#define __MACH_UART_H__
|
||||
|
||||
#define UART_CR_OFFSET 0x00 /* Control Register [8:0] */
|
||||
#define UART_SR_OFFSET 0x2C /* Channel Status [11:0] */
|
||||
#define UART_FIFO_OFFSET 0x30 /* FIFO [15:0] or [7:0] */
|
||||
|
||||
#define UART_SR_TXFULL 0x00000010 /* TX FIFO full */
|
||||
#define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,51 @@
|
|||
/* arch/arm/mach-zynq/include/mach/uncompress.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_UNCOMPRESS_H__
|
||||
#define __MACH_UNCOMPRESS_H__
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <asm/processor.h>
|
||||
#include <mach/zynq_soc.h>
|
||||
#include <mach/uart.h>
|
||||
|
||||
void arch_decomp_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void flush(void)
|
||||
{
|
||||
/*
|
||||
* Wait while the FIFO is not empty
|
||||
*/
|
||||
while (!(__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
|
||||
UART_SR_TXEMPTY))
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
#define arch_decomp_wdog()
|
||||
|
||||
static void putc(char ch)
|
||||
{
|
||||
/*
|
||||
* Wait for room in the FIFO, then write the char into the FIFO
|
||||
*/
|
||||
while (__raw_readl(IOMEM(LL_UART_PADDR + UART_SR_OFFSET)) &
|
||||
UART_SR_TXFULL)
|
||||
cpu_relax();
|
||||
|
||||
__raw_writel(ch, IOMEM(LL_UART_PADDR + UART_FIFO_OFFSET));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
/* arch/arm/mach-zynq/include/mach/vmalloc.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_VMALLOC_H__
|
||||
#define __MACH_VMALLOC_H__
|
||||
|
||||
#define VMALLOC_END 0xE0000000UL
|
||||
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/* arch/arm/mach-zynq/include/mach/zynq_soc.h
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __MACH_XILINX_SOC_H__
|
||||
#define __MACH_XILINX_SOC_H__
|
||||
|
||||
#define PERIPHERAL_CLOCK_RATE 2500000
|
||||
|
||||
/* For now, all mappings are flat (physical = virtual)
|
||||
*/
|
||||
#define UART0_PHYS 0xE0000000
|
||||
#define UART0_VIRT UART0_PHYS
|
||||
|
||||
#define TTC0_PHYS 0xF8001000
|
||||
#define TTC0_VIRT TTC0_PHYS
|
||||
|
||||
#define PL310_L2CC_PHYS 0xF8F02000
|
||||
#define PL310_L2CC_VIRT PL310_L2CC_PHYS
|
||||
|
||||
#define SCU_PERIPH_PHYS 0xF8F00000
|
||||
#define SCU_PERIPH_VIRT SCU_PERIPH_PHYS
|
||||
|
||||
/* The following are intended for the devices that are mapped early */
|
||||
|
||||
#define TTC0_BASE IOMEM(TTC0_VIRT)
|
||||
#define SCU_PERIPH_BASE IOMEM(SCU_PERIPH_VIRT)
|
||||
#define SCU_GIC_CPU_BASE (SCU_PERIPH_BASE + 0x100)
|
||||
#define SCU_GIC_DIST_BASE (SCU_PERIPH_BASE + 0x1000)
|
||||
#define PL310_L2CC_BASE IOMEM(PL310_L2CC_VIRT)
|
||||
|
||||
/*
|
||||
* Mandatory for CONFIG_LL_DEBUG, UART is mapped virtual = physical
|
||||
*/
|
||||
#define LL_UART_PADDR UART0_PHYS
|
||||
#define LL_UART_VADDR UART0_VIRT
|
||||
|
||||
#endif
|
|
@ -0,0 +1,298 @@
|
|||
/*
|
||||
* This file contains driver for the Xilinx PS Timer Counter IP.
|
||||
*
|
||||
* Copyright (C) 2011 Xilinx
|
||||
*
|
||||
* based on arch/mips/kernel/time.c timer driver
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <mach/zynq_soc.h>
|
||||
#include "common.h"
|
||||
|
||||
#define IRQ_TIMERCOUNTER0 42
|
||||
|
||||
/*
|
||||
* This driver configures the 2 16-bit count-up timers as follows:
|
||||
*
|
||||
* T1: Timer 1, clocksource for generic timekeeping
|
||||
* T2: Timer 2, clockevent source for hrtimers
|
||||
* T3: Timer 3, <unused>
|
||||
*
|
||||
* The input frequency to the timer module for emulation is 2.5MHz which is
|
||||
* common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32,
|
||||
* the timers are clocked at 78.125KHz (12.8 us resolution).
|
||||
*
|
||||
* The input frequency to the timer module in silicon will be 200MHz. With the
|
||||
* pre-scaler of 32, the timers are clocked at 6.25MHz (160ns resolution).
|
||||
*/
|
||||
#define XTTCPSS_CLOCKSOURCE 0 /* Timer 1 as a generic timekeeping */
|
||||
#define XTTCPSS_CLOCKEVENT 1 /* Timer 2 as a clock event */
|
||||
|
||||
#define XTTCPSS_TIMER_BASE TTC0_BASE
|
||||
#define XTTCPCC_EVENT_TIMER_IRQ (IRQ_TIMERCOUNTER0 + 1)
|
||||
/*
|
||||
* Timer Register Offset Definitions of Timer 1, Increment base address by 4
|
||||
* and use same offsets for Timer 2
|
||||
*/
|
||||
#define XTTCPSS_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */
|
||||
#define XTTCPSS_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */
|
||||
#define XTTCPSS_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */
|
||||
#define XTTCPSS_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */
|
||||
#define XTTCPSS_MATCH_1_OFFSET 0x30 /* Match 1 Value Reg, RW */
|
||||
#define XTTCPSS_MATCH_2_OFFSET 0x3C /* Match 2 Value Reg, RW */
|
||||
#define XTTCPSS_MATCH_3_OFFSET 0x48 /* Match 3 Value Reg, RW */
|
||||
#define XTTCPSS_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */
|
||||
#define XTTCPSS_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */
|
||||
|
||||
#define XTTCPSS_CNT_CNTRL_DISABLE_MASK 0x1
|
||||
|
||||
/* Setup the timers to use pre-scaling */
|
||||
|
||||
#define TIMER_RATE (PERIPHERAL_CLOCK_RATE / 32)
|
||||
|
||||
/**
|
||||
* struct xttcpss_timer - This definition defines local timer structure
|
||||
*
|
||||
* @base_addr: Base address of timer
|
||||
**/
|
||||
struct xttcpss_timer {
|
||||
void __iomem *base_addr;
|
||||
};
|
||||
|
||||
static struct xttcpss_timer timers[2];
|
||||
static struct clock_event_device xttcpss_clockevent;
|
||||
|
||||
/**
|
||||
* xttcpss_set_interval - Set the timer interval value
|
||||
*
|
||||
* @timer: Pointer to the timer instance
|
||||
* @cycles: Timer interval ticks
|
||||
**/
|
||||
static void xttcpss_set_interval(struct xttcpss_timer *timer,
|
||||
unsigned long cycles)
|
||||
{
|
||||
u32 ctrl_reg;
|
||||
|
||||
/* Disable the counter, set the counter value and re-enable counter */
|
||||
ctrl_reg = __raw_readl(timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
|
||||
__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
|
||||
__raw_writel(cycles, timer->base_addr + XTTCPSS_INTR_VAL_OFFSET);
|
||||
|
||||
/* Reset the counter (0x10) so that it starts from 0, one-shot
|
||||
mode makes this needed for timing to be right. */
|
||||
ctrl_reg |= 0x10;
|
||||
ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
|
||||
__raw_writel(ctrl_reg, timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* xttcpss_clock_event_interrupt - Clock event timer interrupt handler
|
||||
*
|
||||
* @irq: IRQ number of the Timer
|
||||
* @dev_id: void pointer to the xttcpss_timer instance
|
||||
*
|
||||
* returns: Always IRQ_HANDLED - success
|
||||
**/
|
||||
static irqreturn_t xttcpss_clock_event_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct clock_event_device *evt = &xttcpss_clockevent;
|
||||
struct xttcpss_timer *timer = dev_id;
|
||||
|
||||
/* Acknowledge the interrupt and call event handler */
|
||||
__raw_writel(__raw_readl(timer->base_addr + XTTCPSS_ISR_OFFSET),
|
||||
timer->base_addr + XTTCPSS_ISR_OFFSET);
|
||||
|
||||
evt->event_handler(evt);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct irqaction event_timer_irq = {
|
||||
.name = "xttcpss clockevent",
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.handler = xttcpss_clock_event_interrupt,
|
||||
};
|
||||
|
||||
/**
|
||||
* xttcpss_timer_hardware_init - Initialize the timer hardware
|
||||
*
|
||||
* Initialize the hardware to start the clock source, get the clock
|
||||
* event timer ready to use, and hook up the interrupt.
|
||||
**/
|
||||
static void __init xttcpss_timer_hardware_init(void)
|
||||
{
|
||||
/* Setup the clock source counter to be an incrementing counter
|
||||
* with no interrupt and it rolls over at 0xFFFF. Pre-scale
|
||||
it by 32 also. Let it start running now.
|
||||
*/
|
||||
timers[XTTCPSS_CLOCKSOURCE].base_addr = XTTCPSS_TIMER_BASE;
|
||||
|
||||
__raw_writel(0x0, timers[XTTCPSS_CLOCKSOURCE].base_addr +
|
||||
XTTCPSS_IER_OFFSET);
|
||||
__raw_writel(0x9, timers[XTTCPSS_CLOCKSOURCE].base_addr +
|
||||
XTTCPSS_CLK_CNTRL_OFFSET);
|
||||
__raw_writel(0x10, timers[XTTCPSS_CLOCKSOURCE].base_addr +
|
||||
XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
|
||||
/* Setup the clock event timer to be an interval timer which
|
||||
* is prescaled by 32 using the interval interrupt. Leave it
|
||||
* disabled for now.
|
||||
*/
|
||||
|
||||
timers[XTTCPSS_CLOCKEVENT].base_addr = XTTCPSS_TIMER_BASE + 4;
|
||||
|
||||
__raw_writel(0x23, timers[XTTCPSS_CLOCKEVENT].base_addr +
|
||||
XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
__raw_writel(0x9, timers[XTTCPSS_CLOCKEVENT].base_addr +
|
||||
XTTCPSS_CLK_CNTRL_OFFSET);
|
||||
__raw_writel(0x1, timers[XTTCPSS_CLOCKEVENT].base_addr +
|
||||
XTTCPSS_IER_OFFSET);
|
||||
|
||||
/* Setup IRQ the clock event timer */
|
||||
event_timer_irq.dev_id = &timers[XTTCPSS_CLOCKEVENT];
|
||||
setup_irq(XTTCPCC_EVENT_TIMER_IRQ, &event_timer_irq);
|
||||
}
|
||||
|
||||
/**
|
||||
* __raw_readl_cycles - Reads the timer counter register
|
||||
*
|
||||
* returns: Current timer counter register value
|
||||
**/
|
||||
static cycle_t __raw_readl_cycles(struct clocksource *cs)
|
||||
{
|
||||
struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKSOURCE];
|
||||
|
||||
return (cycle_t)__raw_readl(timer->base_addr +
|
||||
XTTCPSS_COUNT_VAL_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Instantiate and initialize the clock source structure
|
||||
*/
|
||||
static struct clocksource clocksource_xttcpss = {
|
||||
.name = "xttcpss_timer1",
|
||||
.rating = 200, /* Reasonable clock source */
|
||||
.read = __raw_readl_cycles,
|
||||
.mask = CLOCKSOURCE_MASK(16),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* xttcpss_set_next_event - Sets the time interval for next event
|
||||
*
|
||||
* @cycles: Timer interval ticks
|
||||
* @evt: Address of clock event instance
|
||||
*
|
||||
* returns: Always 0 - success
|
||||
**/
|
||||
static int xttcpss_set_next_event(unsigned long cycles,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
|
||||
|
||||
xttcpss_set_interval(timer, cycles);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* xttcpss_set_mode - Sets the mode of timer
|
||||
*
|
||||
* @mode: Mode to be set
|
||||
* @evt: Address of clock event instance
|
||||
**/
|
||||
static void xttcpss_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *evt)
|
||||
{
|
||||
struct xttcpss_timer *timer = &timers[XTTCPSS_CLOCKEVENT];
|
||||
u32 ctrl_reg;
|
||||
|
||||
switch (mode) {
|
||||
case CLOCK_EVT_MODE_PERIODIC:
|
||||
xttcpss_set_interval(timer, TIMER_RATE / HZ);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_ONESHOT:
|
||||
case CLOCK_EVT_MODE_UNUSED:
|
||||
case CLOCK_EVT_MODE_SHUTDOWN:
|
||||
ctrl_reg = __raw_readl(timer->base_addr +
|
||||
XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg |= XTTCPSS_CNT_CNTRL_DISABLE_MASK;
|
||||
__raw_writel(ctrl_reg,
|
||||
timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
break;
|
||||
case CLOCK_EVT_MODE_RESUME:
|
||||
ctrl_reg = __raw_readl(timer->base_addr +
|
||||
XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
ctrl_reg &= ~XTTCPSS_CNT_CNTRL_DISABLE_MASK;
|
||||
__raw_writel(ctrl_reg,
|
||||
timer->base_addr + XTTCPSS_CNT_CNTRL_OFFSET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiate and initialize the clock event structure
|
||||
*/
|
||||
static struct clock_event_device xttcpss_clockevent = {
|
||||
.name = "xttcpss_timer2",
|
||||
.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
|
||||
.set_next_event = xttcpss_set_next_event,
|
||||
.set_mode = xttcpss_set_mode,
|
||||
.rating = 200,
|
||||
};
|
||||
|
||||
/**
|
||||
* xttcpss_timer_init - Initialize the timer
|
||||
*
|
||||
* Initializes the timer hardware and register the clock source and clock event
|
||||
* timers with Linux kernal timer framework
|
||||
**/
|
||||
static void __init xttcpss_timer_init(void)
|
||||
{
|
||||
xttcpss_timer_hardware_init();
|
||||
clocksource_register_hz(&clocksource_xttcpss, TIMER_RATE);
|
||||
|
||||
/* Calculate the parameters to allow the clockevent to operate using
|
||||
integer math
|
||||
*/
|
||||
clockevents_calc_mult_shift(&xttcpss_clockevent, TIMER_RATE, 4);
|
||||
|
||||
xttcpss_clockevent.max_delta_ns =
|
||||
clockevent_delta2ns(0xfffe, &xttcpss_clockevent);
|
||||
xttcpss_clockevent.min_delta_ns =
|
||||
clockevent_delta2ns(1, &xttcpss_clockevent);
|
||||
|
||||
/* Indicate that clock event is on 1st CPU as SMP boot needs it */
|
||||
|
||||
xttcpss_clockevent.cpumask = cpumask_of(0);
|
||||
clockevents_register_device(&xttcpss_clockevent);
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiate and initialize the system timer structure
|
||||
*/
|
||||
struct sys_timer xttcpss_sys_timer = {
|
||||
.init = xttcpss_timer_init,
|
||||
};
|
|
@ -821,7 +821,8 @@ config CACHE_L2X0
|
|||
depends on REALVIEW_EB_ARM11MP || MACH_REALVIEW_PB11MP || MACH_REALVIEW_PB1176 || \
|
||||
REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
|
||||
ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
|
||||
ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
|
||||
ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE || \
|
||||
ARCH_PRIMA2 || ARCH_ZYNQ
|
||||
default y
|
||||
select OUTER_CACHE
|
||||
select OUTER_CACHE_SYNC
|
||||
|
|
|
@ -39,6 +39,7 @@ struct omap_clk {
|
|||
#define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */
|
||||
#define CK_443X (1 << 11)
|
||||
#define CK_TI816X (1 << 12)
|
||||
#define CK_446X (1 << 13)
|
||||
|
||||
|
||||
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
|
||||
|
|
|
@ -58,10 +58,12 @@ struct clkops {
|
|||
#define RATE_IN_36XX (1 << 4)
|
||||
#define RATE_IN_4430 (1 << 5)
|
||||
#define RATE_IN_TI816X (1 << 6)
|
||||
#define RATE_IN_4460 (1 << 7)
|
||||
|
||||
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
|
||||
#define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
|
||||
#define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX)
|
||||
#define RATE_IN_44XX (RATE_IN_4430 | RATE_IN_4460)
|
||||
|
||||
/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */
|
||||
#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX)
|
||||
|
|
|
@ -88,6 +88,7 @@ unsigned int omap_rev(void);
|
|||
* cpu_is_omap243x(): True for OMAP2430
|
||||
* cpu_is_omap343x(): True for OMAP3430
|
||||
* cpu_is_omap443x(): True for OMAP4430
|
||||
* cpu_is_omap446x(): True for OMAP4460
|
||||
*/
|
||||
#define GET_OMAP_CLASS (omap_rev() & 0xff)
|
||||
|
||||
|
@ -123,6 +124,7 @@ IS_OMAP_SUBCLASS(243x, 0x243)
|
|||
IS_OMAP_SUBCLASS(343x, 0x343)
|
||||
IS_OMAP_SUBCLASS(363x, 0x363)
|
||||
IS_OMAP_SUBCLASS(443x, 0x443)
|
||||
IS_OMAP_SUBCLASS(446x, 0x446)
|
||||
|
||||
IS_TI_SUBCLASS(816x, 0x816)
|
||||
|
||||
|
@ -137,6 +139,7 @@ IS_TI_SUBCLASS(816x, 0x816)
|
|||
#define cpu_is_ti816x() 0
|
||||
#define cpu_is_omap44xx() 0
|
||||
#define cpu_is_omap443x() 0
|
||||
#define cpu_is_omap446x() 0
|
||||
|
||||
#if defined(MULTI_OMAP1)
|
||||
# if defined(CONFIG_ARCH_OMAP730)
|
||||
|
@ -361,8 +364,10 @@ IS_OMAP_TYPE(3517, 0x3517)
|
|||
# if defined(CONFIG_ARCH_OMAP4)
|
||||
# undef cpu_is_omap44xx
|
||||
# undef cpu_is_omap443x
|
||||
# undef cpu_is_omap446x
|
||||
# define cpu_is_omap44xx() is_omap44xx()
|
||||
# define cpu_is_omap443x() is_omap443x()
|
||||
# define cpu_is_omap446x() is_omap446x()
|
||||
# endif
|
||||
|
||||
/* Macros to detect if we have OMAP1 or OMAP2 */
|
||||
|
@ -410,6 +415,9 @@ IS_OMAP_TYPE(3517, 0x3517)
|
|||
#define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8))
|
||||
#define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8))
|
||||
|
||||
#define OMAP446X_CLASS 0x44600044
|
||||
#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8))
|
||||
|
||||
/*
|
||||
* omap_chip bits
|
||||
*
|
||||
|
@ -439,13 +447,15 @@ IS_OMAP_TYPE(3517, 0x3517)
|
|||
#define CHIP_IS_OMAP4430ES2_1 (1 << 12)
|
||||
#define CHIP_IS_OMAP4430ES2_2 (1 << 13)
|
||||
#define CHIP_IS_TI816X (1 << 14)
|
||||
#define CHIP_IS_OMAP4460ES1_0 (1 << 15)
|
||||
|
||||
#define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
|
||||
|
||||
#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \
|
||||
CHIP_IS_OMAP4430ES2 | \
|
||||
CHIP_IS_OMAP4430ES2_1 | \
|
||||
CHIP_IS_OMAP4430ES2_2)
|
||||
CHIP_IS_OMAP4430ES2_2 | \
|
||||
CHIP_IS_OMAP4460ES1_0)
|
||||
|
||||
/*
|
||||
* "GE" here represents "greater than or equal to" in terms of ES
|
||||
|
@ -468,7 +478,7 @@ void omap2_check_revision(void);
|
|||
/*
|
||||
* Runtime detection of OMAP3 features
|
||||
*/
|
||||
extern u32 omap3_features;
|
||||
extern u32 omap_features;
|
||||
|
||||
#define OMAP3_HAS_L2CACHE BIT(0)
|
||||
#define OMAP3_HAS_IVA BIT(1)
|
||||
|
@ -478,11 +488,15 @@ extern u32 omap3_features;
|
|||
#define OMAP3_HAS_192MHZ_CLK BIT(5)
|
||||
#define OMAP3_HAS_IO_WAKEUP BIT(6)
|
||||
#define OMAP3_HAS_SDRC BIT(7)
|
||||
#define OMAP4_HAS_MPU_1GHZ BIT(8)
|
||||
#define OMAP4_HAS_MPU_1_2GHZ BIT(9)
|
||||
#define OMAP4_HAS_MPU_1_5GHZ BIT(10)
|
||||
|
||||
|
||||
#define OMAP3_HAS_FEATURE(feat,flag) \
|
||||
static inline unsigned int omap3_has_ ##feat(void) \
|
||||
{ \
|
||||
return (omap3_features & OMAP3_HAS_ ##flag); \
|
||||
return omap_features & OMAP3_HAS_ ##flag; \
|
||||
} \
|
||||
|
||||
OMAP3_HAS_FEATURE(l2cache, L2CACHE)
|
||||
|
@ -494,4 +508,19 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
|
|||
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
|
||||
OMAP3_HAS_FEATURE(sdrc, SDRC)
|
||||
|
||||
/*
|
||||
* Runtime detection of OMAP4 features
|
||||
*/
|
||||
extern u32 omap_features;
|
||||
|
||||
#define OMAP4_HAS_FEATURE(feat, flag) \
|
||||
static inline unsigned int omap4_has_ ##feat(void) \
|
||||
{ \
|
||||
return omap_features & OMAP4_HAS_ ##flag; \
|
||||
} \
|
||||
|
||||
OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
|
||||
OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
|
||||
OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue