diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 33921a6..c06e88f 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -82,8 +82,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	tm->tm_mday	= bcd2bin(M48T59_READ(M48T59_MDAY));
 
 	val = M48T59_READ(M48T59_WDAY);
-	if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
-	    (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
+	if (pdata->type == M48T59RTC_TYPE_M48T201)
+		tm->tm_year += (bcd2bin(M48T59_READ(M48T59_CENTURY))-19) * 100;
+	else if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
+		 (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
 		dev_dbg(dev, "Century bit is enabled\n");
 		tm->tm_year += 100;	/* one century */
 	}
@@ -101,8 +103,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
 	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 	spin_unlock_irqrestore(&m48t59->lock, flags);
 
-	dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
-		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+	dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d:%02d:%02d\n",
+		tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
 		tm->tm_hour, tm->tm_min, tm->tm_sec);
 	return 0;
 }
@@ -121,8 +123,8 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	year -= 68;
 #endif
 
-	dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
-		year + 1900, tm->tm_mon, tm->tm_mday,
+	dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d:%02d:%02d\n",
+		tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
 		tm->tm_hour, tm->tm_min, tm->tm_sec);
 
 	if (year < 0)
@@ -139,11 +141,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
 	/* tm_mon is 0-11 */
 	M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
 	M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR);
-
-	if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100))
-		val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
+	if (pdata->type == M48T59RTC_TYPE_M48T59) {
+		/* The Century Enable Bit must be set regardless of whether
+		 * the Century Bit is set, otherwise the clock would advance
+		 * from 31-Dec-1999 to 1-Jan-1900.
+		 */
+		val = M48T59_WDAY_CEB | (year >= 100 ? M48T59_WDAY_CB : 0);
+	}
 	val |= (bin2bcd(tm->tm_wday) & 0x07);
 	M48T59_WRITE(val, M48T59_WDAY);
+	if (pdata->type == M48T59RTC_TYPE_M48T201)
+		M48T59_WRITE(bin2bcd(year / 100 + 19), M48T59_CENTURY);
 
 	/* Clear the WRITE bit */
 	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
@@ -177,10 +185,15 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	tm->tm_year += 68;
 #endif
 	/* tm_mon is 0-11 */
-	tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
+	if (pdata->type == M48T59RTC_TYPE_M48T201)
+		tm->tm_mon = bcd2bin(M48T59_READ(M48T59_INTR) & 0x1f) - 1;
+	else
+		tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
 
 	val = M48T59_READ(M48T59_WDAY);
-	if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
+	if (pdata->type == M48T59RTC_TYPE_M48T201)
+		tm->tm_year += (bcd2bin(M48T59_READ(M48T59_CENTURY))-19) * 100;
+	else if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
 		tm->tm_year += 100;	/* one century */
 
 	tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE));
@@ -192,8 +205,8 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 	spin_unlock_irqrestore(&m48t59->lock, flags);
 
-	dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
-		tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
+	dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d:%02d:%02d\n",
+		tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
 		tm->tm_hour, tm->tm_min, tm->tm_sec);
 	return 0;
 }
@@ -228,6 +241,10 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	 */
 	mday = tm->tm_mday;
 	mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
+	/*
+	 * FIXME: this is wrong when we're setting an alarm to go off after
+	 * midnight tonight.  The alarm will never happen.
+	 */
 	if (mday == 0xff)
 		mday = M48T59_READ(M48T59_MDAY);
 
@@ -244,6 +261,10 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	/* Issue the WRITE command */
 	M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 
+	if (pdata->type == M48T59RTC_TYPE_M48T201)
+		M48T59_WRITE((M48T59_READ(M48T59_INTR) & 0xe0) |
+			     (bin2bcd(tm->tm_mon + 1) & 0x1f),
+			     M48T59_INTR);
 	M48T59_WRITE(mday, M48T59_ALARM_DATE);
 	M48T59_WRITE(hour, M48T59_ALARM_HOUR);
 	M48T59_WRITE(min, M48T59_ALARM_MIN);
@@ -253,8 +274,8 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 	M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 	spin_unlock_irqrestore(&m48t59->lock, flags);
 
-	dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
-		year + 1900, tm->tm_mon, tm->tm_mday,
+	dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d:%02d:%02d\n",
+		tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
 		tm->tm_hour, tm->tm_min, tm->tm_sec);
 	return 0;
 }
@@ -272,12 +293,16 @@ static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
 	int ret = 0;
 
 	spin_lock_irqsave(&m48t59->lock, flags);
+	/*
+	 * Preserve the other fields in M48T59_INTR in case it's an M48T201
+	 * and they contain the alarm month.
+	 */
 	switch (cmd) {
 	case RTC_AIE_OFF:	/* alarm interrupt off */
-		M48T59_WRITE(0x00, M48T59_INTR);
+		M48T59_CLEAR_BITS(M48T59_INTR_AFE, M48T59_INTR);
 		break;
 	case RTC_AIE_ON:	/* alarm interrupt on */
-		M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
+		M48T59_SET_BITS(M48T59_INTR_AFE, M48T59_INTR);
 		break;
 	default:
 		ret = -ENOIOCTLCMD;
@@ -475,6 +500,11 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
 		ops = &m48t02_rtc_ops;
 		pdata->offset = 0x1ff0;
 		break;
+	case M48T59RTC_TYPE_M48T201:
+		name = "m48t201";
+		ops = &m48t59_rtc_ops;
+		pdata->offset = 0x7fff0;
+		break;
 	default:
 		dev_err(&pdev->dev, "Unknown RTC type\n");
 		ret = -ENODEV;
@@ -502,7 +532,7 @@ out:
 		rtc_device_unregister(m48t59->rtc);
 	if (m48t59->irq != NO_IRQ)
 		free_irq(m48t59->irq, &pdev->dev);
-	if (m48t59->ioaddr)
+	if (m48t59->ioaddr && !pdata->ioaddr)
 		iounmap(m48t59->ioaddr);
 	if (m48t59)
 		kfree(m48t59);
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h
index 6fc9614..8e2df6f 100644
--- a/include/linux/rtc/m48t59.h
+++ b/include/linux/rtc/m48t59.h
@@ -38,7 +38,7 @@
 #define M48T59_ALARM_HOUR	0x4
 #define M48T59_ALARM_MIN	0x3
 #define M48T59_ALARM_SEC	0x2
-#define M48T59_UNUSED		0x1
+#define M48T59_CENTURY		0x1	/* Century (M48T201 only) */
 #define M48T59_FLAGS		0x0
 #define M48T59_FLAGS_WDT		0x80	/* watchdog timer expired */
 #define M48T59_FLAGS_AF			0x40	/* alarm */
@@ -47,6 +47,7 @@
 #define M48T59RTC_TYPE_M48T59	0 /* to keep compatibility */
 #define M48T59RTC_TYPE_M48T02	1
 #define M48T59RTC_TYPE_M48T08	2
+#define M48T59RTC_TYPE_M48T201	3
 
 struct m48t59_plat_data {
 	/* The method to access M48T59 registers */
