From 6b6d790ed2011cf836fa79a8d096e9a1d9f67179 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=83=AD=E6=AF=85?= Date: Wed, 14 May 2014 15:52:54 +0800 Subject: [PATCH] rtc : support for rtc-HYM8563 --- arch/arm/boot/dts/rk3288-p977.dts | 6 ++ arch/arm/boot/dts/rk3288-tb.dts | 7 ++ drivers/rtc/Kconfig | 9 +++ drivers/rtc/Makefile | 1 + drivers/rtc/rtc-HYM8563.c | 102 ++++++++++++++++++++++-------- 5 files changed, 97 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/rk3288-p977.dts b/arch/arm/boot/dts/rk3288-p977.dts index d220737117d5..8acef34e0d5c 100755 --- a/arch/arm/boot/dts/rk3288-p977.dts +++ b/arch/arm/boot/dts/rk3288-p977.dts @@ -322,6 +322,12 @@ is_dc_charge = <1>; is_usb_charge = <0>; }; + + rtc@d { + compatible = "rtc,hym8563"; + reg = <0xd>; + irq_gpio = <&gpio0 GPIO_A4 GPIO_ACTIVE_LOW>; + }; }; &i2c1 { diff --git a/arch/arm/boot/dts/rk3288-tb.dts b/arch/arm/boot/dts/rk3288-tb.dts index 114645f8a042..754ced4b5ca5 100644 --- a/arch/arm/boot/dts/rk3288-tb.dts +++ b/arch/arm/boot/dts/rk3288-tb.dts @@ -425,6 +425,13 @@ is_dc_charge = <1>; is_usb_charge = <0>; }; + + rtc@d { + compatible = "rtc,hym8563"; + reg = <0xd>; + irq_gpio = <&gpio0 GPIO_A4 GPIO_ACTIVE_LOW>; + }; + }; &i2c1 { diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 65138a897514..9eb29e758206 100755 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -332,6 +332,15 @@ config RTC_DRV_PCF8563 This driver can also be built as a module. If so, the module will be called rtc-pcf8563. +config RTC_HYM8563 + tristate "rtc of HYM8563" + help + If you say yes here you get support for the + HYM8563 RTC chip. The HYM8564 should work as well. + + This driver can also be built as a module. If so, the module + will be called rtc-HYM8563. + config RTC_DRV_PCF8583 tristate "Philips PCF8583" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index c2b838e98980..00df76aaabd9 100755 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -85,6 +85,7 @@ obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o +obj-$(CONFIG_RTC_HYM8563) += rtc-HYM8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o diff --git a/drivers/rtc/rtc-HYM8563.c b/drivers/rtc/rtc-HYM8563.c index 8288f95d4216..ce088d3e497d 100755 --- a/drivers/rtc/rtc-HYM8563.c +++ b/drivers/rtc/rtc-HYM8563.c @@ -22,11 +22,8 @@ #include #include #include -#include -#include #include "rtc-HYM8563.h" -#include - +#include #define RTC_SPEED 200 * 1000 struct hym8563 { @@ -41,6 +38,55 @@ struct hym8563 { }; static struct i2c_client *gClient = NULL; +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); + + msg.addr = client->addr; + msg.flags = client->flags; + msg.len = count + 1; + msg.buf = (char *)tx_buf; + msg.scl_rate = scl_rate; + + ret = i2c_transfer(adap, &msg, 1); + kfree(tx_buf); + return (ret == 1) ? count : ret; + +} + +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 = ®_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 int hym8563_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], unsigned len) { int ret; @@ -158,7 +204,7 @@ exit: static int hym8563_read_datetime(struct i2c_client *client, struct rtc_time *tm) { struct hym8563 *hym8563 = i2c_get_clientdata(client); - u8 i,regs[HYM8563_RTC_SECTION_LEN] = { 0, }; + 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, ®s[i], 1); @@ -204,8 +250,8 @@ 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,i; - u8 ret = 0; + u8 mon_day; + //u8 ret = 0; pr_debug("%4d-%02d-%02d(%d) %02d:%02d:%02d\n", 1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday, @@ -493,7 +539,7 @@ static const struct rtc_class_ops hym8563_rtc_ops = { .proc = hym8563_rtc_proc }; -static int __devinit hym8563_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) { int rc = 0; u8 reg = 0; @@ -508,11 +554,15 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d .tm_min = 0, .tm_sec = 0, }; + + struct device_node *np = client->dev.of_node; + unsigned long irq_flags; + int result; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - hym8563 = kzalloc(sizeof(struct hym8563), GFP_KERNEL); + hym8563 = devm_kzalloc(&client->dev,sizeof(*hym8563), GFP_KERNEL); if (!hym8563) { return -ENOMEM; } @@ -541,20 +591,14 @@ static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_d hym8563_set_time(client, &tm); //initialize the hym8563 } - if(gpio_request(client->irq, "rtc gpio")) - { - dev_err(&client->dev, "gpio request fail\n"); - gpio_free(client->irq); - goto exit; - } + client->irq = of_get_named_gpio_flags(np, "irq_gpio", 0,(enum of_gpio_flags *)&irq_flags); hym8563->irq = gpio_to_irq(client->irq); - gpio_pull_updown(client->irq,GPIOPullUp); - if (request_threaded_irq(hym8563->irq, NULL, hym8563_wakeup_irq, IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->dev.driver->name, hym8563) < 0) - { - printk("unable to request rtc irq\n"); - goto exit; - } + 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(KERN_ERR "%s:fail to request irq = %d, ret = 0x%x\n",__func__, hym8563->irq, result); + goto exit; + } enable_irq_wake(hym8563->irq); rtc = rtc_device_register(client->name, &client->dev, @@ -578,7 +622,7 @@ exit: return rc; } -static int __devexit hym8563_remove(struct i2c_client *client) +static int hym8563_remove(struct i2c_client *client) { struct hym8563 *hym8563 = i2c_get_clientdata(client); @@ -618,18 +662,20 @@ static const struct i2c_device_id hym8563_id[] = { }; MODULE_DEVICE_TABLE(i2c, hym8563_id); -static struct i2c_driver hym8563_driver = { +static struct of_device_id rtc_dt_ids[] = { + { .compatible = "rtc,hym8563" }, + {}, +}; + +struct i2c_driver hym8563_driver = { .driver = { .name = "rtc_hym8563", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(rtc_dt_ids), }, .probe = hym8563_probe, - .remove = __devexit_p(hym8563_remove), -#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188) || defined(CONFIG_ARCH_RK319X) + .remove = hym8563_remove, //.shutdown=hym8563_shutdown, -#else - .shutdown=hym8563_shutdown, -#endif .id_table = hym8563_id, }; -- 2.34.1