Ejemplo n.º 1
0
/*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;
	hym8563_i2c_set_regs(client, RTC_CTL1, regs, 1);		
	
	//disable clkout
	regs[0] = 0x80;
	hym8563_i2c_set_regs(client, RTC_CLKOUT, regs, 1);
	/*enable alarm interrupt*/
	hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
	regs[0] = 0x0;
	regs[0] |= AIE;
	hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
	hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);

	sr = hym8563_i2c_read_regs(client, RTC_CTL2, regs, 1);
	if (sr < 0) {
		pr_err("read CTL2 err\n");
	}
	
	if(regs[0] & (AF|TF))
	{
		regs[0] &= ~(AF|TF);
		hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
	}
	mutex_unlock(&hym8563->mutex);
	return 0;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
static void hym8563_work_func(struct work_struct *work)
{	
	struct hym8563 *hym8563 = container_of(work, struct hym8563, work);
	struct i2c_client *client = hym8563->client;
	struct rtc_time now;
	u8 data;

	pr_debug("enter\n");

	mutex_lock(&hym8563->mutex);
	hym8563_i2c_read_regs(client, RTC_CTL2, &data, 1);
	data &= ~AF;
	hym8563_i2c_set_regs(client, RTC_CTL2, &data, 1);
	mutex_unlock(&hym8563->mutex);

	hym8563_read_datetime(client, &now);

	mutex_lock(&hym8563->mutex);
	if (hym8563->alarm.enabled && hym8563->alarm.time.tm_sec > now.tm_sec) {
		long timeout = hym8563->alarm.time.tm_sec - now.tm_sec + 1;
		pr_info("stay awake %lds\n", timeout);
		wake_lock_timeout(&hym8563->wake_lock, timeout * HZ);
	}

	if (!hym8563->exiting)
		enable_irq(hym8563->irq);
	mutex_unlock(&hym8563->mutex);
}
Ejemplo n.º 4
0
static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)	
{
	u8 ret = 0;
	struct hym8563 *hym8563 = i2c_get_clientdata(client);
	u8 regs[HYM8563_RTC_SECTION_LEN] = { 0, };
	u8 mon_day;
//	u8 i;

	pr_debug("%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 ret;
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
int hdmi_set_data(int data)
{
    u8 regs = (data+1)&0xff;
    if(gClient)
        hym8563_i2c_set_regs(gClient, RTC_T_COUNT, &regs, 1);
    else 
    {
        printk("%s rtc has no init\n",__func__);
        return -1;
    }   
    return 0;
}
Ejemplo n.º 7
0
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, };
	
	pr_debug("enter\n");
	mutex_lock(&hym8563->mutex);
	hym8563_i2c_read_regs(client, RTC_A_MIN, regs, 4);
	regs[0] = 0x0;
	hym8563_i2c_set_regs(client, RTC_CTL2, regs, 1);
	mutex_unlock(&hym8563->mutex);
	return 0;
}
Ejemplo n.º 8
0
static irqreturn_t hym8563_wakeup_irq(int irq, void *data)
{
	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;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
static int __devinit hym8563_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	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,
	};	
	
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
		return -ENODEV;
		
	hym8563 = kzalloc(sizeof(struct hym8563), GFP_KERNEL);
	if (!hym8563) {
		return -ENOMEM;
	}

	gClient = client;	
	hym8563->client = client;
	hym8563->alarm.enabled = 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 
	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);
	}

	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(gpio_request(client->irq, "rtc gpio"))
	{
		dev_err(&client->dev, "gpio request fail\n");
		gpio_free(client->irq);
		goto exit;
	}
	
	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;
	}	
	enable_irq_wake(hym8563->irq);

	rtc = rtc_device_register(client->name, &client->dev,
				  &hym8563_rtc_ops, THIS_MODULE);
	if (IS_ERR(rtc)) {
		rc = PTR_ERR(rtc);
		rtc = NULL;
		goto exit;
	}
	hym8563->rtc = rtc;

	return 0;

exit:
	if (rtc)
		rtc_device_unregister(rtc);
	if (hym8563) {
		wake_lock_destroy(&hym8563->wake_lock);
		kfree(hym8563);
	}
	return rc;
}

static int __devexit hym8563_remove(struct i2c_client *client)
{
	struct hym8563 *hym8563 = i2c_get_clientdata(client);

	if (hym8563->irq > 0) {
		mutex_lock(&hym8563->mutex);
		hym8563->exiting = 1;
		mutex_unlock(&hym8563->mutex);

		free_irq(hym8563->irq, hym8563);
		cancel_work_sync(&hym8563->work);
	}

	rtc_device_unregister(hym8563->rtc);
	wake_lock_destroy(&hym8563->wake_lock);
	kfree(hym8563);
	hym8563 = NULL;

	return 0;
}


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");
}
Ejemplo n.º 11
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;
	
	pr_debug("%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;
}
Ejemplo n.º 12
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;

	pr_debug("%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);
	if (alarm->enabled && now.tm_year == tm->tm_year &&
	    now.tm_mon == tm->tm_mon && now.tm_mday == tm->tm_mday &&
	    now.tm_hour == tm->tm_hour && now.tm_min == tm->tm_min &&
	    tm->tm_sec > now.tm_sec) {
		long timeout = tm->tm_sec - now.tm_sec + 1;
		pr_info("stay awake %lds\n", timeout);
		wake_lock_timeout(&hym8563->wake_lock, timeout * HZ);
	}

	mutex_lock(&hym8563->mutex);
	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);

	mutex_unlock(&hym8563->mutex);
	return 0;
}