From 227a20fe31c6a03795a202f95af95fb371951963 Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Wed, 16 Jul 2014 09:40:30 +0200 Subject: consistently use the same bitops.h file We have many variants of the same bitops.h file. Consistently use the same file for all architectures which completely use the generic bitops versions. Some architectures had static inline versions of functions identically to the generic versions, these are removed and the generic versions are used directly now. Also several architectures depend on the generic find_*_bit functions but didn't have the GENERIC_FIND_NEXT_BIT Kconfig option selected. This is added where needed. Signed-off-by: Sascha Hauer --- arch/mips/include/asm/bitops.h | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'arch/mips') diff --git a/arch/mips/include/asm/bitops.h b/arch/mips/include/asm/bitops.h index ebf8cf04d3..e77ab83202 100644 --- a/arch/mips/include/asm/bitops.h +++ b/arch/mips/include/asm/bitops.h @@ -12,20 +12,24 @@ * */ -/** - * @file - * @brief mips bit operations - * - * This file is required only to make all sources happy including - * 'linux/bitops.h' - */ - -#ifndef _ASM_MIPS_BITOPS_H_ -#define _ASM_MIPS_BITOPS_H_ +#ifndef _ASM_BITOPS_H_ +#define _ASM_BITOPS_H_ #include #include #include #include +#include +#include +#include +#include +#include + +#define set_bit(x, y) __set_bit(x, y) +#define clear_bit(x, y) __clear_bit(x, y) +#define change_bit(x, y) __change_bit(x, y) +#define test_and_set_bit(x, y) __test_and_set_bit(x, y) +#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y) +#define test_and_change_bit(x, y) __test_and_change_bit(x, y) -#endif /* _ASM_MIPS_BITOPS_H_ */ +#endif /* _ASM_BITOPS_H_ */ -- cgit v1.2.3 From b549a26fc3088b85602caf412bebd16f9e3e8ae9 Mon Sep 17 00:00:00 2001 From: Antony Pavlov Date: Thu, 31 Jul 2014 19:11:31 +0400 Subject: watchdog: add minimal jz4740 driver Also move reset_cpu() for jz4755 SoC from platform code into the new driver code. At the moment mach-xburst lacks clk support so jz4740 watchdog driver looks like a template. We can improve jz4740 watchdog driver later after adding clk support. Signed-off-by: Antony Pavlov Signed-off-by: Sascha Hauer --- arch/mips/dts/jz4755.dtsi | 5 ++ arch/mips/mach-xburst/Kconfig | 2 + arch/mips/mach-xburst/include/mach/jz4750d_regs.h | 22 ----- arch/mips/mach-xburst/reset-jz4750.c | 18 ---- drivers/watchdog/Kconfig | 7 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/jz4740.c | 102 ++++++++++++++++++++++ 7 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 drivers/watchdog/jz4740.c (limited to 'arch/mips') diff --git a/arch/mips/dts/jz4755.dtsi b/arch/mips/dts/jz4755.dtsi index 0e655b65a1..718463548b 100644 --- a/arch/mips/dts/jz4755.dtsi +++ b/arch/mips/dts/jz4755.dtsi @@ -8,6 +8,11 @@ #size-cells = <1>; ranges; + wdt: wdt@b0002000 { + compatible = "ingenic,jz4740-wdt"; + reg = <0xb0002000 0x10>; + }; + serial0: serial@b0030000 { compatible = "ingenic,jz4740-uart"; reg = <0xb0030000 0x20>; diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig index 706d59249b..f7b8470cb8 100644 --- a/arch/mips/mach-xburst/Kconfig +++ b/arch/mips/mach-xburst/Kconfig @@ -6,6 +6,8 @@ config ARCH_TEXT_BASE config CPU_JZ4755 bool + select WATCHDOG + select WATCHDOG_JZ4740 choice prompt "Board type" diff --git a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h index 7a3daadb18..396c823a1f 100644 --- a/arch/mips/mach-xburst/include/mach/jz4750d_regs.h +++ b/arch/mips/mach-xburst/include/mach/jz4750d_regs.h @@ -58,28 +58,6 @@ #define TCU_OSTCSR_RTC_EN (1 << 1) /* select rtcclk as the timer clock input */ #define TCU_OSTCSR_PCK_EN (1 << 0) /* select pclk as the timer clock input */ -/************************************************************************* - * WDT (WatchDog Timer) - *************************************************************************/ -#define WDT_TDR (WDT_BASE + 0x00) -#define WDT_TCER (WDT_BASE + 0x04) -#define WDT_TCNT (WDT_BASE + 0x08) -#define WDT_TCSR (WDT_BASE + 0x0c) - -#define WDT_TCSR_PRESCALE_BIT 3 -#define WDT_TCSR_PRESCALE_MASK (0x7 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE1 (0x0 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE4 (0x1 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE16 (0x2 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE64 (0x3 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE256 (0x4 << WDT_TCSR_PRESCALE_BIT) - #define WDT_TCSR_PRESCALE1024 (0x5 << WDT_TCSR_PRESCALE_BIT) -#define WDT_TCSR_EXT_EN (1 << 2) -#define WDT_TCSR_RTC_EN (1 << 1) -#define WDT_TCSR_PCK_EN (1 << 0) - -#define WDT_TCER_TCEN (1 << 0) - /************************************************************************* * RTC *************************************************************************/ diff --git a/arch/mips/mach-xburst/reset-jz4750.c b/arch/mips/mach-xburst/reset-jz4750.c index 8f33672280..25830f130e 100644 --- a/arch/mips/mach-xburst/reset-jz4750.c +++ b/arch/mips/mach-xburst/reset-jz4750.c @@ -24,8 +24,6 @@ #include #include -#define JZ_EXTAL 24000000 - static void __noreturn jz4750d_halt(void) { while (1) { @@ -39,22 +37,6 @@ static void __noreturn jz4750d_halt(void) unreachable(); } -void __noreturn reset_cpu(ulong addr) -{ - __raw_writew(WDT_TCSR_PRESCALE4 | WDT_TCSR_EXT_EN, (u16 *)WDT_TCSR); - __raw_writew(0, (u16 *)WDT_TCNT); - - /* reset after 4ms */ - __raw_writew(JZ_EXTAL / 1000, (u16 *)WDT_TDR); - /* enable wdt clock */ - __raw_writel(TCU_TSCR_WDTSC, (u32 *)TCU_TSCR); - /* start wdt */ - __raw_writeb(WDT_TCER_TCEN, (u8 *)WDT_TCER); - - unreachable(); -} -EXPORT_SYMBOL(reset_cpu); - void __noreturn poweroff() { u32 ctrl; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2e2900c10f..7f7b02e306 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -21,4 +21,11 @@ config WATCHDOG_IMX depends on ARCH_IMX help Add support for watchdog found on Freescale i.MX SoCs. + +config WATCHDOG_JZ4740 + bool "Ingenic jz4740 SoC hardware watchdog" + depends on MACH_MIPS_XBURST + help + Hardware driver for the built-in watchdog timer on Ingenic jz4740 SoCs. + endif diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index f522b88708..865fc477b1 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_WATCHDOG) += wd_core.o obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o +obj-$(CONFIG_WATCHDOG_JZ4740) += jz4740.o obj-$(CONFIG_WATCHDOG_IMX_RESET_SOURCE) += imxwd.o diff --git a/drivers/watchdog/jz4740.c b/drivers/watchdog/jz4740.c new file mode 100644 index 0000000000..8ac51e060a --- /dev/null +++ b/drivers/watchdog/jz4740.c @@ -0,0 +1,102 @@ +/* + * JZ4740 Watchdog driver + * + * Copyright (C) 2014 Antony Pavlov + * + * Based on jz4740_wdt.c from linux-3.15. + * + * Copyright (C) 2010, Paul Cercueil + * + * 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 +#include +#include + +#define JZ_REG_WDT_TIMER_DATA 0x0 +#define JZ_REG_WDT_COUNTER_ENABLE 0x4 +#define JZ_REG_WDT_TIMER_COUNTER 0x8 +#define JZ_REG_WDT_TIMER_CONTROL 0xC + +#define JZ_WDT_CLOCK_PCLK 0x1 +#define JZ_WDT_CLOCK_RTC 0x2 +#define JZ_WDT_CLOCK_EXT 0x4 + +#define JZ_WDT_CLOCK_DIV_SHIFT 3 + +#define JZ_WDT_CLOCK_DIV_1 (0 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_4 (1 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_16 (2 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_64 (3 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_256 (4 << JZ_WDT_CLOCK_DIV_SHIFT) +#define JZ_WDT_CLOCK_DIV_1024 (5 << JZ_WDT_CLOCK_DIV_SHIFT) + +#define JZ_EXTAL 24000000 + +struct jz4740_wdt_drvdata { + void __iomem *base; +}; + +static struct jz4740_wdt_drvdata *reset_wd; + +void __noreturn reset_cpu(unsigned long addr) +{ + if (reset_wd) { + void __iomem *base = reset_wd->base; + + writew(JZ_WDT_CLOCK_DIV_4 | JZ_WDT_CLOCK_EXT, + base + JZ_REG_WDT_TIMER_CONTROL); + writew(0, base + JZ_REG_WDT_TIMER_COUNTER); + + /* reset after 4ms */ + writew(JZ_EXTAL / 1000, base + JZ_REG_WDT_TIMER_DATA); + + /* start wdt */ + writeb(0x1, base + JZ_REG_WDT_COUNTER_ENABLE); + + mdelay(1000); + } else + pr_err("%s: can't reset cpu\n", __func__); + + hang(); +} +EXPORT_SYMBOL(reset_cpu); + +static int jz4740_wdt_probe(struct device_d *dev) +{ + struct jz4740_wdt_drvdata *priv; + + priv = xzalloc(sizeof(struct jz4740_wdt_drvdata)); + priv->base = dev_request_mem_region(dev, 0); + if (!priv->base) { + dev_err(dev, "could not get memory region\n"); + return -ENODEV; + } + + if (!reset_wd) + reset_wd = priv; + + dev->priv = priv; + + return 0; +} + +static __maybe_unused struct of_device_id jz4740_wdt_dt_ids[] = { + { + .compatible = "ingenic,jz4740-wdt", + }, { + /* sentinel */ + } +}; + +static struct driver_d jz4740_wdt_driver = { + .name = "jz4740-wdt", + .probe = jz4740_wdt_probe, + .of_compatible = DRV_OF_COMPAT(jz4740_wdt_dt_ids), +}; +device_platform_driver(jz4740_wdt_driver); -- cgit v1.2.3