1/**
2 * \file
3 * \brief MMCHS Driver main routine.
4 */
5/*
6 * Copyright (c) 2013, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <assert.h>
18
19#include <barrelfish/barrelfish.h>
20#include <barrelfish/nameservice_client.h>
21#include <driverkit/driverkit.h>
22
23#include <if/cm2_defs.h>
24
25#include "twl6030.h"
26
27static void cm2_connected(void *st, errval_t err, struct cm2_binding *b) {
28    TWL_DEBUG("Connected to cm2 driver\n");
29    assert(err_is_ok(err));
30    struct twl6030_driver_state* dst = (struct twl6030_driver_state*) st;
31    dst->cm2_binding = b;
32    cm2_rpc_client_init(b);
33}
34
35/**
36 * Driver initialization function. This function is called by the driver domain
37 * (see also 'create_handler' in ddomain_service.c).
38 * Typically through a request from the device manager.
39 *
40 * The init function is supposed to set `dev` to the exported service iref.
41 * The init function may use `bfi->dstate` to store additional state about the device.
42 *
43 * \param[in]   bfi   The instance of this driver.
44 * \param[in]   name  The name of this driver instance.
45 * \param[in]   flags Additional flags (The exact flags supported is device/driver specific).
46 * \param[in]   c     Capabilities (for registers etc.) as provided by the device manager.
47 *                    The exact layout of the `c` is device specific.
48 * \param[out]  dev   The service iref over which the device can be contacted.
49 *
50 * \retval SYS_ERR_OK Device initialized successfully.
51 * \retval LIB_ERR_MALLOC_FAIL Unable to allocate memory for the driver.
52 */
53
54static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev) {
55    TWL_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
56
57    bfi->dstate = malloc(sizeof(struct twl6030_driver_state));
58    if (bfi->dstate == NULL) {
59        return LIB_ERR_MALLOC_FAIL;
60    }
61
62    assert(bfi->dstate != NULL);
63
64    struct twl6030_driver_state* st = (struct twl6030_driver_state*) bfi->dstate;
65    st->cap = bfi->caps[0];
66
67    // Connect to the cm2 driver
68    iref_t cm2_iref;
69    errval_t err = nameservice_lookup("cm2", &cm2_iref);
70    if (err_is_fail(err)) {
71        USER_PANIC_ERR(err, "finding cm2 service failed.");
72    }
73
74    err = cm2_bind(cm2_iref, cm2_connected, st, get_default_waitset(), IDC_EXPORT_FLAG_NO_NOTIFY);
75    if (err_is_fail(err)) {
76        USER_PANIC_ERR(err, "call failed.");
77    }
78
79    while(st->cm2_binding == NULL) {
80        messages_wait_and_handle_next();
81    }
82    assert(st->cm2_binding != NULL);
83
84
85    ti_twl6030_init(st);
86    twl6030_init_service(st, dev);
87
88    return SYS_ERR_OK;
89}
90
91/**
92 * Instructs driver to attach to the device.
93 * This function is only called if the driver has previously detached
94 * from the device (see also detach).
95 *
96 * \note After detachment the driver can not assume anything about the
97 * configuration of the device.
98 *
99 * \param[in]   bfi   The instance of this driver.
100 * \retval SYS_ERR_OK Device initialized successfully.
101 */
102static errval_t attach(struct bfdriver_instance* bfi) {
103    TWL_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
104
105    return SYS_ERR_OK;
106}
107
108/**
109 * Instructs driver to detach from the device.
110 * The driver must yield any control over to the device after this function returns.
111 * The device may be left in any state.
112 *
113 * \param[in]   bfi   The instance of this driver.
114 * \retval SYS_ERR_OK Device initialized successfully.
115 */
116static errval_t detach(struct bfdriver_instance* bfi) {
117    TWL_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
118
119    return SYS_ERR_OK;
120}
121
122/**
123 * Instructs the driver to go in a particular sleep state.
124 * Supported states are platform/device specific.
125 *
126 * \param[in]   bfi   The instance of this driver.
127 * \retval SYS_ERR_OK Device initialized successfully.
128 */
129static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
130    TWL_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
131
132    struct twl6030_driver_state* uds = bfi->dstate;
133    uds->level = level;
134
135    return SYS_ERR_OK;
136}
137
138/**
139 * Destroys this driver instance. The driver will yield any
140 * control over the device and free any state allocated.
141 *
142 * \param[in]   bfi   The instance of this driver.
143 * \retval SYS_ERR_OK Device initialized successfully.
144 */
145static errval_t destroy(struct bfdriver_instance* bfi) {
146    TWL_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
147    struct twl6030_driver_state* uds = bfi->dstate;
148    free(uds);
149    bfi->dstate = NULL;
150
151    // XXX: Tear-down the service
152    bfi->device = 0x0;
153
154    return SYS_ERR_OK;
155}
156
157static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap)
158{
159    USER_PANIC("NIY \n");
160    return SYS_ERR_OK;
161}
162
163/**
164 * Registers the driver module with the system.
165 *
166 * To link this particular module in your driver domain,
167 * add it to the addModules list in the Hakefile.
168 */
169DEFINE_MODULE(twl6030, init, attach, detach, set_sleep_level, destroy, get_ep);
170