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 "mmchs.h" 24 25 26static void cm2_connected(void *st, errval_t err, struct cm2_binding *b) { 27 MMCHS_DEBUG("Connected to cm2 driver\n"); 28 assert(err_is_ok(err)); 29 struct mmchs_driver_state* dst = (struct mmchs_driver_state*) st; 30 cm2_rpc_client_init(b); 31 dst->cm2_binding = b; 32} 33 34static void twl6030_connected(void *st, errval_t err, struct twl6030_binding *b) { 35 MMCHS_DEBUG("Connected to twl6030 driver\n"); 36 assert(err_is_ok(err)); 37 struct mmchs_driver_state* dst = (struct mmchs_driver_state*) st; 38 twl6030_rpc_client_init(b); 39 dst->twl6030_binding = b; 40} 41 42 43/** 44 * Driver initialization function. This function is called by the driver domain 45 * (see also 'create_handler' in ddomain_service.c). 46 * Typically through a request from the device manager. 47 * 48 * The init function is supposed to set `dev` to the exported service iref. 49 * The init function may use `bfi->dstate` to store additional state about the device. 50 * 51 * \param[in] bfi The instance of this driver. 52 * \param[in] name The name of this driver instance. 53 * \param[in] flags Additional flags (The exact flags supported is device/driver specific). 54 * \param[in] c Capabilities (for registers etc.) as provided by the device manager. 55 * The exact layout of the `c` is device specific. 56 * \param[out] dev The service iref over which the device can be contacted. 57 * 58 * \retval SYS_ERR_OK Device initialized successfully. 59 * \retval LIB_ERR_MALLOC_FAIL Unable to allocate memory for the driver. 60 */ 61 62static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev) { 63 MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 64 65 bfi->dstate = malloc(sizeof(struct mmchs_driver_state)); 66 if (bfi->dstate == NULL) { 67 return LIB_ERR_MALLOC_FAIL; 68 } 69 assert(bfi->dstate != NULL); 70 struct mmchs_driver_state* st = (struct mmchs_driver_state*) bfi->dstate; 71 st->caps = bfi->caps; 72 73 // Connect to the cm2 driver 74 iref_t cm2_iref; 75 errval_t err = nameservice_lookup("cm2", &cm2_iref); 76 if (err_is_fail(err)) { 77 USER_PANIC_ERR(err, "finding cm2 service failed."); 78 } 79 err = cm2_bind(cm2_iref, cm2_connected, st, get_default_waitset(), IDC_EXPORT_FLAG_NO_NOTIFY); 80 if (err_is_fail(err)) { 81 USER_PANIC_ERR(err, "call failed."); 82 } 83 while(st->cm2_binding == NULL) { 84 messages_wait_and_handle_next(); 85 } 86 assert(st->cm2_binding != NULL); 87 88 // Connect to the twl6030 driver 89 iref_t twl6030_iref; 90 err = nameservice_lookup("twl6030", &twl6030_iref); 91 if (err_is_fail(err)) { 92 USER_PANIC_ERR(err, "finding cm2 service failed."); 93 } 94 err = twl6030_bind(twl6030_iref, twl6030_connected, st, get_default_waitset(), IDC_EXPORT_FLAG_NO_NOTIFY); 95 if (err_is_fail(err)) { 96 USER_PANIC_ERR(err, "call failed."); 97 } 98 while(st->twl6030_binding == NULL) { 99 messages_wait_and_handle_next(); 100 } 101 assert(st->twl6030_binding != NULL); 102 103 // 1. Initialize the device: 104 ctrlmod_init(st); 105 err = st->cm2_binding->rpc_tx_vtbl.enable_hsmmc1(st->cm2_binding); 106 assert(err_is_ok(err)); 107 sdmmc1_enable_power(st); 108 mmchs_init(st); 109 110 // 2. Export service to talk to the device: 111 // FYI: Making this use THC+thread currently fails somewhere in the THC runtime 112 mmchs_init_service(st, dev); 113 114 return SYS_ERR_OK; 115} 116 117/** 118 * Instructs driver to attach to the device. 119 * This function is only called if the driver has previously detached 120 * from the device (see also detach). 121 * 122 * \note After detachment the driver can not assume anything about the 123 * configuration of the device. 124 * 125 * \param[in] bfi The instance of this driver. 126 * \retval SYS_ERR_OK Device initialized successfully. 127 */ 128static errval_t attach(struct bfdriver_instance* bfi) { 129 MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 130 131 return SYS_ERR_OK; 132} 133 134/** 135 * Instructs driver to detach from the device. 136 * The driver must yield any control over to the device after this function returns. 137 * The device may be left in any state. 138 * 139 * \param[in] bfi The instance of this driver. 140 * \retval SYS_ERR_OK Device initialized successfully. 141 */ 142static errval_t detach(struct bfdriver_instance* bfi) { 143 MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 144 145 return SYS_ERR_OK; 146} 147 148/** 149 * Instructs the driver to go in a particular sleep state. 150 * Supported states are platform/device specific. 151 * 152 * \param[in] bfi The instance of this driver. 153 * \retval SYS_ERR_OK Device initialized successfully. 154 */ 155static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) { 156 MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 157 158 struct mmchs_driver_state* uds = bfi->dstate; 159 uds->level = level; 160 161 return SYS_ERR_OK; 162} 163 164/** 165 * Destroys this driver instance. The driver will yield any 166 * control over the device and free any state allocated. 167 * 168 * \param[in] bfi The instance of this driver. 169 * \retval SYS_ERR_OK Device initialized successfully. 170 */ 171static errval_t destroy(struct bfdriver_instance* bfi) { 172 MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name); 173 struct mmchs_driver_state* uds = bfi->dstate; 174 free(uds); 175 bfi->dstate = NULL; 176 177 // XXX: Tear-down the service 178 bfi->device = 0x0; 179 180 return SYS_ERR_OK; 181} 182 183static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap) 184{ 185 USER_PANIC("NIY \n"); 186 return SYS_ERR_OK; 187} 188 189/** 190 * Registers the driver module with the system. 191 * 192 * To link this particular module in your driver domain, 193 * add it to the addModules list in the Hakefile. 194 */ 195DEFINE_MODULE(mmchs, init, attach, detach, set_sleep_level, destroy, get_ep); 196