Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARC: [plat-arcfpga]: Enabling DeviceTree for Angel4 board

* arc-uart platform device now populated dynamically, using
of_platform_populate() - applies to any other device whatsoever.

* uart in turn requires incore arc-intc to be also present in DT

* A irq-domain needs to be instantiated for IRQ requests by DT probed
device (e.g. arc-uart)

TODO: switch over to linear irq domain once all devs have been
transitioned to DT

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Arnd Bergmann <arnd@arndb.de>

+170 -58
+24
Documentation/devicetree/bindings/arc/interrupts.txt
··· 1 + * ARC700 incore Interrupt Controller 2 + 3 + The core interrupt controller provides 32 prioritised interrupts (2 levels) 4 + to ARC700 core. 5 + 6 + Properties: 7 + 8 + - compatible: "snps,arc700-intc" 9 + - interrupt-controller: This is an interrupt controller. 10 + - #interrupt-cells: Must be <1>. 11 + 12 + Single Cell "interrupts" property of a device specifies the IRQ number 13 + between 0 to 31 14 + 15 + intc accessed via the special ARC AUX register interface, hence "reg" property 16 + is not specified. 17 + 18 + Example: 19 + 20 + intc: interrupt-controller { 21 + compatible = "snps,arc700-intc"; 22 + interrupt-controller; 23 + #interrupt-cells = <1>; 24 + };
+1 -1
arch/arc/boot/dts/Makefile
··· 1 1 # Built-in dtb 2 - builtindtb-y := skeleton 2 + builtindtb-y := angel4 3 3 4 4 ifneq ($(CONFIG_ARC_BUILTIN_DTB_NAME),"") 5 5 builtindtb-y := $(patsubst "%",%,$(CONFIG_ARC_BUILTIN_DTB_NAME))
+55
arch/arc/boot/dts/angel4.dts
··· 1 + /* 2 + * Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com) 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + /dts-v1/; 9 + 10 + /include/ "skeleton.dtsi" 11 + 12 + / { 13 + compatible = "snps,arc-angel4"; 14 + clock-frequency = <80000000>; /* 80 MHZ */ 15 + #address-cells = <1>; 16 + #size-cells = <1>; 17 + interrupt-parent = <&intc>; 18 + 19 + chosen { 20 + bootargs = "console=ttyARC0,115200n8"; 21 + }; 22 + 23 + aliases { 24 + serial0 = &arcuart0; 25 + }; 26 + 27 + memory { 28 + device_type = "memory"; 29 + reg = <0x00000000 0x10000000>; /* 256M */ 30 + }; 31 + 32 + fpga { 33 + compatible = "simple-bus"; 34 + #address-cells = <1>; 35 + #size-cells = <1>; 36 + 37 + /* child and parent address space 1:1 mapped */ 38 + ranges; 39 + 40 + intc: interrupt-controller { 41 + compatible = "snps,arc700-intc"; 42 + interrupt-controller; 43 + #interrupt-cells = <1>; 44 + }; 45 + 46 + arcuart0: serial@c0fc1000 { 47 + compatible = "snps,arc-uart"; 48 + reg = <0xc0fc1000 0x100>; 49 + interrupts = <5>; 50 + clock-frequency = <80000000>; 51 + baud = <115200>; 52 + status = "okay"; 53 + }; 54 + }; 55 + };
+12
arch/arc/boot/dts/skeleton.dtsi
··· 18 18 #size-cells = <1>; 19 19 chosen { }; 20 20 aliases { }; 21 + 22 + cpus { 23 + #address-cells = <1>; 24 + #size-cells = <0>; 25 + 26 + cpu@0 { 27 + device_type = "cpu"; 28 + compatible = "snps,arc770d"; 29 + reg = <0>; 30 + }; 31 + }; 32 + 21 33 memory { 22 34 device_type = "memory"; 23 35 reg = <0x00000000 0x10000000>; /* 256M */
+32 -6
arch/arc/kernel/irq.c
··· 9 9 10 10 #include <linux/interrupt.h> 11 11 #include <linux/module.h> 12 + #include <linux/of.h> 13 + #include <linux/irqdomain.h> 12 14 #include <asm/sections.h> 13 15 #include <asm/irq.h> 14 16 ··· 61 59 .irq_unmask = arc_unmask_irq, 62 60 }; 63 61 62 + static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq, 63 + irq_hw_number_t hw) 64 + { 65 + if (irq == TIMER0_IRQ) 66 + irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq); 67 + else 68 + irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq); 69 + 70 + return 0; 71 + } 72 + 73 + static const struct irq_domain_ops arc_intc_domain_ops = { 74 + .xlate = irq_domain_xlate_onecell, 75 + .map = arc_intc_domain_map, 76 + }; 77 + 78 + static struct irq_domain *root_domain; 79 + 64 80 void __init init_onchip_IRQ(void) 65 81 { 66 - int i; 82 + struct device_node *intc = NULL; 67 83 68 - for (i = 0; i < NR_IRQS; i++) 69 - irq_set_chip_and_handler(i, &onchip_intc, handle_level_irq); 84 + intc = of_find_compatible_node(NULL, NULL, "snps,arc700-intc"); 85 + if(!intc) 86 + panic("DeviceTree Missing incore intc\n"); 70 87 71 - #ifdef CONFIG_SMP 72 - irq_set_chip_and_handler(TIMER0_IRQ, &onchip_intc, handle_percpu_irq); 73 - #endif 88 + root_domain = irq_domain_add_legacy(intc, NR_IRQS, 0, 0, 89 + &arc_intc_domain_ops, NULL); 90 + 91 + if (!root_domain) 92 + panic("root irq domain not avail\n"); 93 + 94 + /* with this we don't need to export root_domain */ 95 + irq_set_default_host(root_domain); 74 96 } 75 97 76 98 /*
+46 -51
arch/arc/plat-arcfpga/platform.c
··· 13 13 #include <linux/device.h> 14 14 #include <linux/platform_device.h> 15 15 #include <linux/console.h> 16 + #include <linux/of_platform.h> 16 17 #include <asm/setup.h> 17 18 #include <asm/irq.h> 18 19 #include <asm/clk.h> ··· 21 20 22 21 /*----------------------- Platform Devices -----------------------------*/ 23 22 24 - #if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE) 25 - 26 23 static unsigned long arc_uart_info[] = { 27 - CONFIG_ARC_SERIAL_BAUD, /* uart->baud */ 28 - -1, /* uart->port.uartclk */ 29 - -1, /* uart->is_emulated (runtime @running_on_hw) */ 24 + 0, /* uart->is_emulated (runtime @running_on_hw) */ 25 + 0, /* uart->port.uartclk */ 26 + 0, /* uart->baud */ 30 27 0 31 28 }; 32 29 33 - #define ARC_UART_DEV(n) \ 34 - \ 35 - static struct resource arc_uart##n##_res[] = { \ 36 - { \ 37 - .start = UART##n##_BASE, \ 38 - .end = UART##n##_BASE + 0xFF, \ 39 - .flags = IORESOURCE_MEM, \ 40 - }, \ 41 - { \ 42 - .start = UART##n##_IRQ, \ 43 - .end = UART##n##_IRQ, \ 44 - .flags = IORESOURCE_IRQ, \ 45 - }, \ 46 - }; \ 47 - \ 48 - static struct platform_device arc_uart##n##_dev = { \ 49 - .name = "arc-uart", \ 50 - .id = n, \ 51 - .num_resources = ARRAY_SIZE(arc_uart##n##_res), \ 52 - .resource = arc_uart##n##_res, \ 53 - .dev = { \ 54 - .platform_data = &arc_uart_info, \ 55 - }, \ 56 - } 30 + #if defined(CONFIG_SERIAL_ARC_CONSOLE) 31 + /* 32 + * static platform data - but only for early serial 33 + * TBD: derive this from a special DT node 34 + */ 35 + static struct resource arc_uart0_res[] = { 36 + { 37 + .start = UART0_BASE, 38 + .end = UART0_BASE + 0xFF, 39 + .flags = IORESOURCE_MEM, 40 + }, 41 + { 42 + .start = UART0_IRQ, 43 + .end = UART0_IRQ, 44 + .flags = IORESOURCE_IRQ, 45 + }, 46 + }; 57 47 58 - ARC_UART_DEV(0); 59 - #if CONFIG_SERIAL_ARC_NR_PORTS > 1 60 - ARC_UART_DEV(1); 61 - #endif 48 + static struct platform_device arc_uart0_dev = { 49 + .name = "arc-uart", 50 + .id = 0, 51 + .num_resources = ARRAY_SIZE(arc_uart0_res), 52 + .resource = arc_uart0_res, 53 + .dev = { 54 + .platform_data = &arc_uart_info, 55 + }, 56 + }; 62 57 63 58 static struct platform_device *fpga_early_devs[] __initdata = { 64 - #if defined(CONFIG_SERIAL_ARC_CONSOLE) 65 59 &arc_uart0_dev, 66 - #endif 67 60 }; 61 + #endif 68 62 69 63 static void arc_fpga_serial_init(void) 70 64 { 65 + /* To let driver workaround ISS bug: baudh Reg can't be set to 0 */ 66 + arc_uart_info[0] = !running_on_hw; 67 + 71 68 arc_uart_info[1] = arc_get_core_freq(); 72 69 73 - /* To let driver workaround ISS bug: baudh Reg can't be set to 0 */ 74 - arc_uart_info[2] = !running_on_hw; 70 + arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD; 75 71 72 + #if defined(CONFIG_SERIAL_ARC_CONSOLE) 76 73 early_platform_add_devices(fpga_early_devs, 77 74 ARRAY_SIZE(fpga_early_devs)); 78 75 ··· 96 97 * otherwise the early console never gets a chance to run. 97 98 */ 98 99 add_preferred_console("ttyARC", 0, "115200"); 100 + #endif 99 101 } 100 - 101 - #else 102 - 103 - static void arc_fpga_serial_init(void) 104 - { 105 - } 106 - 107 - #endif /* CONFIG_SERIAL_ARC */ 108 102 109 103 /* 110 104 * Early Platform Initialization called from setup_arch() ··· 109 117 arc_fpga_serial_init(); 110 118 } 111 119 112 - static struct platform_device *fpga_devs[] __initdata = { 120 + static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = { 113 121 #if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE) 114 - &arc_uart0_dev, 115 - #if CONFIG_SERIAL_ARC_NR_PORTS > 1 116 - &arc_uart1_dev, 122 + OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info), 117 123 #endif 118 - #endif 124 + {} 119 125 }; 120 126 121 127 int __init fpga_plat_init(void) 122 128 { 123 129 pr_info("[plat-arcfpga]: registering device resources\n"); 124 130 125 - platform_add_devices(fpga_devs, ARRAY_SIZE(fpga_devs)); 131 + /* 132 + * Traverses flattened DeviceTree - registering platform devices 133 + * complete with their resources 134 + */ 135 + of_platform_populate(NULL, of_default_bus_match_table, 136 + plat_auxdata_lookup, NULL); 126 137 127 138 return 0; 128 139 }