[PATCH 2/2]: Add support for Dallas/Maxim DS1685/1687 RTC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Wire SGI O2 (IP32) to use the rtc-ds1685 driver as its RTC.

Signed-off-by: Joshua Kinard <kumba@xxxxxxxxxx>
---
 arch/mips/sgi-ip32/ip32-platform.c |   25 ++++++++++-----
 arch/mips/sgi-ip32/ip32-reset.c    |   53 ---------------------------------
 drivers/rtc/Kconfig                |   17 +++++++++-
 include/linux/rtc/ds1685.h         |   58 +++++++++++++++++++++++++++++++++++--
 4 files changed, 88 insertions(+), 65 deletions(-)

diff -Naurp linux-2.6.37.rtc-ds1685/arch/mips/sgi-ip32/ip32-platform.c linux-2.6.37.rtc-ds1685.ip32/arch/mips/sgi-ip32/ip32-platform.c --- linux-2.6.37.rtc-ds1685/arch/mips/sgi-ip32/ip32-platform.c 2011-02-15 04:19:45.882076002 -0500 +++ linux-2.6.37.rtc-ds1685.ip32/arch/mips/sgi-ip32/ip32-platform.c 2011-02-15 04:31:46.972076001 -0500
@@ -90,21 +90,30 @@ static __init int sgio2btns_devinit(void

 device_initcall(sgio2btns_devinit);

-static struct resource sgio2_cmos_rsrc[] = {
+#define MACE_RTC_RES_START (MACE_BASE + offsetof(struct sgi_mace, isa.rtc))
+#define MACE_RTC_RES_END (MACE_RTC_RES_START + 32767)
+
+static struct resource ip32_rtc_resources[] = {
 	{
-		.start = 0x70,
-		.end   = 0x71,
-		.flags = IORESOURCE_IO
+		.start	= MACEISA_RTC_IRQ,
+		.end	= MACEISA_RTC_IRQ,
+		.flags	= IORESOURCE_IRQ
+	}, {
+		.start	= MACE_RTC_RES_START,
+		.end	= MACE_RTC_RES_END,
+		.flags	= IORESOURCE_MEM,
 	}
 };

-static __init int sgio2_cmos_devinit(void)
+
+
+static __init int sgio2_rtc_devinit(void)
 {
-	return IS_ERR(platform_device_register_simple("rtc_cmos", -1,
-						      sgio2_cmos_rsrc, 1));
+	return IS_ERR(platform_device_register_simple("rtc-ds1685", -1,
+		      ip32_rtc_resources, ARRAY_SIZE(ip32_rtc_resources)));
 }

-device_initcall(sgio2_cmos_devinit);
+device_initcall(sgio2_rtc_devinit);

 MODULE_AUTHOR("Ralf Baechle <ralf@xxxxxxxxxxxxxx>");
 MODULE_LICENSE("GPL");
diff -Naurp linux-2.6.37.rtc-ds1685/arch/mips/sgi-ip32/ip32-reset.c linux-2.6.37.rtc-ds1685.ip32/arch/mips/sgi-ip32/ip32-reset.c --- linux-2.6.37.rtc-ds1685/arch/mips/sgi-ip32/ip32-reset.c 2011-02-15 04:19:45.882076002 -0500 +++ linux-2.6.37.rtc-ds1685.ip32/arch/mips/sgi-ip32/ip32-reset.c 2011-02-15 04:58:46.582076001 -0500
@@ -33,7 +33,7 @@
 #define POWERDOWN_FREQ		(HZ / 4)
 #define PANIC_FREQ		(HZ / 8)

-static struct timer_list power_timer, blink_timer, debounce_timer;
+static struct timer_list power_timer, blink_timer;
 static int has_panicked, shuting_down;

 static void ip32_machine_restart(char *command) __attribute__((noreturn));
@@ -89,33 +89,6 @@ static void blink_timeout(unsigned long
 	mod_timer(&blink_timer, jiffies + data);
 }

-static void debounce(unsigned long data)
-{
-	unsigned char reg_a, reg_c, xctrl_a;
-
-	reg_c = CMOS_READ(RTC_INTR_FLAGS);
-	reg_a = CMOS_READ(RTC_REG_A);
-	CMOS_WRITE(reg_a | DS_REGA_DV0, RTC_REG_A);
-	wbflush();
-	xctrl_a = CMOS_READ(DS_B1_XCTRL4A);
-	if ((xctrl_a & DS_XCTRL4A_IFS) || (reg_c & RTC_IRQF )) {
-		/* Interrupt still being sent. */
-		debounce_timer.expires = jiffies + 50;
-		add_timer(&debounce_timer);
-
-		/* clear interrupt source */
-		CMOS_WRITE(xctrl_a & ~DS_XCTRL4A_IFS, DS_B1_XCTRL4A);
-		CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
-		return;
-	}
-	CMOS_WRITE(reg_a & ~DS_REGA_DV0, RTC_REG_A);
-
-	if (has_panicked)
-		ip32_machine_restart(NULL);
-
-	enable_irq(MACEISA_RTC_IRQ);
-}
-
 static inline void ip32_power_button(void)
 {
 	if (has_panicked)
@@ -136,27 +109,6 @@ static inline void ip32_power_button(voi
 	add_timer(&power_timer);
 }

-static irqreturn_t ip32_rtc_int(int irq, void *dev_id)
-{
-	unsigned char reg_c;
-
-	reg_c = CMOS_READ(RTC_INTR_FLAGS);
-	if (!(reg_c & RTC_IRQF)) {
-		printk(KERN_WARNING
-			"%s: RTC IRQ without RTC_IRQF\n", __func__);
-	}
-	/* Wait until interrupt goes away */
-	disable_irq_nosync(MACEISA_RTC_IRQ);
-	init_timer(&debounce_timer);
-	debounce_timer.function = debounce;
-	debounce_timer.expires = jiffies + 50;
-	add_timer(&debounce_timer);
-
-	printk(KERN_DEBUG "Power button pressed\n");
-	ip32_power_button();
-	return IRQ_HANDLED;
-}
-
 static int panic_event(struct notifier_block *this, unsigned long event,
 		       void *ptr)
 {
@@ -196,9 +148,6 @@ static __init int ip32_reboot_setup(void
 	blink_timer.function = blink_timeout;
 	atomic_notifier_chain_register(&panic_notifier_list, &panic_block);

-	if (request_irq(MACEISA_RTC_IRQ, ip32_rtc_int, 0, "rtc", NULL))
-		panic("Can't allocate MACEISA RTC IRQ");
-
 	return 0;
 }

diff -Naurp linux-2.6.37.rtc-ds1685/drivers/rtc/Kconfig linux-2.6.37.rtc-ds1685.ip32/drivers/rtc/Kconfig
--- linux-2.6.37.rtc-ds1685/drivers/rtc/Kconfig	2011-02-15 04:56:37.322076002 -0500
+++ linux-2.6.37.rtc-ds1685.ip32/drivers/rtc/Kconfig 2011-02-15 04:36:20.372076000 -0500
@@ -501,17 +501,30 @@ config RTC_DRV_DS1553

 config RTC_DRV_DS1685
 	tristate "Dallas/Maxim DS1685/DS1687"
-	depends on I2C
+	depends on (I2C || SGI_IP32)
 	help
 	  If you say yes here you get support for the Dallas/Maxim
 	  DS1685/DS1687 timekeeping chip.

 	  Systems that use this chip include EPPC-405-UC modules, by
-	  electronic system design GmbH.
+	  electronic system design GmbH, and the SGI O2 (IP32).
+
+	  This module also supports the DS17285/DS17287 timekeeping chips
+	  that are sometimes found in place of the DS1685/DS1687 in some
+	  SGI O2 systems.

 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-ds1685.

+config RTC_DRV_DS17285
+	bool "Enable DS17285/DS17287 Differences"
+	depends on (SGI_IP32 && RTC_DRV_DS1685)
+	help
+	  If your SGI O2 has one of these RTC chips instead of the more
+	  common DS1687-5 chip, say Y here to enable the minor differences
+	  this particular chip has.  For more information, refer to the
+	  Dallas/Maxim datasheet for the DS17285/DS17287 chip.
+
 config RTC_DRV_DS1742
 	tristate "Maxim/Dallas DS1742/1743"
 	help
diff -Naurp linux-2.6.37.rtc-ds1685/include/linux/rtc/ds1685.h linux-2.6.37.rtc-ds1685.ip32/include/linux/rtc/ds1685.h --- linux-2.6.37.rtc-ds1685/include/linux/rtc/ds1685.h 2011-02-15 04:28:04.582076001 -0500 +++ linux-2.6.37.rtc-ds1685.ip32/include/linux/rtc/ds1685.h 2011-02-15 04:54:04.612076002 -0500
@@ -16,6 +16,19 @@
 #define _LINUX_RTC_DS1685_H_

 /*
+ * Note: IP32 documentation hints that IP32 systems actually have a DS17287
+ * RTC chip.  Having checked four different O2 systems myself, I have only
+ * observed DS1687-5 chips, same as in SGI Octane systems (IP30).
+ *
+ * That said, the DS17287 has some minor differences, so this driver can be
+ * built to support these small differences if their functionality is really
+ * needed.  Due to the lack of actually seeing one, however, these differences
+ * are not tested, but follow the information provided in the DS17285/DS17287
+ * data sheet.
+ */
+
+
+/*
  * Found in the original RTC driver for SGI IP30 (Octane) systems, it is used
  * in the ds1685_begin_access macro while loop to avoid RTC access lockouts.
  */
@@ -190,7 +203,29 @@ static const char *sqw_freq[16] = {
 #endif /* CONFIG_PROC_FS */


-#define DS1685_REG(r) volatile unsigned char r;
+/*
+ * SGI O2 (IP32) Systems need 1 byte of padding between the registers in
+ * order for the driver to function properly.  O2's should be using DS17287
+ * RTC chips, but most have DS1687-5 modules instead.  The differences
+ * between the two are minor, but accounted for anyways.
+ */
+#ifdef CONFIG_SGI_IP32
+  #define DS1685_PAD                   0xff
+  #define DS1685_REG(r)					\
+       volatile unsigned char r;			\
+       unsigned char r##_pad[DS1685_PAD]
+  #define DS1685_NVRAM1_PAD            0x31ce
+  #define DS1685_NVRAM2_PAD            0x7fbf
+
+  #ifdef CONFIG_RTC_DS17285
+    #define DS17285_RSVRD_PAD          0xa00
+  #else
+    #define DS17285_RSVRD_PAD          0x2c00
+  #endif
+#else
+  #define DS1685_REG(r)					\
+       volatile unsigned char r;
+#endif


 /*
@@ -213,6 +248,9 @@ struct ds1685_time_regs {
 	DS1685_REG(ctrlc);		/* Control Register C		*/
 	DS1685_REG(ctrld);		/* Control Register D		*/
 	volatile unsigned char nvram1[NVRAM_SZ_TIME];
+#ifdef CONFIG_SGI_IP32
+	unsigned char nvram1_pad[DS1685_NVRAM1_PAD];
+#endif
 };


@@ -221,6 +259,9 @@ struct ds1685_time_regs {
  */
 struct ds1685_bank0_regs {
 	volatile unsigned char nvram2[NVRAM_SZ_BANK0];
+#ifdef CONFIG_SGI_IP32
+	unsigned char nvram2_pad[DS1685_NVRAM2_PAD];
+#endif
 };


@@ -247,10 +288,21 @@ struct ds1685_bank1_regs {
 	DS1685_REG(rsvrd2);		/* Recovery Stack.  Holds last	*/
 	DS1685_REG(rtc_addr2);		/* four RTC addresses for the	*/
 	DS1685_REG(rtc_addr3);		/* BIOS to recover from an SMI.	*/
+#ifdef CONFIG_RTC_DS17285
+	DS1685_REG(ext_nvram_addr_lsb);	/* LSB of NVRAM Addr; DS17285/7 */
+	DS1685_REG(ext_nvram_addr_msb);	/* MSB of NVRAM Addr; DS17285/7 */
+#else
 	DS1685_REG(ext_nvram_addr);	/* Ext. NVRAM Addr; DS1685/7	*/
 	DS1685_REG(rsvrd3);		/* Reserved			*/
+#endif
 	DS1685_REG(rsvrd4);		/* Reserved			*/
 	DS1685_REG(ext_nvram_dport);	/* Ext. NVRAM Data Port		*/
+#ifdef CONFIG_SGI_IP32
+	volatile unsigned char rsvrd_pad[DS17285_RSVRD_PAD];
+#endif
+#ifdef CONFIG_RTC_DS17285
+	DS1685_REG(rtc_write_cnt);      /* RTC Write Counter; DS17285/7 */
+#endif
 };


@@ -269,7 +321,7 @@ struct ds1685_rtc_regs {


 /*
- * DS1685/1687 data structure.
+ * DS1685/1687/17285/17287 data structure.
  */
 struct ds1685_priv {
 	struct rtc_device *rtc;			/* RTC device pointer */
@@ -381,7 +433,7 @@ struct ds1685_priv {

 /*
  * This fetches the Silicon Serial Number, a unique ID specific to every
- * DS1685/1687.
+ * DS1685/1687/17285/17287.
  *
  * This number starts at 0x40, and is 8-bytes long, ending at 0x47.
  * The first byte is the model #, the next six bytes are the serial




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux