162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Setup code for PC-style Real-Time Clock.
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Author: Wade Farnsworth <wfarnsworth@mvista.com>
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * 2007 (c) MontaVista Software, Inc. This file is licensed under
762306a36Sopenharmony_ci * the terms of the GNU General Public License version 2. This program
862306a36Sopenharmony_ci * is licensed "as is" without any warranty of any kind, whether express
962306a36Sopenharmony_ci * or implied.
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/platform_device.h>
1362306a36Sopenharmony_ci#include <linux/err.h>
1462306a36Sopenharmony_ci#include <linux/init.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/mc146818rtc.h>
1762306a36Sopenharmony_ci#include <linux/of_address.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int  __init add_rtc(void)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	struct device_node *np;
2362306a36Sopenharmony_ci	struct platform_device *pd;
2462306a36Sopenharmony_ci	struct resource res[2];
2562306a36Sopenharmony_ci	unsigned int num_res = 1;
2662306a36Sopenharmony_ci	int ret;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	memset(&res, 0, sizeof(res));
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "pnpPNP,b00");
3162306a36Sopenharmony_ci	if (!np)
3262306a36Sopenharmony_ci		return -ENODEV;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	ret = of_address_to_resource(np, 0, &res[0]);
3562306a36Sopenharmony_ci	of_node_put(np);
3662306a36Sopenharmony_ci	if (ret)
3762306a36Sopenharmony_ci		return ret;
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	/*
4062306a36Sopenharmony_ci	 * RTC_PORT(x) is hardcoded in asm/mc146818rtc.h.  Verify that the
4162306a36Sopenharmony_ci	 * address provided by the device node matches.
4262306a36Sopenharmony_ci	 */
4362306a36Sopenharmony_ci	if (res[0].start != RTC_PORT(0))
4462306a36Sopenharmony_ci		return -EINVAL;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "chrp,iic");
4762306a36Sopenharmony_ci	if (!np)
4862306a36Sopenharmony_ci		np = of_find_compatible_node(NULL, NULL, "pnpPNP,000");
4962306a36Sopenharmony_ci	if (np) {
5062306a36Sopenharmony_ci		of_node_put(np);
5162306a36Sopenharmony_ci		/*
5262306a36Sopenharmony_ci		 * Use a fixed interrupt value of 8 since on PPC if we are
5362306a36Sopenharmony_ci		 * using this its off an i8259 which we ensure has interrupt
5462306a36Sopenharmony_ci		 * numbers 0..15.
5562306a36Sopenharmony_ci		 */
5662306a36Sopenharmony_ci		res[1].start = 8;
5762306a36Sopenharmony_ci		res[1].end = 8;
5862306a36Sopenharmony_ci		res[1].flags = IORESOURCE_IRQ;
5962306a36Sopenharmony_ci		num_res++;
6062306a36Sopenharmony_ci	}
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	pd = platform_device_register_simple("rtc_cmos", -1,
6362306a36Sopenharmony_ci					     &res[0], num_res);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return PTR_ERR_OR_ZERO(pd);
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_cifs_initcall(add_rtc);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ciMODULE_LICENSE("GPL");
70