diff options
Diffstat (limited to 'drivers/rtc/rtc-mpc5121.c')
| -rw-r--r-- | drivers/rtc/rtc-mpc5121.c | 81 | 
1 files changed, 73 insertions, 8 deletions
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 09ccd8d3ba2a..da60915818b6 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -3,6 +3,7 @@   *   * Copyright 2007, Domen Puncer <[email protected]>   * Copyright 2008, Freescale Semiconductor, Inc. All rights reserved. + * Copyright 2011, Dmitry Eremin-Solenikov   *   * 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 @@ -145,6 +146,55 @@ static int mpc5121_rtc_set_time(struct device *dev, struct rtc_time *tm)  	return 0;  } +static int mpc5200_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs; +	int tmp; + +	tm->tm_sec = in_8(®s->second); +	tm->tm_min = in_8(®s->minute); + +	/* 12 hour format? */ +	if (in_8(®s->hour) & 0x20) +		tm->tm_hour = (in_8(®s->hour) >> 1) + +			(in_8(®s->hour) & 1 ? 12 : 0); +	else +		tm->tm_hour = in_8(®s->hour); + +	tmp = in_8(®s->wday_mday); +	tm->tm_mday = tmp & 0x1f; +	tm->tm_mon = in_8(®s->month) - 1; +	tm->tm_year = in_be16(®s->year) - 1900; +	tm->tm_wday = (tmp >> 5) % 7; +	tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); +	tm->tm_isdst = 0; + +	return 0; +} + +static int mpc5200_rtc_set_time(struct device *dev, struct rtc_time *tm) +{ +	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); +	struct mpc5121_rtc_regs __iomem *regs = rtc->regs; + +	mpc5121_rtc_update_smh(regs, tm); + +	/* date */ +	out_8(®s->month_set, tm->tm_mon + 1); +	out_8(®s->weekday_set, tm->tm_wday ? tm->tm_wday : 7); +	out_8(®s->date_set, tm->tm_mday); +	out_be16(®s->year_set, tm->tm_year + 1900); + +	/* set date sequence */ +	out_8(®s->set_date, 0x1); +	out_8(®s->set_date, 0x3); +	out_8(®s->set_date, 0x1); +	out_8(®s->set_date, 0x0); + +	return 0; +} +  static int mpc5121_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)  {  	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev); @@ -248,11 +298,18 @@ static const struct rtc_class_ops mpc5121_rtc_ops = {  	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,  }; +static const struct rtc_class_ops mpc5200_rtc_ops = { +	.read_time = mpc5200_rtc_read_time, +	.set_time = mpc5200_rtc_set_time, +	.read_alarm = mpc5121_rtc_read_alarm, +	.set_alarm = mpc5121_rtc_set_alarm, +	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable, +}; +  static int __devinit mpc5121_rtc_probe(struct platform_device *op)  {  	struct mpc5121_rtc_data *rtc;  	int err = 0; -	u32 ka;  	rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);  	if (!rtc) @@ -287,15 +344,22 @@ static int __devinit mpc5121_rtc_probe(struct platform_device *op)  		goto out_dispose2;  	} -	ka = in_be32(&rtc->regs->keep_alive); -	if (ka & 0x02) { -		dev_warn(&op->dev, -			"mpc5121-rtc: Battery or oscillator failure!\n"); -		out_be32(&rtc->regs->keep_alive, ka); +	if (of_device_is_compatible(op->dev.of_node, "fsl,mpc5121-rtc")) { +		u32 ka; +		ka = in_be32(&rtc->regs->keep_alive); +		if (ka & 0x02) { +			dev_warn(&op->dev, +				"mpc5121-rtc: Battery or oscillator failure!\n"); +			out_be32(&rtc->regs->keep_alive, ka); +		} + +		rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, +						&mpc5121_rtc_ops, THIS_MODULE); +	} else { +		rtc->rtc = rtc_device_register("mpc5200-rtc", &op->dev, +						&mpc5200_rtc_ops, THIS_MODULE);  	} -	rtc->rtc = rtc_device_register("mpc5121-rtc", &op->dev, -					&mpc5121_rtc_ops, THIS_MODULE);  	if (IS_ERR(rtc->rtc)) {  		err = PTR_ERR(rtc->rtc);  		goto out_free_irq; @@ -340,6 +404,7 @@ static int __devexit mpc5121_rtc_remove(struct platform_device *op)  static struct of_device_id mpc5121_rtc_match[] __devinitdata = {  	{ .compatible = "fsl,mpc5121-rtc", }, +	{ .compatible = "fsl,mpc5200-rtc", },  	{},  };  |