add 添加外挂RTC hym8563diff --git a/lichee/linux-3.10/arch/arm/configs/sun8iw11p1smp_androidm_defconfig b/lichee/linux-3.10/arch/arm/configs/sun8iw11p1smp_androidm_defconfig
index ae8b7ec..ad2e2c2 100755
--- a/lichee/linux-3.10/arch/arm/configs/sun8iw11p1smp_androidm_defconfig
+++ b/lichee/linux-3.10/arch/arm/configs/sun8iw11p1smp_androidm_defconfig
@@ -2801,7 +2801,7 @@ CONFIG_RTC_INTF_DEV=y# CONFIG_RTC_DRV_ISL12022 is not set# CONFIG_RTC_DRV_X1205 is not set# CONFIG_RTC_DRV_PCF8523 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
+CONFIG_RTC_DRV_PCF8563=y# CONFIG_RTC_DRV_PCF8583 is not set# CONFIG_RTC_DRV_M41T80 is not set# CONFIG_RTC_DRV_BQ32K is not set
@@ -2847,7 +2847,7 @@ CONFIG_RTC_INTF_DEV=y## on-CPU RTC drivers#
-CONFIG_RTC_DRV_SUNXI=y
+#CONFIG_RTC_DRV_SUNXI=y# CONFIG_RTC_DRV_SNVS is not set#
diff --git a/lichee/linux-3.10/drivers/rtc/rtc-pcf8563.c b/lichee/linux-3.10/drivers/rtc/rtc-pcf8563.c
old mode 100644
new mode 100755
index 97b354a..b9f4a92
--- a/lichee/linux-3.10/drivers/rtc/rtc-pcf8563.c
+++ b/lichee/linux-3.10/drivers/rtc/rtc-pcf8563.c
@@ -20,287 +20,767 @@#include <linux/slab.h>#include <linux/module.h>#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/wakelock.h>
+#include <linux/of_gpio.h>
+#include <linux/irqdomain.h>#define DRV_VERSION "0.4.3"-#define PCF8563_REG_ST1       0x00 /* status */
-#define PCF8563_REG_ST2        0x01
+#define   RTC_CTL1        0x00
+#define   RTC_CTL2        0x01
+#define   RTC_SEC     0x02
+#define   RTC_MIN     0x03
+#define   RTC_HOUR        0x04
+#define   RTC_DAY     0x05
+#define   RTC_WEEK        0x06
+#define   RTC_MON     0x07
+#define   RTC_YEAR        0x08
+#define   RTC_A_MIN   0x09
+#define   RTC_A_HOUR  0x0A
+#define   RTC_A_DAY   0x0B
+#define   RTC_A_WEEK  0x0C
+#define   RTC_CLKOUT  0x0D
+#define   RTC_T_CTL   0x0E
+#define   RTC_T_COUNT 0x0F
+#define   CENTURY 0x80
+#define   TI      0x10
+#define   AF      0x08
+#define   TF      0x04
+#define   AIE     0x02
+#define   TIE     0x01
+#define   FE      0x80
+#define   TE      0x80
+#define   FD1     0x02
+#define   FD0     0x01
+#define   TD1     0x02
+#define   TD0     0x01
+#define   VL      0x80
+
+#define HYM8563_REG_LEN   0x10
+#define HYM8563_RTC_SECTION_LEN   0x07
+#define RTC_SPEED     200 * 1000
+unsigned int g_crtc_used = 0;
+static unsigned char crtc_twi_id = 0;
+
+struct hym8563 {
+  int irq;
+  struct i2c_client *client;
+  struct mutex mutex;
+  struct rtc_device *rtc;
+  struct rtc_wkalrm alarm;
+  struct wake_lock wake_lock;
+};
+static struct i2c_client *gClient = NULL;-#define PCF8563_REG_SC     0x02 /* datetime */
-#define PCF8563_REG_MN     0x03
-#define PCF8563_REG_HR     0x04
-#define PCF8563_REG_DM     0x05
-#define PCF8563_REG_DW     0x06
-#define PCF8563_REG_MO     0x07
-#define PCF8563_REG_YR     0x08
+static int i2c_master_reg8_send(const struct i2c_client *client, const char reg, const char *buf, int count, int scl_rate)
+{
+  struct i2c_adapter *adap=client->adapter;
+  struct i2c_msg msg;
+  int ret;
+  char *tx_buf = (char *)kzalloc(count + 1, GFP_KERNEL);
+  if(!tx_buf)
+      return -ENOMEM;
+  tx_buf[0] = reg;
+  memcpy(tx_buf+1, buf, count); -#define PCF8563_REG_AMN     0x09 /* alarm */
-#define PCF8563_REG_AHR        0x0A
-#define PCF8563_REG_ADM        0x0B
-#define PCF8563_REG_ADW        0x0C
+  msg.addr = client->addr;
+  msg.flags = client->flags;
+  msg.len = count + 1;
+  msg.buf = (char *)tx_buf;
+  //msg.scl_rate = scl_rate;-#define PCF8563_REG_CLKO    0x0D /* clock out */
-#define PCF8563_REG_TMRC   0x0E /* timer control */
-#define PCF8563_REG_TMR        0x0F /* timer */
+  ret = i2c_transfer(adap, &msg, 1);
+  kfree(tx_buf);
+  return (ret == 1) ? count : ret;-#define PCF8563_SC_LV        0x80 /* low voltage */
-#define PCF8563_MO_C       0x80 /* century */
+}
+
+static int i2c_master_reg8_recv(const struct i2c_client *client, const char reg, char *buf, int count, int scl_rate)
+{
+  struct i2c_adapter *adap=client->adapter;
+  struct i2c_msg msgs[2];
+  int ret;
+  char reg_buf = reg;
+
+  msgs[0].addr = client->addr;
+  msgs[0].flags = client->flags;
+  msgs[0].len = 1;
+  msgs[0].buf = &reg_buf;
+  //msgs[0].scl_rate = scl_rate;
+
+  msgs[1].addr = client->addr;
+  msgs[1].flags = client->flags | I2C_M_RD;
+  msgs[1].len = count;
+  msgs[1].buf = (char *)buf;
+  //msgs[1].scl_rate = scl_rate;
+
+  ret = i2c_transfer(adap, msgs, 2);
+
+  return (ret == 2)? count : ret;
+}-static struct i2c_driver pcf8563_driver;-struct pcf8563 {
-   struct rtc_device *rtc;
-   /*
-    * The meaning of MO_C bit varies by the chip type.
-    * From PCF8563 datasheet: this bit is toggled when the years
-    * register overflows from 99 to 00
-    *   0 indicates the century is 20xx
-    *   1 indicates the century is 19xx
-    * From RTC8564 datasheet: this bit indicates change of
-    * century. When the year digit data overflows from 99 to 00,
-    * this bit is set. By presetting it to 0 while still in the
-    * 20th century, it will be set in year 2000, ...
-    * There seems no reliable way to know how the system use this
-    * bit.  So let's do it heuristically, assuming we are live in
-    * 1970...2069.
-    */
-   int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
-   int voltage_low; /* incicates if a low_voltage was detected */
-};-/*
- * In the routines that deal directly with the pcf8563 hardware, we use
- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
- */
-static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int hym8563_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len)
+{
+  int ret;
+  ret = i2c_master_reg8_recv(client, reg, buf, len, RTC_SPEED);
+  return ret;
+}
+
+static int hym8563_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], __u16 len){
-   struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
-   unsigned char buf[13] = { PCF8563_REG_ST1 };
-
-   struct i2c_msg msgs[] = {
-       {/* setup read ptr */
-           .addr = client->addr,
-           .len = 1,
-           .buf = buf
-       },
-       {/* read status + date */
-           .addr = client->addr,
-           .flags = I2C_M_RD,
-           .len = 13,
-           .buf = buf
-       },
-   };
-
-   /* read registers */
-   if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
-       dev_err(&client->dev, "%s: read error\n", __func__);
-       return -EIO;
+  int ret;
+  ret = i2c_master_reg8_send(client, reg, buf, (int)len, RTC_SPEED);
+  return ret;
+}
+
+
+int hym8563_enable_count(struct i2c_client *client, int en)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[2];
+
+  if (!hym8563)
+      return -1;
+
+  if (en) {
+      hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+      regs[0] |= TIE;
+      hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+      regs[0] = 0;
+      regs[0] |= (TE | TD1);
+      hym8563_i2c_set_regs(client, RTC_T_CTL, regs, 1);
+  }
+  else {
+      hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+      regs[0] &= ~TIE;
+      hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+      regs[0] = 0;
+      regs[0] |= (TD0 | TD1);
+      hym8563_i2c_set_regs(client, RTC_T_CTL, regs, 1);}
+  return 0;
+}
+
+//0 < sec <=255
+int hym8563_set_count(struct i2c_client *client, int sec)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[2];
+
+  if (!hym8563)
+      return -1;
+
+  if (sec >= 255)
+      regs[0] = 255;
+  else if (sec <= 1)
+      regs[0] = 1;
+  else
+      regs[0] = sec;
+
+  hym8563_i2c_set_regs(client, RTC_T_COUNT, regs, 1);
+
+  return 0;
+}-    if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
-       pcf8563->voltage_low = 1;
-       dev_info(&client->dev,
-           "low voltage detected, date/time is not reliable.\n");
+
+/*the init of the hym8563 at first time */
+static int hym8563_init_device(struct i2c_client *client)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[2];
+  int sr;
+
+  mutex_lock(&hym8563->mutex);
+  regs[0]=0;
+  sr = hym8563_i2c_set_regs(client, RTC_CTL1, regs, 1);
+  if (sr < 0)
+      goto exit;
+
+  //disable clkout
+  regs[0] = 0x80;
+  sr = hym8563_i2c_set_regs(client, RTC_CLKOUT, regs, 1);
+  if (sr < 0)
+      goto exit;
+
+  /*enable alarm && count interrupt*/
+  sr = hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+  if (sr < 0)
+      goto exit;
+  regs[0] = 0x0;
+  regs[0] |= (AIE | TIE);
+  sr = hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+  if (sr < 0)
+      goto exit;
+  sr = hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+  if (sr < 0)
+      goto exit;
+
+  sr = hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+  if (sr < 0) {
+      pr_err("read CTL2 err\n");
+      goto exit;
+  }
+
+  if(regs[0] & (AF|TF))
+  {
+      regs[0] &= ~(AF|TF);
+      sr = hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);}
+
+exit:
+  mutex_unlock(&hym8563->mutex);
+
+  return sr;
+}
+
+static int hym8563_read_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[HYM8563_RTC_SECTION_LEN] = { 0, };
+  mutex_lock(&hym8563->mutex);
+//    for (i = 0; i < HYM8563_RTC_SECTION_LEN; i++) {
+//        hym8563_i2c_read_regs(client, RTC_SEC+i, &regs[i], 1);
+//    }
+  hym8563_i2c_read_regs(client, RTC_SEC, regs, HYM8563_RTC_SECTION_LEN);
+
+  mutex_unlock(&hym8563->mutex);
+
+  tm->tm_sec = bcd2bin(regs[0x00] & 0x7F);
+  tm->tm_min = bcd2bin(regs[0x01] & 0x7F);
+  tm->tm_hour = bcd2bin(regs[0x02] & 0x3F);
+  tm->tm_mday = bcd2bin(regs[0x03] & 0x3F);
+  tm->tm_wday = bcd2bin(regs[0x04] & 0x07);
+
+  tm->tm_mon = bcd2bin(regs[0x05] & 0x1F) ;
+  tm->tm_mon -= 1;            //inorder to cooperate the systerm time
+
+  tm->tm_year = bcd2bin(regs[0x06] & 0xFF);
+  if(regs[5] & 0x80)
+      tm->tm_year += 1900;
+  else
+      tm->tm_year += 2000;
+
+  tm->tm_year -= 1900;            //inorder to cooperate the systerm time
+  if(tm->tm_year < 0)
+      tm->tm_year = 0;
+  tm->tm_isdst = 0;
+
+  printk("%4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+      1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+      tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+  return 0;
+}
+
+static int hym8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+  return hym8563_read_datetime(to_i2c_client(dev), tm);
+}-    dev_dbg(&client->dev,
-       "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
-       "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
-       __func__,
-       buf[0], buf[1], buf[2], buf[3],
-       buf[4], buf[5], buf[6], buf[7],
-       buf[8]);
-
-
-   tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
-   tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
-   tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
-   tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
-   tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
-   tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-   tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
-   if (tm->tm_year < 70)
-       tm->tm_year += 100;    /* assume we are in 1970...2069 */
-   /* detect the polarity heuristically. see note above. */
-   pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
-       (tm->tm_year >= 100) : (tm->tm_year < 100);
-
-   dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
-       "mday=%d, mon=%d, year=%d, wday=%d\n",
-       __func__,
-       tm->tm_sec, tm->tm_min, tm->tm_hour,
-       tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
-   /* the clock can give out invalid datetime, but we cannot return
-    * -EINVAL otherwise hwclock will refuse to set the time on bootup.
-    */
-   if (rtc_valid_tm(tm) < 0)
-       dev_err(&client->dev, "retrieved date/time is not valid.\n");
+static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[HYM8563_RTC_SECTION_LEN] = { 0, };
+  u8 mon_day;
+  //u8 ret = 0;
+
+  printk("%4d-%02d-%02d(%d) %02d:%02d:%02d\n",
+      1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+      tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+  mon_day = rtc_month_days((tm->tm_mon), tm->tm_year + 1900);
+
+  if(tm->tm_sec >= 60 || tm->tm_sec < 0 )        //set  sec
+      regs[0x00] = bin2bcd(0x00);
+  else
+      regs[0x00] = bin2bcd(tm->tm_sec);
+
+  if(tm->tm_min >= 60 || tm->tm_min < 0 )        //set  min
+      regs[0x01] = bin2bcd(0x00);
+  else
+      regs[0x01] = bin2bcd(tm->tm_min);
+
+  if(tm->tm_hour >= 24 || tm->tm_hour < 0 )      //set  hour
+      regs[0x02] = bin2bcd(0x00);
+  else
+      regs[0x02] = bin2bcd(tm->tm_hour);
+
+  if((tm->tm_mday) > mon_day)               //if the input month day is bigger than the biggest day of this month, set the biggest day
+      regs[0x03] = bin2bcd(mon_day);
+  else if((tm->tm_mday) > 0)
+      regs[0x03] = bin2bcd(tm->tm_mday);
+  else if((tm->tm_mday) <= 0)
+      regs[0x03] = bin2bcd(0x01);
+
+  if( tm->tm_year >= 200)      // year >= 2100
+      regs[0x06] = bin2bcd(99);  //year = 2099
+  else if(tm->tm_year >= 100)          // 2000 <= year < 2100
+      regs[0x06] = bin2bcd(tm->tm_year - 100);
+  else if(tm->tm_year >= 0){               // 1900 <= year < 2000
+      regs[0x06] = bin2bcd(tm->tm_year);
+      regs[0x05] |= 0x80;
+  }else{                                  // year < 1900
+      regs[0x06] = bin2bcd(0);   //year = 1900
+      regs[0x05] |= 0x80;
+  }
+  regs[0x04] = bin2bcd(tm->tm_wday);      //set  the  weekday
+  regs[0x05] = (regs[0x05] & 0x80)| (bin2bcd(tm->tm_mon + 1) & 0x7F);        //set  the  month
+
+  mutex_lock(&hym8563->mutex);
+//    for(i=0;i<HYM8563_RTC_SECTION_LEN;i++){
+//        ret = hym8563_i2c_set_regs(client, RTC_SEC+i, &regs[i], 1);
+//    }
+  hym8563_i2c_set_regs(client, RTC_SEC, regs, HYM8563_RTC_SECTION_LEN);
+
+  mutex_unlock(&hym8563->mutex);return 0;}-static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm){
-   struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
-   int i, err;
-   unsigned char buf[9];
-
-   dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
-       "mday=%d, mon=%d, year=%d, wday=%d\n",
-       __func__,
-       tm->tm_sec, tm->tm_min, tm->tm_hour,
-       tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
-
-   /* hours, minutes and seconds */
-   buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
-   buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
-   buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
-
-   buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
-
-   /* month, 1 - 12 */
-   buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
-
-   /* year and century */
-   buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
-   if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
-       buf[PCF8563_REG_MO] |= PCF8563_MO_C;
-
-   buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
-
-   /* write register's data */
-   for (i = 0; i < 7; i++) {
-       unsigned char data[2] = { PCF8563_REG_SC + i,
-                       buf[PCF8563_REG_SC + i] };
-
-       err = i2c_master_send(client, data, sizeof(data));
-       if (err != sizeof(data)) {
-           dev_err(&client->dev,
-               "%s: err=%d addr=%02x, data=%02x\n",
-               __func__, err, data[0], data[1]);
-           return -EIO;
+  return hym8563_set_time(to_i2c_client(dev), tm);
+}
+
+static int hym8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
+{
+  struct i2c_client *client = to_i2c_client(dev);
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  u8 regs[4] = { 0, };
+
+  printk("enter\n");
+  mutex_lock(&hym8563->mutex);
+  hym8563_i2c_read_regs(client, RTC_A_MIN, regs, 4);
+  regs[0] = 0x0;
+  regs[0] |= TIE;
+  hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+  mutex_unlock(&hym8563->mutex);
+  return 0;
+}
+
+static int hym8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+  struct i2c_client *client = to_i2c_client(dev);
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);
+  struct rtc_time now, *tm = &alarm->time;
+  u8 regs[4] = { 0, };
+  u8 mon_day;
+  unsigned long   alarm_sec, now_sec;
+  int diff_sec = 0;
+
+  printk("%4d-%02d-%02d(%d) %02d:%02d:%02d enabled %d\n",
+      1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+      tm->tm_hour, tm->tm_min, tm->tm_sec, alarm->enabled);
+
+
+  hym8563_read_datetime(client, &now);
+
+
+  mutex_lock(&hym8563->mutex);
+  rtc_tm_to_time(tm, &alarm_sec);
+  rtc_tm_to_time(&now, &now_sec);
+
+  diff_sec = alarm_sec - now_sec;
+
+  if((diff_sec > 0) && (diff_sec < 256))
+  {
+      printk("%s:diff_sec= %ds , use time\n",__func__, diff_sec);
+
+      if (alarm->enabled == 1)
+      {
+          hym8563_set_count(client, diff_sec);
+          hym8563_enable_count(client, 1);}
+
+      else
+      {
+          hym8563_enable_count(client, 0);
+      }
+
+  }
+  else
+  {
+      printk("%s:diff_sec= %ds , use alarm\n",__func__, diff_sec);
+      hym8563_enable_count(client, 0);
+
+      if(tm->tm_sec > 0)
+      {
+          rtc_tm_to_time(tm, &alarm_sec);
+          rtc_time_to_tm(alarm_sec, tm);
+      }
+
+      hym8563->alarm = *alarm;
+
+      regs[0] = 0x0;
+      hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+      mon_day = rtc_month_days(tm->tm_mon, tm->tm_year + 1900);
+      hym8563_i2c_read_regs(client, RTC_A_MIN, regs, 4);
+
+      if (tm->tm_min >= 60 || tm->tm_min < 0)        //set  min
+      regs[0x00] = bin2bcd(0x00) & 0x7f;
+      else
+      regs[0x00] = bin2bcd(tm->tm_min) & 0x7f;
+      if (tm->tm_hour >= 24 || tm->tm_hour < 0)  //set  hour
+      regs[0x01] = bin2bcd(0x00) & 0x7f;
+      else
+      regs[0x01] = bin2bcd(tm->tm_hour) & 0x7f;
+      regs[0x03] = bin2bcd (tm->tm_wday) & 0x7f;
+
+      /* if the input month day is bigger than the biggest day of this month, set the biggest day */
+      if (tm->tm_mday > mon_day)
+      regs[0x02] = bin2bcd(mon_day) & 0x7f;
+      else if (tm->tm_mday > 0)
+      regs[0x02] = bin2bcd(tm->tm_mday) & 0x7f;
+      else if (tm->tm_mday <= 0)
+      regs[0x02] = bin2bcd(0x01) & 0x7f;
+
+      hym8563_i2c_set_regs(client, RTC_A_MIN, regs, 4);
+      hym8563_i2c_read_regs(client, RTC_A_MIN, regs, 4);
+      hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+      if (alarm->enabled == 1)
+      regs[0] |= AIE;
+      else
+      regs[0] &= 0x0;
+      hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
+      hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
+
+      if(diff_sec <= 0)
+      {
+          pr_info("alarm sec  <= now sec\n");
+      }
+}
+
+  mutex_unlock(&hym8563->mutex);return 0;}-#ifdef CONFIG_RTC_INTF_DEV
-static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
+static int hym8563_i2c_open_alarm(struct i2c_client *client){
-   struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
-   struct rtc_time tm;
+  u8 data;
+  hym8563_i2c_read_regs(client, RTC_CTL2, &data, 1);
+  data |= AIE;
+  hym8563_i2c_set_regs(client, RTC_CTL2, &data, 1);-  switch (cmd) {
-   case RTC_VL_READ:
-       if (pcf8563->voltage_low)
-           dev_info(dev, "low voltage detected, date/time is not reliable.\n");
+  return 0;
+}-        if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
-                   sizeof(int)))
-           return -EFAULT;
-       return 0;
-   case RTC_VL_CLR:
-       /*
-        * Clear the VL bit in the seconds register in case
-        * the time has not been set already (which would
-        * have cleared it). This does not really matter
-        * because of the cached voltage_low value but do it
-        * anyway for consistency.
-        */
-       if (pcf8563_get_datetime(to_i2c_client(dev), &tm))
-           pcf8563_set_datetime(to_i2c_client(dev), &tm);
-
-       /* Clear the cached value. */
-       pcf8563->voltage_low = 0;
+static int hym8563_i2c_close_alarm(struct i2c_client *client)
+{
+  u8 data;
+  hym8563_i2c_read_regs(client, RTC_CTL2, &data, 1);
+  data &= ~AIE;
+  hym8563_i2c_set_regs(client, RTC_CTL2, &data, 1);-      return 0;
+  return 0;
+}
+
+static int hym8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+  struct i2c_client *client = to_i2c_client(dev);
+
+  switch (cmd) {
+  case RTC_AIE_OFF:
+      if(hym8563_i2c_close_alarm(client) < 0)
+          goto err;
+      break;
+  case RTC_AIE_ON:
+      if(hym8563_i2c_open_alarm(client))
+          goto err;
+      break;default:return -ENOIOCTLCMD;
-   }
+  }
+  return 0;
+err:
+  return -EIO;}#else
-#define pcf8563_rtc_ioctl NULL
+#define hym8563_rtc_ioctl NULL#endif-static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
+static int hym8563_rtc_proc(struct device *dev, struct seq_file *seq){
-   return pcf8563_get_datetime(to_i2c_client(dev), tm);
+  return 0;}
+#else
+#define hym8563_rtc_proc NULL
+#endif-static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static irqreturn_t hym8563_wakeup_irq(int irq, void *data){
-   return pcf8563_set_datetime(to_i2c_client(dev), tm);
+  struct hym8563 *hym8563 = data;
+  struct i2c_client *client = hym8563->client;
+  u8 value;
+
+  mutex_lock(&hym8563->mutex);
+  hym8563_i2c_read_regs(client, RTC_CTL2, &value, 1);
+  value &= ~(AF|TF);
+  hym8563_i2c_set_regs(client, RTC_CTL2, &value, 1);
+  mutex_unlock(&hym8563->mutex);
+
+  rtc_update_irq(hym8563->rtc, 1, RTC_IRQF | RTC_AF | RTC_UF);
+
+  //printk("%s:irq=%d\n",__func__,irq);
+  return IRQ_HANDLED;}-static const struct rtc_class_ops pcf8563_rtc_ops = {
-   .ioctl      = pcf8563_rtc_ioctl,
-   .read_time  = pcf8563_rtc_read_time,
-   .set_time   = pcf8563_rtc_set_time,
+static const struct rtc_class_ops hym8563_rtc_ops = {
+  .read_time  = hym8563_rtc_read_time,
+  .set_time   = hym8563_rtc_set_time,
+  .read_alarm = hym8563_rtc_read_alarm,
+  .set_alarm  = hym8563_rtc_set_alarm,
+  .ioctl      = hym8563_rtc_ioctl,
+  .proc       = hym8563_rtc_proc};-static int pcf8563_probe(struct i2c_client *client,
-               const struct i2c_device_id *id)
+static int  hym8563_probe(struct i2c_client *client, const struct i2c_device_id *id){
-   struct pcf8563 *pcf8563;
-
-   dev_dbg(&client->dev, "%s\n", __func__);
-
+  int rc = 0;
+  u8 reg = 0;
+  struct hym8563 *hym8563;
+  struct rtc_device *rtc = NULL;
+  struct rtc_time tm_read, tm = {
+      .tm_wday = 6,
+      .tm_year = 111,
+      .tm_mon = 0,
+      .tm_mday = 1,
+      .tm_hour = 12,
+      .tm_min = 0,
+      .tm_sec = 0,
+  };
+
+  struct device_node *np = of_find_node_by_name(NULL,"crtc");
+  unsigned long irq_flags = 0;
+  int result;
+  printk("hym8563_probe\n");if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))return -ENODEV;
-
-   pcf8563 = devm_kzalloc(&client->dev, sizeof(struct pcf8563),
-               GFP_KERNEL);
-   if (!pcf8563)
+
+  hym8563 = devm_kzalloc(&client->dev,sizeof(*hym8563), GFP_KERNEL);
+  if (!hym8563) {return -ENOMEM;
+  }-  dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+  gClient = client;
+  hym8563->client = client;
+  hym8563->alarm.enabled = 0;
+  client->irq = 0;
+  mutex_init(&hym8563->mutex);
+  wake_lock_init(&hym8563->wake_lock, WAKE_LOCK_SUSPEND, "rtc_hym8563");
+  i2c_set_clientdata(client, hym8563);
+
+  hym8563_init_device(client);
+  hym8563_enable_count(client, 0);
+
+  // check power down
+  printk("hym8563_probe 11\n");
+  hym8563_i2c_read_regs(client,RTC_SEC,&reg,1);
+  if (reg&0x80) {
+      dev_info(&client->dev, "clock/calendar information is no longer guaranteed\n");
+      hym8563_set_time(client, &tm);
+  }
+printk("hym8563_probe reg=0x%x\n",reg);
+  hym8563_read_datetime(client, &tm_read);    //read time from hym8563
+
+  if(((tm_read.tm_year < 70) | (tm_read.tm_year > 137 )) | (tm_read.tm_mon == -1) | (rtc_valid_tm(&tm_read) != 0)) //if the hym8563 haven't initialized
+  {
+      hym8563_set_time(client, &tm);  //initialize the hym8563
+  }
+  if(!np){
+      printk("rtc hym8563_probe can't get irq gpio\n");
+  }else {
+      printk("rtc hym8563_probe get irq gpio\n");
+  client->irq = of_get_named_gpio_flags(np, "crtc_irq_gpio", 0,(enum of_gpio_flags *)&irq_flags);
+  if(client->irq >= 0)
+        {
+          printk("rtc hym8563_probe get irq\n");
+          hym8563->irq = gpio_to_irq(client->irq);
+          //result = devm_request_irq(&client->dev, hym8563->irq, hym8563_wakeup_irq,
+          //               irq_flags | IRQF_ONESHOT, client->dev.driver->name, hym8563);
+          result = devm_request_threaded_irq(&client->dev, hym8563->irq, NULL, hym8563_wakeup_irq, irq_flags | IRQF_ONESHOT, client->dev.driver->name,hym8563 );
+          if (result) {
+              printk( "%s:fail rtc to request irq = %d, ret = 0x%x\n",__func__, hym8563->irq, result);
+              goto exit;
+          }
+          enable_irq_wake(hym8563->irq);
+          device_init_wakeup(&client->dev, 1);
+        }
+  }
+  //device_init_wakeup(&client->dev, 1);
+  rtc = devm_rtc_device_register(&client->dev,
+          client->name,
+                          &hym8563_rtc_ops, THIS_MODULE);
+  if (IS_ERR(rtc)) {
+      rc = PTR_ERR(rtc);
+      rtc = NULL;
+      goto exit;
+  }
+  hym8563->rtc = rtc;
+printk("hym8563_probe ok\n");
+  return 0;-  i2c_set_clientdata(client, pcf8563);
+exit:
+  if (hym8563) {
+      wake_lock_destroy(&hym8563->wake_lock);
+  }
+  return rc;
+}-    pcf8563->rtc = devm_rtc_device_register(&client->dev,
-               pcf8563_driver.driver.name,
-               &pcf8563_rtc_ops, THIS_MODULE);
+static int  hym8563_remove(struct i2c_client *client)
+{
+  struct hym8563 *hym8563 = i2c_get_clientdata(client);- if (IS_ERR(pcf8563->rtc))
-       return PTR_ERR(pcf8563->rtc);
+  wake_lock_destroy(&hym8563->wake_lock);return 0;}-static int pcf8563_remove(struct i2c_client *client)
+
+void hym8563_shutdown(struct i2c_client * client)
+{ u8 regs[2];
+    int ret;
+    //disable clkout
+    regs[0] = 0x00;
+    ret=hym8563_i2c_set_regs(client, RTC_CLKOUT, regs, 1);
+    if(ret<0)
+        printk("rtc shutdown is error\n");
+}
+
+static int pcf8563_detect(struct i2c_client *new_client, struct i2c_board_info *info){
-   return 0;
+  struct i2c_adapter *adapter = new_client->adapter;
+
+  printk(" richard rtc pcf8563_detect: %s:bus[%d] addr[0x%x]\n", __func__, adapter->nr, new_client->addr);
+
+  if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+      return -ENODEV;
+
+  if (crtc_twi_id == adapter->nr) {
+      printk("rtc pcf8563_detect crtc_twi_id=%d\n",crtc_twi_id);
+      strlcpy(info->type, "rtc_hym8563", I2C_NAME_SIZE);
+      return 0;
+  }
+
+  return -ENODEV;}-static const struct i2c_device_id pcf8563_id[] = {
-   { "pcf8563", 0 },
-   { "rtc8564", 0 },
+
+static const struct i2c_device_id hym8563_id[] = {
+  { "rtc_hym8563", 0 },{ }};
-MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+MODULE_DEVICE_TABLE(i2c, hym8563_id);-#ifdef CONFIG_OF
-static const struct of_device_id pcf8563_of_match[] = {
-   { .compatible = "nxp,pcf8563" },
-   {}
+static struct of_device_id rtc_dt_ids[] = {
+  { .compatible = "rtc,hym8563" },
+  {},};
-MODULE_DEVICE_TABLE(of, pcf8563_of_match);
-#endif-static struct i2c_driver pcf8563_driver = {
+static const unsigned short normal_i2c[] = { 0x51, I2C_CLIENT_END };
+struct i2c_driver hym8563_driver = {
+  .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,.driver       = {
-       .name   = "rtc-pcf8563",
+      .name   = "rtc_hym8563",.owner   = THIS_MODULE,
-       .of_match_table = of_match_ptr(pcf8563_of_match),
+      .of_match_table = of_match_ptr(rtc_dt_ids),},
-   .probe      = pcf8563_probe,
-   .remove     = pcf8563_remove,
-   .id_table   = pcf8563_id,
+  .probe      = hym8563_probe,
+  .remove     = hym8563_remove,
+  .detect = pcf8563_detect,
+  //.shutdown=hym8563_shutdown,
+  .id_table   = hym8563_id,
+  .address_list = normal_i2c,};-module_i2c_driver(pcf8563_driver);
+
+
+static int crtc_fetch_sysconfig_para()
+{
+        int ret = -1;
+
+
+    struct device_node *np = NULL;
+    np = of_find_node_by_name(NULL,"crtc");
+    if (!np) {
+                printk("ERROR! get crtc failed, func:%s, line:%d\n",__FUNCTION__, __LINE__);
+                goto devicetree_get_item_err;
+    }
+printk("crtc crtc_fetch_sysconfig_para\n");
+    if (!of_device_is_available(np)) {
+            printk("%s: crtc is not used\n", __func__);
+            goto devicetree_get_item_err;
+        }else {
+            g_crtc_used = 1;
+      }
+printk("crtc crtc_fetch_sysconfig_para crtc_used=%d\n",g_crtc_used);
+    if(1 == g_crtc_used){
+           ret = of_property_read_u32(np, "crtc_twi_id", &crtc_twi_id);
+           if (ret) {
+                   pr_err("get crtc_twi_id is fail, %d\n", ret);
+                   goto devicetree_get_item_err;
+           }
+
+    }else{
+          pr_err("%s crtc_unused \n",__func__);
+    }
+printk("crtc crtc_fetch_sysconfig_para 2\n");
+        return ret;
+
+devicetree_get_item_err:
+printk("crtc crtc_fetch_sysconfig_para 3\n");
+        ret = -1;
+        return ret;
+
+}
+
+static int __init rtc_pcf8563_init(void)
+{
+  int ret;
+
+
+  if (crtc_fetch_sysconfig_para()) {
+      printk("fetch_crtc_sysconfig_para failed!\n");
+      return -1;
+  }
+  printk("step4 : rtc_pcf8563_init crtc_used=%d,crtc_twi_id=%d\n",g_crtc_used,crtc_twi_id);
+
+  if (g_crtc_used == 0) {
+      printk("*** crtc_used set to 0 !\n");
+      return -1;
+  }
+//gadap = i2c_get_adapter(crtc_twi_id);
+  ret = i2c_add_driver(&hym8563_driver);
+  if (ret < 0) {
+      printk("add pcf8563 i2c driver failed\n");
+      return -ENODEV;
+  }
+  /*ret = i2c_register_board_info(crtc_twi_id, pcf8563_i2c_board_info, ARRAY_SIZE(pcf8563_i2c_board_info));
+  if (ret < 0) {
+      printk("rtc_i2c_board_info add failed\n");
+      return ret;
+  }
+*/
+printk("step4 : rtc_pcf8563_init ok\n");
+  return (ret);
+}
+
+/*----------------------------------------------------------------------------*/
+static void __exit rtc_pcf8563_exit(void)
+{
+
+  i2c_del_driver(&hym8563_driver);
+}
+
+module_init(rtc_pcf8563_init);
+module_exit(rtc_pcf8563_exit);
+//module_i2c_driver(pcf8563_driver);MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
diff --git a/lichee/linux-3.10/drivers/rtc/rtc-pcf8563123.c b/lichee/linux-3.10/drivers/rtc/rtc-pcf8563123.c
new file mode 100755
index 0000000..e22f7bf
--- /dev/null
+++ b/lichee/linux-3.10/drivers/rtc/rtc-pcf8563123.c
@@ -0,0 +1,415 @@
+/*
+ * An I2C driver for the Philips PCF8563 RTC
+ * Copyright 2005-06 Tower Technologies
+ *
+ * Author: Alessandro Zummo <a.zummo@towertech.it>
+ * Maintainers: http://www.nslu2-linux.org/
+ *
+ * based on the other drivers in this same directory.
+ *
+ * http://www.semiconductors.philips.com/acrobat/datasheets/PCF8563-04.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/i2c.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of.h>
+
+#define DRV_VERSION "0.4.3"
+
+#define PCF8563_REG_ST1       0x00 /* status */
+#define PCF8563_REG_ST2       0x01
+
+#define PCF8563_REG_SC        0x02 /* datetime */
+#define PCF8563_REG_MN        0x03
+#define PCF8563_REG_HR        0x04
+#define PCF8563_REG_DM        0x05
+#define PCF8563_REG_DW        0x06
+#define PCF8563_REG_MO        0x07
+#define PCF8563_REG_YR        0x08
+
+#define PCF8563_REG_AMN       0x09 /* alarm */
+#define PCF8563_REG_AHR       0x0A
+#define PCF8563_REG_ADM       0x0B
+#define PCF8563_REG_ADW       0x0C
+
+#define PCF8563_REG_CLKO  0x0D /* clock out */
+#define PCF8563_REG_TMRC  0x0E /* timer control */
+#define PCF8563_REG_TMR       0x0F /* timer */
+
+#define PCF8563_SC_LV     0x80 /* low voltage */
+#define PCF8563_MO_C      0x80 /* century */
+
+static struct i2c_driver pcf8563_driver;
+struct i2c_adapter *gadap;
+static unsigned char crtc_twi_id = 0;
+unsigned int g_crtc_used = 0;
+struct pcf8563 {
+  struct rtc_device *rtc;
+  /*
+   * The meaning of MO_C bit varies by the chip type.
+   * From PCF8563 datasheet: this bit is toggled when the years
+   * register overflows from 99 to 00
+   *   0 indicates the century is 20xx
+   *   1 indicates the century is 19xx
+   * From RTC8564 datasheet: this bit indicates change of
+   * century. When the year digit data overflows from 99 to 00,
+   * this bit is set. By presetting it to 0 while still in the
+   * 20th century, it will be set in year 2000, ...
+   * There seems no reliable way to know how the system use this
+   * bit.  So let's do it heuristically, assuming we are live in
+   * 1970...2069.
+   */
+  int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
+  int voltage_low; /* incicates if a low_voltage was detected */
+};
+
+/*
+ * In the routines that deal directly with the pcf8563 hardware, we use
+ * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
+ */
+static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+  struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+  unsigned char buf[13] = { PCF8563_REG_ST1 };
+
+  struct i2c_msg msgs[] = {
+      {/* setup read ptr */
+          .addr = client->addr,
+          .len = 1,
+          .buf = buf
+      },
+      {/* read status + date */
+          .addr = client->addr,
+          .flags = I2C_M_RD,
+          .len = 13,
+          .buf = buf
+      },
+  };
+
+  /* read registers */
+  if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
+      dev_err(&client->dev, "%s: read error\n", __func__);
+      return -EIO;
+  }
+
+  if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
+      pcf8563->voltage_low = 1;
+      dev_info(&client->dev,
+          "low voltage detected, date/time is not reliable.\n");
+  }
+
+  dev_dbg(&client->dev,
+      "%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
+      "mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
+      __func__,
+      buf[0], buf[1], buf[2], buf[3],
+      buf[4], buf[5], buf[6], buf[7],
+      buf[8]);
+
+
+  tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
+  tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
+  tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
+  tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
+  tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
+  tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+  tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
+  if (tm->tm_year < 70)
+      tm->tm_year += 100;    /* assume we are in 1970...2069 */
+  /* detect the polarity heuristically. see note above. */
+  pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
+      (tm->tm_year >= 100) : (tm->tm_year < 100);
+
+  dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+      "mday=%d, mon=%d, year=%d, wday=%d\n",
+      __func__,
+      tm->tm_sec, tm->tm_min, tm->tm_hour,
+      tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+  /* the clock can give out invalid datetime, but we cannot return
+   * -EINVAL otherwise hwclock will refuse to set the time on bootup.
+   */
+  if (rtc_valid_tm(tm) < 0)
+      dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+  return 0;
+}
+
+static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+{
+  struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+  int i, err;
+  unsigned char buf[9];
+
+  dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+      "mday=%d, mon=%d, year=%d, wday=%d\n",
+      __func__,
+      tm->tm_sec, tm->tm_min, tm->tm_hour,
+      tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
+
+  /* hours, minutes and seconds */
+  buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
+  buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
+  buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
+
+  buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
+
+  /* month, 1 - 12 */
+  buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
+
+  /* year and century */
+  buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
+  if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
+      buf[PCF8563_REG_MO] |= PCF8563_MO_C;
+
+  buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
+
+  /* write register's data */
+  for (i = 0; i < 7; i++) {
+      unsigned char data[2] = { PCF8563_REG_SC + i,
+                      buf[PCF8563_REG_SC + i] };
+
+      err = i2c_master_send(client, data, sizeof(data));
+      if (err != sizeof(data)) {
+          dev_err(&client->dev,
+              "%s: err=%d addr=%02x, data=%02x\n",
+              __func__, err, data[0], data[1]);
+          return -EIO;
+      }
+  }
+
+  return 0;
+}
+
+#ifdef CONFIG_RTC_INTF_DEV
+static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
+{
+  struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev));
+  struct rtc_time tm;
+
+  switch (cmd) {
+  case RTC_VL_READ:
+      if (pcf8563->voltage_low)
+          dev_info(dev, "low voltage detected, date/time is not reliable.\n");
+
+      if (copy_to_user((void __user *)arg, &pcf8563->voltage_low,
+                  sizeof(int)))
+          return -EFAULT;
+      return 0;
+  case RTC_VL_CLR:
+      /*
+       * Clear the VL bit in the seconds register in case
+       * the time has not been set already (which would
+       * have cleared it). This does not really matter
+       * because of the cached voltage_low value but do it
+       * anyway for consistency.
+       */
+      if (pcf8563_get_datetime(to_i2c_client(dev), &tm))
+          pcf8563_set_datetime(to_i2c_client(dev), &tm);
+
+      /* Clear the cached value. */
+      pcf8563->voltage_low = 0;
+
+      return 0;
+  default:
+      return -ENOIOCTLCMD;
+  }
+}
+#else
+#define pcf8563_rtc_ioctl NULL
+#endif
+
+static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+  return pcf8563_get_datetime(to_i2c_client(dev), tm);
+}
+
+static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+  return pcf8563_set_datetime(to_i2c_client(dev), tm);
+}
+
+static const struct rtc_class_ops pcf8563_rtc_ops = {
+  .ioctl      = pcf8563_rtc_ioctl,
+  .read_time  = pcf8563_rtc_read_time,
+  .set_time   = pcf8563_rtc_set_time,
+};
+
+static int pcf8563_probe(struct i2c_client *client,
+              const struct i2c_device_id *id)
+{
+  struct pcf8563 *pcf8563;
+
+  dev_dbg(&client->dev, "%s\n", __func__);
+printk("rtc pcf8563_probe\n");
+  if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+      return -ENODEV;
+printk("rtc pcf8563_probe 1\n");
+  pcf8563 = devm_kzalloc(&client->dev, sizeof(struct pcf8563),
+              GFP_KERNEL);
+  if (!pcf8563)
+      return -ENOMEM;
+printk("rtc pcf8563_probe 2\n");
+  dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
+  i2c_set_clientdata(client, pcf8563);
+
+  pcf8563->rtc = devm_rtc_device_register(&client->dev,
+              pcf8563_driver.driver.name,
+              &pcf8563_rtc_ops, THIS_MODULE);
+
+  if (IS_ERR(pcf8563->rtc))
+      return PTR_ERR(pcf8563->rtc);
+printk("rtc pcf8563_probe ok\n");
+  return 0;
+}
+
+static int pcf8563_detect(struct i2c_client *new_client, struct i2c_board_info *info)
+{
+  struct i2c_adapter *adapter = new_client->adapter;
+
+  printk(" richard rtc pcf8563_detect: %s:bus[%d] addr[0x%x]\n", __func__, adapter->nr, new_client->addr);
+
+  if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+      return -ENODEV;
+
+  if (crtc_twi_id == adapter->nr) {
+      printk("rtc pcf8563_detect crtc_twi_id=%d\n",crtc_twi_id);
+      strlcpy(info->type, "pcf8563", I2C_NAME_SIZE);
+      return 0;
+  }
+
+  return -ENODEV;
+}
+
+static int pcf8563_remove(struct i2c_client *client)
+{
+  return 0;
+}
+
+static const struct i2c_device_id pcf8563_id[] = {
+  { "pcf8563", 0 },
+  //{ "rtc8564", 0 },
+  { }
+};
+MODULE_DEVICE_TABLE(i2c, pcf8563_id);
+
+//#ifdef CONFIG_OF
+static const struct of_device_id pcf8563_of_match[] = {
+  { .compatible = "pcf8563", },
+  {}
+};
+MODULE_DEVICE_TABLE(of, pcf8563_of_match);
+//#endif
+static const unsigned short normal_i2c[] = { 0x51, I2C_CLIENT_END };
+static struct i2c_driver pcf8563_driver = {
+  .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+  .driver     = {
+      .name   = "pcf8563",
+      .owner  = THIS_MODULE,
+      .of_match_table = of_match_ptr(pcf8563_of_match),
+  },
+  .probe      = pcf8563_probe,
+  .remove     = pcf8563_remove,
+  .detect = pcf8563_detect,
+  .id_table   = pcf8563_id,
+  .address_list = normal_i2c,
+};
+
+static int crtc_fetch_sysconfig_para()
+{
+        int ret = -1;
+
+
+    struct device_node *np = NULL;
+    np = of_find_node_by_name(NULL,"crtc");
+    if (!np) {
+                printk("ERROR! get crtc failed, func:%s, line:%d\n",__FUNCTION__, __LINE__);
+                goto devicetree_get_item_err;
+    }
+printk("crtc crtc_fetch_sysconfig_para\n");
+    if (!of_device_is_available(np)) {
+            printk("%s: crtc is not used\n", __func__);
+            goto devicetree_get_item_err;
+        }else {
+            g_crtc_used = 1;
+      }
+printk("crtc crtc_fetch_sysconfig_para crtc_used=%d\n",g_crtc_used);
+    if(1 == g_crtc_used){
+           ret = of_property_read_u32(np, "crtc_twi_id", &crtc_twi_id);
+           if (ret) {
+                   pr_err("get crtc_twi_id is fail, %d\n", ret);
+                   goto devicetree_get_item_err;
+           }
+
+    }else{
+          pr_err("%s crtc_unused \n",__func__);
+    }
+printk("crtc crtc_fetch_sysconfig_para 2\n");
+        return ret;
+
+devicetree_get_item_err:
+printk("crtc crtc_fetch_sysconfig_para 3\n");
+        ret = -1;
+        return ret;
+
+}
+static struct i2c_board_info __initdata pcf8563_i2c_board_info[] = {
+  {
+      .type = "pcf8563",
+      .addr = 0x51,
+  },
+};
+static int __init rtc_pcf8563_init(void)
+{
+  int ret;
+
+
+  if (crtc_fetch_sysconfig_para()) {
+      printk("fetch_crtc_sysconfig_para failed!\n");
+      return -1;
+  }
+  printk("step4 : rtc_pcf8563_init crtc_used=%d,crtc_twi_id=%d\n",g_crtc_used,crtc_twi_id);
+
+  if (g_crtc_used == 0) {
+      printk("*** crtc_used set to 0 !\n");
+      return -1;
+  }
+//gadap = i2c_get_adapter(crtc_twi_id);
+  ret = i2c_add_driver(&pcf8563_driver);
+  if (ret < 0) {
+      printk("add pcf8563 i2c driver failed\n");
+      return -ENODEV;
+  }
+  /*ret = i2c_register_board_info(crtc_twi_id, pcf8563_i2c_board_info, ARRAY_SIZE(pcf8563_i2c_board_info));
+  if (ret < 0) {
+      printk("rtc_i2c_board_info add failed\n");
+      return ret;
+  }
+*/
+printk("step4 : rtc_pcf8563_init ok\n");
+  return (ret);
+}
+
+/*----------------------------------------------------------------------------*/
+static void __exit rtc_pcf8563_exit(void)
+{
+
+  i2c_del_driver(&pcf8563_driver);
+}
+
+module_init(rtc_pcf8563_init);
+module_exit(rtc_pcf8563_exit);
+//module_i2c_driver(pcf8563_driver);
+
+MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
+MODULE_DESCRIPTION("Philips PCF8563/Epson RTC8564 RTC driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
diff --git a/lichee/linux-3.10/drivers/rtc/rtc-sunxi.c b/lichee/linux-3.10/drivers/rtc/rtc-sunxi.c
index a47ac21..075dc1b 100755
--- a/lichee/linux-3.10/drivers/rtc/rtc-sunxi.c
+++ b/lichee/linux-3.10/drivers/rtc/rtc-sunxi.c
@@ -448,17 +448,20 @@ static int sunxi_rtc_probe(struct platform_device *pdev)dev_err(&pdev->dev, "Unable to setup RTC data\n");return -ENODEV;}
-
+  chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);if (!chip)return -ENOMEM;
-
+  platform_set_drvdata(pdev, chip);chip->dev = &pdev->dev;res = platform_get_resource(pdev, IORESOURCE_MEM, 0);chip->base = devm_ioremap_resource(&pdev->dev, res);
-
+
+  //modify
+  writel(0, chip->base + SUNXI_VDD_RTC);
+  if (IS_ERR(chip->base))return PTR_ERR(chip->base);@@ -541,7 +544,7 @@ static int sunxi_rtc_probe(struct platform_device *pdev)dev_info(&pdev->dev, "RTC enabled\n");return 0;
-
+  fail:pm_runtime_put_sync(&pdev->dev);pm_runtime_disable(&pdev->dev);
diff --git a/lichee/linux-3.10/drivers/rtc/rtc-sunxi.h b/lichee/linux-3.10/drivers/rtc/rtc-sunxi.h
old mode 100644
new mode 100755
index 165ef5e..caf1e11
--- a/lichee/linux-3.10/drivers/rtc/rtc-sunxi.h
+++ b/lichee/linux-3.10/drivers/rtc/rtc-sunxi.h
@@ -23,6 +23,8 @@#define SUNXI_ALARM_CONFIG                      0x0050#define SUNXI_ALRM_WAKEUP_OUTPUT_EN             BIT(0)+#define SUNXI_VDD_RTC               0x0190
+/* alarm0 which based on seconds can power on system,* while alarm1 can't, so alarm1 is not used.*/

全志 添加外挂RTC Hym8563相关推荐

  1. 电脑本地视频怎么添加外挂字幕-奇它博客

    我们通过网盘(天翼网盘.迅雷盘等)下载的高画质电影没有字幕或者没有中文字幕的时候,可以通过下载外挂字幕的方法来换字幕.当然如果视频本身使用了内嵌字幕,那么内嵌字幕是无法被替换的.电脑本地视频怎么添加外 ...

  2. 杰理之添加外挂 flash 驱动及实现音乐播放功能

    功能简单说明:在音乐模式下实现播放外挂 flash 里面的歌曲的功能,操作方式与 SD 卡,U 盘一致. 注意:flash 需预先把音乐文件和 fat 文件系统烧录进 flash.目前不支持写操作. ...

  3. 杰里之AC692x 添加外挂 flash 驱动及实现音乐播放功能篇

    功能简单说明:在音乐模式下实现播放外挂 flash 里面的歌曲的功能,操作方式与 SD 卡,U 盘一致. 注意:flash 需预先把音乐文件和 fat 文件系统烧录进 flash.目前不支持写操作. ...

  4. Linux添加PCF8563 RTC支持

    文章目录 1. 添加驱动支持 2. 添加设备树 3. 测试 原文链接:https://blog.csdn.net/WXXGoodJob/article/details/88692949 SOC:RK3 ...

  5. RK3288下添加PCF8563 RTC支持

    SOC:RK3288 kernel:Linux4.4 1.  添加驱动支持 Device Drivers  ---> [*] Real Time Clock  ---> [*]   Set ...

  6. 树莓派3B添加DS1307 RTC时钟模块

    前段时间用树莓派做了一个小项目,到实施阶段后才突然发现树莓派没有硬件时钟,最后在某宝找到了时钟模块,商家只提供硬件,不提供技术服务,只能百度搜索配置方法,最后参照树莓派 3B+ 安装 DS1307 R ...

  7. 全志 添加PWM7参数

    添加pwm7的参数diff --git a/lichee/linux-3.10/arch/arm/boot/dts/sun8iw11p1.dtsi b/lichee/linux-3.10/arch/a ...

  8. 杰理之添加外挂 flash 驱动及实现音乐播放功能【篇】

    功能简单说明:在音乐模式下实现播放外挂 flash 里面的歌曲的功能,操作方式与 SD 卡,U 盘一致. 注意:flash 需预先把音乐文件和 fat 文件系统烧录进 flash.目前不支持写操作.

  9. 全志 添加TP休眠触摸唤醒 Patch

    add TP触摸屏唤醒diff --git a/android/frameworks/base/packages/SettingsProvider/res/values/defaults.xml b/ ...

最新文章

  1. 数据结构与算法(8-2)有序表查找(折半查找(二分查找)、插值查找)
  2. BeanUtils使用
  3. php5.3.0以上出现Strict Standards错误
  4. MATLAB实战系列(二十八)-用matlab爬取火车票信息
  5. 关于jQuery的$.getJSON乱码问题
  6. 【MFC】在工具栏中添加编辑框
  7. 关于 ABAP 调试器里的 16 进制值的显示问题
  8. 学习RUNOOB.COM进度一
  9. linux 查看本机网关地址,linux查看服务器网关地址
  10. Kiwi浏览器 MIUI禁第三方广告 ADB停用系统应用
  11. php 数组重复最多,PHP获取数组中重复最多元素的简单示例
  12. 线路板铜厚测试软件,厚铜线路板的铜厚是如何实现的
  13. 深度学习模型提升模型效果的常见方法
  14. Ubuntu 12.04安装及配置vsftp步骤
  15. 读书笔记18:命令模式
  16. 服务器显示跨域请求,出现跨域问题的原因及其解决方法
  17. python aiml开发文档_Python AIML搭建聊天机器人
  18. Origin画甘特图-II
  19. PS、PR、AE、AI、AU区别
  20. 冰点还原密码查看工具

热门文章

  1. 【DONE】dbeaver不会用,请教!!!
  2. Microsoft SQL Server 2005 安装程序错误解疑
  3. typora图床教程-阿里云版
  4. linux case if for语法
  5. 什么是 Webhook?
  6. hadoop yarn的三种资源调度器详解
  7. golang网络编程
  8. Scala集合:List修改及删除数据
  9. Linux shell只读变量
  10. Play! Framework 系列(一):初探 play 框架