浏览代码

Merge git://git.marvell.com/orion into devel

Russell King 16 年之前
父节点
当前提交
cf281a99b6

+ 16 - 4
arch/arm/configs/kirkwood_defconfig

@@ -180,6 +180,7 @@ CONFIG_MACH_DB88F6281_BP=y
 CONFIG_MACH_RD88F6192_NAS=y
 CONFIG_MACH_RD88F6192_NAS=y
 CONFIG_MACH_RD88F6281=y
 CONFIG_MACH_RD88F6281=y
 CONFIG_MACH_SHEEVAPLUG=y
 CONFIG_MACH_SHEEVAPLUG=y
+CONFIG_MACH_TS219=y
 CONFIG_PLAT_ORION=y
 CONFIG_PLAT_ORION=y
 
 
 #
 #
@@ -852,13 +853,20 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_EVBUG is not set
 # CONFIG_INPUT_EVBUG is not set
 
 
 #
 #
 # Input Device Drivers
 # Input Device Drivers
 #
 #
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TABLET is not set
 # CONFIG_INPUT_TABLET is not set
@@ -868,7 +876,11 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 #
 #
 # Hardware I/O ports
 # Hardware I/O ports
 #
 #
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 # CONFIG_GAMEPORT is not set
 # CONFIG_GAMEPORT is not set
 
 
 #
 #
@@ -1271,7 +1283,7 @@ CONFIG_RTC_INTF_DEV=y
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_S35390A is not set
+CONFIG_RTC_DRV_S35390A=y
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
 
 

+ 6 - 0
arch/arm/mach-kirkwood/Kconfig

@@ -26,6 +26,12 @@ config MACH_SHEEVAPLUG
 	  Say 'Y' here if you want your kernel to support the
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell SheevaPlug Reference Board.
 	  Marvell SheevaPlug Reference Board.
 
 
+config MACH_TS219
+	bool "QNAP TS-119 and TS-219 Turbo NAS"
+	help
+	  Say 'Y' here if you want your kernel to support the
+	  QNAP TS-119 and TS-219 Turbo NAS devices.
+
 endmenu
 endmenu
 
 
 endif
 endif

+ 1 - 0
arch/arm/mach-kirkwood/Makefile

@@ -4,3 +4,4 @@ obj-$(CONFIG_MACH_DB88F6281_BP)		+= db88f6281-bp-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6192_NAS)	+= rd88f6192-nas-setup.o
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
 obj-$(CONFIG_MACH_RD88F6281)		+= rd88f6281-setup.o
 obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
 obj-$(CONFIG_MACH_SHEEVAPLUG)		+= sheevaplug-setup.o
+obj-$(CONFIG_MACH_TS219)		+= ts219-setup.o

+ 40 - 0
arch/arm/mach-kirkwood/common.c

@@ -14,6 +14,7 @@
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
 #include <linux/mbus.h>
 #include <linux/mbus.h>
 #include <linux/mv643xx_eth.h>
 #include <linux/mv643xx_eth.h>
+#include <linux/mv643xx_i2c.h>
 #include <linux/ata_platform.h>
 #include <linux/ata_platform.h>
 #include <linux/spi/orion_spi.h>
 #include <linux/spi/orion_spi.h>
 #include <net/dsa.h>
 #include <net/dsa.h>
@@ -370,6 +371,45 @@ void __init kirkwood_spi_init()
 }
 }
 
 
 
 
+/*****************************************************************************
+ * I2C
+ ****************************************************************************/
+static struct mv64xxx_i2c_pdata kirkwood_i2c_pdata = {
+	.freq_m		= 8, /* assumes 166 MHz TCLK */
+	.freq_n		= 3,
+	.timeout	= 1000, /* Default timeout of 1 second */
+};
+
+static struct resource kirkwood_i2c_resources[] = {
+	{
+		.name	= "i2c",
+		.start	= I2C_PHYS_BASE,
+		.end	= I2C_PHYS_BASE + 0x1f,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.name	= "i2c",
+		.start	= IRQ_KIRKWOOD_TWSI,
+		.end	= IRQ_KIRKWOOD_TWSI,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device kirkwood_i2c = {
+	.name		= MV64XXX_I2C_CTLR_NAME,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(kirkwood_i2c_resources),
+	.resource	= kirkwood_i2c_resources,
+	.dev		= {
+		.platform_data	= &kirkwood_i2c_pdata,
+	},
+};
+
+void __init kirkwood_i2c_init(void)
+{
+	platform_device_register(&kirkwood_i2c);
+}
+
+
 /*****************************************************************************
 /*****************************************************************************
  * UART0
  * UART0
  ****************************************************************************/
  ****************************************************************************/

+ 2 - 0
arch/arm/mach-kirkwood/common.h

@@ -37,9 +37,11 @@ void kirkwood_pcie_init(void);
 void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
 void kirkwood_sata_init(struct mv_sata_platform_data *sata_data);
 void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
 void kirkwood_sdio_init(struct mvsdio_platform_data *mvsdio_data);
 void kirkwood_spi_init(void);
 void kirkwood_spi_init(void);
+void kirkwood_i2c_init(void);
 void kirkwood_uart0_init(void);
 void kirkwood_uart0_init(void);
 void kirkwood_uart1_init(void);
 void kirkwood_uart1_init(void);
 
 
+extern int kirkwood_tclk;
 extern struct sys_timer kirkwood_timer;
 extern struct sys_timer kirkwood_timer;
 
 
 
 

+ 1 - 0
arch/arm/mach-kirkwood/include/mach/kirkwood.h

@@ -93,6 +93,7 @@
 #define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
 #define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
 #define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0300)
 #define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0300)
 #define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0600)
 #define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0600)
+#define  I2C_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x1000)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
 #define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2000)
 #define  UART0_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x2000)
 #define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2100)
 #define  UART1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2100)

+ 2 - 2
arch/arm/mach-kirkwood/mpp.h

@@ -90,13 +90,13 @@
 
 
 #define MPP10_GPO		MPP( 10, 0x0, 0, 1, 1,   1,   1,   1    )
 #define MPP10_GPO		MPP( 10, 0x0, 0, 1, 1,   1,   1,   1    )
 #define MPP10_SPI_SCK		MPP( 10, 0x2, 0, 1, 1,   1,   1,   1    )
 #define MPP10_SPI_SCK		MPP( 10, 0x2, 0, 1, 1,   1,   1,   1    )
-#define MPP10_UArt0_TXD		MPP( 10, 0X3, 0, 1, 1,   1,   1,   1    )
+#define MPP10_UART0_TXD		MPP( 10, 0X3, 0, 1, 1,   1,   1,   1    )
 #define MPP10_SATA1_ACTn	MPP( 10, 0x5, 0, 1, 0,   0,   1,   1    )
 #define MPP10_SATA1_ACTn	MPP( 10, 0x5, 0, 1, 0,   0,   1,   1    )
 #define MPP10_PTP_TRIG_GEN	MPP( 10, 0xc, 0, 1, 1,   1,   1,   1    )
 #define MPP10_PTP_TRIG_GEN	MPP( 10, 0xc, 0, 1, 1,   1,   1,   1    )
 
 
 #define MPP11_GPIO		MPP( 11, 0x0, 1, 1, 1,   1,   1,   1    )
 #define MPP11_GPIO		MPP( 11, 0x0, 1, 1, 1,   1,   1,   1    )
 #define MPP11_SPI_MISO		MPP( 11, 0x2, 1, 0, 1,   1,   1,   1    )
 #define MPP11_SPI_MISO		MPP( 11, 0x2, 1, 0, 1,   1,   1,   1    )
-#define MPP11_UArt0_RXD		MPP( 11, 0x3, 1, 0, 1,   1,   1,   1    )
+#define MPP11_UART0_RXD		MPP( 11, 0x3, 1, 0, 1,   1,   1,   1    )
 #define MPP11_PTP_EVENT_REQ	MPP( 11, 0x4, 1, 0, 1,   1,   1,   1    )
 #define MPP11_PTP_EVENT_REQ	MPP( 11, 0x4, 1, 0, 1,   1,   1,   1    )
 #define MPP11_PTP_TRIG_GEN	MPP( 11, 0xc, 0, 1, 1,   1,   1,   1    )
 #define MPP11_PTP_TRIG_GEN	MPP( 11, 0xc, 0, 1, 1,   1,   1,   1    )
 #define MPP11_PTP_CLK		MPP( 11, 0xd, 1, 0, 1,   1,   1,   1    )
 #define MPP11_PTP_CLK		MPP( 11, 0xd, 1, 0, 1,   1,   1,   1    )

+ 220 - 0
arch/arm/mach-kirkwood/ts219-setup.c

@@ -0,0 +1,220 @@
+/*
+ *
+ * QNAP TS-119/TS-219 Turbo NAS Board Setup
+ *
+ * Copyright (C) 2009  Martin Michlmayr <tbm@cyrius.com>
+ * Copyright (C) 2008  Byron Bradley <byron.bbradley@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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/orion_spi.h>
+#include <linux/i2c.h>
+#include <linux/mv643xx_eth.h>
+#include <linux/ata_platform.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+#include <linux/timex.h>
+#include <linux/serial_reg.h>
+#include <linux/pci.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/kirkwood.h>
+#include "common.h"
+#include "mpp.h"
+
+/****************************************************************************
+ * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the
+ *     partitions on the device because we want to keep compatability with
+ *     the QNAP firmware.
+ * Layout as used by QNAP:
+ *  0x00000000-0x00080000 : "U-Boot"
+ *  0x00200000-0x00400000 : "Kernel"
+ *  0x00400000-0x00d00000 : "RootFS"
+ *  0x00d00000-0x01000000 : "RootFS2"
+ *  0x00080000-0x000c0000 : "U-Boot Config"
+ *  0x000c0000-0x00200000 : "NAS Config"
+ *
+ * We'll use "RootFS1" instead of "RootFS" to stay compatible with the layout
+ * used by the QNAP TS-109/TS-209.
+ *
+ ***************************************************************************/
+
+static struct mtd_partition qnap_ts219_partitions[] = {
+	{
+		.name		= "U-Boot",
+		.size		= 0x00080000,
+		.offset		= 0,
+		.mask_flags	= MTD_WRITEABLE,
+	}, {
+		.name		= "Kernel",
+		.size		= 0x00200000,
+		.offset		= 0x00200000,
+	}, {
+		.name		= "RootFS1",
+		.size		= 0x00900000,
+		.offset		= 0x00400000,
+	}, {
+		.name		= "RootFS2",
+		.size		= 0x00300000,
+		.offset		= 0x00d00000,
+	}, {
+		.name		= "U-Boot Config",
+		.size		= 0x00040000,
+		.offset		= 0x00080000,
+	}, {
+		.name		= "NAS Config",
+		.size		= 0x00140000,
+		.offset		= 0x000c0000,
+	},
+};
+
+static const struct flash_platform_data qnap_ts219_flash = {
+	.type		= "m25p128",
+	.name		= "spi_flash",
+	.parts		= qnap_ts219_partitions,
+	.nr_parts	= ARRAY_SIZE(qnap_ts219_partitions),
+};
+
+static struct spi_board_info __initdata qnap_ts219_spi_slave_info[] = {
+	{
+		.modalias	= "m25p80",
+		.platform_data	= &qnap_ts219_flash,
+		.irq		= -1,
+		.max_speed_hz	= 20000000,
+		.bus_num	= 0,
+		.chip_select	= 0,
+	},
+};
+
+static struct i2c_board_info __initdata qnap_ts219_i2c_rtc = {
+	I2C_BOARD_INFO("s35390a", 0x30),
+};
+
+static struct mv643xx_eth_platform_data qnap_ts219_ge00_data = {
+	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
+};
+
+static struct mv_sata_platform_data qnap_ts219_sata_data = {
+	.n_ports	= 2,
+};
+
+static struct gpio_keys_button qnap_ts219_buttons[] = {
+	{
+		.code		= KEY_COPY,
+		.gpio		= 15,
+		.desc		= "USB Copy",
+		.active_low	= 1,
+	},
+	{
+		.code		= KEY_RESTART,
+		.gpio		= 16,
+		.desc		= "Reset",
+		.active_low	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data qnap_ts219_button_data = {
+	.buttons	= qnap_ts219_buttons,
+	.nbuttons	= ARRAY_SIZE(qnap_ts219_buttons),
+};
+
+static struct platform_device qnap_ts219_button_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.num_resources	= 0,
+	.dev		= {
+		.platform_data	= &qnap_ts219_button_data,
+	}
+};
+
+static unsigned int qnap_ts219_mpp_config[] __initdata = {
+	MPP0_SPI_SCn,
+	MPP1_SPI_MOSI,
+	MPP2_SPI_SCK,
+	MPP3_SPI_MISO,
+	MPP8_TW_SDA,
+	MPP9_TW_SCK,
+	MPP10_UART0_TXD,
+	MPP11_UART0_RXD,
+	MPP13_UART1_TXD,	/* PIC controller */
+	MPP14_UART1_RXD,	/* PIC controller */
+	MPP15_GPIO,		/* USB Copy button */
+	MPP16_GPIO,		/* Reset button */
+	MPP20_SATA1_ACTn,
+	MPP21_SATA0_ACTn,
+	MPP22_SATA1_PRESENTn,
+	MPP23_SATA0_PRESENTn,
+	0
+};
+
+
+/*****************************************************************************
+ * QNAP TS-x19 specific power off method via UART1-attached PIC
+ ****************************************************************************/
+
+#define UART1_REG(x)	(UART1_VIRT_BASE + ((UART_##x) << 2))
+
+void qnap_ts219_power_off(void)
+{
+	/* 19200 baud divisor */
+	const unsigned divisor = ((kirkwood_tclk + (8 * 19200)) / (16 * 19200));
+
+	pr_info("%s: triggering power-off...\n", __func__);
+
+	/* hijack UART1 and reset into sane state (19200,8n1) */
+	writel(0x83, UART1_REG(LCR));
+	writel(divisor & 0xff, UART1_REG(DLL));
+	writel((divisor >> 8) & 0xff, UART1_REG(DLM));
+	writel(0x03, UART1_REG(LCR));
+	writel(0x00, UART1_REG(IER));
+	writel(0x00, UART1_REG(FCR));
+	writel(0x00, UART1_REG(MCR));
+
+	/* send the power-off command 'A' to PIC */
+	writel('A', UART1_REG(TX));
+}
+
+static void __init qnap_ts219_init(void)
+{
+	/*
+	 * Basic setup. Needs to be called early.
+	 */
+	kirkwood_init();
+	kirkwood_mpp_conf(qnap_ts219_mpp_config);
+
+	kirkwood_uart0_init();
+	kirkwood_uart1_init(); /* A PIC controller is connected here. */
+	spi_register_board_info(qnap_ts219_spi_slave_info,
+				ARRAY_SIZE(qnap_ts219_spi_slave_info));
+	kirkwood_spi_init();
+	kirkwood_i2c_init();
+	i2c_register_board_info(0, &qnap_ts219_i2c_rtc, 1);
+	kirkwood_ge00_init(&qnap_ts219_ge00_data);
+	kirkwood_sata_init(&qnap_ts219_sata_data);
+	kirkwood_ehci_init();
+	platform_device_register(&qnap_ts219_button_device);
+
+	pm_power_off = qnap_ts219_power_off;
+
+}
+
+MACHINE_START(TS219, "QNAP TS-119/TS-219")
+	/* Maintainer: Martin Michlmayr <tbm@cyrius.com> */
+	.phys_io	= KIRKWOOD_REGS_PHYS_BASE,
+	.io_pg_offst	= ((KIRKWOOD_REGS_VIRT_BASE) >> 18) & 0xfffc,
+	.boot_params	= 0x00000100,
+	.init_machine	= qnap_ts219_init,
+	.map_io		= kirkwood_map_io,
+	.init_irq	= kirkwood_init_irq,
+	.timer		= &kirkwood_timer,
+MACHINE_END

+ 8 - 2
arch/arm/mach-orion5x/ts78xx-fpga.h

@@ -6,8 +6,14 @@
  */
  */
 enum fpga_ids {
 enum fpga_ids {
 	/* Technologic Systems */
 	/* Technologic Systems */
-	TS7800_REV_B2 = FPGAID(0x00b480, 0x02),
-	TS7800_REV_B3 = FPGAID(0x00b480, 0x03),
+	TS7800_REV_1	= FPGAID(0x00b480, 0x01),
+	TS7800_REV_2	= FPGAID(0x00b480, 0x02),
+	TS7800_REV_3	= FPGAID(0x00b480, 0x03),
+	TS7800_REV_4	= FPGAID(0x00b480, 0x04),
+	TS7800_REV_5	= FPGAID(0x00b480, 0x05),
+
+	/* Unaffordable & Expensive */
+	UAE_DUMMY	= FPGAID(0xffffff, 0x01),
 };
 };
 
 
 struct fpga_device {
 struct fpga_device {

+ 5 - 2
arch/arm/mach-orion5x/ts78xx-setup.c

@@ -282,8 +282,11 @@ static void ts78xx_fpga_supports(void)
 {
 {
 	/* TODO: put this 'table' into ts78xx-fpga.h */
 	/* TODO: put this 'table' into ts78xx-fpga.h */
 	switch (ts78xx_fpga.id) {
 	switch (ts78xx_fpga.id) {
-	case TS7800_REV_B2:
-	case TS7800_REV_B3:
+	case TS7800_REV_1:
+	case TS7800_REV_2:
+	case TS7800_REV_3:
+	case TS7800_REV_4:
+	case TS7800_REV_5:
 		ts78xx_fpga.supports.ts_rtc.present = 1;
 		ts78xx_fpga.supports.ts_rtc.present = 1;
 		ts78xx_fpga.supports.ts_nand.present = 1;
 		ts78xx_fpga.supports.ts_nand.present = 1;
 		break;
 		break;

+ 9 - 1
arch/arm/tools/mach-types

@@ -12,7 +12,7 @@
 #
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
 #
-# Last update: Thu Mar 12 18:01:45 2009
+# Last update: Mon Mar 23 20:09:01 2009
 #
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
 #
@@ -2124,3 +2124,11 @@ mx27wallace		MACH_MX27WALLACE	MX27WALLACE		2133
 fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
 fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
 smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
 smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
+ccw9p9215		MACH_CCW9P9215		CCW9P9215		2137
+dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
+ts219			MACH_TS219		TS219			2139
+tny_a9263		MACH_TNY_A9263		TNY_A9263		2140
+apollo			MACH_APOLLO		APOLLO			2141
+at91cap9stk		MACH_AT91CAP9STK	AT91CAP9STK		2142
+spc300			MACH_SPC300		SPC300			2143
+eko			MACH_EKO		EKO			2144

+ 11 - 0
drivers/rtc/rtc-mv.c

@@ -12,6 +12,7 @@
 #include <linux/bcd.h>
 #include <linux/bcd.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
+#include <linux/delay.h>
 
 
 
 
 #define RTC_TIME_REG_OFFS	0
 #define RTC_TIME_REG_OFFS	0
@@ -119,6 +120,16 @@ static int __init mv_rtc_probe(struct platform_device *pdev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	/* make sure it is actually functional */
+	if (rtc_time == 0x01000000) {
+		ssleep(1);
+		rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
+		if (rtc_time == 0x01000000) {
+			dev_err(&pdev->dev, "internal RTC not ticking\n");
+			return -ENODEV;
+		}
+	}
+
 	platform_set_drvdata(pdev, pdata);
 	platform_set_drvdata(pdev, pdata);
 	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 	pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 					 &mv_rtc_ops, THIS_MODULE);
 					 &mv_rtc_ops, THIS_MODULE);