From b3f89562100ad7d8deecc5a97ac74db7708c1bba Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Wed, 18 Jul 2012 21:11:59 -0400 Subject: [PATCH 1/4] C6X: remove megamod-pic requirement on direct-mapped core pic The megamodule PIC cascades a number of interrupt sources into the core priority PIC. The megamodule code depends on the core hardware interrupt numbers being mapped one-to-one with regard to linux interrupt numbers. This patch removes that dependence in order to pave the way for removing the direct mapping in the core PIC code. Signed-off-by: Mark Salter --- arch/c6x/platforms/megamod-pic.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/arch/c6x/platforms/megamod-pic.c b/arch/c6x/platforms/megamod-pic.c index c1c4e2ae3f85..74e3371eb824 100644 --- a/arch/c6x/platforms/megamod-pic.c +++ b/arch/c6x/platforms/megamod-pic.c @@ -243,27 +243,37 @@ static struct megamod_pic * __init init_megamod_pic(struct device_node *np) * as their interrupt parent. */ for (i = 0; i < NR_COMBINERS; i++) { + struct irq_data *irq_data; + irq_hw_number_t hwirq; irq = irq_of_parse_and_map(np, i); if (irq == NO_IRQ) continue; + irq_data = irq_get_irq_data(irq); + if (!irq_data) { + pr_err("%s: combiner-%d no irq_data for virq %d!\n", + np->full_name, i, irq); + continue; + } + + hwirq = irq_data->hwirq; + /* - * We count on the core priority interrupts (4 - 15) being - * direct mapped. Check that device tree provided something - * in that range. + * Check that device tree provided something in the range + * of the core priority interrupts (4 - 15). */ - if (irq < 4 || irq >= NR_PRIORITY_IRQS) { - pr_err("%s: combiner-%d virq %d out of range!\n", - np->full_name, i, irq); + if (hwirq < 4 || hwirq >= NR_PRIORITY_IRQS) { + pr_err("%s: combiner-%d core irq %ld out of range!\n", + np->full_name, i, hwirq); continue; } /* record the mapping */ - mapping[irq - 4] = i; + mapping[hwirq - 4] = i; - pr_debug("%s: combiner-%d cascading to virq %d\n", - np->full_name, i, irq); + pr_debug("%s: combiner-%d cascading to hwirq %ld\n", + np->full_name, i, hwirq); cascade_data[i].pic = pic; cascade_data[i].index = i; From f84f1f462bfaf0e45511f97ef54068b8539a7af6 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Wed, 18 Jul 2012 23:49:40 -0400 Subject: [PATCH 2/4] C6X: remove dependence on legacy IRQs The core priority PIC code uses legacy irq support to facilitate direct mapping of core hw interrupt numbers to linux interrupt numbers. This patch removes the legacy irq usage and replaces it with a generic linear mapping. Signed-off-by: Mark Salter --- arch/c6x/include/asm/irq.h | 2 -- arch/c6x/kernel/irq.c | 21 ++++++++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/arch/c6x/include/asm/irq.h b/arch/c6x/include/asm/irq.h index ab4577f93d96..1324e62bd4ef 100644 --- a/arch/c6x/include/asm/irq.h +++ b/arch/c6x/include/asm/irq.h @@ -34,8 +34,6 @@ */ #define NR_PRIORITY_IRQS 16 -#define NR_IRQS_LEGACY NR_PRIORITY_IRQS - /* Total number of virq in the platform */ #define NR_IRQS 256 diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c index c90fb5e82ad7..247e0eb5e467 100644 --- a/arch/c6x/kernel/irq.c +++ b/arch/c6x/kernel/irq.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Texas Instruments Incorporated + * Copyright (C) 2011-2012 Texas Instruments Incorporated * * This borrows heavily from powerpc version, which is: * @@ -35,9 +35,7 @@ static DEFINE_RAW_SPINLOCK(core_irq_lock); static void mask_core_irq(struct irq_data *data) { - unsigned int prio = data->irq; - - BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS); + unsigned int prio = data->hwirq; raw_spin_lock(&core_irq_lock); and_creg(IER, ~(1 << prio)); @@ -46,7 +44,7 @@ static void mask_core_irq(struct irq_data *data) static void unmask_core_irq(struct irq_data *data) { - unsigned int prio = data->irq; + unsigned int prio = data->hwirq; raw_spin_lock(&core_irq_lock); or_creg(IER, 1 << prio); @@ -59,15 +57,15 @@ static struct irq_chip core_chip = { .irq_unmask = unmask_core_irq, }; +static int prio_to_virq[NR_PRIORITY_IRQS]; + asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); - BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS); - - generic_handle_irq(prio); + generic_handle_irq(prio_to_virq[prio]); irq_exit(); @@ -82,6 +80,8 @@ static int core_domain_map(struct irq_domain *h, unsigned int virq, if (hw < 4 || hw >= NR_PRIORITY_IRQS) return -EINVAL; + prio_to_virq[hw] = virq; + irq_set_status_flags(virq, IRQ_LEVEL); irq_set_chip_and_handler(virq, &core_chip, handle_level_irq); return 0; @@ -102,9 +102,8 @@ void __init init_IRQ(void) np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic"); if (np != NULL) { /* create the core host */ - core_domain = irq_domain_add_legacy(np, NR_PRIORITY_IRQS, - 0, 0, &core_domain_ops, - NULL); + core_domain = irq_domain_add_linear(np, NR_PRIORITY_IRQS, + &core_domain_ops, NULL); if (core_domain) irq_set_default_host(core_domain); of_node_put(np); From dbe91a2e6e53aa85efa0aac86e3a22ba95f8b85f Mon Sep 17 00:00:00 2001 From: Ken Cox Date: Wed, 18 Jul 2012 23:19:10 -0400 Subject: [PATCH 3/4] C6X: add basic support for TMS320C6678 SoC This patch adds support for the TMS320C6678 SoC on an EVMC6678LE evaluation board. The 6678 is a C66x family CPU which is very similar to the already supported C64x CPUs with the addition of floating point instructions. Signed-off-by: Ken Cox Signed-off-by: Mark Salter CC: Aurelien Jacquiot CC: linux-c6x-dev@linux-c6x.org --- arch/c6x/boot/dts/evmc6678.dts | 83 ++++++++++++++++ arch/c6x/boot/dts/tms320c6678.dtsi | 146 ++++++++++++++++++++++++++++ arch/c6x/configs/evmc6678_defconfig | 42 ++++++++ arch/c6x/kernel/setup.c | 4 + arch/c6x/platforms/Kconfig | 4 + arch/c6x/platforms/plldata.c | 65 +++++++++++++ 6 files changed, 344 insertions(+) create mode 100644 arch/c6x/boot/dts/evmc6678.dts create mode 100644 arch/c6x/boot/dts/tms320c6678.dtsi create mode 100644 arch/c6x/configs/evmc6678_defconfig diff --git a/arch/c6x/boot/dts/evmc6678.dts b/arch/c6x/boot/dts/evmc6678.dts new file mode 100644 index 000000000000..ab686301d321 --- /dev/null +++ b/arch/c6x/boot/dts/evmc6678.dts @@ -0,0 +1,83 @@ +/* + * arch/c6x/boot/dts/evmc6678.dts + * + * EVMC6678 Evaluation Platform For TMS320C6678 + * + * Copyright (C) 2012 Texas Instruments Incorporated + * + * Author: Ken Cox + * + * 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. + * + */ + +/dts-v1/; + +/include/ "tms320c6678.dtsi" + +/ { + model = "Advantech EVMC6678"; + compatible = "advantech,evmc6678"; + + chosen { + bootargs = "root=/dev/nfs ip=dhcp rw"; + }; + + memory { + device_type = "memory"; + reg = <0x80000000 0x20000000>; + }; + + soc { + megamod_pic: interrupt-controller@1800000 { + interrupts = < 12 13 14 15 >; + }; + + timer8: timer@2280000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 66 >; + }; + + timer9: timer@2290000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 68 >; + }; + + timer10: timer@22A0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 70 >; + }; + + timer11: timer@22B0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 72 >; + }; + + timer12: timer@22C0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 74 >; + }; + + timer13: timer@22D0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 76 >; + }; + + timer14: timer@22E0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 78 >; + }; + + timer15: timer@22F0000 { + interrupt-parent = <&megamod_pic>; + interrupts = < 80 >; + }; + + clock-controller@2310000 { + clock-frequency = <100000000>; + }; + }; +}; diff --git a/arch/c6x/boot/dts/tms320c6678.dtsi b/arch/c6x/boot/dts/tms320c6678.dtsi new file mode 100644 index 000000000000..386196e5eae7 --- /dev/null +++ b/arch/c6x/boot/dts/tms320c6678.dtsi @@ -0,0 +1,146 @@ + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + reg = <0>; + model = "ti,c66x"; + }; + cpu@1 { + device_type = "cpu"; + reg = <1>; + model = "ti,c66x"; + }; + cpu@2 { + device_type = "cpu"; + reg = <2>; + model = "ti,c66x"; + }; + cpu@3 { + device_type = "cpu"; + reg = <3>; + model = "ti,c66x"; + }; + cpu@4 { + device_type = "cpu"; + reg = <4>; + model = "ti,c66x"; + }; + cpu@5 { + device_type = "cpu"; + reg = <5>; + model = "ti,c66x"; + }; + cpu@6 { + device_type = "cpu"; + reg = <6>; + model = "ti,c66x"; + }; + cpu@7 { + device_type = "cpu"; + reg = <7>; + model = "ti,c66x"; + }; + }; + + soc { + compatible = "simple-bus"; + model = "tms320c6678"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + core_pic: interrupt-controller { + compatible = "ti,c64x+core-pic"; + interrupt-controller; + #interrupt-cells = <1>; + }; + + megamod_pic: interrupt-controller@1800000 { + compatible = "ti,c64x+megamod-pic"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x1800000 0x1000>; + interrupt-parent = <&core_pic>; + }; + + cache-controller@1840000 { + compatible = "ti,c64x+cache"; + reg = <0x01840000 0x8400>; + }; + + timer8: timer@2280000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x01 >; + reg = <0x2280000 0x40>; + }; + + timer9: timer@2290000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x02 >; + reg = <0x2290000 0x40>; + }; + + timer10: timer@22A0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x04 >; + reg = <0x22A0000 0x40>; + }; + + timer11: timer@22B0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x08 >; + reg = <0x22B0000 0x40>; + }; + + timer12: timer@22C0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x10 >; + reg = <0x22C0000 0x40>; + }; + + timer13: timer@22D0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x20 >; + reg = <0x22D0000 0x40>; + }; + + timer14: timer@22E0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x40 >; + reg = <0x22E0000 0x40>; + }; + + timer15: timer@22F0000 { + compatible = "ti,c64x+timer64"; + ti,core-mask = < 0x80 >; + reg = <0x22F0000 0x40>; + }; + + clock-controller@2310000 { + compatible = "ti,c6678-pll", "ti,c64x+pll"; + reg = <0x02310000 0x200>; + ti,c64x+pll-bypass-delay = <200>; + ti,c64x+pll-reset-delay = <12000>; + ti,c64x+pll-lock-delay = <80000>; + }; + + device-state-controller@2620000 { + compatible = "ti,c64x+dscr"; + reg = <0x02620000 0x1000>; + + ti,dscr-devstat = <0x20>; + ti,dscr-silicon-rev = <0x18 28 0xf>; + + ti,dscr-mac-fuse-regs = <0x110 1 2 3 4 + 0x114 5 6 0 0>; + + }; + }; +}; diff --git a/arch/c6x/configs/evmc6678_defconfig b/arch/c6x/configs/evmc6678_defconfig new file mode 100644 index 000000000000..5f126d4905b1 --- /dev/null +++ b/arch/c6x/configs/evmc6678_defconfig @@ -0,0 +1,42 @@ +CONFIG_SOC_TMS320C6678=y +CONFIG_EXPERIMENTAL=y +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_SYSVIPC=y +CONFIG_SPARSE_IRQ=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_EXPERT=y +# CONFIG_FUTEX is not set +# CONFIG_SLUB_DEBUG is not set +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="" +# CONFIG_CMDLINE_FORCE is not set +CONFIG_BOARD_EVM6678=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=2 +CONFIG_BLK_DEV_RAM_SIZE=17000 +CONFIG_MISC_DEVICES=y +# CONFIG_INPUT is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_HWMON is not set +# CONFIG_USB_SUPPORT is not set +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_MISC_FILESYSTEMS is not set +CONFIG_CRC16=y +# CONFIG_ENABLE_MUST_CHECK is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_BUGVERBOSE is not set diff --git a/arch/c6x/kernel/setup.c b/arch/c6x/kernel/setup.c index ce46186600c5..f4e72bd8c103 100644 --- a/arch/c6x/kernel/setup.c +++ b/arch/c6x/kernel/setup.c @@ -143,6 +143,10 @@ static void __init get_cpuinfo(void) p->cpu_name = "C64x+"; p->cpu_voltage = "1.2"; break; + case 21: + p->cpu_name = "C66X"; + p->cpu_voltage = "1.2"; + break; default: p->cpu_name = "unknown"; break; diff --git a/arch/c6x/platforms/Kconfig b/arch/c6x/platforms/Kconfig index 401ee678fd01..c4a0fad89aaf 100644 --- a/arch/c6x/platforms/Kconfig +++ b/arch/c6x/platforms/Kconfig @@ -14,3 +14,7 @@ config SOC_TMS320C6472 config SOC_TMS320C6474 bool "TMS320C6474" default n + +config SOC_TMS320C6678 + bool "TMS320C6678" + default n diff --git a/arch/c6x/platforms/plldata.c b/arch/c6x/platforms/plldata.c index 2cfd6f42968f..755359eb6286 100644 --- a/arch/c6x/platforms/plldata.c +++ b/arch/c6x/platforms/plldata.c @@ -335,6 +335,68 @@ static void __init c6474_setup_clocks(struct device_node *node) } #endif /* CONFIG_SOC_TMS320C6474 */ +#ifdef CONFIG_SOC_TMS320C6678 +static struct clk_lookup c6678_clks[] = { + CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]), + CLK(NULL, "pll1_refclk", &c6x_soc_pll1.sysclks[1]), + CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]), + CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]), + CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]), + CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]), + CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]), + CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]), + CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]), + CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]), + CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]), + CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]), + CLK(NULL, "core", &c6x_core_clk), + CLK("", NULL, NULL) +}; + +static void __init c6678_setup_clocks(struct device_node *node) +{ + struct pll_data *pll = &c6x_soc_pll1; + struct clk *sysclks = pll->sysclks; + + pll->flags = PLL_HAS_MUL; + + sysclks[1].flags |= FIXED_DIV_PLL; + sysclks[1].div = 1; + + sysclks[2].div = PLLDIV2; + + sysclks[3].flags |= FIXED_DIV_PLL; + sysclks[3].div = 2; + + sysclks[4].flags |= FIXED_DIV_PLL; + sysclks[4].div = 3; + + sysclks[5].div = PLLDIV5; + + sysclks[6].flags |= FIXED_DIV_PLL; + sysclks[6].div = 64; + + sysclks[7].flags |= FIXED_DIV_PLL; + sysclks[7].div = 6; + + sysclks[8].div = PLLDIV8; + + sysclks[9].flags |= FIXED_DIV_PLL; + sysclks[9].div = 12; + + sysclks[10].flags |= FIXED_DIV_PLL; + sysclks[10].div = 3; + + sysclks[11].flags |= FIXED_DIV_PLL; + sysclks[11].div = 6; + + c6x_core_clk.parent = &sysclks[0]; + c6x_i2c_clk.parent = &sysclks[7]; + + c6x_clks_init(c6678_clks); +} +#endif /* CONFIG_SOC_TMS320C6678 */ + static struct of_device_id c6x_clkc_match[] __initdata = { #ifdef CONFIG_SOC_TMS320C6455 { .compatible = "ti,c6455-pll", .data = c6455_setup_clocks }, @@ -347,6 +409,9 @@ static struct of_device_id c6x_clkc_match[] __initdata = { #endif #ifdef CONFIG_SOC_TMS320C6474 { .compatible = "ti,c6474-pll", .data = c6474_setup_clocks }, +#endif +#ifdef CONFIG_SOC_TMS320C6678 + { .compatible = "ti,c6678-pll", .data = c6678_setup_clocks }, #endif { .compatible = "ti,c64x+pll" }, {} From b9b8722d4704137d1c85b8e62364b487cbbe8bf0 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Wed, 18 Jul 2012 23:34:17 -0400 Subject: [PATCH 4/4] C6X: clean up compiler warning commit a610d6e6: pull clearing RESTORE_SIGMASK into block_sigmask() left behind a compiler warning: arch/c6x/kernel/signal.c:252:6: warning: unused variable 'ret' This patch cleans up the warning by removing the unused variable. Signed-off-by: Mark Salter --- arch/c6x/kernel/signal.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c index 3d8f3c22a94f..3998b24e26f2 100644 --- a/arch/c6x/kernel/signal.c +++ b/arch/c6x/kernel/signal.c @@ -249,8 +249,6 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int syscall) { - int ret; - /* Are we from a system call? */ if (syscall) { /* If so, check system call restarting.. */