diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 19:41:08 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-02 19:41:08 -0700 |
commit | c9297d284126b80c9cfd72c690e0da531c99fc48 (patch) | |
tree | bec7ce343f2a37def4e99ec556deb3998dbeb041 /drivers | |
parent | 17e3cd222af1c72a750cd83565bb8dfc7bc12335 (diff) | |
parent | 6fc61ee69433e7e0433cabd36f78bb5fb3b26524 (diff) |
Merge tag 'nds32-for-linus-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux
Pull nds32 architecture support from Greentime Hu:
"This contains the core nds32 Linux port (including interrupt
controller driver and timer driver), which has been through seven
rounds of review on mailing list.
It is able to boot to shell and passes most LTP-2017 testsuites in
nds32 AE3XX platform:
Total Tests: 1901
Total Skipped Tests: 618
Total Failures: 78"
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
* tag 'nds32-for-linus-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux: (44 commits)
nds32: To use the generic dump_stack()
nds32: fix building failed if using elf toolchain.
nios2: add ioremap_nocache declaration before include asm-generic/io.h.
nds32: fix building failed if using older version gcc.
dt-bindings: timer: Add andestech atcpit100 timer binding doc
clocksource/drivers/atcpit100: VDSO support
clocksource/drivers/atcpit100: Add andestech atcpit100 timer
net: faraday add nds32 support.
irqchip: Andestech Internal Vector Interrupt Controller driver
dt-bindings: interrupt-controller: Andestech Internal Vector Interrupt Controller
dt-bindings: nds32 SoC Bindings
dt-bindings: nds32 L2 cache controller Bindings
dt-bindings: nds32 CPU Bindings
MAINTAINERS: Add nds32
nds32: Build infrastructure
nds32: defconfig
nds32: Miscellaneous header files
nds32: Device tree support
nds32: Generic timers support
nds32: Loadable modules
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clocksource/Kconfig | 9 | ||||
-rw-r--r-- | drivers/clocksource/Makefile | 1 | ||||
-rw-r--r-- | drivers/clocksource/timer-atcpit100.c | 266 | ||||
-rw-r--r-- | drivers/irqchip/Makefile | 1 | ||||
-rw-r--r-- | drivers/irqchip/irq-ativic32.c | 107 | ||||
-rw-r--r-- | drivers/net/ethernet/faraday/Kconfig | 8 | ||||
-rw-r--r-- | drivers/video/console/Kconfig | 2 |
7 files changed, 390 insertions, 4 deletions
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index d2e5382821a4..14c9796e37ac 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -592,4 +592,13 @@ config CLKSRC_ST_LPC Enable this option to use the Low Power controller timer as clocksource. +config ATCPIT100_TIMER + bool "ATCPIT100 timer driver" + depends on NDS32 || COMPILE_TEST + depends on HAS_IOMEM + select TIMER_OF + default NDS32 + help + This option enables support for the Andestech ATCPIT100 timers. + endmenu diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index d6dec4489d66..a79523b22e52 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -76,3 +76,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o +obj-$(CONFIG_ATCPIT100_TIMER) += timer-atcpit100.o diff --git a/drivers/clocksource/timer-atcpit100.c b/drivers/clocksource/timer-atcpit100.c new file mode 100644 index 000000000000..5e23d7b4a722 --- /dev/null +++ b/drivers/clocksource/timer-atcpit100.c @@ -0,0 +1,266 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation +/* + * Andestech ATCPIT100 Timer Device Driver Implementation + * Rick Chen, Andes Technology Corporation <rick@andestech.com> + * + */ + +#include <linux/irq.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/sched.h> +#include <linux/sched_clock.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include "timer-of.h" +#ifdef CONFIG_NDS32 +#include <asm/vdso_timer_info.h> +#endif + +/* + * Definition of register offsets + */ + +/* ID and Revision Register */ +#define ID_REV 0x0 + +/* Configuration Register */ +#define CFG 0x10 + +/* Interrupt Enable Register */ +#define INT_EN 0x14 +#define CH_INT_EN(c, i) ((1<<i)<<(4*c)) +#define CH0INT0EN 0x01 + +/* Interrupt Status Register */ +#define INT_STA 0x18 +#define CH0INT0 0x01 + +/* Channel Enable Register */ +#define CH_EN 0x1C +#define CH0TMR0EN 0x1 +#define CH1TMR0EN 0x10 + +/* Channel 0 , 1 Control Register */ +#define CH0_CTL (0x20) +#define CH1_CTL (0x20 + 0x10) + +/* Channel clock source , bit 3 , 0:External clock , 1:APB clock */ +#define APB_CLK BIT(3) + +/* Channel mode , bit 0~2 */ +#define TMR_32 0x1 +#define TMR_16 0x2 +#define TMR_8 0x3 + +/* Channel 0 , 1 Reload Register */ +#define CH0_REL (0x24) +#define CH1_REL (0x24 + 0x10) + +/* Channel 0 , 1 Counter Register */ +#define CH0_CNT (0x28) +#define CH1_CNT (0x28 + 0x10) + +#define TIMER_SYNC_TICKS 3 + +static void atcpit100_ch1_tmr0_en(void __iomem *base) +{ + writel(~0, base + CH1_REL); + writel(APB_CLK|TMR_32, base + CH1_CTL); +} + +static void atcpit100_ch0_tmr0_en(void __iomem *base) +{ + writel(APB_CLK|TMR_32, base + CH0_CTL); +} + +static void atcpit100_clkevt_time_setup(void __iomem *base, unsigned long delay) +{ + writel(delay, base + CH0_CNT); + writel(delay, base + CH0_REL); +} + +static void atcpit100_timer_clear_interrupt(void __iomem *base) +{ + u32 val; + + val = readl(base + INT_STA); + writel(val | CH0INT0, base + INT_STA); +} + +static void atcpit100_clocksource_start(void __iomem *base) +{ + u32 val; + + val = readl(base + CH_EN); + writel(val | CH1TMR0EN, base + CH_EN); +} + +static void atcpit100_clkevt_time_start(void __iomem *base) +{ + u32 val; + + val = readl(base + CH_EN); + writel(val | CH0TMR0EN, base + CH_EN); +} + +static void atcpit100_clkevt_time_stop(void __iomem *base) +{ + u32 val; + + atcpit100_timer_clear_interrupt(base); + val = readl(base + CH_EN); + writel(val & ~CH0TMR0EN, base + CH_EN); +} + +static int atcpit100_clkevt_next_event(unsigned long evt, + struct clock_event_device *clkevt) +{ + u32 val; + struct timer_of *to = to_timer_of(clkevt); + + val = readl(timer_of_base(to) + CH_EN); + writel(val & ~CH0TMR0EN, timer_of_base(to) + CH_EN); + writel(evt, timer_of_base(to) + CH0_REL); + writel(val | CH0TMR0EN, timer_of_base(to) + CH_EN); + + return 0; +} + +static int atcpit100_clkevt_set_periodic(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + + atcpit100_clkevt_time_setup(timer_of_base(to), timer_of_period(to)); + atcpit100_clkevt_time_start(timer_of_base(to)); + + return 0; +} +static int atcpit100_clkevt_shutdown(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + + atcpit100_clkevt_time_stop(timer_of_base(to)); + + return 0; +} +static int atcpit100_clkevt_set_oneshot(struct clock_event_device *evt) +{ + struct timer_of *to = to_timer_of(evt); + u32 val; + + writel(~0x0, timer_of_base(to) + CH0_REL); + val = readl(timer_of_base(to) + CH_EN); + writel(val | CH0TMR0EN, timer_of_base(to) + CH_EN); + + return 0; +} + +static irqreturn_t atcpit100_timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = (struct clock_event_device *)dev_id; + struct timer_of *to = to_timer_of(evt); + + atcpit100_timer_clear_interrupt(timer_of_base(to)); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static struct timer_of to = { + .flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE, + + .clkevt = { + .name = "atcpit100_tick", + .rating = 300, + .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = atcpit100_clkevt_shutdown, + .set_state_periodic = atcpit100_clkevt_set_periodic, + .set_state_oneshot = atcpit100_clkevt_set_oneshot, + .tick_resume = atcpit100_clkevt_shutdown, + .set_next_event = atcpit100_clkevt_next_event, + .cpumask = cpu_all_mask, + }, + + .of_irq = { + .handler = atcpit100_timer_interrupt, + .flags = IRQF_TIMER | IRQF_IRQPOLL, + }, + + /* + * FIXME: we currently only support clocking using PCLK + * and using EXTCLK is not supported in the driver. + */ + .of_clk = { + .name = "PCLK", + } +}; + +static u64 notrace atcpit100_timer_sched_read(void) +{ + return ~readl(timer_of_base(&to) + CH1_CNT); +} + +#ifdef CONFIG_NDS32 +static void fill_vdso_need_info(struct device_node *node) +{ + struct resource timer_res; + of_address_to_resource(node, 0, &timer_res); + timer_info.mapping_base = (unsigned long)timer_res.start; + timer_info.cycle_count_down = true; + timer_info.cycle_count_reg_offset = CH1_CNT; +} +#endif + +static int __init atcpit100_timer_init(struct device_node *node) +{ + int ret; + u32 val; + void __iomem *base; + + ret = timer_of_init(node, &to); + if (ret) + return ret; + + base = timer_of_base(&to); + + sched_clock_register(atcpit100_timer_sched_read, 32, + timer_of_rate(&to)); + + ret = clocksource_mmio_init(base + CH1_CNT, + node->name, timer_of_rate(&to), 300, 32, + clocksource_mmio_readl_down); + + if (ret) { + pr_err("Failed to register clocksource\n"); + return ret; + } + + /* clear channel 0 timer0 interrupt */ + atcpit100_timer_clear_interrupt(base); + + clockevents_config_and_register(&to.clkevt, timer_of_rate(&to), + TIMER_SYNC_TICKS, 0xffffffff); + atcpit100_ch0_tmr0_en(base); + atcpit100_ch1_tmr0_en(base); + atcpit100_clocksource_start(base); + atcpit100_clkevt_time_start(base); + + /* Enable channel 0 timer0 interrupt */ + val = readl(base + INT_EN); + writel(val | CH0INT0EN, base + INT_EN); + +#ifdef CONFIG_NDS32 + fill_vdso_need_info(node); +#endif + + return ret; +} + +TIMER_OF_DECLARE(atcpit100, "andestech,atcpit100", atcpit100_timer_init); diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index d27e3e3619e0..de7cf483e1b7 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -85,3 +85,4 @@ obj-$(CONFIG_IRQ_UNIPHIER_AIDET) += irq-uniphier-aidet.o obj-$(CONFIG_ARCH_SYNQUACER) += irq-sni-exiu.o obj-$(CONFIG_MESON_IRQ_GPIO) += irq-meson-gpio.o obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o +obj-$(CONFIG_NDS32) += irq-ativic32.o diff --git a/drivers/irqchip/irq-ativic32.c b/drivers/irqchip/irq-ativic32.c new file mode 100644 index 000000000000..f69a8588521c --- /dev/null +++ b/drivers/irqchip/irq-ativic32.c @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2005-2017 Andes Technology Corporation + +#include <linux/irq.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_address.h> +#include <linux/interrupt.h> +#include <linux/irqdomain.h> +#include <linux/irqchip.h> +#include <nds32_intrinsic.h> + +static void ativic32_ack_irq(struct irq_data *data) +{ + __nds32__mtsr_dsb(BIT(data->hwirq), NDS32_SR_INT_PEND2); +} + +static void ativic32_mask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 & (~(BIT(data->hwirq))), NDS32_SR_INT_MASK2); +} + +static void ativic32_unmask_irq(struct irq_data *data) +{ + unsigned long int_mask2 = __nds32__mfsr(NDS32_SR_INT_MASK2); + __nds32__mtsr_dsb(int_mask2 | (BIT(data->hwirq)), NDS32_SR_INT_MASK2); +} + +static struct irq_chip ativic32_chip = { + .name = "ativic32", + .irq_ack = ativic32_ack_irq, + .irq_mask = ativic32_mask_irq, + .irq_unmask = ativic32_unmask_irq, +}; + +static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 }; + +static struct irq_domain *root_domain; +static int ativic32_irq_domain_map(struct irq_domain *id, unsigned int virq, + irq_hw_number_t hw) +{ + + unsigned long int_trigger_type; + u32 type; + struct irq_data *irq_data; + int_trigger_type = __nds32__mfsr(NDS32_SR_INT_TRIGGER); + irq_data = irq_get_irq_data(virq); + if (!irq_data) + return -EINVAL; + + if (int_trigger_type & (BIT(hw))) { + irq_set_chip_and_handler(virq, &ativic32_chip, handle_edge_irq); + type = IRQ_TYPE_EDGE_RISING; + } else { + irq_set_chip_and_handler(virq, &ativic32_chip, handle_level_irq); + type = IRQ_TYPE_LEVEL_HIGH; + } + + irqd_set_trigger_type(irq_data, type); + return 0; +} + +static struct irq_domain_ops ativic32_ops = { + .map = ativic32_irq_domain_map, + .xlate = irq_domain_xlate_onecell +}; + +static irq_hw_number_t get_intr_src(void) +{ + return ((__nds32__mfsr(NDS32_SR_ITYPE) & ITYPE_mskVECTOR) >> ITYPE_offVECTOR) + - NDS32_VECTOR_offINTERRUPT; +} + +asmlinkage void asm_do_IRQ(struct pt_regs *regs) +{ + irq_hw_number_t hwirq = get_intr_src(); + handle_domain_irq(root_domain, hwirq, regs); +} + +int __init ativic32_init_irq(struct device_node *node, struct device_node *parent) +{ + unsigned long int_vec_base, nivic, nr_ints; + + if (WARN(parent, "non-root ativic32 are not supported")) + return -EINVAL; + + int_vec_base = __nds32__mfsr(NDS32_SR_IVB); + + if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) + panic("Unable to use atcivic32 for this cpu.\n"); + + nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC; + if (nivic >= ARRAY_SIZE(nivic_map)) + panic("The number of input for ativic32 is not supported.\n"); + + nr_ints = nivic_map[nivic]; + + root_domain = irq_domain_add_linear(node, nr_ints, + &ativic32_ops, NULL); + + if (!root_domain) + panic("%s: unable to create IRQ domain\n", node->full_name); + + return 0; +} +IRQCHIP_DECLARE(ativic32, "andestech,ativic32", ativic32_init_irq); diff --git a/drivers/net/ethernet/faraday/Kconfig b/drivers/net/ethernet/faraday/Kconfig index 040c7f163325..0fb8df656677 100644 --- a/drivers/net/ethernet/faraday/Kconfig +++ b/drivers/net/ethernet/faraday/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_FARADAY bool "Faraday devices" default y - depends on ARM + depends on ARM || NDS32 || COMPILE_TEST ---help--- If you have a network (Ethernet) card belonging to this class, say Y. @@ -18,7 +18,8 @@ if NET_VENDOR_FARADAY config FTMAC100 tristate "Faraday FTMAC100 10/100 Ethernet support" - depends on ARM + depends on ARM || NDS32 || COMPILE_TEST + depends on !64BIT || BROKEN select MII ---help--- This driver supports the FTMAC100 10/100 Ethernet controller @@ -27,7 +28,8 @@ config FTMAC100 config FTGMAC100 tristate "Faraday FTGMAC100 Gigabit Ethernet support" - depends on ARM + depends on ARM || NDS32 || COMPILE_TEST + depends on !64BIT || BROKEN select PHYLIB ---help--- This driver supports the FTGMAC100 Gigabit Ethernet controller diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 7f1f1fbcef9e..27bb893cf6b2 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -9,7 +9,7 @@ config VGA_CONSOLE depends on !4xx && !PPC_8xx && !SPARC && !M68K && !PARISC && !FRV && \ !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \ (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \ - !ARM64 && !ARC && !MICROBLAZE && !OPENRISC + !ARM64 && !ARC && !MICROBLAZE && !OPENRISC && !NDS32 default y help Saying Y here will allow you to use Linux in text mode through a |