diff --git a/Documentation/devicetree/bindings/reset/sirf,rstc.txt b/Documentation/devicetree/bindings/reset/sirf,rstc.txt new file mode 100644 index 000000000000..0505de742d30 --- /dev/null +++ b/Documentation/devicetree/bindings/reset/sirf,rstc.txt @@ -0,0 +1,42 @@ +CSR SiRFSoC Reset Controller +====================================== + +Please also refer to reset.txt in this directory for common reset +controller binding usage. + +Required properties: +- compatible: Should be "sirf,prima2-rstc" or "sirf,marco-rstc" +- reg: should be register base and length as documented in the + datasheet +- #reset-cells: 1, see below + +example: + +rstc: reset-controller@88010000 { + compatible = "sirf,prima2-rstc"; + reg = <0x88010000 0x1000>; + #reset-cells = <1>; +}; + +Specifying reset lines connected to IP modules +============================================== + +The reset controller(rstc) manages various reset sources. This module provides +reset signals for most blocks in system. Those device nodes should specify the +reset line on the rstc in their resets property, containing a phandle to the +rstc device node and a RESET_INDEX specifying which module to reset, as described +in reset.txt. + +For SiRFSoC, RESET_INDEX is just reset_bit defined in SW_RST0 and SW_RST1 registers. +For modules whose rest_bit is in SW_RST0, its RESET_INDEX is 0~31. For modules whose +rest_bit is in SW_RST1, its RESET_INDEX is 32~63. + +example: + +vpp@90020000 { + compatible = "sirf,prima2-vpp"; + reg = <0x90020000 0x10000>; + interrupts = <31>; + clocks = <&clks 35>; + resets = <&rstc 6>; +}; diff --git a/arch/arm/boot/dts/atlas6.dtsi b/arch/arm/boot/dts/atlas6.dtsi index f8674bcc4489..f7f9cafb42f5 100644 --- a/arch/arm/boot/dts/atlas6.dtsi +++ b/arch/arm/boot/dts/atlas6.dtsi @@ -65,9 +65,10 @@ clks: clock-controller@88000000 { #clock-cells = <1>; }; - reset-controller@88010000 { + rstc: reset-controller@88010000 { compatible = "sirf,prima2-rstc"; reg = <0x88010000 0x1000>; + #reset-cells = <1>; }; rsc-controller@88020000 { diff --git a/arch/arm/boot/dts/marco.dtsi b/arch/arm/boot/dts/marco.dtsi index 1579c3491ccd..0c9647d28765 100644 --- a/arch/arm/boot/dts/marco.dtsi +++ b/arch/arm/boot/dts/marco.dtsi @@ -58,9 +58,10 @@ rstc-iobg { #size-cells = <1>; ranges = <0xc2000000 0xc2000000 0x1000000>; - reset-controller@c2000000 { + rstc: reset-controller@c2000000 { compatible = "sirf,marco-rstc"; reg = <0xc2000000 0x10000>; + #reset-cells = <1>; }; }; diff --git a/arch/arm/boot/dts/prima2.dtsi b/arch/arm/boot/dts/prima2.dtsi index 0e219932d7cc..0ca0d7fd7a6e 100644 --- a/arch/arm/boot/dts/prima2.dtsi +++ b/arch/arm/boot/dts/prima2.dtsi @@ -76,9 +76,10 @@ clks: clock-controller@88000000 { #clock-cells = <1>; }; - reset-controller@88010000 { + rstc: reset-controller@88010000 { compatible = "sirf,prima2-rstc"; reg = <0x88010000 0x1000>; + #reset-cells = <1>; }; rsc-controller@88020000 { diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig index 2c726b4f9356..3e8189186a5b 100644 --- a/arch/arm/mach-prima2/Kconfig +++ b/arch/arm/mach-prima2/Kconfig @@ -1,5 +1,6 @@ config ARCH_SIRF bool "CSR SiRF" if ARCH_MULTI_V7 + select ARCH_HAS_RESET_CONTROLLER select ARCH_REQUIRE_GPIOLIB select GENERIC_IRQ_CHIP select NO_IOPORT diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c index d49aff74de98..3b8865a140ee 100644 --- a/arch/arm/mach-prima2/common.c +++ b/arch/arm/mach-prima2/common.c @@ -15,7 +15,7 @@ #include #include "common.h" -void __init sirfsoc_init_late(void) +static void __init sirfsoc_init_late(void) { sirfsoc_pm_init(); } @@ -27,7 +27,7 @@ static __init void sirfsoc_map_io(void) } #ifdef CONFIG_ARCH_ATLAS6 -static const char *atlas6_dt_match[] __initdata = { +static const char *atlas6_dt_match[] __initconst = { "sirf,atlas6", NULL }; @@ -42,7 +42,7 @@ MACHINE_END #endif #ifdef CONFIG_ARCH_PRIMA2 -static const char *prima2_dt_match[] __initdata = { +static const char *prima2_dt_match[] __initconst = { "sirf,prima2", NULL }; @@ -58,7 +58,7 @@ MACHINE_END #endif #ifdef CONFIG_ARCH_MARCO -static const char *marco_dt_match[] __initdata = { +static const char *marco_dt_match[] __initconst = { "sirf,marco", NULL }; diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c index cbcbe9cb094c..c7102539c0b0 100644 --- a/arch/arm/mach-prima2/l2x0.c +++ b/arch/arm/mach-prima2/l2x0.c @@ -11,24 +11,23 @@ #include #include -struct l2x0_aux -{ +struct l2x0_aux { u32 val; u32 mask; }; -static struct l2x0_aux prima2_l2x0_aux __initconst = { +static const struct l2x0_aux prima2_l2x0_aux __initconst = { .val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT, .mask = 0, }; -static struct l2x0_aux marco_l2x0_aux __initconst = { +static const struct l2x0_aux marco_l2x0_aux __initconst = { .val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) | (1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT), .mask = L2X0_AUX_CTRL_MASK, }; -static struct of_device_id sirf_l2x0_ids[] __initconst = { +static const struct of_device_id sirf_l2x0_ids[] __initconst = { { .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, }, { .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, }, {}, diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c index e358b0736dea..335c12e92262 100644 --- a/arch/arm/mach-prima2/platsmp.c +++ b/arch/arm/mach-prima2/platsmp.c @@ -138,9 +138,9 @@ static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus) } struct smp_operations sirfsoc_smp_ops __initdata = { - .smp_prepare_cpus = sirfsoc_smp_prepare_cpus, - .smp_secondary_init = sirfsoc_secondary_init, - .smp_boot_secondary = sirfsoc_boot_secondary, + .smp_prepare_cpus = sirfsoc_smp_prepare_cpus, + .smp_secondary_init = sirfsoc_secondary_init, + .smp_boot_secondary = sirfsoc_boot_secondary, #ifdef CONFIG_HOTPLUG_CPU .cpu_die = sirfsoc_cpu_die, #endif diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c index ccb53391147a..a59976743332 100644 --- a/arch/arm/mach-prima2/rstc.c +++ b/arch/arm/mach-prima2/rstc.c @@ -13,57 +13,36 @@ #include #include #include +#include #include +#include + +#define SIRFSOC_RSTBIT_NUM 64 void __iomem *sirfsoc_rstc_base; static DEFINE_MUTEX(rstc_lock); -static struct of_device_id rstc_ids[] = { - { .compatible = "sirf,prima2-rstc" }, - { .compatible = "sirf,marco-rstc" }, - {}, -}; - -static int __init sirfsoc_of_rstc_init(void) +static int sirfsoc_reset_module(struct reset_controller_dev *rcdev, + unsigned long sw_reset_idx) { - struct device_node *np; + u32 reset_bit = sw_reset_idx; - np = of_find_matching_node(NULL, rstc_ids); - if (!np) { - pr_err("unable to find compatible sirf rstc node in dtb\n"); - return -ENOENT; - } - - 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) -{ - u32 reset_bit; - - if (of_property_read_u32(dev->of_node, "reset-bit", &reset_bit)) + if (reset_bit >= SIRFSOC_RSTBIT_NUM) return -EINVAL; mutex_lock(&rstc_lock); - if (of_device_is_compatible(dev->of_node, "sirf,prima2-rstc")) { + if (of_device_is_compatible(rcdev->of_node, "sirf,prima2-rstc")) { /* * 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, + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | (1 << reset_bit), sirfsoc_rstc_base + (reset_bit / 32) * 4); msleep(10); - writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, + writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~(1 << reset_bit), sirfsoc_rstc_base + (reset_bit / 32) * 4); } else { /* @@ -73,9 +52,9 @@ int sirfsoc_reset_device(struct device *dev) * datasheet doesn't require explicit delay between the set and clear * of reset bit. it could be shorter if tests pass. */ - writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8); + writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8); msleep(10); - writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); + writel(1 << reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4); } mutex_unlock(&rstc_lock); @@ -83,6 +62,52 @@ int sirfsoc_reset_device(struct device *dev) return 0; } +static struct reset_control_ops sirfsoc_rstc_ops = { + .reset = sirfsoc_reset_module, +}; + +static struct reset_controller_dev sirfsoc_reset_controller = { + .ops = &sirfsoc_rstc_ops, + .nr_resets = SIRFSOC_RSTBIT_NUM, +}; + +static int sirfsoc_rstc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + sirfsoc_rstc_base = of_iomap(np, 0); + if (!sirfsoc_rstc_base) { + dev_err(&pdev->dev, "unable to map rstc cpu registers\n"); + return -ENOMEM; + } + + sirfsoc_reset_controller.of_node = np; + + reset_controller_register(&sirfsoc_reset_controller); + + return 0; +} + +static const struct of_device_id rstc_ids[] = { + { .compatible = "sirf,prima2-rstc" }, + { .compatible = "sirf,marco-rstc" }, + {}, +}; + +static struct platform_driver sirfsoc_rstc_driver = { + .probe = sirfsoc_rstc_probe, + .driver = { + .name = "sirfsoc_rstc", + .owner = THIS_MODULE, + .of_match_table = rstc_ids, + }, +}; + +static int __init sirfsoc_rstc_init(void) +{ + return platform_driver_register(&sirfsoc_rstc_driver); +} +subsys_initcall(sirfsoc_rstc_init); + #define SIRFSOC_SYS_RST_BIT BIT(31) void sirfsoc_restart(enum reboot_mode mode, const char *cmd) diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c index 9f2da2eec4dc..a17c88b74fa1 100644 --- a/arch/arm/mach-prima2/rtciobrg.c +++ b/arch/arm/mach-prima2/rtciobrg.c @@ -137,4 +137,4 @@ postcore_initcall(sirfsoc_rtciobrg_init); MODULE_AUTHOR("Zhiwu Song , " "Barry Song "); MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2");