162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Support for OLPC XO-1 Real Time Clock (RTC) 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2011 One Laptop per Child 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/mc146818rtc.h> 962306a36Sopenharmony_ci#include <linux/platform_device.h> 1062306a36Sopenharmony_ci#include <linux/rtc.h> 1162306a36Sopenharmony_ci#include <linux/of.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <asm/msr.h> 1462306a36Sopenharmony_ci#include <asm/olpc.h> 1562306a36Sopenharmony_ci#include <asm/x86_init.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic void rtc_wake_on(struct device *dev) 1862306a36Sopenharmony_ci{ 1962306a36Sopenharmony_ci olpc_xo1_pm_wakeup_set(CS5536_PM_RTC); 2062306a36Sopenharmony_ci} 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic void rtc_wake_off(struct device *dev) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci olpc_xo1_pm_wakeup_clear(CS5536_PM_RTC); 2562306a36Sopenharmony_ci} 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistatic struct resource rtc_platform_resource[] = { 2862306a36Sopenharmony_ci [0] = { 2962306a36Sopenharmony_ci .start = RTC_PORT(0), 3062306a36Sopenharmony_ci .end = RTC_PORT(1), 3162306a36Sopenharmony_ci .flags = IORESOURCE_IO, 3262306a36Sopenharmony_ci }, 3362306a36Sopenharmony_ci [1] = { 3462306a36Sopenharmony_ci .start = RTC_IRQ, 3562306a36Sopenharmony_ci .end = RTC_IRQ, 3662306a36Sopenharmony_ci .flags = IORESOURCE_IRQ, 3762306a36Sopenharmony_ci } 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic struct cmos_rtc_board_info rtc_info = { 4162306a36Sopenharmony_ci .rtc_day_alarm = 0, 4262306a36Sopenharmony_ci .rtc_mon_alarm = 0, 4362306a36Sopenharmony_ci .rtc_century = 0, 4462306a36Sopenharmony_ci .wake_on = rtc_wake_on, 4562306a36Sopenharmony_ci .wake_off = rtc_wake_off, 4662306a36Sopenharmony_ci}; 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_cistatic struct platform_device xo1_rtc_device = { 4962306a36Sopenharmony_ci .name = "rtc_cmos", 5062306a36Sopenharmony_ci .id = -1, 5162306a36Sopenharmony_ci .num_resources = ARRAY_SIZE(rtc_platform_resource), 5262306a36Sopenharmony_ci .dev.platform_data = &rtc_info, 5362306a36Sopenharmony_ci .resource = rtc_platform_resource, 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistatic int __init xo1_rtc_init(void) 5762306a36Sopenharmony_ci{ 5862306a36Sopenharmony_ci int r; 5962306a36Sopenharmony_ci struct device_node *node; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci node = of_find_compatible_node(NULL, NULL, "olpc,xo1-rtc"); 6262306a36Sopenharmony_ci if (!node) 6362306a36Sopenharmony_ci return 0; 6462306a36Sopenharmony_ci of_node_put(node); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci pr_info("olpc-xo1-rtc: Initializing OLPC XO-1 RTC\n"); 6762306a36Sopenharmony_ci rdmsrl(MSR_RTC_DOMA_OFFSET, rtc_info.rtc_day_alarm); 6862306a36Sopenharmony_ci rdmsrl(MSR_RTC_MONA_OFFSET, rtc_info.rtc_mon_alarm); 6962306a36Sopenharmony_ci rdmsrl(MSR_RTC_CEN_OFFSET, rtc_info.rtc_century); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci r = platform_device_register(&xo1_rtc_device); 7262306a36Sopenharmony_ci if (r) 7362306a36Sopenharmony_ci return r; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci x86_platform.legacy.rtc = 0; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci device_init_wakeup(&xo1_rtc_device.dev, 1); 7862306a36Sopenharmony_ci return 0; 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ciarch_initcall(xo1_rtc_init); 81