From a1198f83407ae3421f3f58355a0f296d5ea6249c Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Jun 2013 11:37:02 +0200 Subject: clocksource: dw_apb_timer_of: enable the use the clocksource as sched clock Currently the dw_apb_timer always expects a separate special timer to be availbable for the sched_clock. Some devices using dw_apb_timers do not have this sptimer but can use the clocksource as sched_clock instead. Therefore enable the driver to distiguish between devices with and without sptimer based on the devicetree data and select the correct timer as sched_clock. Signed-off-by: Heiko Stuebner Acked-by: Linus Walleij Acked-by: Jamie Iles --- drivers/clocksource/dw_apb_timer_of.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index ab09ed3742ee..d6c0fda76a7e 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -57,6 +57,9 @@ static void add_clockevent(struct device_node *event_timer) dw_apb_clockevent_register(ced); } +static void __iomem *sched_io_base; +static u32 sched_rate; + static void add_clocksource(struct device_node *source_timer) { void __iomem *iobase; @@ -71,9 +74,15 @@ static void add_clocksource(struct device_node *source_timer) dw_apb_clocksource_start(cs); dw_apb_clocksource_register(cs); -} -static void __iomem *sched_io_base; + /* + * Fallback to use the clocksource as sched_clock if no separate + * timer is found. sched_io_base then points to the current_value + * register of the clocksource timer. + */ + sched_io_base = iobase + 0x04; + sched_rate = rate; +} static u32 read_sched_clock(void) { @@ -89,16 +98,15 @@ static const struct of_device_id sptimer_ids[] __initconst = { static void init_sched_clock(void) { struct device_node *sched_timer; - u32 rate; sched_timer = of_find_matching_node(NULL, sptimer_ids); - if (!sched_timer) - panic("No RTC for sched clock to use"); - - timer_get_base_and_rate(sched_timer, &sched_io_base, &rate); - of_node_put(sched_timer); + if (sched_timer) { + timer_get_base_and_rate(sched_timer, &sched_io_base, + &sched_rate); + of_node_put(sched_timer); + } - setup_sched_clock(read_sched_clock, 32, rate); + setup_sched_clock(read_sched_clock, 32, sched_rate); } static const struct of_device_id osctimer_ids[] __initconst = { -- cgit v1.2.3 From a8b447f2bbbba737ff4478f498d7f83c75a9461b Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Jun 2013 11:37:36 +0200 Subject: clocksource: dw_apb_timer_of: add clock-handling Add the possibility to get the clock-frequency from a timer clock instead of specifying it as dt property. Additionally also add the possibility to also define a controlling periphal clock for the timer block. The clock-frequency property is kept to act as fallback if no clocks are specified. Signed-off-by: Heiko Stuebner Acked-by: Jamie Iles --- Documentation/devicetree/bindings/rtc/dw-apb.txt | 19 +++++++++++++++++ drivers/clocksource/dw_apb_timer_of.c | 26 +++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/rtc/dw-apb.txt b/Documentation/devicetree/bindings/rtc/dw-apb.txt index 93e2b0f048e6..eb2327b2bdb3 100644 --- a/Documentation/devicetree/bindings/rtc/dw-apb.txt +++ b/Documentation/devicetree/bindings/rtc/dw-apb.txt @@ -5,9 +5,20 @@ Required properties: - reg: physical base address of the controller and length of memory mapped region. - interrupts: IRQ line for the timer. +- either clocks+clock-names or clock-frequency properties + +Optional properties: +- clocks : list of clock specifiers, corresponding to entries in + the clock-names property; +- clock-names : should contain "timer" and "pclk" entries, matching entries + in the clocks property. - clock-frequency: The frequency in HZ of the timer. - clock-freq: For backwards compatibility with picoxcell +If using the clock specifiers, the pclk clock is optional, as not all +systems may use one. + + Example: timer1: timer@ffc09000 { @@ -23,3 +34,11 @@ Example: clock-frequency = <200000000>; reg = <0xffd00000 0x1000>; }; + + timer3: timer@ffe00000 { + compatible = "snps,dw-apb-timer-osc"; + interrupts = <0 170 4>; + reg = <0xffe00000 0x1000>; + clocks = <&timer_clk>, <&timer_pclk>; + clock-names = "timer", "pclk"; + }; diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index d6c0fda76a7e..1964f8716966 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -27,14 +28,37 @@ static void timer_get_base_and_rate(struct device_node *np, void __iomem **base, u32 *rate) { + struct clk *timer_clk; + struct clk *pclk; + *base = of_iomap(np, 0); if (!*base) panic("Unable to map regs for %s", np->name); + /* + * Not all implementations use a periphal clock, so don't panic + * if it's not present + */ + pclk = of_clk_get_by_name(np, "pclk"); + if (!IS_ERR(pclk)) + if (clk_prepare_enable(pclk)) + pr_warn("pclk for %s is present, but could not be activated\n", + np->name); + + timer_clk = of_clk_get_by_name(np, "timer"); + if (IS_ERR(timer_clk)) + goto try_clock_freq; + + if (!clk_prepare_enable(timer_clk)) { + *rate = clk_get_rate(timer_clk); + return; + } + +try_clock_freq: if (of_property_read_u32(np, "clock-freq", rate) && of_property_read_u32(np, "clock-frequency", rate)) - panic("No clock-frequency property for %s", np->name); + panic("No clock nor clock-frequency property for %s", np->name); } static void add_clockevent(struct device_node *event_timer) -- cgit v1.2.3 From 1b4eca0f634be2a99f2baa6c29dfd183590ead3f Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Jun 2013 11:38:11 +0200 Subject: clocksource: dw_apb_timer_of: select DW_APB_TIMER dw_apb_timer_of is the driver part facing devicetree platforms and calls into dw_apb_timer with the data gathered from the dt. Currently the two platforms using the dw_apb_timer_of select both the options for the core timer and the dt addon. As dw_apb_timer_of always depends on dw_apb_timer let it select DW_APB_TIMER itself without the need for every platform to do it. Signed-off-by: Heiko Stuebner Acked-by: Jamie Iles Acked-by: Dinh Nguyen --- arch/arm/mach-picoxcell/Kconfig | 1 - arch/arm/mach-socfpga/Kconfig | 1 - drivers/clocksource/Kconfig | 1 + 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-picoxcell/Kconfig b/arch/arm/mach-picoxcell/Kconfig index 13bae78b215a..b1022f4315f7 100644 --- a/arch/arm/mach-picoxcell/Kconfig +++ b/arch/arm/mach-picoxcell/Kconfig @@ -4,7 +4,6 @@ config ARCH_PICOXCELL select ARM_PATCH_PHYS_VIRT select ARM_VIC select CPU_V6K - select DW_APB_TIMER select DW_APB_TIMER_OF select GENERIC_CLOCKEVENTS select HAVE_TCM diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig index 566e804d4036..a279fb315069 100644 --- a/arch/arm/mach-socfpga/Kconfig +++ b/arch/arm/mach-socfpga/Kconfig @@ -7,7 +7,6 @@ config ARCH_SOCFPGA select CLKDEV_LOOKUP select COMMON_CLK select CPU_V7 - select DW_APB_TIMER select DW_APB_TIMER_OF select GENERIC_CLOCKEVENTS select GPIO_PL061 if GPIOLIB diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index f151c6cf27c3..48a0f2e1dd78 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -21,6 +21,7 @@ config DW_APB_TIMER config DW_APB_TIMER_OF bool + select DW_APB_TIMER config ARMADA_370_XP_TIMER bool -- cgit v1.2.3 From 10021488997317d1121505a7ac659124c058efed Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 4 Jun 2013 11:38:42 +0200 Subject: clocksource: dw_apb_timer_of: use clocksource_of_init dw_apb_timer_init used to search the devicetree for matching timer devices, making calls to it from board files necessary. Change the dw_apb_timer_init to work with CLOCKSOURCE_OF_DECLARE. With this change the function gets called once for each timer node and tracks these number of calls to attach clockevent and clocksource devices to the nodes. Also remove the calls to dw_apb_timer_init from all previous users, as clocksource_of_init is the default for init_time now. Tested on the upcoming rk3066 code. Signed-off-by: Heiko Stuebner Acked-by: Rob Herring Acked-by: Arnd Bergmann Acked-by: Jamie Iles Acked-by: Dinh Nguyen --- arch/arm/mach-picoxcell/common.c | 2 -- arch/arm/mach-socfpga/socfpga.c | 2 -- drivers/clocksource/Kconfig | 1 + drivers/clocksource/dw_apb_timer_of.c | 41 +++++++++++++++++------------------ include/linux/dw_apb_timer.h | 1 - 5 files changed, 21 insertions(+), 26 deletions(-) diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c index 70b441ad1d18..7cde0424d33c 100644 --- a/arch/arm/mach-picoxcell/common.c +++ b/arch/arm/mach-picoxcell/common.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -88,7 +87,6 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell") .map_io = picoxcell_map_io, .nr_irqs = NR_IRQS_LEGACY, .init_irq = irqchip_init, - .init_time = dw_apb_timer_init, .init_machine = picoxcell_init_machine, .dt_compat = picoxcell_dt_match, .restart = picoxcell_wdt_restart, diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c index 46a051359f02..8ea11b472b91 100644 --- a/arch/arm/mach-socfpga/socfpga.c +++ b/arch/arm/mach-socfpga/socfpga.c @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include #include #include #include @@ -120,7 +119,6 @@ DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA") .smp = smp_ops(socfpga_smp_ops), .map_io = socfpga_map_io, .init_irq = socfpga_init_irq, - .init_time = dw_apb_timer_init, .init_machine = socfpga_cyclone5_init, .restart = socfpga_cyclone5_restart, .dt_compat = altera_dt_match, diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 48a0f2e1dd78..5871933c4e51 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -22,6 +22,7 @@ config DW_APB_TIMER config DW_APB_TIMER_OF bool select DW_APB_TIMER + select CLKSRC_OF config ARMADA_370_XP_TIMER bool diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c index 1964f8716966..cef554432a33 100644 --- a/drivers/clocksource/dw_apb_timer_of.c +++ b/drivers/clocksource/dw_apb_timer_of.c @@ -133,27 +133,26 @@ static void init_sched_clock(void) setup_sched_clock(read_sched_clock, 32, sched_rate); } -static const struct of_device_id osctimer_ids[] __initconst = { - { .compatible = "picochip,pc3x2-timer" }, - { .compatible = "snps,dw-apb-timer-osc" }, - {}, -}; - -void __init dw_apb_timer_init(void) +static int num_called; +static void __init dw_apb_timer_init(struct device_node *timer) { - struct device_node *event_timer, *source_timer; - - event_timer = of_find_matching_node(NULL, osctimer_ids); - if (!event_timer) - panic("No timer for clockevent"); - add_clockevent(event_timer); - - source_timer = of_find_matching_node(event_timer, osctimer_ids); - if (!source_timer) - panic("No timer for clocksource"); - add_clocksource(source_timer); - - of_node_put(source_timer); + switch (num_called) { + case 0: + pr_debug("%s: found clockevent timer\n", __func__); + add_clockevent(timer); + of_node_put(timer); + break; + case 1: + pr_debug("%s: found clocksource timer\n", __func__); + add_clocksource(timer); + of_node_put(timer); + init_sched_clock(); + break; + default: + break; + } - init_sched_clock(); + num_called++; } +CLOCKSOURCE_OF_DECLARE(pc3x2_timer, "picochip,pc3x2-timer", dw_apb_timer_init); +CLOCKSOURCE_OF_DECLARE(apb_timer, "snps,dw-apb-timer-osc", dw_apb_timer_init); diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h index dd755ce2a5eb..07261d52a6df 100644 --- a/include/linux/dw_apb_timer.h +++ b/include/linux/dw_apb_timer.h @@ -53,5 +53,4 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs); cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs); void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs); -extern void dw_apb_timer_init(void); #endif /* __DW_APB_TIMER_H__ */ -- cgit v1.2.3 From 8b57b004839b9bf5fc0614e9ef342c09adfa6fb7 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Thu, 13 Jun 2013 16:18:11 +0200 Subject: arm: Add basic clocks for Rockchip rk3066a SoCs This adds a basic clock setup for rk3066a SoCs. Only the gates are set up currently, as the mux and dividers should use the upcoming generic devicetree bindings. Clocks whose rates need to be known are supplied by fixed-rate "dummy"-clocks that provide the correct rate. This is uncritical insofar that the only bootloader currently in existence for Rockchip devices is the propietary Rockchip one that always setups the clocks in the necessary way. Signed-off-by: Heiko Stuebner Reviewed-by: Mike Turquette --- arch/arm/boot/dts/rk3066a-clocks.dtsi | 299 ++++++++++++++++++++++++++++++++++ 1 file changed, 299 insertions(+) create mode 100644 arch/arm/boot/dts/rk3066a-clocks.dtsi diff --git a/arch/arm/boot/dts/rk3066a-clocks.dtsi b/arch/arm/boot/dts/rk3066a-clocks.dtsi new file mode 100644 index 000000000000..6e307fc4c451 --- /dev/null +++ b/arch/arm/boot/dts/rk3066a-clocks.dtsi @@ -0,0 +1,299 @@ +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + */ + +/ { + clocks { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* + * This is a dummy clock, to be used as placeholder on + * other mux clocks when a specific parent clock is not + * yet implemented. It should be dropped when the driver + * is complete. + */ + dummy: dummy { + compatible = "fixed-clock"; + clock-frequency = <0>; + #clock-cells = <0>; + }; + + xin24m: xin24m { + compatible = "fixed-clock"; + clock-frequency = <24000000>; + #clock-cells = <0>; + }; + + dummy48m: dummy48m { + compatible = "fixed-clock"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + + dummy150m: dummy150m { + compatible = "fixed-clock"; + clock-frequency = <150000000>; + #clock-cells = <0>; + }; + + clk_gates0: gate-clk@200000d0 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000d0 0x4>; + clocks = <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>; + + clock-output-names = + "gate_core_periph", "gate_cpu_gpll", + "gate_ddrphy", "gate_aclk_cpu", + "gate_hclk_cpu", "gate_pclk_cpu", + "gate_atclk_cpu", "gate_i2s0", + "gate_i2s0_frac", "gate_i2s1", + "gate_i2s1_frac", "gate_i2s2", + "gate_i2s2_frac", "gate_spdif", + "gate_spdif_frac", "gate_testclk"; + + #clock-cells = <1>; + }; + + clk_gates1: gate-clk@200000d4 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000d4 0x4>; + clocks = <&xin24m>, <&xin24m>, + <&xin24m>, <&dummy>, + <&dummy>, <&xin24m>, + <&xin24m>, <&dummy>, + <&xin24m>, <&dummy>, + <&xin24m>, <&dummy>, + <&xin24m>, <&dummy>, + <&xin24m>, <&dummy>; + + clock-output-names = + "gate_timer0", "gate_timer1", + "gate_timer2", "gate_jtag", + "gate_aclk_lcdc1_src", "gate_otgphy0", + "gate_otgphy1", "gate_ddr_gpll", + "gate_uart0", "gate_frac_uart0", + "gate_uart1", "gate_frac_uart1", + "gate_uart2", "gate_frac_uart2", + "gate_uart3", "gate_frac_uart3"; + + #clock-cells = <1>; + }; + + clk_gates2: gate-clk@200000d8 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000d8 0x4>; + clocks = <&clk_gates2 1>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&clk_gates2 3>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy48m>, + <&dummy>, <&dummy48m>, + <&dummy>, <&dummy>; + + clock-output-names = + "gate_periph_src", "gate_aclk_periph", + "gate_hclk_periph", "gate_pclk_periph", + "gate_smc", "gate_mac", + "gate_hsadc", "gate_hsadc_frac", + "gate_saradc", "gate_spi0", + "gate_spi1", "gate_mmc0", + "gate_mac_lbtest", "gate_mmc1", + "gate_emmc", "gate_tsadc"; + + #clock-cells = <1>; + }; + + clk_gates3: gate-clk@200000dc { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000dc 0x4>; + clocks = <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>, <&dummy>; + + clock-output-names = + "gate_aclk_lcdc0_src", "gate_dclk_lcdc0", + "gate_dclk_lcdc1", "gate_pclkin_cif0", + "gate_pclkin_cif1", "reserved", + "reserved", "gate_cif0_out", + "gate_cif1_out", "gate_aclk_vepu", + "gate_hclk_vepu", "gate_aclk_vdpu", + "gate_hclk_vdpu", "gate_gpu_src", + "reserved", "gate_xin27m"; + + #clock-cells = <1>; + }; + + clk_gates4: gate-clk@200000e0 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000e0 0x4>; + clocks = <&clk_gates2 2>, <&clk_gates2 3>, + <&clk_gates2 1>, <&clk_gates2 1>, + <&clk_gates2 1>, <&clk_gates2 2>, + <&clk_gates2 2>, <&clk_gates2 2>, + <&clk_gates0 4>, <&clk_gates0 4>, + <&clk_gates0 3>, <&clk_gates0 3>, + <&clk_gates0 3>, <&clk_gates2 3>, + <&clk_gates0 4>; + + clock-output-names = + "gate_hclk_peri_axi_matrix", "gate_pclk_peri_axi_matrix", + "gate_aclk_cpu_peri", "gate_aclk_peri_axi_matrix", + "gate_aclk_pei_niu", "gate_hclk_usb_peri", + "gate_hclk_peri_ahb_arbi", "gate_hclk_emem_peri", + "gate_hclk_cpubus", "gate_hclk_ahb2apb", + "gate_aclk_strc_sys", "gate_aclk_l2mem_con", + "gate_aclk_intmem", "gate_pclk_tsadc", + "gate_hclk_hdmi"; + + #clock-cells = <1>; + }; + + clk_gates5: gate-clk@200000e4 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000e4 0x4>; + clocks = <&clk_gates0 3>, <&clk_gates2 1>, + <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates0 4>, <&clk_gates0 5>, + <&clk_gates2 1>, <&clk_gates2 2>, + <&clk_gates2 2>, <&clk_gates2 2>, + <&clk_gates2 2>, <&clk_gates4 5>, + <&clk_gates4 5>, <&dummy>; + + clock-output-names = + "gate_aclk_dmac1", "gate_aclk_dmac2", + "gate_pclk_efuse", "gate_pclk_tzpc", + "gate_pclk_grf", "gate_pclk_pmu", + "gate_hclk_rom", "gate_pclk_ddrupctl", + "gate_aclk_smc", "gate_hclk_nandc", + "gate_hclk_mmc0", "gate_hclk_mmc1", + "gate_hclk_emmc", "gate_hclk_otg0", + "gate_hclk_otg1", "gate_aclk_gpu"; + + #clock-cells = <1>; + }; + + clk_gates6: gate-clk@200000e8 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000e8 0x4>; + clocks = <&clk_gates3 0>, <&clk_gates0 4>, + <&clk_gates0 4>, <&clk_gates1 4>, + <&clk_gates0 4>, <&clk_gates3 0>, + <&clk_gates0 4>, <&clk_gates1 4>, + <&clk_gates3 0>, <&clk_gates0 4>, + <&clk_gates0 4>, <&clk_gates1 4>, + <&clk_gates0 4>, <&clk_gates3 0>, + <&dummy>, <&dummy>; + + clock-output-names = + "gate_aclk_lcdc0", "gate_hclk_lcdc0", + "gate_hclk_lcdc1", "gate_aclk_lcdc1", + "gate_hclk_cif0", "gate_aclk_cif0", + "gate_hclk_cif1", "gate_aclk_cif1", + "gate_aclk_ipp", "gate_hclk_ipp", + "gate_hclk_rga", "gate_aclk_rga", + "gate_hclk_vio_bus", "gate_aclk_vio0", + "gate_aclk_vcodec", "gate_shclk_vio_h2h"; + + #clock-cells = <1>; + }; + + clk_gates7: gate-clk@200000ec { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000ec 0x4>; + clocks = <&clk_gates2 2>, <&clk_gates0 4>, + <&clk_gates0 4>, <&clk_gates0 4>, + <&clk_gates0 4>, <&clk_gates2 2>, + <&clk_gates2 2>, <&clk_gates0 5>, + <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates0 5>, <&clk_gates2 3>, + <&clk_gates2 3>, <&clk_gates2 3>, + <&clk_gates2 3>, <&clk_gates2 3>; + + clock-output-names = + "gate_hclk_emac", "gate_hclk_spdif", + "gate_hclk_i2s0_2ch", "gate_hclk_i2s1_2ch", + "gate_hclk_i2s_8ch", "gate_hclk_hsadc", + "gate_hclk_pidf", "gate_pclk_timer0", + "gate_pclk_timer1", "gate_pclk_timer2", + "gate_pclk_pwm01", "gate_pclk_pwm23", + "gate_pclk_spi0", "gate_pclk_spi1", + "gate_pclk_saradc", "gate_pclk_wdt"; + + #clock-cells = <1>; + }; + + clk_gates8: gate-clk@200000f0 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000f0 0x4>; + clocks = <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates2 3>, <&clk_gates2 3>, + <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates2 3>, <&clk_gates2 3>, + <&clk_gates2 3>, <&clk_gates0 5>, + <&clk_gates0 5>, <&clk_gates0 5>, + <&clk_gates2 3>, <&clk_gates2 3>, + <&dummy>, <&clk_gates0 5>; + + clock-output-names = + "gate_pclk_uart0", "gate_pclk_uart1", + "gate_pclk_uart2", "gate_pclk_uart3", + "gate_pclk_i2c0", "gate_pclk_i2c1", + "gate_pclk_i2c2", "gate_pclk_i2c3", + "gate_pclk_i2c4", "gate_pclk_gpio0", + "gate_pclk_gpio1", "gate_pclk_gpio2", + "gate_pclk_gpio3", "gate_pclk_gpio4", + "reserved", "gate_pclk_gpio6"; + + #clock-cells = <1>; + }; + + clk_gates9: gate-clk@200000f4 { + compatible = "rockchip,rk2928-gate-clk"; + reg = <0x200000f4 0x4>; + clocks = <&dummy>, <&clk_gates0 5>, + <&dummy>, <&dummy>, + <&dummy>, <&clk_gates1 4>, + <&clk_gates0 5>, <&dummy>, + <&dummy>, <&dummy>, + <&dummy>; + + clock-output-names = + "gate_clk_core_dbg", "gate_pclk_dbg", + "gate_clk_trace", "gate_atclk", + "gate_clk_l2c", "gate_aclk_vio1", + "gate_pclk_publ", "gate_aclk_intmem0", + "gate_aclk_intmem1", "gate_aclk_intmem2", + "gate_aclk_intmem3"; + + #clock-cells = <1>; + }; + }; + +}; -- cgit v1.2.3 From 38bd6892abbf7d60b1e9ff7f1a2b8019b552eed3 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 28 May 2013 22:13:52 +0200 Subject: arm: add debug uarts for rockchip rk29xx and rk3xxx series Uarts on all recent Rockchip SoCs are Synopsis DesignWare 8250 types. Only their addresses vary very much. This patch adds the necessary definitions to use any of the uart ports for early debug purposes. Signed-off-by: Heiko Stuebner --- arch/arm/Kconfig.debug | 34 +++++++++++++++++++++++++++++++ arch/arm/include/debug/rockchip.S | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 arch/arm/include/debug/rockchip.S diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1d41908d5cda..5cd90bfdddfe 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -353,6 +353,13 @@ choice their output to the standard serial port on the RealView PB1176 platform. + config DEBUG_ROCKCHIP_UART + bool "Kernel low-level debugging messages via Rockchip UART" + depends on ARCH_ROCKCHIP + help + Say Y here if you want kernel low-level debugging support + on Rockchip based platforms. + config DEBUG_S3C_UART0 depends on PLAT_SAMSUNG select DEBUG_EXYNOS_UART if ARCH_EXYNOS @@ -587,6 +594,32 @@ choice bool "Zoom2/3 UART" endchoice +choice + prompt "Low-level debug console UART" + depends on DEBUG_ROCKCHIP_UART + + config DEBUG_RK29_UART0 + bool "RK29 UART0" + + config DEBUG_RK29_UART1 + bool "RK29 UART1" + + config DEBUG_RK29_UART2 + bool "RK29 UART2" + + config DEBUG_RK3X_UART0 + bool "RK3X UART0" + + config DEBUG_RK3X_UART1 + bool "RK3X UART1" + + config DEBUG_RK3X_UART2 + bool "RK3X UART2" + + config DEBUG_RK3X_UART3 + bool "RK3X UART3" +endchoice + choice prompt "Low-level debug console UART" depends on DEBUG_LL && DEBUG_TEGRA_UART @@ -639,6 +672,7 @@ config DEBUG_LL_INCLUDE default "debug/picoxcell.S" if DEBUG_PICOXCELL_UART default "debug/pxa.S" if DEBUG_PXA_UART1 || DEBUG_MMP_UART2 || \ DEBUG_MMP_UART3 + default "debug/rockchip.S" if DEBUG_ROCKCHIP_UART default "debug/sirf.S" if DEBUG_SIRFPRIMA2_UART1 || DEBUG_SIRFMARCO_UART1 default "debug/socfpga.S" if DEBUG_SOCFPGA_UART default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1 diff --git a/arch/arm/include/debug/rockchip.S b/arch/arm/include/debug/rockchip.S new file mode 100644 index 000000000000..cfd883e69588 --- /dev/null +++ b/arch/arm/include/debug/rockchip.S @@ -0,0 +1,42 @@ +/* + * Early serial output macro for Rockchip SoCs + * + * Copyright (C) 2012 Maxime Ripard + * + * Maxime Ripard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#if defined(CONFIG_DEBUG_RK29_UART0) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20060000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed60000 +#elif defined(CONFIG_DEBUG_RK29_UART1) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20064000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed64000 +#elif defined(CONFIG_DEBUG_RK29_UART2) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20068000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed68000 +#elif defined(CONFIG_DEBUG_RK3X_UART0) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x10124000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfeb24000 +#elif defined(CONFIG_DEBUG_RK3X_UART1) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x10126000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfeb26000 +#elif defined(CONFIG_DEBUG_RK3X_UART2) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20064000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed64000 +#elif defined(CONFIG_DEBUG_RK3X_UART3) +#define ROCKCHIP_UART_DEBUG_PHYS_BASE 0x20068000 +#define ROCKCHIP_UART_DEBUG_VIRT_BASE 0xfed68000 +#endif + + .macro addruart, rp, rv, tmp + ldr \rp, =ROCKCHIP_UART_DEBUG_PHYS_BASE + ldr \rv, =ROCKCHIP_UART_DEBUG_VIRT_BASE + .endm + +#define UART_SHIFT 2 +#include -- cgit v1.2.3 From d63dc0514d56e108cc96e334ca26b538263e52a2 Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Sun, 2 Jun 2013 23:09:41 +0200 Subject: arm: add basic support for Rockchip RK3066a boards This adds a generic devicetree board file and a dtsi for boards based on the RK3066a SoCs from Rockchip. Apart from the generic parts (gic, clocks, pinctrl) the only components currently supported are the timers, uarts and mmc ports (all DesignWare- based). Signed-off-by: Heiko Stuebner Acked-by: Olof Johansson --- arch/arm/Kconfig | 2 + arch/arm/Makefile | 1 + arch/arm/boot/dts/rk3066a.dtsi | 390 ++++++++++++++++++++++++++++++++++++++ arch/arm/mach-rockchip/Kconfig | 16 ++ arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/rockchip.c | 52 +++++ 6 files changed, 462 insertions(+) create mode 100644 arch/arm/boot/dts/rk3066a.dtsi create mode 100644 arch/arm/mach-rockchip/Kconfig create mode 100644 arch/arm/mach-rockchip/Makefile create mode 100644 arch/arm/mach-rockchip/rockchip.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 49d993cee512..94d3491ae40a 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -981,6 +981,8 @@ source "arch/arm/mach-mmp/Kconfig" source "arch/arm/mach-realview/Kconfig" +source "arch/arm/mach-rockchip/Kconfig" + source "arch/arm/mach-sa1100/Kconfig" source "arch/arm/plat-samsung/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 1ba358ba16b8..126313fcc594 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -171,6 +171,7 @@ machine-$(CONFIG_ARCH_PICOXCELL) += picoxcell machine-$(CONFIG_ARCH_PRIMA2) += prima2 machine-$(CONFIG_ARCH_PXA) += pxa machine-$(CONFIG_ARCH_REALVIEW) += realview +machine-$(CONFIG_ARCH_ROCKCHIP) += rockchip machine-$(CONFIG_ARCH_RPC) += rpc machine-$(CONFIG_ARCH_S3C24XX) += s3c24xx machine-$(CONFIG_ARCH_S3C64XX) += s3c64xx diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi new file mode 100644 index 000000000000..56bfac93d3f6 --- /dev/null +++ b/arch/arm/boot/dts/rk3066a.dtsi @@ -0,0 +1,390 @@ +/* + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include "skeleton.dtsi" +#include "rk3066a-clocks.dtsi" + +/ { + compatible = "rockchip,rk3066a"; + interrupt-parent = <&gic>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + next-level-cache = <&L2>; + reg = <0x0>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a9"; + next-level-cache = <&L2>; + reg = <0x1>; + }; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + gic: interrupt-controller@1013d000 { + compatible = "arm,cortex-a9-gic"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x1013d000 0x1000>, + <0x1013c100 0x0100>; + }; + + L2: l2-cache-controller@10138000 { + compatible = "arm,pl310-cache"; + reg = <0x10138000 0x1000>; + cache-unified; + cache-level = <2>; + }; + + local-timer@1013c600 { + compatible = "arm,cortex-a9-twd-timer"; + reg = <0x1013c600 0x20>; + interrupts = ; + clocks = <&dummy150m>; + }; + + timer@20038000 { + compatible = "snps,dw-apb-timer-osc"; + reg = <0x20038000 0x100>; + interrupts = ; + clocks = <&clk_gates1 0>, <&clk_gates7 7>; + clock-names = "timer", "pclk"; + }; + + timer@2003a000 { + compatible = "snps,dw-apb-timer-osc"; + reg = <0x2003a000 0x100>; + interrupts = ; + clocks = <&clk_gates1 1>, <&clk_gates7 8>; + clock-names = "timer", "pclk"; + }; + + timer@2000e000 { + compatible = "snps,dw-apb-timer-osc"; + reg = <0x2000e000 0x100>; + interrupts = ; + clocks = <&clk_gates1 2>, <&clk_gates7 9>; + clock-names = "timer", "pclk"; + }; + + pinctrl@20008000 { + compatible = "rockchip,rk3066a-pinctrl"; + reg = <0x20008000 0x150>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + gpio0: gpio0@20034000 { + compatible = "rockchip,gpio-bank"; + reg = <0x20034000 0x100>; + interrupts = ; + clocks = <&clk_gates8 9>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio1@2003c000 { + compatible = "rockchip,gpio-bank"; + reg = <0x2003c000 0x100>; + interrupts = ; + clocks = <&clk_gates8 10>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio2@2003e000 { + compatible = "rockchip,gpio-bank"; + reg = <0x2003e000 0x100>; + interrupts = ; + clocks = <&clk_gates8 11>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio3@20080000 { + compatible = "rockchip,gpio-bank"; + reg = <0x20080000 0x100>; + interrupts = ; + clocks = <&clk_gates8 12>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio4: gpio4@20084000 { + compatible = "rockchip,gpio-bank"; + reg = <0x20084000 0x100>; + interrupts = ; + clocks = <&clk_gates8 13>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio6: gpio6@2000a000 { + compatible = "rockchip,gpio-bank"; + reg = <0x2000a000 0x100>; + interrupts = ; + clocks = <&clk_gates8 15>; + + gpio-controller; + #gpio-cells = <2>; + + interrupt-controller; + #interrupt-cells = <2>; + }; + + pcfg_pull_default: pcfg_pull_default { + bias-pull-pin-default; + }; + + pcfg_pull_none: pcfg_pull_none { + bias-disable; + }; + + uart0 { + uart0_xfer: uart0-xfer { + rockchip,pins = , + ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart0_cts: uart0-cts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart0_rts: uart0-rts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + }; + + uart1 { + uart1_xfer: uart1-xfer { + rockchip,pins = , + ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart1_cts: uart1-cts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart1_rts: uart1-rts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + }; + + uart2 { + uart2_xfer: uart2-xfer { + rockchip,pins = , + ; + rockchip,config = <&pcfg_pull_default>; + }; + /* no rts / cts for uart2 */ + }; + + uart3 { + uart3_xfer: uart3-xfer { + rockchip,pins = , + ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart3_cts: uart3-cts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + uart3_rts: uart3-rts { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + }; + + sd0 { + sd0_clk: sd0-clk { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd0_cmd: sd0-cmd { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd0_cd: sd0-cd { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd0_wp: sd0-wp { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd0_bus1: sd0-bus-width1 { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd0_bus4: sd0-bus-width4 { + rockchip,pins = , + , + , + ; + rockchip,config = <&pcfg_pull_default>; + }; + }; + + sd1 { + sd1_clk: sd1-clk { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd1_cmd: sd1-cmd { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd1_cd: sd1-cd { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd1_wp: sd1-wp { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd1_bus1: sd1-bus-width1 { + rockchip,pins = ; + rockchip,config = <&pcfg_pull_default>; + }; + + sd1_bus4: sd1-bus-width4 { + rockchip,pins = , + , + , + ; + rockchip,config = <&pcfg_pull_default>; + }; + }; + }; + + uart0: serial@10124000 { + compatible = "snps,dw-apb-uart"; + reg = <0x10124000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <1>; + clocks = <&clk_gates1 8>; + status = "disabled"; + }; + + uart1: serial@10126000 { + compatible = "snps,dw-apb-uart"; + reg = <0x10126000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <1>; + clocks = <&clk_gates1 10>; + status = "disabled"; + }; + + uart2: serial@20064000 { + compatible = "snps,dw-apb-uart"; + reg = <0x20064000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <1>; + clocks = <&clk_gates1 12>; + status = "disabled"; + }; + + uart3: serial@20068000 { + compatible = "snps,dw-apb-uart"; + reg = <0x20068000 0x400>; + interrupts = ; + reg-shift = <2>; + reg-io-width = <1>; + clocks = <&clk_gates1 14>; + status = "disabled"; + }; + + dwmmc@10214000 { + compatible = "rockchip,rk2928-dw-mshc"; + reg = <0x10214000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + + clocks = <&clk_gates5 10>, <&clk_gates2 11>; + clock-names = "biu", "ciu"; + + status = "disabled"; + }; + + dwmmc@10218000 { + compatible = "rockchip,rk2928-dw-mshc"; + reg = <0x10218000 0x1000>; + interrupts = ; + #address-cells = <1>; + #size-cells = <0>; + + clocks = <&clk_gates5 11>, <&clk_gates2 13>; + clock-names = "biu", "ciu"; + + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig new file mode 100644 index 000000000000..25ee12b21f01 --- /dev/null +++ b/arch/arm/mach-rockchip/Kconfig @@ -0,0 +1,16 @@ +config ARCH_ROCKCHIP + bool "Rockchip RK2928 and RK3xxx SOCs" if ARCH_MULTI_V7 + select PINCTRL + select PINCTRL_ROCKCHIP + select ARCH_REQUIRE_GPIOLIB + select ARM_GIC + select CACHE_L2X0 + select HAVE_ARM_TWD if LOCAL_TIMERS + select HAVE_SMP + select LOCAL_TIMERS if SMP + select COMMON_CLK + select GENERIC_CLOCKEVENTS + select DW_APB_TIMER_OF + help + Support for Rockchip's Cortex-A9 Single-to-Quad-Core-SoCs + containing the RK2928, RK30xx and RK31xx series. diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile new file mode 100644 index 000000000000..1547d4fc920a --- /dev/null +++ b/arch/arm/mach-rockchip/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip.o diff --git a/arch/arm/mach-rockchip/rockchip.c b/arch/arm/mach-rockchip/rockchip.c new file mode 100644 index 000000000000..724d2d81f976 --- /dev/null +++ b/arch/arm/mach-rockchip/rockchip.c @@ -0,0 +1,52 @@ +/* + * Device Tree support for Rockchip SoCs + * + * Copyright (c) 2013 MundoReader S.L. + * Author: Heiko Stuebner + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +static void __init rockchip_timer_init(void) +{ + of_clk_init(NULL); + clocksource_of_init(); +} + +static void __init rockchip_dt_init(void) +{ + l2x0_of_init(0, ~0UL); + of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); +} + +static const char * const rockchip_board_dt_compat[] = { + "rockchip,rk2928", + "rockchip,rk3066a", + "rockchip,rk3066b", + "rockchip,rk3188", + NULL, +}; + +DT_MACHINE_START(ROCKCHIP_DT, "Rockchip Cortex-A9 (Device Tree)") + .init_machine = rockchip_dt_init, + .init_time = rockchip_timer_init, + .dt_compat = rockchip_board_dt_compat, +MACHINE_END -- cgit v1.2.3