1/*
2 * Copyright (c) 2012, ETH Zurich.
3 * All rights reserved.
4 *
5 * This file is distributed under the terms in the attached LICENSE file.
6 * If you do not find this file, copies can be found by writing to:
7 * ETH Zurich D-INFK, CAB F.78, Universitaetstr 6, CH-8092 Zurich.
8 */
9
10#include <barrelfish/barrelfish.h>
11#include <barrelfish/debug.h>
12#include <barrelfish/inthandler.h>
13#include <barrelfish/waitset.h>
14
15#include <driverkit/driverkit.h>
16
17#include "omap44xx_ctrlmod.h"
18
19#include "mmchs.h"
20#include "cap_slots.h"
21#include "mmchs_debug.h"
22
23#if defined(CTRLMOD_SERVICE_DEBUG) || defined(MMCHS_SERVICE_DEBUG) || defined(GLOBAL_DEBUG)
24#define CTRLMOD_DEBUG(x...) debug_printf(x)
25#else
26#define CTRLMOD_DEBUG(x...) ((void)0)
27#endif
28
29static volatile uint32_t dummy = 0;
30static void wait_msec(long msec)
31{
32    int i = 0, sum = 0;
33    long end = (1200000 * msec / 8);
34
35    // Cannot use volatile variables in loop
36    while (++i < end)  {
37        sum += i + end;
38    }
39
40    dummy += sum;
41}
42
43/*
44 * \brief Initialization of control module
45 */
46void ctrlmod_init(struct mmchs_driver_state* st)
47{
48    CTRLMOD_DEBUG("%s:%d\n", __FUNCTION__, __LINE__);
49
50    lvaddr_t vaddr;
51    errval_t err = map_device_cap(st->caps[PADCONF_CORE_SLOT], &vaddr);
52    assert(err_is_ok(err));
53
54    // Initialize Mackerel
55    omap44xx_sysctrl_padconf_core_initialize(&st->ctrlmod, (mackerel_addr_t) vaddr);
56}
57
58/*
59 * We need to configure the extended-drain I/O pads to the right voltage and
60 * turn on the external power supply (TWL6030 on the pandaboard)
61 */
62void sdmmc1_enable_power(struct mmchs_driver_state* st)
63{
64    // compare with Table 18-109 in OMAP TRM, p3681
65    // Step 1: software must keep PWRDNZ low when setting up voltages
66    CTRLMOD_DEBUG("%s: Step 1\n", __FUNCTION__);
67    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x0);
68    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x0);
69
70    // Step 2: preliminary settings for MMC1_PBIAS and MMC1 I/O cell
71    CTRLMOD_DEBUG("%s: Step 2\n", __FUNCTION__);
72    //  1. turn of hiz mode
73    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_hiz_mode_wrf(&st->ctrlmod, 0x0);
74
75    //  2. setup PBIAS_IRQ (MA_IRQ_75)
76    // We don't use the interrupt
77
78    //  3. pad multiplexing -- looks ok when dumping pad registers, so I'm
79    //  not doing anything right now -SG
80
81    //  4. set MMC1 speed control to 26MHz@30pF (0x0) -- alternative 65MHz@30pF (0x1)
82    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr0_speedctrl_wrf(&st->ctrlmod,
83            0x0);
84    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr1_speedctrl_wrf(&st->ctrlmod,
85            0x0);
86    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_dr2_speedctrl_wrf(&st->ctrlmod,
87            0x0);
88
89    //  5. set MMC1 pullup strength to 10-50kOhm (0x1) -- alt. 50-110kOhm (0x0)
90    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp0_wrf(&st->ctrlmod,
91            0x0);
92    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp1_wrf(&st->ctrlmod,
93            0x0);
94    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp2_wrf(&st->ctrlmod,
95            0x0);
96    omap44xx_sysctrl_padconf_core_control_mmc1_sdmmc1_pustrength_grp3_wrf(&st->ctrlmod,
97            0x0);
98
99    // Step 3: Program desired SDMMC1_VDDS for MMC I/O in I2C attached power
100    // controller (3.0V)
101    errval_t err = st->twl6030_binding->rpc_tx_vtbl.vmmc_vsel(st->twl6030_binding, 3000);
102    assert(err_is_ok(err));
103
104    // Step 4: Set VMODE bit according to Step 3 (0x1 == 3.0V)
105    CTRLMOD_DEBUG("%s: Step 4\n", __FUNCTION__);
106    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&st->ctrlmod, 0x1);
107
108    // Step 5: wait for SDMMC1_VDDS voltage to stabilize TODO
109    // might already be stable after reset? -SG
110
111    // Step 6: Disable PWRDNZ mode for MMC1_PBIAS and MMC1 I/O cell
112    CTRLMOD_DEBUG("%s: Step 6\n", __FUNCTION__);
113    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x1);
114    wait_msec(100);
115    omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x1);
116
117    CTRLMOD_DEBUG("%s:%d: wait until supply_hi_out is 0x1\n", __FUNCTION__, __LINE__);
118    while (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&st->ctrlmod)
119            != 0x1) {}
120
121    // Step 7: Store SUPPLY_HI_OUT bit
122    uint8_t supply_hi_out =
123        omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_supply_hi_out_rdf(&st->ctrlmod);
124    CTRLMOD_DEBUG("%s: Step 7: supply_hi_out = %d\n", __FUNCTION__, supply_hi_out);
125    CTRLMOD_DEBUG("%s: Step 7: vmode_error = %d\n", __FUNCTION__,
126                  omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&st->ctrlmod));
127    CTRLMOD_DEBUG("%s: Step 8\n", __FUNCTION__);
128
129    // Step 8: check VMODE_ERROR and set PWRDNZ if error
130    if (omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_error_rdf(&st->ctrlmod)) {
131        CTRLMOD_DEBUG("got VMODE error\n");
132        omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pwrdnz_wrf(&st->ctrlmod, 0x0);
133        omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_pwrdnz_wrf(&st->ctrlmod, 0x0);
134    }
135
136    // Step 9: check if SUPPLY_HI_OUT corresponds to SDMMC1_VDDS (3.0V)
137    if (supply_hi_out != 0x1) {
138        CTRLMOD_DEBUG("SDMMC1_VDDS seems to be != 3.0V\n");
139        // TODO: redo setting SDMMC1_VDDS
140    } else {
141        // supply_hi_out should be 0x1 (3.0V)
142        assert(supply_hi_out == 0x1);
143        // set VMODE bit to supply_hi_out
144        omap44xx_sysctrl_padconf_core_control_pbiaslite_mmc1_pbiaslite_vmode_wrf(&st->ctrlmod, supply_hi_out);
145    }
146
147    // Step 12: clear PBIAS IRQ
148    // Ignored
149}
150