diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/arch/mips/loongson1/common | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/arch/mips/loongson1/common')
-rw-r--r-- | kernel/arch/mips/loongson1/common/Makefile | 5 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/irq.c | 147 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/platform.c | 234 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/prom.c | 83 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/reset.c | 54 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/setup.c | 29 | ||||
-rw-r--r-- | kernel/arch/mips/loongson1/common/time.c | 226 |
7 files changed, 0 insertions, 778 deletions
diff --git a/kernel/arch/mips/loongson1/common/Makefile b/kernel/arch/mips/loongson1/common/Makefile deleted file mode 100644 index 723b4ce3b..000000000 --- a/kernel/arch/mips/loongson1/common/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for common code of loongson1 based machines. -# - -obj-y += time.o irq.o platform.o prom.o reset.o setup.o diff --git a/kernel/arch/mips/loongson1/common/irq.c b/kernel/arch/mips/loongson1/common/irq.c deleted file mode 100644 index 455a7704a..000000000 --- a/kernel/arch/mips/loongson1/common/irq.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - -#include <linux/interrupt.h> -#include <linux/irq.h> -#include <asm/irq_cpu.h> - -#include <loongson1.h> -#include <irq.h> - -#define LS1X_INTC_REG(n, x) \ - ((void __iomem *)KSEG1ADDR(LS1X_INTC_BASE + (n * 0x18) + (x))) - -#define LS1X_INTC_INTISR(n) LS1X_INTC_REG(n, 0x0) -#define LS1X_INTC_INTIEN(n) LS1X_INTC_REG(n, 0x4) -#define LS1X_INTC_INTSET(n) LS1X_INTC_REG(n, 0x8) -#define LS1X_INTC_INTCLR(n) LS1X_INTC_REG(n, 0xc) -#define LS1X_INTC_INTPOL(n) LS1X_INTC_REG(n, 0x10) -#define LS1X_INTC_INTEDGE(n) LS1X_INTC_REG(n, 0x14) - -static void ls1x_irq_ack(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) - | (1 << bit), LS1X_INTC_INTCLR(n)); -} - -static void ls1x_irq_mask(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - & ~(1 << bit), LS1X_INTC_INTIEN(n)); -} - -static void ls1x_irq_mask_ack(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - & ~(1 << bit), LS1X_INTC_INTIEN(n)); - __raw_writel(__raw_readl(LS1X_INTC_INTCLR(n)) - | (1 << bit), LS1X_INTC_INTCLR(n)); -} - -static void ls1x_irq_unmask(struct irq_data *d) -{ - unsigned int bit = (d->irq - LS1X_IRQ_BASE) & 0x1f; - unsigned int n = (d->irq - LS1X_IRQ_BASE) >> 5; - - __raw_writel(__raw_readl(LS1X_INTC_INTIEN(n)) - | (1 << bit), LS1X_INTC_INTIEN(n)); -} - -static struct irq_chip ls1x_irq_chip = { - .name = "LS1X-INTC", - .irq_ack = ls1x_irq_ack, - .irq_mask = ls1x_irq_mask, - .irq_mask_ack = ls1x_irq_mask_ack, - .irq_unmask = ls1x_irq_unmask, -}; - -static void ls1x_irq_dispatch(int n) -{ - u32 int_status, irq; - - /* Get pending sources, masked by current enables */ - int_status = __raw_readl(LS1X_INTC_INTISR(n)) & - __raw_readl(LS1X_INTC_INTIEN(n)); - - if (int_status) { - irq = LS1X_IRQ(n, __ffs(int_status)); - do_IRQ(irq); - } -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned int pending; - - pending = read_c0_cause() & read_c0_status() & ST0_IM; - - if (pending & CAUSEF_IP7) - do_IRQ(TIMER_IRQ); - else if (pending & CAUSEF_IP2) - ls1x_irq_dispatch(0); /* INT0 */ - else if (pending & CAUSEF_IP3) - ls1x_irq_dispatch(1); /* INT1 */ - else if (pending & CAUSEF_IP4) - ls1x_irq_dispatch(2); /* INT2 */ - else if (pending & CAUSEF_IP5) - ls1x_irq_dispatch(3); /* INT3 */ - else if (pending & CAUSEF_IP6) - ls1x_irq_dispatch(4); /* INT4 */ - else - spurious_interrupt(); - -} - -struct irqaction cascade_irqaction = { - .handler = no_action, - .name = "cascade", - .flags = IRQF_NO_THREAD, -}; - -static void __init ls1x_irq_init(int base) -{ - int n; - - /* Disable interrupts and clear pending, - * setup all IRQs as high level triggered - */ - for (n = 0; n < 4; n++) { - __raw_writel(0x0, LS1X_INTC_INTIEN(n)); - __raw_writel(0xffffffff, LS1X_INTC_INTCLR(n)); - __raw_writel(0xffffffff, LS1X_INTC_INTPOL(n)); - /* set DMA0, DMA1 and DMA2 to edge trigger */ - __raw_writel(n ? 0x0 : 0xe000, LS1X_INTC_INTEDGE(n)); - } - - - for (n = base; n < LS1X_IRQS; n++) { - irq_set_chip_and_handler(n, &ls1x_irq_chip, - handle_level_irq); - } - - setup_irq(INT0_IRQ, &cascade_irqaction); - setup_irq(INT1_IRQ, &cascade_irqaction); - setup_irq(INT2_IRQ, &cascade_irqaction); - setup_irq(INT3_IRQ, &cascade_irqaction); -} - -void __init arch_init_irq(void) -{ - mips_cpu_irq_init(); - ls1x_irq_init(LS1X_IRQ_BASE); -} diff --git a/kernel/arch/mips/loongson1/common/platform.c b/kernel/arch/mips/loongson1/common/platform.c deleted file mode 100644 index ddf1d4cbf..000000000 --- a/kernel/arch/mips/loongson1/common/platform.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - -#include <linux/clk.h> -#include <linux/dma-mapping.h> -#include <linux/err.h> -#include <linux/phy.h> -#include <linux/serial_8250.h> -#include <linux/stmmac.h> -#include <linux/usb/ehci_pdriver.h> -#include <asm-generic/sizes.h> - -#include <cpufreq.h> -#include <loongson1.h> - -/* 8250/16550 compatible UART */ -#define LS1X_UART(_id) \ - { \ - .mapbase = LS1X_UART ## _id ## _BASE, \ - .irq = LS1X_UART ## _id ## _IRQ, \ - .iotype = UPIO_MEM, \ - .flags = UPF_IOREMAP | UPF_FIXED_TYPE, \ - .type = PORT_16550A, \ - } - -static struct plat_serial8250_port ls1x_serial8250_pdata[] = { - LS1X_UART(0), - LS1X_UART(1), - LS1X_UART(2), - LS1X_UART(3), - {}, -}; - -struct platform_device ls1x_uart_pdev = { - .name = "serial8250", - .id = PLAT8250_DEV_PLATFORM, - .dev = { - .platform_data = ls1x_serial8250_pdata, - }, -}; - -void __init ls1x_serial_setup(struct platform_device *pdev) -{ - struct clk *clk; - struct plat_serial8250_port *p; - - clk = clk_get(&pdev->dev, pdev->name); - if (IS_ERR(clk)) { - pr_err("unable to get %s clock, err=%ld", - pdev->name, PTR_ERR(clk)); - return; - } - clk_prepare_enable(clk); - - for (p = pdev->dev.platform_data; p->flags != 0; ++p) - p->uartclk = clk_get_rate(clk); -} - -/* CPUFreq */ -static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = { - .clk_name = "cpu_clk", - .osc_clk_name = "osc_33m_clk", - .max_freq = 266 * 1000, - .min_freq = 33 * 1000, -}; - -struct platform_device ls1x_cpufreq_pdev = { - .name = "ls1x-cpufreq", - .dev = { - .platform_data = &ls1x_cpufreq_pdata, - }, -}; - -/* Synopsys Ethernet GMAC */ -static struct stmmac_mdio_bus_data ls1x_mdio_bus_data = { - .phy_mask = 0, -}; - -static struct stmmac_dma_cfg ls1x_eth_dma_cfg = { - .pbl = 1, -}; - -int ls1x_eth_mux_init(struct platform_device *pdev, void *priv) -{ - struct plat_stmmacenet_data *plat_dat = NULL; - u32 val; - - val = __raw_readl(LS1X_MUX_CTRL1); - - plat_dat = dev_get_platdata(&pdev->dev); - if (plat_dat->bus_id) { - __raw_writel(__raw_readl(LS1X_MUX_CTRL0) | GMAC1_USE_UART1 | - GMAC1_USE_UART0, LS1X_MUX_CTRL0); - switch (plat_dat->interface) { - case PHY_INTERFACE_MODE_RGMII: - val &= ~(GMAC1_USE_TXCLK | GMAC1_USE_PWM23); - break; - case PHY_INTERFACE_MODE_MII: - val |= (GMAC1_USE_TXCLK | GMAC1_USE_PWM23); - break; - default: - pr_err("unsupported mii mode %d\n", - plat_dat->interface); - return -ENOTSUPP; - } - val &= ~GMAC1_SHUT; - } else { - switch (plat_dat->interface) { - case PHY_INTERFACE_MODE_RGMII: - val &= ~(GMAC0_USE_TXCLK | GMAC0_USE_PWM01); - break; - case PHY_INTERFACE_MODE_MII: - val |= (GMAC0_USE_TXCLK | GMAC0_USE_PWM01); - break; - default: - pr_err("unsupported mii mode %d\n", - plat_dat->interface); - return -ENOTSUPP; - } - val &= ~GMAC0_SHUT; - } - __raw_writel(val, LS1X_MUX_CTRL1); - - return 0; -} - -static struct plat_stmmacenet_data ls1x_eth0_pdata = { - .bus_id = 0, - .phy_addr = -1, - .interface = PHY_INTERFACE_MODE_MII, - .mdio_bus_data = &ls1x_mdio_bus_data, - .dma_cfg = &ls1x_eth_dma_cfg, - .has_gmac = 1, - .tx_coe = 1, - .init = ls1x_eth_mux_init, -}; - -static struct resource ls1x_eth0_resources[] = { - [0] = { - .start = LS1X_GMAC0_BASE, - .end = LS1X_GMAC0_BASE + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .name = "macirq", - .start = LS1X_GMAC0_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device ls1x_eth0_pdev = { - .name = "stmmaceth", - .id = 0, - .num_resources = ARRAY_SIZE(ls1x_eth0_resources), - .resource = ls1x_eth0_resources, - .dev = { - .platform_data = &ls1x_eth0_pdata, - }, -}; - -static struct plat_stmmacenet_data ls1x_eth1_pdata = { - .bus_id = 1, - .phy_addr = -1, - .interface = PHY_INTERFACE_MODE_MII, - .mdio_bus_data = &ls1x_mdio_bus_data, - .dma_cfg = &ls1x_eth_dma_cfg, - .has_gmac = 1, - .tx_coe = 1, - .init = ls1x_eth_mux_init, -}; - -static struct resource ls1x_eth1_resources[] = { - [0] = { - .start = LS1X_GMAC1_BASE, - .end = LS1X_GMAC1_BASE + SZ_64K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .name = "macirq", - .start = LS1X_GMAC1_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -struct platform_device ls1x_eth1_pdev = { - .name = "stmmaceth", - .id = 1, - .num_resources = ARRAY_SIZE(ls1x_eth1_resources), - .resource = ls1x_eth1_resources, - .dev = { - .platform_data = &ls1x_eth1_pdata, - }, -}; - -/* USB EHCI */ -static u64 ls1x_ehci_dmamask = DMA_BIT_MASK(32); - -static struct resource ls1x_ehci_resources[] = { - [0] = { - .start = LS1X_EHCI_BASE, - .end = LS1X_EHCI_BASE + SZ_32K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = LS1X_EHCI_IRQ, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct usb_ehci_pdata ls1x_ehci_pdata = { -}; - -struct platform_device ls1x_ehci_pdev = { - .name = "ehci-platform", - .id = -1, - .num_resources = ARRAY_SIZE(ls1x_ehci_resources), - .resource = ls1x_ehci_resources, - .dev = { - .dma_mask = &ls1x_ehci_dmamask, - .platform_data = &ls1x_ehci_pdata, - }, -}; - -/* Real Time Clock */ -struct platform_device ls1x_rtc_pdev = { - .name = "ls1x-rtc", - .id = -1, -}; diff --git a/kernel/arch/mips/loongson1/common/prom.c b/kernel/arch/mips/loongson1/common/prom.c deleted file mode 100644 index 68600980e..000000000 --- a/kernel/arch/mips/loongson1/common/prom.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> - * - * Modified from arch/mips/pnx833x/common/prom.c. - * - * 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. - */ - -#include <linux/serial_reg.h> -#include <asm/bootinfo.h> - -#include <loongson1.h> -#include <prom.h> - -int prom_argc; -char **prom_argv, **prom_envp; -unsigned long memsize, highmemsize; - -char *prom_getenv(char *envname) -{ - char **env = prom_envp; - int i; - - i = strlen(envname); - - while (*env) { - if (strncmp(envname, *env, i) == 0 && *(*env + i) == '=') - return *env + i + 1; - env++; - } - - return 0; -} - -static inline unsigned long env_or_default(char *env, unsigned long dfl) -{ - char *str = prom_getenv(env); - return str ? simple_strtol(str, 0, 0) : dfl; -} - -void __init prom_init_cmdline(void) -{ - char *c = &(arcs_cmdline[0]); - int i; - - for (i = 1; i < prom_argc; i++) { - strcpy(c, prom_argv[i]); - c += strlen(prom_argv[i]); - if (i < prom_argc - 1) - *c++ = ' '; - } - *c = 0; -} - -void __init prom_init(void) -{ - void __iomem *uart_base; - prom_argc = fw_arg0; - prom_argv = (char **)fw_arg1; - prom_envp = (char **)fw_arg2; - - prom_init_cmdline(); - - memsize = env_or_default("memsize", DEFAULT_MEMSIZE); - highmemsize = env_or_default("highmemsize", 0x0); - - if (strstr(arcs_cmdline, "console=ttyS3")) - uart_base = ioremap_nocache(LS1X_UART3_BASE, 0x0f); - else if (strstr(arcs_cmdline, "console=ttyS2")) - uart_base = ioremap_nocache(LS1X_UART2_BASE, 0x0f); - else if (strstr(arcs_cmdline, "console=ttyS1")) - uart_base = ioremap_nocache(LS1X_UART1_BASE, 0x0f); - else - uart_base = ioremap_nocache(LS1X_UART0_BASE, 0x0f); - setup_8250_early_printk_port((unsigned long)uart_base, 0, 0); -} - -void __init prom_free_prom_memory(void) -{ -} diff --git a/kernel/arch/mips/loongson1/common/reset.c b/kernel/arch/mips/loongson1/common/reset.c deleted file mode 100644 index c41e4ca56..000000000 --- a/kernel/arch/mips/loongson1/common/reset.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - -#include <linux/io.h> -#include <linux/pm.h> -#include <asm/idle.h> -#include <asm/reboot.h> - -#include <loongson1.h> - -static void __iomem *wdt_base; - -static void ls1x_halt(void) -{ - while (1) { - if (cpu_wait) - cpu_wait(); - } -} - -static void ls1x_restart(char *command) -{ - __raw_writel(0x1, wdt_base + WDT_EN); - __raw_writel(0x1, wdt_base + WDT_TIMER); - __raw_writel(0x1, wdt_base + WDT_SET); - - ls1x_halt(); -} - -static void ls1x_power_off(void) -{ - ls1x_halt(); -} - -static int __init ls1x_reboot_setup(void) -{ - wdt_base = ioremap_nocache(LS1X_WDT_BASE, 0x0f); - if (!wdt_base) - panic("Failed to remap watchdog registers"); - - _machine_restart = ls1x_restart; - _machine_halt = ls1x_halt; - pm_power_off = ls1x_power_off; - - return 0; -} - -arch_initcall(ls1x_reboot_setup); diff --git a/kernel/arch/mips/loongson1/common/setup.c b/kernel/arch/mips/loongson1/common/setup.c deleted file mode 100644 index 62f41afee..000000000 --- a/kernel/arch/mips/loongson1/common/setup.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - -#include <asm/bootinfo.h> - -#include <prom.h> - -void __init plat_mem_setup(void) -{ - add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM); -} - -const char *get_system_type(void) -{ - unsigned int processor_id = (¤t_cpu_data)->processor_id; - - switch (processor_id & PRID_REV_MASK) { - case PRID_REV_LOONGSON1B: - return "LOONGSON LS1B"; - default: - return "LOONGSON (unknown)"; - } -} diff --git a/kernel/arch/mips/loongson1/common/time.c b/kernel/arch/mips/loongson1/common/time.c deleted file mode 100644 index df0f850d6..000000000 --- a/kernel/arch/mips/loongson1/common/time.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2014 Zhang, Keguang <keguang.zhang@gmail.com> - * - * 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. - */ - -#include <linux/clk.h> -#include <linux/interrupt.h> -#include <asm/time.h> - -#include <loongson1.h> -#include <platform.h> - -#ifdef CONFIG_CEVT_CSRC_LS1X - -#if defined(CONFIG_TIMER_USE_PWM1) -#define LS1X_TIMER_BASE LS1X_PWM1_BASE -#define LS1X_TIMER_IRQ LS1X_PWM1_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM2) -#define LS1X_TIMER_BASE LS1X_PWM2_BASE -#define LS1X_TIMER_IRQ LS1X_PWM2_IRQ - -#elif defined(CONFIG_TIMER_USE_PWM3) -#define LS1X_TIMER_BASE LS1X_PWM3_BASE -#define LS1X_TIMER_IRQ LS1X_PWM3_IRQ - -#else -#define LS1X_TIMER_BASE LS1X_PWM0_BASE -#define LS1X_TIMER_IRQ LS1X_PWM0_IRQ -#endif - -DEFINE_RAW_SPINLOCK(ls1x_timer_lock); - -static void __iomem *timer_base; -static uint32_t ls1x_jiffies_per_tick; - -static inline void ls1x_pwmtimer_set_period(uint32_t period) -{ - __raw_writel(period, timer_base + PWM_HRC); - __raw_writel(period, timer_base + PWM_LRC); -} - -static inline void ls1x_pwmtimer_restart(void) -{ - __raw_writel(0x0, timer_base + PWM_CNT); - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); -} - -void __init ls1x_pwmtimer_init(void) -{ - timer_base = ioremap(LS1X_TIMER_BASE, 0xf); - if (!timer_base) - panic("Failed to remap timer registers"); - - ls1x_jiffies_per_tick = DIV_ROUND_CLOSEST(mips_hpt_frequency, HZ); - - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); -} - -static cycle_t ls1x_clocksource_read(struct clocksource *cs) -{ - unsigned long flags; - int count; - u32 jifs; - static int old_count; - static u32 old_jifs; - - raw_spin_lock_irqsave(&ls1x_timer_lock, flags); - /* - * Although our caller may have the read side of xtime_lock, - * this is now a seqlock, and we are cheating in this routine - * by having side effects on state that we cannot undo if - * there is a collision on the seqlock and our caller has to - * retry. (Namely, old_jifs and old_count.) So we must treat - * jiffies as volatile despite the lock. We read jiffies - * before latching the timer count to guarantee that although - * the jiffies value might be older than the count (that is, - * the counter may underflow between the last point where - * jiffies was incremented and the point where we latch the - * count), it cannot be newer. - */ - jifs = jiffies; - /* read the count */ - count = __raw_readl(timer_base + PWM_CNT); - - /* - * It's possible for count to appear to go the wrong way for this - * reason: - * - * The timer counter underflows, but we haven't handled the resulting - * interrupt and incremented jiffies yet. - * - * Previous attempts to handle these cases intelligently were buggy, so - * we just do the simple thing now. - */ - if (count < old_count && jifs == old_jifs) - count = old_count; - - old_count = count; - old_jifs = jifs; - - raw_spin_unlock_irqrestore(&ls1x_timer_lock, flags); - - return (cycle_t) (jifs * ls1x_jiffies_per_tick) + count; -} - -static struct clocksource ls1x_clocksource = { - .name = "ls1x-pwmtimer", - .read = ls1x_clocksource_read, - .mask = CLOCKSOURCE_MASK(24), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static irqreturn_t ls1x_clockevent_isr(int irq, void *devid) -{ - struct clock_event_device *cd = devid; - - ls1x_pwmtimer_restart(); - cd->event_handler(cd); - - return IRQ_HANDLED; -} - -static void ls1x_clockevent_set_mode(enum clock_event_mode mode, - struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - switch (mode) { - case CLOCK_EVT_MODE_PERIODIC: - ls1x_pwmtimer_set_period(ls1x_jiffies_per_tick); - ls1x_pwmtimer_restart(); - case CLOCK_EVT_MODE_RESUME: - __raw_writel(INT_EN | CNT_EN, timer_base + PWM_CTRL); - break; - case CLOCK_EVT_MODE_ONESHOT: - case CLOCK_EVT_MODE_SHUTDOWN: - __raw_writel(__raw_readl(timer_base + PWM_CTRL) & ~CNT_EN, - timer_base + PWM_CTRL); - break; - default: - break; - } - raw_spin_unlock(&ls1x_timer_lock); -} - -static int ls1x_clockevent_set_next(unsigned long evt, - struct clock_event_device *cd) -{ - raw_spin_lock(&ls1x_timer_lock); - ls1x_pwmtimer_set_period(evt); - ls1x_pwmtimer_restart(); - raw_spin_unlock(&ls1x_timer_lock); - - return 0; -} - -static struct clock_event_device ls1x_clockevent = { - .name = "ls1x-pwmtimer", - .features = CLOCK_EVT_FEAT_PERIODIC, - .rating = 300, - .irq = LS1X_TIMER_IRQ, - .set_next_event = ls1x_clockevent_set_next, - .set_mode = ls1x_clockevent_set_mode, -}; - -static struct irqaction ls1x_pwmtimer_irqaction = { - .name = "ls1x-pwmtimer", - .handler = ls1x_clockevent_isr, - .dev_id = &ls1x_clockevent, - .flags = IRQF_PERCPU | IRQF_TIMER, -}; - -static void __init ls1x_time_init(void) -{ - struct clock_event_device *cd = &ls1x_clockevent; - int ret; - - if (!mips_hpt_frequency) - panic("Invalid timer clock rate"); - - ls1x_pwmtimer_init(); - - clockevent_set_clock(cd, mips_hpt_frequency); - cd->max_delta_ns = clockevent_delta2ns(0xffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x000300, cd); - cd->cpumask = cpumask_of(smp_processor_id()); - clockevents_register_device(cd); - - ls1x_clocksource.rating = 200 + mips_hpt_frequency / 10000000; - ret = clocksource_register_hz(&ls1x_clocksource, mips_hpt_frequency); - if (ret) - panic(KERN_ERR "Failed to register clocksource: %d\n", ret); - - setup_irq(LS1X_TIMER_IRQ, &ls1x_pwmtimer_irqaction); -} -#endif /* CONFIG_CEVT_CSRC_LS1X */ - -void __init plat_time_init(void) -{ - struct clk *clk = NULL; - - /* initialize LS1X clocks */ - ls1x_clk_init(); - -#ifdef CONFIG_CEVT_CSRC_LS1X - /* setup LS1X PWM timer */ - clk = clk_get(NULL, "ls1x_pwmtimer"); - if (IS_ERR(clk)) - panic("unable to get timer clock, err=%ld", PTR_ERR(clk)); - - mips_hpt_frequency = clk_get_rate(clk); - ls1x_time_init(); -#else - /* setup mips r4k timer */ - clk = clk_get(NULL, "cpu_clk"); - if (IS_ERR(clk)) - panic("unable to get cpu clock, err=%ld", PTR_ERR(clk)); - - mips_hpt_frequency = clk_get_rate(clk) / 2; -#endif /* CONFIG_CEVT_CSRC_LS1X */ -} |