blob: df2af6fbc61604bcf3d8bbf28f88fecb7272a459 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/rpc_server_time_remote.c
2 *
3 * Copyright (C) 2007 Google, Inc.
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2009-2011 The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 * Author: Iliyan Malchev <ibm@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/err.h>
21#include <mach/msm_rpcrouter.h>
22#include "rpc_server_time_remote.h"
23#include <linux/rtc.h>
24#include <linux/android_alarm.h>
25#include <linux/rtc-msm.h>
26
27/* time_remote_mtoa server definitions. */
28
29#define TIME_REMOTE_MTOA_PROG 0x3000005d
30#define TIME_REMOTE_MTOA_VERS_OLD 0
31#define TIME_REMOTE_MTOA_VERS 0x9202a8e4
32#define TIME_REMOTE_MTOA_VERS_COMP 0x00010002
33#define RPC_TIME_REMOTE_MTOA_NULL 0
34#define RPC_TIME_TOD_SET_APPS_BASES 2
35#define RPC_TIME_GET_APPS_USER_TIME 3
36
37struct rpc_time_tod_set_apps_bases_args {
38 uint32_t tick;
39 uint64_t stamp;
40};
41
42static int read_rtc0_time(struct msm_rpc_server *server,
43 struct rpc_request_hdr *req,
44 unsigned len)
45{
46 int err;
47 unsigned long tm_sec;
48 uint32_t size = 0;
49 void *reply;
50 uint32_t output_valid;
51 uint32_t rpc_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
52 struct rtc_time tm;
53 struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
54
55 if (rtc == NULL) {
56 pr_err("%s: unable to open rtc device (%s)\n",
57 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
58 goto send_reply;
59 }
60
61 err = rtc_read_time(rtc, &tm);
62 if (err) {
63 pr_err("%s: Error reading rtc device (%s) : %d\n",
64 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE, err);
65 goto close_dev;
66 }
67
68 err = rtc_valid_tm(&tm);
69 if (err) {
70 pr_err("%s: Invalid RTC time (%s)\n",
71 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
72 goto close_dev;
73 }
74
75 rtc_tm_to_time(&tm, &tm_sec);
76 rpc_status = RPC_ACCEPTSTAT_SUCCESS;
77
78close_dev:
79 rtc_class_close(rtc);
80
81send_reply:
82 reply = msm_rpc_server_start_accepted_reply(server, req->xid,
83 rpc_status);
84 if (rpc_status == RPC_ACCEPTSTAT_SUCCESS) {
85 output_valid = *((uint32_t *)(req + 1));
86 *(uint32_t *)reply = output_valid;
87 size = sizeof(uint32_t);
88 if (be32_to_cpu(output_valid)) {
89 reply += sizeof(uint32_t);
90 *(uint32_t *)reply = cpu_to_be32(tm_sec);
91 size += sizeof(uint32_t);
92 }
93 }
94 err = msm_rpc_server_send_accepted_reply(server, size);
95 if (err)
96 pr_err("%s: send accepted reply failed: %d\n", __func__, err);
97
98 return 1;
99}
100
101static int handle_rpc_call(struct msm_rpc_server *server,
102 struct rpc_request_hdr *req, unsigned len)
103{
104 struct timespec ts, tv;
105
106 switch (req->procedure) {
107 case RPC_TIME_REMOTE_MTOA_NULL:
108 return 0;
109
110 case RPC_TIME_TOD_SET_APPS_BASES: {
111 struct rpc_time_tod_set_apps_bases_args *args;
112 args = (struct rpc_time_tod_set_apps_bases_args *)(req + 1);
113 args->tick = be32_to_cpu(args->tick);
114 args->stamp = be64_to_cpu(args->stamp);
115 printk(KERN_INFO "RPC_TIME_TOD_SET_APPS_BASES:\n"
116 "\ttick = %d\n"
117 "\tstamp = %lld\n",
118 args->tick, args->stamp);
119 getnstimeofday(&ts);
120 msmrtc_updateatsuspend(&ts);
121 rtc_hctosys();
122 getnstimeofday(&tv);
123 /* Update the alarm information with the new time info. */
124 alarm_update_timedelta(ts, tv);
125 return 0;
126 }
127
128 case RPC_TIME_GET_APPS_USER_TIME:
129 return read_rtc0_time(server, req, len);
130
131 default:
132 return -ENODEV;
133 }
134}
135
136static struct msm_rpc_server rpc_server[] = {
137 {
138 .prog = TIME_REMOTE_MTOA_PROG,
139 .vers = TIME_REMOTE_MTOA_VERS_OLD,
140 .rpc_call = handle_rpc_call,
141 },
142 {
143 .prog = TIME_REMOTE_MTOA_PROG,
144 .vers = TIME_REMOTE_MTOA_VERS,
145 .rpc_call = handle_rpc_call,
146 },
147 {
148 .prog = TIME_REMOTE_MTOA_PROG,
149 .vers = TIME_REMOTE_MTOA_VERS_COMP,
150 .rpc_call = handle_rpc_call,
151 },
152};
153
154static int __init rpc_server_init(void)
155{
156 /* Dual server registration to support backwards compatibility vers */
157 int ret;
158 ret = msm_rpc_create_server(&rpc_server[2]);
159 if (ret < 0)
160 return ret;
161 ret = msm_rpc_create_server(&rpc_server[1]);
162 if (ret < 0)
163 return ret;
164 return msm_rpc_create_server(&rpc_server[0]);
165}
166
167
168module_init(rpc_server_init);