1ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen/*
2ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * Copyright (C) 2011 The Android Open Source Project
3ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen *
4ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * Licensed under the Apache License, Version 2.0 (the "License");
5ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * you may not use this file except in compliance with the License.
6ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * You may obtain a copy of the License at
7ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen *
8ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen *      http://www.apache.org/licenses/LICENSE-2.0
9ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen *
10ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * Unless required by applicable law or agreed to in writing, software
11ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * distributed under the License is distributed on an "AS IS" BASIS,
12ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * See the License for the specific language governing permissions and
14ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen * limitations under the License.
15ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen */
16ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
17ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen#define LOG_TAG "local_time_hw_default"
18ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen//#define LOG_NDEBUG 0
19ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
20ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen#include <errno.h>
2107c085565a3b24bb658d05b8aa08fb7420725602Elliott Hughes#include <malloc.h>
22ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen#include <stdint.h>
2307c085565a3b24bb658d05b8aa08fb7420725602Elliott Hughes#include <string.h>
2432dde03332e9822d751ab71fc38c7bda48ec811cJiyong Park#include <time.h>
25ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
26d88dfe8607af019186a309674d9081a056ed3daaMark Salyzyn#include <log/log.h>
27ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
28ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen#include <hardware/hardware.h>
29ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen#include <hardware/local_time_hal.h>
30ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
31e8343251f54f54e46c927da852dca9b63a2a016bGreg Kaiser// We only support gcc and clang, both of which support this attribute.
32e8343251f54f54e46c927da852dca9b63a2a016bGreg Kaiser#define UNUSED_ARGUMENT __attribute((unused))
33e8343251f54f54e46c927da852dca9b63a2a016bGreg Kaiser
34ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstruct stub_local_time_device {
35ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    struct local_time_hw_device device;
36ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen};
37ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
38ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstatic int64_t ltdev_get_local_time(struct local_time_hw_device* dev)
39ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen{
40ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    struct timespec ts;
41ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    uint64_t now;
42ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    int ret;
43ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
44ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
45ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    if (ret < 0) {
465ad38a901dcca2961f3ed35ae0b206c13bc515cdMike J. Chen        ALOGW("%s failed to fetch CLOCK_MONOTONIC value! (res = %d)",
47ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen                dev->common.module->name, ret);
48ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        return 0;
49ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    }
50ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
51ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    now = (((uint64_t)ts.tv_sec) * 1000000000ull) +
52ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen           ((uint64_t)ts.tv_nsec);
53ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
54ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    return (int64_t)now;
55ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen}
56ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
57e8343251f54f54e46c927da852dca9b63a2a016bGreg Kaiserstatic uint64_t ltdev_get_local_freq(
58e8343251f54f54e46c927da852dca9b63a2a016bGreg Kaiser        struct local_time_hw_device* dev UNUSED_ARGUMENT)
59ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen{
60ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    // For better or worse, linux clock_gettime routines normalize all clock
61ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    // frequencies to 1GHz
62ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    return 1000000000ull;
63ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen}
64ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
65ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstatic int ltdev_close(hw_device_t *device)
66ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen{
67ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    free(device);
68ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    return 0;
69ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen}
70ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
71ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstatic int ltdev_open(const hw_module_t* module, const char* name,
72ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen                     hw_device_t** device)
73ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen{
74ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    struct stub_local_time_device *ltdev;
75ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
76ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    if (strcmp(name, LOCAL_TIME_HARDWARE_INTERFACE) != 0)
77ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        return -EINVAL;
78ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
79ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev = calloc(1, sizeof(struct stub_local_time_device));
80ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    if (!ltdev)
81ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        return -ENOMEM;
82ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
83ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.common.tag = HARDWARE_DEVICE_TAG;
84ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.common.version = 0;
85ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.common.module = (struct hw_module_t *) module;
86ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.common.close = ltdev_close;
87ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
88ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.get_local_time = ltdev_get_local_time;
89ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.get_local_freq = ltdev_get_local_freq;
90ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.set_local_slew = NULL;
91ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    ltdev->device.get_debug_log  = NULL;
92ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
93ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    *device = &ltdev->device.common;
94ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
95ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    return 0;
96ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen}
97ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
98ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstatic struct hw_module_methods_t hal_module_methods = {
99ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    .open = ltdev_open,
100ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen};
101ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen
102ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chenstruct local_time_module HAL_MODULE_INFO_SYM = {
103ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    .common = {
104ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .tag = HARDWARE_MODULE_TAG,
105ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .version_major = 1,
106ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .version_minor = 0,
107ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .id = LOCAL_TIME_HARDWARE_MODULE_ID,
108ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .name = "Default local_time HW HAL",
109ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .author = "The Android Open Source Project",
110ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen        .methods = &hal_module_methods,
111ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen    },
112ad255ee424e36f1fbf5e92e320328ceae1aecd49Mike J. Chen};
113