"serial_kernel",
"angler",
"corectrl",
- "fdif"
+ "fdif",
+ "mmchs"
] ]
-- ARMv7-A modules for Versatile Express EMM board (GEM5, qemu)
-- ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
--
-- Hakefile for omap44xx sd-card driver
---
+--
--------------------------------------------------------------------------
[
- build application { target = "mmchs",
- cFiles = [
- "main.c", "cm2.c", "ctrlmod.c",
- "i2c.c", "mmchs.c", "twl6030.c",
- "service.c"
- ],
- mackerelDevices = [
- "ti_i2c",
- "ti_twl6030",
- "omap/omap44xx_mmchs1",
- "omap/omap44xx_sysctrl_padconf_core",
- "omap/omap44xx_l3init_cm2",
- "omap/omap44xx_ckgen_cm2",
- "omap/omap44xx_l4per_cm2"
- ],
+ build library { target = "mmchs_module",
+ cFiles = [
+ "main.c", "cm2.c", "ctrlmod.c",
+ "i2c.c", "mmchs.c", "twl6030.c",
+ "service.c"
+ ],
+ mackerelDevices = [
+ "ti_i2c",
+ "ti_twl6030",
+ "omap/omap44xx_mmchs1",
+ "omap/omap44xx_sysctrl_padconf_core",
+ "omap/omap44xx_l3init_cm2",
+ "omap/omap44xx_ckgen_cm2",
+ "omap/omap44xx_l4per_cm2"
+ ],
+
+ flounderDefs = [ "ata_rw28" ],
+ flounderBindings = [ "ata_rw28" ],
+ flounderTHCStubs = [ "ata_rw28" ],
- flounderDefs = [ "ata_rw28" ],
- flounderBindings = [ "ata_rw28" ],
- flounderTHCStubs = [ "ata_rw28" ],
+ addLibraries = [ "driverkit", "thc" ],
+ architectures = ["armv7"]
+ },
- addLibraries = [ "driverkit", "thc" ],
- architectures = ["armv7"]
+ build application {
+ target = "mmchs",
+ cFiles = [ "mmchs_domain.c"],
+ addModules = ["mmchs_module"],
+ addLinkFlags = ["-T" ++ Config.source_dir ++ "/lib/driverkit/bfdrivers.ld" ]
}
-]
\ No newline at end of file
+]
--- /dev/null
+/*
+ * Copyright (c) 2016, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef __CAP_SLOTS__
+#define __CAP_SLOTS__
+
+#define CM2_SLOT 0
+#define CLKGEN_CM2_SLOT 1
+#define IC2_SLOT 2
+#define L4_PER_HSMMC1_SLOT 3
+#define PADCONF_CORE_SLOT 4
+
+#endif // __CAP_SLOTS__
#include <driverkit/driverkit.h>
#include <arch/arm/omap44xx/device_registers.h>
-#include <dev/omap/omap44xx_l3init_cm2_dev.h>
-#include <dev/omap/omap44xx_ckgen_cm2_dev.h>
-#include <dev/omap/omap44xx_l4per_cm2_dev.h>
-#include "omap44xx_cm2.h"
+#include "mmchs.h"
+#include "cap_slots.h"
-static omap44xx_l3init_cm2_t l3init_cm2;
-static omap44xx_l4per_cm2_t l4per_cm2;
-static omap44xx_ckgen_cm2_t clkgen_cm2;
-
-void cm2_enable_hsmmc1(void)
+void cm2_enable_hsmmc1(struct mmchs_driver_state* st)
{
- omap44xx_l3init_cm2_cm_l3init_clkstctrl_clktrctrl_wrf(&l3init_cm2, 0x2);
- omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_modulemode_wrf(&l3init_cm2, 0x2);
- while (omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_idlest_rdf(&l3init_cm2) != 0x0);
+ omap44xx_l3init_cm2_cm_l3init_clkstctrl_clktrctrl_wrf(&st->l3init_cm2, 0x2);
+ omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_modulemode_wrf(&st->l3init_cm2, 0x2);
+ while (omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_idlest_rdf(&st->l3init_cm2) != 0x0);
}
-void cm2_enable_i2c(size_t i2c_index)
+void cm2_enable_i2c(struct mmchs_driver_state* st, size_t i2c_index)
{
assert (i2c_index < 4);
- omap44xx_l4per_cm2_cm_l4per_i2c_clkctrl_modulemode_wrf(&l4per_cm2, i2c_index, 0x2);
- while (omap44xx_l4per_cm2_cm_l4per_i2c_clkctrl_idlest_rdf(&l4per_cm2, i2c_index)
+ omap44xx_l4per_cm2_cm_l4per_i2c_clkctrl_modulemode_wrf(&st->l4per_cm2, i2c_index, 0x2);
+ while (omap44xx_l4per_cm2_cm_l4per_i2c_clkctrl_idlest_rdf(&st->l4per_cm2, i2c_index)
!= 0x0);
}
-void cm2_init(void)
+void cm2_init(struct mmchs_driver_state* st)
{
lvaddr_t l3init_vaddr;
- errval_t err = map_device_register(OMAP44XX_CM2, 0x1000, &l3init_vaddr);
+ errval_t err = map_device_cap(st->caps[CM2_SLOT], &l3init_vaddr);
assert(err_is_ok(err));
- omap44xx_l3init_cm2_initialize(&l3init_cm2, (mackerel_addr_t)l3init_vaddr);
+ omap44xx_l3init_cm2_initialize(&st->l3init_cm2, (mackerel_addr_t)l3init_vaddr);
+ omap44xx_l4per_cm2_initialize(&st->l4per_cm2, (mackerel_addr_t)l3init_vaddr);
lvaddr_t clkgen_vaddr;
- err = map_device_register(OMAP44XX_CLKGEN_CM2, 0x1000, &clkgen_vaddr);
+ err = map_device_cap(st->caps[CLKGEN_CM2_SLOT], &clkgen_vaddr);
assert(err_is_ok(err));
- omap44xx_ckgen_cm2_initialize(&clkgen_cm2, (mackerel_addr_t)clkgen_vaddr);
-
- //lvaddr_t l4per_vaddr;
- //err = map_device_register(OMAP44XX_L4PER_CM2, 0x1000, &l4per_vaddr);
- //assert(err_is_ok(err));
- omap44xx_l4per_cm2_initialize(&l4per_cm2, (mackerel_addr_t)l3init_vaddr);
+ omap44xx_ckgen_cm2_initialize(&st->clkgen_cm2, (mackerel_addr_t)clkgen_vaddr);
}
-int cm2_get_hsmmc1_base_clock(void)
+int cm2_get_hsmmc1_base_clock(struct mmchs_driver_state* st)
{
- return omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_clksel_rdf(&l3init_cm2) == 0x0 ?
+ return omap44xx_l3init_cm2_cm_l3init_hsmmc1_clkctrl_clksel_rdf(&st->l3init_cm2) == 0x0 ?
64000000 : 96000000;
}
#include "twl6030.h"
#include "omap44xx_ctrlmod.h"
+#include "mmchs.h"
+#include "cap_slots.h"
#include "mmchs_debug.h"
#if defined(CTRLMOD_SERVICE_DEBUG) || defined(MMCHS_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
#define CTRLMOD_DEBUG(x...) ((void)0)
#endif
-#define SYSCTRL_PADCONF_CORE 0x4a100000u
-static omap44xx_sysctrl_padconf_core_t ctrlmod;
-
static volatile uint32_t dummy = 0;
static void wait_msec(long msec)
{
/*
* \brief Initialization of control module
*/
-void ctrlmod_init(void)
+void ctrlmod_init(struct mmchs_driver_state* st)
{
CTRLMOD_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
+
lvaddr_t vaddr;
- errval_t err = map_device_register(SYSCTRL_PADCONF_CORE, 0x1000, &vaddr);
+ errval_t err = map_device_cap(st->caps[PADCONF_CORE_SLOT], &vaddr);
assert(err_is_ok(err));
// Initialize Mackerel
- omap44xx_sysctrl_padconf_core_initialize(&ctrlmod, (mackerel_addr_t) vaddr);
+ omap44xx_sysctrl_padconf_core_initialize(&st->ctrlmod, (mackerel_addr_t) vaddr);
}
/*
* We need to configure the extended-drain I/O pads to the right voltage and
* turn on the external power supply (TWL6030 on the pandaboard)
*/
-void sdmmc1_enable_power(void)
+void sdmmc1_enable_power(struct mmchs_driver_state* st)
{
// compare with Table 18-109 in OMAP TRM, p3681
// Step 1: software must keep PWRDNZ low when setting up voltages
CTRLMOD_DEBUG("%s: Step 1\n", __FUNCTION__);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&ctrlmod, 0x0);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&ctrlmod, 0x0);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x0);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x0);
// Step 2: preliminary settings for MMC1_PBIAS and MMC1 I/O cell
CTRLMOD_DEBUG("%s: Step 2\n", __FUNCTION__);
// 1. turn of hiz mode
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_hiz_mode_wrf(&ctrlmod, 0x0);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_hiz_mode_wrf(&st->ctrlmod, 0x0);
// 2. setup PBIAS_IRQ (MA_IRQ_75)
// We don't use the interrupt
// not doing anything right now -SG
// 4. set MMC1 speed control to 26MHz@30pF (0x0) -- alternative 65MHz@30pF (0x1)
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr0_speedctrl_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr0_speedctrl_wrf(&st->ctrlmod,
0x0);
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr1_speedctrl_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr1_speedctrl_wrf(&st->ctrlmod,
0x0);
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr2_speedctrl_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr2_speedctrl_wrf(&st->ctrlmod,
0x0);
// 5. set MMC1 pullup strength to 10-50kOhm (0x1) -- alt. 50-110kOhm (0x0)
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp0_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp0_wrf(&st->ctrlmod,
0x0);
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp1_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp1_wrf(&st->ctrlmod,
0x0);
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp2_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp2_wrf(&st->ctrlmod,
0x0);
- omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp3_wrf(&ctrlmod,
+ omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp3_wrf(&st->ctrlmod,
0x0);
// Step 3: Program desired SDMMC1_VDDS for MMC I/O in I2C attached power
// controller (3.0V)
- errval_t err = ti_twl6030_set_vmmc_vsel(3000);
+ errval_t err = ti_twl6030_set_vmmc_vsel(st->twl, 3000);
assert(err_is_ok(err));
// Step 4: Set VMODE bit according to Step 3 (0x1 == 3.0V)
CTRLMOD_DEBUG("%s: Step 4\n", __FUNCTION__);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&ctrlmod, 0x1);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&st->ctrlmod, 0x1);
// Step 5: wait for SDMMC1_VDDS voltage to stabilize TODO
// might already be stable after reset? -SG
// Step 6: Disable PWRDNZ mode for MMC1_PBIAS and MMC1 I/O cell
CTRLMOD_DEBUG("%s: Step 6\n", __FUNCTION__);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&ctrlmod, 0x1);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x1);
wait_msec(100);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&ctrlmod, 0x1);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x1);
CTRLMOD_DEBUG("%s:%d: wait until supply_hi_out is 0x1\n", __FUNCTION__, __LINE__);
- while (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&ctrlmod)
+ while (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&st->ctrlmod)
!= 0x1) {}
// Step 7: Store SUPPLY_HI_OUT bit
uint8_t supply_hi_out =
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&ctrlmod);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&st->ctrlmod);
CTRLMOD_DEBUG("%s: Step 7: supply_hi_out = %d\n", __FUNCTION__, supply_hi_out);
CTRLMOD_DEBUG("%s: Step 7: vmode_error = %d\n", __FUNCTION__,
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&ctrlmod));
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&st->ctrlmod));
CTRLMOD_DEBUG("%s: Step 8\n", __FUNCTION__);
// Step 8: check VMODE_ERROR and set PWRDNZ if error
- if (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&ctrlmod)) {
+ if (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&st->ctrlmod)) {
CTRLMOD_DEBUG("got VMODE error\n");
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&ctrlmod, 0x0);
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&ctrlmod, 0x0);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x0);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x0);
}
// Step 9: check if SUPPLY_HI_OUT corresponds to SDMMC1_VDDS (3.0V)
// supply_hi_out should be 0x1 (3.0V)
assert(supply_hi_out == 0x1);
// set VMODE bit to supply_hi_out
- omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&ctrlmod, supply_hi_out);
+ omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&st->ctrlmod, supply_hi_out);
}
// Step 12: clear PBIAS IRQ
#include "omap44xx_cm2.h" // for turning on I2C clocks
#include "i2c.h"
+#include "twl6030.h"
+#include "mmchs.h"
+#include "cap_slots.h"
#if defined(I2C_SERVICE_DEBUG) || defined(MMCHS_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
#define I2C_DEBUG(x...) debug_printf(x)
-//#define PBS (10*1024)
-//static char prbuf[PBS];
#else
#define I2C_DEBUG(x...) ((void)0)
#endif
-// there are 4 GP i2c controllers on the pandaboard
-#define I2C_COUNT 4
-static ti_i2c_t i2c[I2C_COUNT];
-static bool i2c_initialized[I2C_COUNT];
-
static lpaddr_t i2c_pbase[I2C_COUNT] = {
0x48070000u,
0x48072000u,
0x48350000u,
};
+lpaddr_t i2c_get_pbase(size_t dev) {
+ assert(dev < 4);
+ return i2c_pbase[dev];
+}
+
+// XXX: This is not converted to module because
+// of weird use of mackerel namespaces...
+static ti_i2c_t i2c[I2C_COUNT];
+static bool i2c_initialized[I2C_COUNT];
+
// default timeout for waits in ticks
#define DEFAULT_TIMEOUT (tsc_get_hz() / 4)
/*
* \brief initialize I2C controller `i`.
*/
-void ti_i2c_init(int i)
+void ti_i2c_init(struct mmchs_driver_state* st, int i)
{
I2C_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
// map & initialize mackerel device
lvaddr_t i2c_vbase;
- errval_t err = map_device_register(i2c_pbase[i], 0x1000, &i2c_vbase);
+ errval_t err = map_device_cap(st->caps[IC2_SLOT], &i2c_vbase);
assert(err_is_ok(err));
ti_i2c_initialize(&i2c[i], (mackerel_addr_t)i2c_vbase);
ti_i2c_t *dev = &i2c[i];
// turn on clocks
- cm2_enable_i2c(i);
+ cm2_enable_i2c(st, i);
I2C_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
return SYS_ERR_OK;
}
-
#include <barrelfish/types.h>
#include <errors/errno.h>
+// there are 4 GP i2c controllers on the pandaboard
+#define I2C_COUNT 4
+
enum i2c_flags {
I2C_RD = 0x1,
I2C_WR = 0x2,
uint8_t *buf;
};
-void ti_i2c_init(int i);
+struct mmchs_driver_state;
+void ti_i2c_init(struct mmchs_driver_state* st, int i);
errval_t ti_i2c_transfer(int i, struct i2c_msg *msgs, size_t msgcount);
+lpaddr_t i2c_get_pbase(size_t dev);
#endif // __TI_I2C_H__
*/
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <barrelfish/barrelfish.h>
+#include <driverkit/driverkit.h>
+
#include "mmchs.h"
+/**
+ * Driver initialization function. This function is called by the driver domain
+ * (see also 'create_handler' in ddomain_service.c).
+ * Typically through a request from the device manager.
+ *
+ * The init function is supposed to set `dev` to the exported service iref.
+ * The init function may use `bfi->dstate` to store additional state about the device.
+ *
+ * \param[in] bfi The instance of this driver.
+ * \param[in] name The name of this driver instance.
+ * \param[in] flags Additional flags (The exact flags supported is device/driver specific).
+ * \param[in] c Capabilities (for registers etc.) as provided by the device manager.
+ * The exact layout of the `c` is device specific.
+ * \param[out] dev The service iref over which the device can be contacted.
+ *
+ * \retval SYS_ERR_OK Device initialized successfully.
+ * \retval LIB_ERR_MALLOC_FAIL Unable to allocate memory for the driver.
+ */
+static errval_t init(struct bfdriver_instance* bfi, const char* name, uint64_t flags,
+ struct capref* caps, size_t caps_len, char** args, size_t args_len, iref_t* dev) {
+ MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
+
+ bfi->dstate = malloc(sizeof(struct mmchs_driver_state));
+ if (bfi->dstate == NULL) {
+ return LIB_ERR_MALLOC_FAIL;
+ }
+ assert(bfi->dstate != NULL);
+ struct mmchs_driver_state* st = (struct mmchs_driver_state*) bfi->dstate;
+ st->caps = caps;
+
+ // 1. Initialize the device:
+ cm2_init(st);
+ ti_twl6030_init(st);
+ ctrlmod_init(st);
+ cm2_enable_hsmmc1(st);
+ sdmmc1_enable_power(st);
+ mmchs_init(st);
-int main(int argc, char **argv)
-{
- cm2_init();
- ti_twl6030_init();
- ctrlmod_init();
- cm2_enable_hsmmc1();
- sdmmc1_enable_power();
+ // 2. Export service to talk to the device:
+ init_service(st);
- mmchs_init();
+ // 3. Set iref of your exported service (this is reported back to Kaluga)
+ *dev = 0x00;
- init_service();
+ return SYS_ERR_OK;
+}
- return 0;
-}
\ No newline at end of file
+/**
+ * Instructs driver to attach to the device.
+ * This function is only called if the driver has previously detached
+ * from the device (see also detach).
+ *
+ * \note After detachment the driver can not assume anything about the
+ * configuration of the device.
+ *
+ * \param[in] bfi The instance of this driver.
+ * \retval SYS_ERR_OK Device initialized successfully.
+ */
+static errval_t attach(struct bfdriver_instance* bfi) {
+ MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
+
+ return SYS_ERR_OK;
+}
+
+/**
+ * Instructs driver to detach from the device.
+ * The driver must yield any control over to the device after this function returns.
+ * The device may be left in any state.
+ *
+ * \param[in] bfi The instance of this driver.
+ * \retval SYS_ERR_OK Device initialized successfully.
+ */
+static errval_t detach(struct bfdriver_instance* bfi) {
+ MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
+
+ return SYS_ERR_OK;
+}
+
+/**
+ * Instructs the driver to go in a particular sleep state.
+ * Supported states are platform/device specific.
+ *
+ * \param[in] bfi The instance of this driver.
+ * \retval SYS_ERR_OK Device initialized successfully.
+ */
+static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
+ MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
+
+ struct mmchs_driver_state* uds = bfi->dstate;
+ uds->level = level;
+
+ return SYS_ERR_OK;
+}
+
+/**
+ * Destroys this driver instance. The driver will yield any
+ * control over the device and free any state allocated.
+ *
+ * \param[in] bfi The instance of this driver.
+ * \retval SYS_ERR_OK Device initialized successfully.
+ */
+static errval_t destroy(struct bfdriver_instance* bfi) {
+ MMCHS_DEBUG("%s:%s:%d: %s\n", __FILE__, __FUNCTION__, __LINE__, bfi->driver->name);
+ struct mmchs_driver_state* uds = bfi->dstate;
+ free(uds);
+ bfi->dstate = NULL;
+
+ // XXX: Tear-down the service
+ bfi->device = 0x0;
+
+ return SYS_ERR_OK;
+}
+
+/**
+ * Registers the driver module with the system.
+ *
+ * To link this particular module in your driver domain,
+ * add it to the addModules list in the Hakefile.
+ */
+DEFINE_MODULE(mmchs, init, attach, detach, set_sleep_level, destroy);
#include <driverkit/driverkit.h>
#include <arch/arm/omap44xx/device_registers.h>
-#include <dev/omap/omap44xx_mmchs1_dev.h>
-
#include "mmchs.h"
+#include "cap_slots.h"
-#define DBUF_SIZE (64*1024)
-static char dbuf[DBUF_SIZE];
-
-static omap44xx_mmchs1_t mmchs;
-
-static void mmchs_soft_reset(void)
+static void mmchs_soft_reset(struct mmchs_driver_state* st)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
- omap44xx_mmchs1_mmchs_sysconfig_softreset_wrf(&mmchs, 0x1);
- while (omap44xx_mmchs1_mmchs_sysstatus_resetdone_rdf(&mmchs) != 0x1);
+ omap44xx_mmchs1_mmchs_sysconfig_softreset_wrf(&st->mmchs, 0x1);
+ while (omap44xx_mmchs1_mmchs_sysstatus_resetdone_rdf(&st->mmchs) != 0x1);
MMCHS_DEBUG("%s:%d: sysctl reset\n", __FUNCTION__, __LINE__);
- omap44xx_mmchs1_mmchs_sysctl_sra_wrf(&mmchs, 0x1);
- while (omap44xx_mmchs1_mmchs_sysctl_sra_rdf(&mmchs) != 0x0);
+ omap44xx_mmchs1_mmchs_sysctl_sra_wrf(&st->mmchs, 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_sra_rdf(&st->mmchs) != 0x0);
}
-static void set_hardware_capabilities(void)
+static void set_hardware_capabilities(struct mmchs_driver_state* st)
{
- omap44xx_mmchs1_mmchs_capa_vs18_wrf(&mmchs, 0x1);
- omap44xx_mmchs1_mmchs_capa_vs30_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_capa_vs18_wrf(&st->mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_capa_vs30_wrf(&st->mmchs, 0x1);
}
-static void set_wake_up_configuration(void)
+static void set_wake_up_configuration(struct mmchs_driver_state* st)
{
- omap44xx_mmchs1_mmchs_sysconfig_enawakeup_wrf(&mmchs, 0x1);
- omap44xx_mmchs1_mmchs_hctl_iwe_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_sysconfig_enawakeup_wrf(&st->mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_hctl_iwe_wrf(&st->mmchs, 0x1);
}
/**
* \see TRM rev Z, Section 24.5.1.2.1.7.2
*/
-static void change_clock_frequency_to_fit_protocol(uint32_t clock)
+static void change_clock_frequency_to_fit_protocol(struct mmchs_driver_state* st, uint32_t clock)
{
- omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_sysctl_clkd_wrf(&mmchs, clock);
+ omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_sysctl_clkd_wrf(&st->mmchs, clock);
MMCHS_DEBUG("%s:%d: Wait until clock is stable.\n", __FUNCTION__, __LINE__);
- while (omap44xx_mmchs1_mmchs_sysctl_ics_rdf(&mmchs) != 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_ics_rdf(&st->mmchs) != 0x1);
- omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&st->mmchs, 0x1);
}
-static void mmc_host_and_bus_configuration(void)
+static void mmc_host_and_bus_configuration(struct mmchs_driver_state* st)
{
- omap44xx_mmchs1_mmchs_con_od_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_con_dw8_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_con_ceata_wrf(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_con_od_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_con_dw8_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_con_ceata_wrf(&st->mmchs, 0x0);
- omap44xx_mmchs1_mmchs_hctl_sdvs_wrf(&mmchs, 0x6);
- omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_hctl_dtw_wrf(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_hctl_sdvs_wrf(&st->mmchs, 0x6);
+ omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_hctl_dtw_wrf(&st->mmchs, 0x0);
- omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_sysctl_ice_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_sysctl_cen_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_sysctl_ice_wrf(&st->mmchs, 0x1);
- MMCHS_DEBUG("%s:%d: clksel = %u\n", __FUNCTION__, __LINE__, cm2_get_hsmmc1_base_clock());
- change_clock_frequency_to_fit_protocol(0x258);
+ MMCHS_DEBUG("%s:%d: clksel = %u\n", __FUNCTION__, __LINE__, cm2_get_hsmmc1_base_clock(st));
+ change_clock_frequency_to_fit_protocol(st, 0x258);
MMCHS_DEBUG("%s:%d: Wait until internal clock is stable.\n", __FUNCTION__, __LINE__);
- while (omap44xx_mmchs1_mmchs_sysctl_ics_rdf(&mmchs) != 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_ics_rdf(&st->mmchs) != 0x1);
- omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&mmchs, 0x1);
- assert(omap44xx_mmchs1_mmchs_hctl_sdbp_rdf(&mmchs) == 0x1);
+ omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&st->mmchs, 0x1);
+ assert(omap44xx_mmchs1_mmchs_hctl_sdbp_rdf(&st->mmchs) == 0x1);
// Pessimistic settings, we want to have this thing always ON for testing
- omap44xx_mmchs1_mmchs_sysconfig_clockactivity_wrf(&mmchs, 0x3);
- omap44xx_mmchs1_mmchs_sysconfig_standbymode_wrf(&mmchs, 0x1);
- omap44xx_mmchs1_mmchs_sysconfig_sidlemode_wrf(&mmchs, 0x1);
- omap44xx_mmchs1_mmchs_sysconfig_autoidle_wrf(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_sysconfig_clockactivity_wrf(&st->mmchs, 0x3);
+ omap44xx_mmchs1_mmchs_sysconfig_standbymode_wrf(&st->mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_sysconfig_sidlemode_wrf(&st->mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_sysconfig_autoidle_wrf(&st->mmchs, 0x0);
}
/**
* \see TRM rev Z, Section 24.5.1.2.1.1.1
*/
-static void cmd_line_reset(void)
+static void cmd_line_reset(struct mmchs_driver_state* st)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
- omap44xx_mmchs1_mmchs_sysctl_src_wrf(&mmchs, 0x1);
- while (omap44xx_mmchs1_mmchs_sysctl_src_rdf(&mmchs) != 0x1);
- while (omap44xx_mmchs1_mmchs_sysctl_src_rdf(&mmchs) != 0x0);
+ omap44xx_mmchs1_mmchs_sysctl_src_wrf(&st->mmchs, 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_src_rdf(&st->mmchs) != 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_src_rdf(&st->mmchs) != 0x0);
}
/**
* \see TRM rev Z, Section 24.5.1.2.1.2.1
*/
-static void dat_line_reset(void)
+static void dat_line_reset(struct mmchs_driver_state* st)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
- omap44xx_mmchs1_mmchs_sysctl_srd_wrf(&mmchs, 0x1);
- while (omap44xx_mmchs1_mmchs_sysctl_srd_rdf(&mmchs) != 0x1);
- while (omap44xx_mmchs1_mmchs_sysctl_srd_rdf(&mmchs) != 0x0);
+ omap44xx_mmchs1_mmchs_sysctl_srd_wrf(&st->mmchs, 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_srd_rdf(&st->mmchs) != 0x1);
+ while (omap44xx_mmchs1_mmchs_sysctl_srd_rdf(&st->mmchs) != 0x0);
}
/**
* \see TRM rev Z, Section 24.5.1.2.1.7.1
*/
-static void send_command(omap44xx_mmchs1_indx_status_t cmd, uint32_t arg)
+static void send_command(struct mmchs_driver_state* st, omap44xx_mmchs1_indx_status_t cmd, uint32_t arg)
{
MMCHS_DEBUG("%s:%d: cmd = 0x%x arg=0x%x\n", __FUNCTION__, __LINE__, cmd, arg);
MMCHS_DEBUG("%s:%d: Wait until command line is free.\n", __FUNCTION__, __LINE__);
- while (omap44xx_mmchs1_mmchs_pstate_cmdi_rdf(&mmchs) != 0x0);
+ while (omap44xx_mmchs1_mmchs_pstate_cmdi_rdf(&st->mmchs) != 0x0);
MMCHS_DEBUG("%s:%d: \n", __FUNCTION__, __LINE__);
- omap44xx_mmchs1_mmchs_stat_rawwr(&mmchs, ~0x0);
+ omap44xx_mmchs1_mmchs_stat_rawwr(&st->mmchs, ~0x0);
// Only for MMC cards
- omap44xx_mmchs1_mmchs_con_mit_wrf(&mmchs, 0x0);
- omap44xx_mmchs1_mmchs_con_str_wrf(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_con_mit_wrf(&st->mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_con_str_wrf(&st->mmchs, 0x0);
- omap44xx_mmchs1_mmchs_csre_rawwr(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_csre_rawwr(&st->mmchs, 0x0);
- omap44xx_mmchs1_mmchs_blk_blen_wrf(&mmchs, 512);
- omap44xx_mmchs1_mmchs_blk_nblk_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_blk_blen_wrf(&st->mmchs, 512);
+ omap44xx_mmchs1_mmchs_blk_nblk_wrf(&st->mmchs, 0x1);
- omap44xx_mmchs1_mmchs_sysctl_dto_wrf(&mmchs, 0xE); // omapconf
+ omap44xx_mmchs1_mmchs_sysctl_dto_wrf(&st->mmchs, 0xE); // omapconf
- omap44xx_mmchs1_mmchs_arg_rawwr(&mmchs, arg);
+ omap44xx_mmchs1_mmchs_arg_rawwr(&st->mmchs, arg);
// Enable interrupts
- omap44xx_mmchs1_mmchs_ie_rawwr(&mmchs, ~0x0);
- //omap44xx_mmchs1_mmchs_ise_rawwr(&mmchs, ~0x0);
+ omap44xx_mmchs1_mmchs_ie_rawwr(&st->mmchs, ~0x0);
+ //omap44xx_mmchs1_mmchs_ise_rawwr(&st->mmchs, ~0x0);
omap44xx_mmchs1_mmchs_cmd_t cmdreg = omap44xx_mmchs1_mmchs_cmd_default;
}
cmdreg = omap44xx_mmchs1_mmchs_cmd_indx_insert(cmdreg, cmd);
- omap44xx_mmchs1_mmchs_cmd_wr(&mmchs, cmdreg);
+ omap44xx_mmchs1_mmchs_cmd_wr(&st->mmchs, cmdreg);
MMCHS_DEBUG("%s:%d: Wait until mmchs_stat.cc == 0x1\n", __FUNCTION__, __LINE__);
uint32_t cc = 0;
size_t i = 0;
do {
- uint32_t cto = omap44xx_mmchs1_mmchs_stat_cto_rdf(&mmchs);
- uint32_t ccrc = omap44xx_mmchs1_mmchs_stat_ccrc_rdf(&mmchs);
- cc = omap44xx_mmchs1_mmchs_stat_cc_rdf(&mmchs);
+ uint32_t cto = omap44xx_mmchs1_mmchs_stat_cto_rdf(&st->mmchs);
+ uint32_t ccrc = omap44xx_mmchs1_mmchs_stat_ccrc_rdf(&st->mmchs);
+ cc = omap44xx_mmchs1_mmchs_stat_cc_rdf(&st->mmchs);
if (cto == 0x1 && ccrc == 0x1) {
MMCHS_DEBUG("%s:%d: cto = 1 ccrc = 1: Conflict on cmd line.\n", __FUNCTION__, __LINE__);
- cmd_line_reset();
+ cmd_line_reset(st);
return;
}
if (cto == 0x1 && ccrc == 0x0) {
MMCHS_DEBUG("%s:%d: cto = 1 ccrc = 0: Abort.\n", __FUNCTION__, __LINE__);
- cmd_line_reset();
+ cmd_line_reset(st);
return;
}
if (i++ > 1000) {
- omap44xx_mmchs1_mmchs_stat_pr(dbuf, DBUF_SIZE, &mmchs);
- MMCHS_DEBUG("%s:%d: %s\n", __FUNCTION__, __LINE__, dbuf);
+ omap44xx_mmchs1_mmchs_stat_pr(st->dbuf, DBUF_SIZE, &st->mmchs);
+ MMCHS_DEBUG("%s:%d: %s\n", __FUNCTION__, __LINE__, st->dbuf);
USER_PANIC("Command not Ackd?");
}
wait_msec(1);
/*omap44xx_mmchs1_mmchs_pstate_pr(dbuf, DBUF_SIZE, &mmchs);
- MMCHS_DEBUG("%s:%d: \n%s\n", __FUNCTION__, __LINE__, dbuf);
+ MMCHS_DEBUG("%s:%d: \n%s\n", __FUNCTION__, __LINE__, st->dbuf);
MMCHS_DEBUG("%s:%d: mmchs_rsp10 = 0x%x\n", __FUNCTION__, __LINE__,
- omap44xx_mmchs1_mmchs_rsp10_rd(&mmchs));
+ omap44xx_mmchs1_mmchs_rsp10_rd(&st->mmchs));
MMCHS_DEBUG("%s:%d: mmchs_rsp32 = 0x%x\n", __FUNCTION__, __LINE__,
- omap44xx_mmchs1_mmchs_rsp32_rd(&mmchs));
+ omap44xx_mmchs1_mmchs_rsp32_rd(&st->mmchs));
MMCHS_DEBUG("%s:%d: mmchs_rsp54 = 0x%x\n", __FUNCTION__, __LINE__,
- omap44xx_mmchs1_mmchs_rsp54_rd(&mmchs));
+ omap44xx_mmchs1_mmchs_rsp54_rd(&st->mmchs));
MMCHS_DEBUG("%s:%d: mmchs_rsp76 = 0x%x\n", __FUNCTION__, __LINE__,
- omap44xx_mmchs1_mmchs_rsp76_rd(&mmchs));*/
+ omap44xx_mmchs1_mmchs_rsp76_rd(&st->mmchs));*/
- uint32_t resp_type = omap44xx_mmchs1_mmchs_cmd_rsp_type_rdf(&mmchs);
+ uint32_t resp_type = omap44xx_mmchs1_mmchs_cmd_rsp_type_rdf(&st->mmchs);
if (resp_type == 0x0) {
MMCHS_DEBUG("%s:%d: No response.\n", __FUNCTION__, __LINE__);
return;
/**
* \see TRM rev Z, Figure 24-38
*/
-static void mmchs_identify_card(void)
+static void mmchs_identify_card(struct mmchs_driver_state* st)
{
// Module Initialization is done in mmchs_init()
- omap44xx_mmchs1_mmchs_ie_rawwr(&mmchs, 0xFFFFFFFF);
+ omap44xx_mmchs1_mmchs_ie_rawwr(&st->mmchs, 0xFFFFFFFF);
- omap44xx_mmchs1_mmchs_con_init_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_con_init_wrf(&st->mmchs, 0x1);
- omap44xx_mmchs1_mmchs_cmd_rawwr(&mmchs, 0x0);
- while (omap44xx_mmchs1_mmchs_stat_cc_rdf(&mmchs) != 0x1);
+ omap44xx_mmchs1_mmchs_cmd_rawwr(&st->mmchs, 0x0);
+ while (omap44xx_mmchs1_mmchs_stat_cc_rdf(&st->mmchs) != 0x1);
wait_msec(10);
- omap44xx_mmchs1_mmchs_stat_cc_wrf(&mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_stat_cc_wrf(&st->mmchs, 0x1);
- omap44xx_mmchs1_mmchs_cmd_rawwr(&mmchs, 0x0);
- while (omap44xx_mmchs1_mmchs_stat_cc_rdf(&mmchs) != 0x1);
+ omap44xx_mmchs1_mmchs_cmd_rawwr(&st->mmchs, 0x0);
+ while (omap44xx_mmchs1_mmchs_stat_cc_rdf(&st->mmchs) != 0x1);
- omap44xx_mmchs1_mmchs_stat_cc_wrf(&mmchs, 0x1);
- omap44xx_mmchs1_mmchs_con_init_wrf(&mmchs, 0x0);
+ omap44xx_mmchs1_mmchs_stat_cc_wrf(&st->mmchs, 0x1);
+ omap44xx_mmchs1_mmchs_con_init_wrf(&st->mmchs, 0x0);
- //omap44xx_mmchs1_mmchs_stat_rawwr(&mmchs, 0xFFFFFFFF);
+ //omap44xx_mmchs1_mmchs_stat_rawwr(&st->mmchs, 0xFFFFFFFF);
- omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&mmchs, 0x1);
- change_clock_frequency_to_fit_protocol(0xF0UL);
+ omap44xx_mmchs1_mmchs_hctl_sdbp_wrf(&st->mmchs, 0x1);
+ change_clock_frequency_to_fit_protocol(st, 0xF0UL);
- send_command(0, 0x0);
+ send_command(st, 0, 0x0);
uint32_t arg8 = (0x1 << 8) | 0b10101010;
- send_command(8, arg8);
- assert(omap44xx_mmchs1_mmchs_stat_cc_rdf(&mmchs) == 0x1);
+ send_command(st, 8, arg8);
+ assert(omap44xx_mmchs1_mmchs_stat_cc_rdf(&st->mmchs) == 0x1);
- send_command(55, 0x0);
+ send_command(st, 55, 0x0);
uint32_t ocrdata = 0;
do {
- send_command(55, 0x0);
+ send_command(st, 55, 0x0);
MMCHS_DEBUG("%s:%d: ACMD41\n", __FUNCTION__, __LINE__);
uint32_t arg41 = 0x1 << 30 | ocrdata;
- send_command(41, arg41);
+ send_command(st, 41, arg41);
wait_msec(10);
- ocrdata = omap44xx_mmchs1_mmchs_rsp10_rd(&mmchs);
- } while ((omap44xx_mmchs1_mmchs_rsp10_rd(&mmchs) & (1 << 31)) == 0);
+ ocrdata = omap44xx_mmchs1_mmchs_rsp10_rd(&st->mmchs);
+ } while ((omap44xx_mmchs1_mmchs_rsp10_rd(&st->mmchs) & (1 << 31)) == 0);
MMCHS_DEBUG("%s:%d: CMD2\n", __FUNCTION__, __LINE__);
- send_command(2, 0x0);
+ send_command(st, 2, 0x0);
MMCHS_DEBUG("%s:%d: CMD3\n", __FUNCTION__, __LINE__);
- send_command(3, 0x1);
- uint32_t rca = omap44xx_mmchs1_mmchs_rsp10_rd(&mmchs) >> 16;
+ send_command(st, 3, 0x1);
+ uint32_t rca = omap44xx_mmchs1_mmchs_rsp10_rd(&st->mmchs) >> 16;
MMCHS_DEBUG("Status: 0x%X\n", rca & 0xFFFF);
MMCHS_DEBUG("RCA: 0x%X\n", (rca >> 16) & 0xFFFF);
MMCHS_DEBUG("%s:%d: CMD9\n", __FUNCTION__, __LINE__);
- send_command(9, rca << 16);
+ send_command(st, 9, rca << 16);
MMCHS_DEBUG("%s:%d: CMD7\n", __FUNCTION__, __LINE__);
- send_command(7, rca << 16);
+ send_command(st, 7, rca << 16);
MMCHS_DEBUG("%s:%d: CMD16\n", __FUNCTION__, __LINE__);
- send_command(16, 512);
+ send_command(st, 16, 512);
}
-static errval_t complete_card_transaction(void)
+static errval_t complete_card_transaction(struct mmchs_driver_state* st)
{
size_t i = 0;
do {
- if ( omap44xx_mmchs1_mmchs_stat_tc_rdf(&mmchs) == 0x1 ) {
+ if ( omap44xx_mmchs1_mmchs_stat_tc_rdf(&st->mmchs) == 0x1 ) {
//send_command(12, 0);
return SYS_ERR_OK; // Fine as long as we support only finite transfers
} else {
- bool deb = omap44xx_mmchs1_mmchs_stat_deb_rdf(&mmchs);
- bool dcrc = omap44xx_mmchs1_mmchs_stat_dcrc_rdf(&mmchs);
- bool dto = omap44xx_mmchs1_mmchs_stat_dto_rdf(&mmchs);
+ bool deb = omap44xx_mmchs1_mmchs_stat_deb_rdf(&st->mmchs);
+ bool dcrc = omap44xx_mmchs1_mmchs_stat_dcrc_rdf(&st->mmchs);
+ bool dto = omap44xx_mmchs1_mmchs_stat_dto_rdf(&st->mmchs);
if (deb || dcrc || dto) {
MMCHS_DEBUG("%s:%d: Error interrupt during transfer: deb=%d dcrc=%d dto=%d.\n",
__FUNCTION__, __LINE__, deb, dcrc, dto);
- dat_line_reset();
+ dat_line_reset(st);
return MMC_ERR_TRANSFER;
}
}
* \retval MMC_ERR_TRANSFER Error interrupt or no transfer complete interrupt.
* \retval MMC_ERR_READ_READY Card not ready to read.
*/
-errval_t mmchs_read_block(size_t block_nr, void *buffer)
+errval_t mmchs_read_block(struct mmchs_driver_state* st, size_t block_nr, void *buffer)
{
MMCHS_DEBUG("%s:%d: Wait for free data lines.\n", __FUNCTION__, __LINE__);
- while (omap44xx_mmchs1_mmchs_pstate_dati_rdf(&mmchs) != 0x0);
+ while (omap44xx_mmchs1_mmchs_pstate_dati_rdf(&st->mmchs) != 0x0);
// Send data command
- send_command(17, block_nr);
+ send_command(st, 17, block_nr);
// TODO(gz): Check for errors
- for (size_t i = 0; i < (omap44xx_mmchs1_mmchs_blk_blen_rdf(&mmchs) + 3) / 4; i++) {
+ for (size_t i = 0; i < (omap44xx_mmchs1_mmchs_blk_blen_rdf(&st->mmchs) + 3) / 4; i++) {
size_t timeout = 1000;
- while (omap44xx_mmchs1_mmchs_stat_brr_rdf(&mmchs) == 0x0 && timeout--) {
+ while (omap44xx_mmchs1_mmchs_stat_brr_rdf(&st->mmchs) == 0x0 && timeout--) {
wait_msec(1);
}
if (timeout == 0) {
return MMC_ERR_READ_READY;
}
- ((uint32_t *) buffer)[i] = omap44xx_mmchs1_mmchs_data_rd(&mmchs);
+ ((uint32_t *) buffer)[i] = omap44xx_mmchs1_mmchs_data_rd(&st->mmchs);
}
- return complete_card_transaction();
+ return complete_card_transaction(st);
}
/**
* \retval MMC_ERR_TRANSFER Error interrupt or no transfer complete interrupt.
* \retval MMC_ERR_WRITE_READY Card not ready to write.
*/
-errval_t mmchs_write_block(size_t block_nr, void *buffer)
+errval_t mmchs_write_block(struct mmchs_driver_state* st, size_t block_nr, void *buffer)
{
MMCHS_DEBUG("%s:%d: Wait for free data lines.\n", __FUNCTION__, __LINE__);
size_t timeout = 1000;
- while (omap44xx_mmchs1_mmchs_pstate_dati_rdf(&mmchs) != 0x0 && timeout--) {
+ while (omap44xx_mmchs1_mmchs_pstate_dati_rdf(&st->mmchs) != 0x0 && timeout--) {
wait_msec(1);
}
if (timeout == 0) {
}
// Send data command
- send_command(24, block_nr);
+ send_command(st, 24, block_nr);
// TODO(gz): Check for errors
- for (size_t i = 0; i < (omap44xx_mmchs1_mmchs_blk_blen_rdf(&mmchs) + 3) / 4; i++) {
- while (omap44xx_mmchs1_mmchs_stat_bwr_rdf(&mmchs) == 0x0);
- omap44xx_mmchs1_mmchs_data_wr(&mmchs, ((uint32_t *) buffer)[i]);
+ for (size_t i = 0; i < (omap44xx_mmchs1_mmchs_blk_blen_rdf(&st->mmchs) + 3) / 4; i++) {
+ while (omap44xx_mmchs1_mmchs_stat_bwr_rdf(&st->mmchs) == 0x0);
+ omap44xx_mmchs1_mmchs_data_wr(&st->mmchs, ((uint32_t *) buffer)[i]);
}
- return complete_card_transaction();
+ return complete_card_transaction(st);
}
/**
*
* \see TRM rev Z, 24.5.1.1.2
*/
-void mmchs_init(void)
+void mmchs_init(struct mmchs_driver_state* st)
{
lvaddr_t mmchs_vaddr;
- errval_t err = map_device_register(OMAP44XX_MAP_L4_PER_HSMMC1,
- OMAP44XX_MAP_L4_PER_HSMMC1_SIZE,
- &mmchs_vaddr);
+ errval_t err = map_device_cap(st->caps[L4_PER_HSMMC1_SLOT], &mmchs_vaddr);
assert(err_is_ok(err));
- omap44xx_mmchs1_initialize(&mmchs, (mackerel_addr_t)mmchs_vaddr);
+ omap44xx_mmchs1_initialize(&st->mmchs, (mackerel_addr_t)mmchs_vaddr);
- mmchs_soft_reset();
- set_hardware_capabilities();
- set_wake_up_configuration();
- mmc_host_and_bus_configuration();
+ mmchs_soft_reset(st);
+ set_hardware_capabilities(st);
+ set_wake_up_configuration(st);
+ mmc_host_and_bus_configuration(st);
- mmchs_identify_card();
+ mmchs_identify_card(st);
}
#define MMCHS2_H
#include <barrelfish/barrelfish.h>
+#include <dev/omap/omap44xx_mmchs1_dev.h>
+#include <dev/omap/omap44xx_l3init_cm2_dev.h>
+#include <dev/omap/omap44xx_ckgen_cm2_dev.h>
+#include <dev/omap/omap44xx_l4per_cm2_dev.h>
#include "mmchs_debug.h"
#include "omap44xx_cm2.h"
#include "i2c.h"
#include "twl6030.h"
-void mmchs_init(void);
-errval_t mmchs_read_block(size_t block_nr, void *buffer);
-errval_t mmchs_write_block(size_t block_nr, void *buffer);
+#define DBUF_SIZE (10*4096)
-void init_service(void);
+struct mmchs_driver_state {
+ uint64_t level;
-#endif // MMCHS2_H
\ No newline at end of file
+ omap44xx_l3init_cm2_t l3init_cm2;
+ omap44xx_l4per_cm2_t l4per_cm2;
+ omap44xx_ckgen_cm2_t clkgen_cm2;
+ omap44xx_sysctrl_padconf_core_t ctrlmod;
+ omap44xx_mmchs1_t mmchs;
+ ti_twl6030_t twl;
+
+ struct capref* caps;
+
+
+ char dbuf[DBUF_SIZE];
+};
+
+void mmchs_init(struct mmchs_driver_state*);
+errval_t mmchs_read_block(struct mmchs_driver_state*, size_t block_nr, void *buffer);
+errval_t mmchs_write_block(struct mmchs_driver_state*, size_t block_nr, void *buffer);
+
+void init_service(struct mmchs_driver_state*);
+
+#endif // MMCHS2_H
#ifndef MMCHS2_DEBUG_H
#define MMCHS2_DEBUG_H
-//#define MMCHS_SERVICE_DEBUG 1
+#define MMCHS_SERVICE_DEBUG 1
#if defined(MMCHS_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
#define MMCHS_DEBUG(x...) debug_printf(x)
#define MMCHS_DEBUG(x...) ((void)0)
#endif
-#endif // MMCHS2_DEBUG_H
\ No newline at end of file
+#endif // MMCHS2_DEBUG_H
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <barrelfish/barrelfish.h>
+#include <driverkit/driverkit.h>
+#include <barrelfish/nameservice_client.h>
+
+#include "i2c.h"
+#include "twl6030.h"
+#include <arch/arm/omap44xx/device_registers.h>
+#include <maps/omap44xx_map.h>
+
+#include "cap_slots.h"
+
+/// XXX: TODO not needed once kaluga <-> driver domain communicate over dcontrol iface
+static errval_t find_cap_for(lpaddr_t address, size_t size, struct capref* out)
+{
+ errval_t err;
+ struct cnoderef argcn_cnref = {
+ .croot = CPTR_ROOTCN,
+ .cnode = ROOTCN_SLOT_ADDR(ROOTCN_SLOT_ARGCN),
+ .level = CNODE_TYPE_OTHER,
+ };
+
+ struct capref device_cap_iter = {
+ .cnode = argcn_cnref,
+ .slot = 0
+ };
+
+ for (; device_cap_iter.slot < L2_CNODE_SLOTS; device_cap_iter.slot++) {
+ // Get cap data
+ struct capability cap;
+ err = debug_cap_identify(device_cap_iter, &cap);
+ // If cap type was Null, kernel returns error
+ if (err_no(err) == SYS_ERR_IDENTIFY_LOOKUP ||
+ err_no(err) == SYS_ERR_CAP_NOT_FOUND ||
+ err_no(err) == SYS_ERR_LMP_CAPTRANSFER_SRC_LOOKUP) {
+ continue;
+ }
+
+ struct frame_identity fid;
+ err = frame_identify(device_cap_iter, &fid);
+ if (err_is_fail(err)) {
+ DEBUG_ERR(err, "Failure in frame_identify");
+ return err;
+ }
+ assert(err_is_ok(err));
+
+ lpaddr_t address_base = address & ~(BASE_PAGE_SIZE-1);
+ // XXX: should be address+size <= ...
+ // Need to add proper register size
+ if (address_base >= fid.base &&
+ (address_base + size) <= (fid.base + fid.bytes)) {
+ *out = device_cap_iter;
+ return SYS_ERR_OK;
+ }
+ }
+
+ return DRIVERKIT_ERR_NO_CAP_FOUND;
+}
+
+
+int main(int argc, char** argv)
+{
+ size_t drivers = 0;
+ struct bfdriver* cur = NULL;
+ driverkit_list(&cur, &drivers);
+ for (size_t i=0; i<drivers; i++) {
+ printf("%s:%s:%d: Found device driver class = %s\n", __FILE__, __FUNCTION__, __LINE__, cur->name);
+ cur += 1;
+ }
+
+ struct capref* caps = calloc(5, sizeof(struct capref));
+
+
+ errval_t err = find_cap_for(OMAP44XX_CM2, 0x1000, &caps[CM2_SLOT]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "finding cap failed.");
+ }
+ err = find_cap_for(OMAP44XX_CLKGEN_CM2, 0x1000, &caps[CLKGEN_CM2_SLOT]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "finding cap failed.");
+ }
+ err = find_cap_for(i2c_get_pbase(I2C_HC), 0x1000, &caps[IC2_SLOT]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "finding cap failed.");
+ }
+#define SYSCTRL_PADCONF_CORE 0x4a100000u
+ err = find_cap_for(SYSCTRL_PADCONF_CORE, 0x1000, &caps[PADCONF_CORE_SLOT]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "finding cap failed.");
+ }
+ err = find_cap_for(OMAP44XX_MAP_L4_PER_HSMMC1, OMAP44XX_MAP_L4_PER_HSMMC1_SIZE, &caps[L4_PER_HSMMC1_SLOT]);
+ if (err_is_fail(err)) {
+ USER_PANIC_ERR(err, "finding cap failed.");
+ }
+
+ iref_t dev, ctrl;
+ driverkit_create_driver("mmchs", "mmchs_inst", caps, 1, NULL, 0, 0, &dev, &ctrl);
+
+ messages_handler_loop();
+ return 0;
+}
#define __OMAP44XX_CM2_H__
#include <barrelfish/barrelfish.h>
+#include <dev/omap/omap44xx_l3init_cm2_dev.h>
+#include <dev/omap/omap44xx_ckgen_cm2_dev.h>
+#include <dev/omap/omap44xx_l4per_cm2_dev.h>
-void cm2_enable_i2c(size_t i2c_index);
-int cm2_get_hsmmc1_base_clock(void);
-void cm2_debug_print(void);
-void cm2_print_standby_state(void);
+struct mmchs_driver_state;
-void cm2_enable_hsmmc1(void);
-void cm2_init(void);
+void cm2_enable_i2c(struct mmchs_driver_state* st, size_t i2c_index);
+int cm2_get_hsmmc1_base_clock(struct mmchs_driver_state* st);
+void cm2_enable_hsmmc1(struct mmchs_driver_state*);
+void cm2_init(struct mmchs_driver_state*);
#endif /* __OMAP44XX_CM2_H__ */
#define PBIAS_IRQ (32+75)
// initialize registers
-void ctrlmod_init(void);
+struct mmchs_driver_state;
+void ctrlmod_init(struct mmchs_driver_state*);
// turn on sdmmc1 power
-void sdmmc1_enable_power(void);
+void sdmmc1_enable_power(struct mmchs_driver_state*);
void pbias_handle_irq(void *args);
#define SECTION_SIZE 512
#define SECTION_ROUND_UP(x) ( ((x) + (SECTION_SIZE-1)) & (~(SECTION_SIZE-1)) )
-static void read_dma(struct ata_rw28_thc_service_binding_t *sv,
+static void read_dma(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv,
uint32_t read_size, uint32_t start_lba)
{
size_t buffer_size = SECTION_ROUND_UP(read_size);
uint8_t *bufptr = (uint8_t *)buffer;
for (size_t i = 0; i < (buffer_size / SECTION_SIZE); i++) {
MMCHS_DEBUG("%s:%d: i=%d start_lba=%d\n", __FUNCTION__, __LINE__, i, start_lba);
- errval_t err = mmchs_read_block(start_lba+i, bufptr);
+ errval_t err = mmchs_read_block(st, start_lba+i, bufptr);
assert(err_is_ok(err));
bufptr += SECTION_SIZE;
}
free(buffer);
}
-static void read_dma_block(struct ata_rw28_thc_service_binding_t *sv, uint32_t lba)
+static void read_dma_block(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv, uint32_t lba)
{
MMCHS_DEBUG("%s:%d lba=%d\n", __FUNCTION__, __LINE__, lba);
void *buffer = malloc(SECTION_SIZE);
assert(buffer != NULL);
- errval_t err = mmchs_read_block(lba, buffer);
+ errval_t err = mmchs_read_block(st, lba, buffer);
assert(err_is_ok(err));
sv->send.read_dma_block(sv, buffer, SECTION_SIZE);
free(buffer);
}
-static void write_dma(struct ata_rw28_thc_service_binding_t *sv,
+static void write_dma(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv,
uint8_t *buffer, size_t buffer_len, uint32_t lba)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
sv->send.write_dma(sv, LIB_ERR_NOT_IMPLEMENTED);
}
-static void identify_device(struct ata_rw28_thc_service_binding_t *sv)
+static void identify_device(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
sv->send.identify_device(sv, NULL, 0);
}
-static void flush_cache(struct ata_rw28_thc_service_binding_t *sv)
+static void flush_cache(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv)
{
MMCHS_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
sv->send.flush_cache(sv, SYS_ERR_OK);
}
-static void service_client(struct ata_rw28_thc_service_binding_t *sv)
+static void service_client(struct mmchs_driver_state* st, struct ata_rw28_thc_service_binding_t *sv)
{
DO_FINISH({
bool stop = false;
switch (m.msg) {
case ata_rw28_read_dma:
- read_dma(sv, m.args.read_dma.in.read_size, m.args.read_dma.in.start_lba);
+ read_dma(st, sv, m.args.read_dma.in.read_size, m.args.read_dma.in.start_lba);
break;
case ata_rw28_read_dma_block:
- read_dma_block(sv, m.args.read_dma_block.in.lba);
+ read_dma_block(st, sv, m.args.read_dma_block.in.lba);
break;
case ata_rw28_write_dma:
- write_dma(sv, m.args.write_dma.in.buffer, m.args.write_dma.in.buffer_size, m.args.write_dma.in.lba);
+ write_dma(st, sv, m.args.write_dma.in.buffer, m.args.write_dma.in.buffer_size, m.args.write_dma.in.lba);
break;
case ata_rw28_identify_device:
- identify_device(sv);
+ identify_device(st, sv);
break;
case ata_rw28_flush_cache:
- flush_cache(sv);
+ flush_cache(st, sv);
break;
default:
});
}
-void init_service(void)
+void init_service(struct mmchs_driver_state* st)
{
errval_t err;
iref_t iref;
}
MMCHS_DEBUG("%s:%d: Got service %p\n", __FUNCTION__, __LINE__, sv);
- ASYNC({service_client(sv);});
+ ASYNC({service_client(st, sv);});
}
});
}
#include "i2c.h"
#include "twl6030.h"
-static uint8_t _ti_twl6030_id1_read_8(void *d, size_t off);
-static void _ti_twl6030_id1_write_8(void *d, size_t off, uint8_t regval);
-#define ti_twl6030_id1_read_8(dev, off) _ti_twl6030_id1_read_8(dev, off)
-#define ti_twl6030_id1_write_8(dev, off, regval) _ti_twl6030_id1_write_8(dev, off, regval)
-#include <dev/ti_twl6030_dev.h>
-
-// I2C Host controller id
-#define I2C_HC 0
// I2C slave address for id1 reads and writes is 0x48
#define ID1_I2C_ADDR 0x48
-#define PBS (8*1024)
-static char PRBUF[PBS];
-#define PRBUFL PRBUF, (PBS-1)
-
#include "mmchs_debug.h"
#if defined(TWL_SERIVCE_DEBUG) || defined(MMCHS_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
#define TWL_DEBUG(x...) printf(x)
#define TWL_DEBUG(x...) ((void)0)
#endif
-static ti_twl6030_t twl;
-
-static inline uint8_t _ti_twl6030_id1_read_8(void *d, size_t off)
+inline uint8_t _ti_twl6030_id1_read_8(void *d, size_t off)
{
errval_t err;
return result;
}
-static inline void _ti_twl6030_id1_write_8(void *d, size_t off, uint8_t regval)
+inline void _ti_twl6030_id1_write_8(void *d, size_t off, uint8_t regval)
{
struct i2c_msg msg;
errval_t err;
return;
}
-void ti_twl6030_init(void)
+void ti_twl6030_init(struct mmchs_driver_state* st)
{
TWL_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
- ti_i2c_init(I2C_HC);
+ ti_i2c_init(st, I2C_HC);
}
-void ti_twl6030_vmmc_pr(void)
+void ti_twl6030_vmmc_pr(ti_twl6030_t twl)
{
+#define PBS (8*1024)
+static char PRBUF[PBS];
+#define PRBUFL PRBUF, (PBS-1)
+
ti_twl6030_pr(PRBUFL, &twl);
TWL_DEBUG("%s\n", PRBUF);
}
}
-void ti_twl6030_vmmc_off(void)
+void ti_twl6030_vmmc_off(ti_twl6030_t twl)
{
// turn off
ti_twl6030_cfg_state_w_t st = ti_twl6030_cfg_state_w_default;
ti_twl6030_vmmc_cfg_state_w_rawwr(&twl, st);
}
-void ti_twl6030_vmmc_on(void)
+void ti_twl6030_vmmc_on(ti_twl6030_t twl)
{
// turn on
ti_twl6030_cfg_state_w_t st = ti_twl6030_cfg_state_w_default;
}
-errval_t ti_twl6030_set_vmmc_vsel(int millis)
+errval_t ti_twl6030_set_vmmc_vsel(ti_twl6030_t twl, int millis)
{
TWL_DEBUG("ti_twl6030_vmmc_vsel\n");
//ti_twl6030_mmcctrl_vmmc_auto_off_wrf(&twl, 0x0);
ti_twl6030_mmcctrl_sw_fc_wrf(&twl, 0x1);
- ti_twl6030_vmmc_off();
+ ti_twl6030_vmmc_off(twl);
wait_msec(10);
ti_twl6030_vsel_t vsel = millis_to_vsel(millis);
ti_twl6030_vmmc_cfg_voltage_vsel_wrf(&twl, vsel);
- ti_twl6030_vmmc_on();
+ ti_twl6030_vmmc_on(twl);
//ti_twl6030_mmcctrl_vmmc_auto_off_wrf(&twl, 0x0);
- ti_twl6030_vmmc_pr();
+ ti_twl6030_vmmc_pr(twl);
return SYS_ERR_OK;
#include <barrelfish/types.h>
#include <errors/errno.h>
-void ti_twl6030_init(void);
-errval_t ti_twl6030_set_vmmc_vsel(int millis);
+// I2C Host controller id
+#define I2C_HC 0
-void ti_twl6030_vmmc_pr(void);
+uint8_t _ti_twl6030_id1_read_8(void *d, size_t off);
+void _ti_twl6030_id1_write_8(void *d, size_t off, uint8_t regval);
+#define ti_twl6030_id1_read_8(dev, off) _ti_twl6030_id1_read_8(dev, off)
+#define ti_twl6030_id1_write_8(dev, off, regval) _ti_twl6030_id1_write_8(dev, off, regval)
+#include <dev/ti_twl6030_dev.h>
-void ti_twl6030_vmmc_on(void);
-void ti_twl6030_vmmc_off(void);
+struct mmchs_driver_state;
+void ti_twl6030_init(struct mmchs_driver_state*);
+errval_t ti_twl6030_set_vmmc_vsel(ti_twl6030_t twl, int millis);
+
+void ti_twl6030_vmmc_pr(ti_twl6030_t twl);
+
+void ti_twl6030_vmmc_on(ti_twl6030_t twl);
+void ti_twl6030_vmmc_off(ti_twl6030_t twl);
#endif // __TI_TWL6030_H__