summaryrefslogtreecommitdiff
path: root/cleopatre/linux-2.6.25.10-spc300/arch
diff options
context:
space:
mode:
authorsave2009-10-12 07:54:17 +0000
committersave2009-10-12 07:54:17 +0000
commit9f448f6d9d2b934b15210db18ebb3db75c180c57 (patch)
treedb36b6f44993943ab853f91b9871d2cb781dad59 /cleopatre/linux-2.6.25.10-spc300/arch
parent03d79d86ab0e3fab1bcb0292e4ea4115ab12eb08 (diff)
cleo/linux/drivers/watchdog: manage ARM watchdog
This watchdog is running by default on kernel part (on timer tick handler), but it can be switched on user mode by using spc300_wdt driver. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@6072 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cleopatre/linux-2.6.25.10-spc300/arch')
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/Makefile2
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-spk300g.c1
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-device-wdt.c131
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c39
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h2
-rw-r--r--cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c13
6 files changed, 171 insertions, 17 deletions
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/Makefile b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/Makefile
index 05ba3c9e64..c2b24b4499 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/Makefile
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/Makefile
@@ -2,6 +2,6 @@
# Makefile for the linux kernel.
#
-obj-y := spc300.o spc300-devices.o
+obj-y := spc300.o spc300-devices.o spc300-device-wdt.o
obj-$(CONFIG_MACH_ARIZONA) += board-arizona.o
obj-$(CONFIG_MACH_SPK300G) += board-spk300g.o
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-spk300g.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-spk300g.c
index 519b838b06..2378343e52 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-spk300g.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/board-spk300g.c
@@ -202,6 +202,7 @@ static void __init spk300g_init(void)
spc300_add_device_spictrl();
spc300_add_device_ethernet();
spc300_add_device_gpio();
+ spc300_add_device_wdt();
}
MACHINE_START(SPC300, "SPK300-G - ARM SPC300 based board")
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-device-wdt.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-device-wdt.c
new file mode 100644
index 0000000000..01bf76d159
--- /dev/null
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-device-wdt.c
@@ -0,0 +1,131 @@
+/*
+ * arch/arm/mach-spc300/spc300_device_wdt.c
+ *
+ * (C) Copyright 2009 SPiDCOM Technologies
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/arch/wdt.h>
+
+/** Global watchdog mode variable */
+uint32_t spc300_wdt_user_mode = 0;
+EXPORT_SYMBOL(spc300_wdt_user_mode);
+
+/**
+ * Start watchdog timer.
+ */
+void spc300_wdt_start(void)
+{
+ //Enable WDT with reset pulse = 32pclk and without interrupt management
+ WDT_CR_VA = WDT_BF(RPL, 4) | WDT_BF(RMOD, 0) | WDT_BF(EN, 1);
+}
+
+/**
+ * Stop watchdog timer.
+ */
+void spc300_wdt_stop(void)
+{
+ WDT_CR_VA = WDT_BF(EN, 0);
+}
+
+/**
+ * Switch watchdog between user and kernel mode.
+ *
+ * \param use_umode 1 to switch to user mode.
+ */
+void spc300_wdt_switch(int use_umode)
+{
+ if(use_umode)
+ spc300_wdt_user_mode = 1;
+ else
+ spc300_wdt_user_mode = 0;
+}
+
+/**
+ * Refresh watchdog timer.
+ */
+void spc300_wdt_refresh(void)
+{
+ WDT_CRR_VA = WDT_BF(CR, WDT_CR_VAL);
+}
+
+/**
+ * Change the watchdog time interval.
+ *
+ * \param new_time new time interval in seconds.
+ * \return range error.
+ */
+int spc300_wdt_settimeout(int new_time)
+{
+ uint32_t cnt_value, top;
+
+ //Timeout period = (2^(16+ TOP_reg)) / PCLK
+
+ if ((new_time < 0) || (new_time > WDT_MAX_TIME))
+ return -EINVAL;
+
+ cnt_value = new_time * PCLK;
+
+ for(top=15 ; top>0 ; top--)
+ {
+ if(cnt_value >= (1<<(top+16)))
+ {
+ WDT_TORR_VA = WDT_BFINS(TOP, top, WDT_TORR_VA);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Get the watchdog time interval.
+ *
+ * \return time interval.
+ */
+int spc300_wdt_gettimeout(void)
+{
+ uint32_t top;
+
+ //Timeout period = (2^(16+ TOP_reg)) / PCLK
+
+ top = WDT_BFEXT(TOP, WDT_TORR_VA);
+
+ return ((1 << (top+16)) / PCLK);
+}
+
+/**
+ * Restart watchdog timer.
+ *
+ * \param timeout time interval in seconds.
+ * \return if new timeout is done.
+ */
+int spc300_wdt_restart(int timeout)
+{
+ int result;
+
+ spc300_wdt_stop();
+ result = spc300_wdt_settimeout(timeout);
+ spc300_wdt_start();
+ return result;
+}
+
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
index c945e3fdec..c81979dc43 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.c
@@ -207,10 +207,15 @@ static struct gpio_chip spc300_gpio_chips[MAX_INTERNAL_GPIOS];
#ifdef CONFIG_SPC300_GPIO_USER_MODE
static struct resource spc300_gpio_resource[] = {
[0] = {
+ .start = ARM_GPIO_BASE,
+ .end = ARM_GPIO_BASE + SZ_1K,
+ .flags = IORESOURCE_IO
+ },
+ [1] = {
.start = INT_GPIO,
.end = INT_GPIO,
.flags = IORESOURCE_IRQ,
- },
+ }
};
static struct platform_device spc300_gpio_device = {
.name = "spc300gpio",
@@ -223,22 +228,28 @@ static struct platform_device spc300_gpio_device = {
/**
- * Watch-Dog Device Structure.
+ * Watchdog Device Structure.
*/
-static struct resource spc300_wd_ressource = {
- .start = ARM_WDT_BASE,
- .end = ARM_WDT_BASE + SZ_1K,
- .flags = IORESOURCE_MEM
+#ifdef CONFIG_SPC300_WATCHDOG
+static struct resource spc300_wd_resource[] = {
+ [0] = {
+ .start = ARM_WDT_BASE,
+ .end = ARM_WDT_BASE + SZ_1K,
+ .flags = IORESOURCE_IO
+ },
+ [1] = {
+ .start = INT_WDT,
+ .end = INT_WDT,
+ .flags = IORESOURCE_IRQ,
+ }
};
static struct platform_device spc300_wd_device = {
- .name = "spc300wd",
+ .name = "spc300wdt",
.id = 0,
- .dev = {
- .platform_data = NULL,
- },
- .num_resources = 1,
- .resource = &spc300_wd_ressource
+ .num_resources = ARRAY_SIZE(spc300_wd_resource),
+ .resource = spc300_wd_resource
};
+#endif
/**
@@ -594,9 +605,11 @@ void spc300_add_device_gpio(void)
/**
* Register Watch-Dog device.
*/
-void spc300_add_device_wd(void)
+void spc300_add_device_wdt(void)
{
+#ifdef CONFIG_SPC300_WATCHDOG
platform_device_register(&spc300_wd_device);
+#endif
}
/**
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
index ca8a8e257a..e5a0638268 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300-devices.h
@@ -70,7 +70,7 @@ void spc300_add_device_spidevs(struct spc300_flash_spi_dev *flash, struct spc300
/**
* Register Watch-Dog device.
*/
-void spc300_add_device_wd(void);
+void spc300_add_device_wdt(void);
/**
* Register GPDMA device.
diff --git a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
index 32e5a7e74f..9fb2ef2774 100644
--- a/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
+++ b/cleopatre/linux-2.6.25.10-spc300/arch/arm/mach-spc300/spc300.c
@@ -32,6 +32,7 @@
#include <asm/arch/hardware/timer.h>
#include <asm/arch/hardware/gic.h>
+#include <asm/arch/wdt.h>
#include <asm/arch/nvram.h>
@@ -73,7 +74,8 @@ static struct map_desc spc300_io_desc[] __initdata = {
{ IO_ADDRESS(ARM_UART2_BASE) , __phys_to_pfn(ARM_UART2_BASE) , SZ_1K , MT_DEVICE },
{ IO_ADDRESS(SPI_BASE) , __phys_to_pfn(SPI_BASE) , SZ_1K , MT_DEVICE },
{ IO_ADDRESS(MARIA_REGBANK_BASE) , __phys_to_pfn(MARIA_REGBANK_BASE) , SZ_4K , MT_DEVICE },
- { IO_ADDRESS(ARM_GPIO_BASE) , __phys_to_pfn(ARM_GPIO_BASE) , SZ_1K , MT_DEVICE }
+ { IO_ADDRESS(ARM_GPIO_BASE) , __phys_to_pfn(ARM_GPIO_BASE) , SZ_1K , MT_DEVICE },
+ { IO_ADDRESS(ARM_WDT_BASE) , __phys_to_pfn(ARM_WDT_BASE) , SZ_1K , MT_DEVICE }
};
static struct map_desc spc300_nvram_io_desc;
static struct map_desc spc300_plccode_io_desc;
@@ -157,7 +159,11 @@ void spc300_init_irq(void)
*/
static irqreturn_t spc300_timer_interrupt(int irq, void *dev_id)
{
- uint32_t dummy;
+ volatile uint32_t dummy;
+
+ //Refresh Watchdog if we used it on kernel mode
+ if(!spc300_wdt_user_mode)
+ spc300_wdt_refresh();
//Check if it's our timer
if(TIMER1INTSTAT_1_VA)
@@ -212,6 +218,9 @@ static void __init spc300_init_time(void)
{
uint32_t dummy;
+ //Restart Watchdog that is refreshed under timer interrupt
+ spc300_wdt_restart(2); //2 seconds for timeout
+
//Disable timer 1
TIMER1CONTROLREG_1_VA = ~(TIMER_ENABLE_MASK | TIMER_MODE_MASK) & TIMER_INTMASK_MASK;