Added C++ ctors and partial SDHOST driver
[rpi-open-firmware.git] / arm_chainloader / drivers / sdhost.cc
1 /*=============================================================================
2 Copyright (C) 2016 Kristina Brooks
3 All rights reserved.
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 FILE DESCRIPTION
16 SDHOST driver. This used to be known as ALTMMC.
17
18 =============================================================================*/
19
20 #include <chainloader.h>
21 #include <hardware.h>
22
23 #include "sd2.hpp"
24
25 #define SDEDM_WRITE_THRESHOLD_SHIFT 9
26 #define SDEDM_READ_THRESHOLD_SHIFT 14
27 #define SDEDM_THRESHOLD_MASK 0x1f
28
29 #define SAFE_READ_THRESHOLD 4
30 #define SAFE_WRITE_THRESHOLD 4
31
32 #define logf(fmt, ...) printf("[sdhost::%s]: " fmt, __FUNCTION__, ##__VA_ARGS__);
33
34 struct sdhost_t {
35 void set_power(bool on) {
36 SH_VDD = on ? SH_VDD_POWER_ON_SET : 0x0;
37 }
38
39 bool wait(uint32_t timeout = 10000) {
40 uint32_t t = timeout;
41
42 while(SH_CMD & SH_CMD_NEW_FLAG_SET) {
43 if (t == 0) {
44 logf("timed out after %dus!\n", timeout)
45 return false;
46 }
47 t--;
48 udelay(10);
49 }
50
51 return true;
52 }
53
54 bool send(uint32_t command, uint32_t arg) {
55 if (!wait())
56 return false;
57
58 SH_ARG = arg;
59 SH_CMD = (command & SH_CMD_COMMAND_SET) | SH_CMD_NEW_FLAG_SET;
60
61 udelay(300);
62 mfence();
63
64 return true;
65 }
66
67 void configure_pinmux() {
68 GP_FSEL4 = 0x24000000;
69 GP_FSEL5 = 0x924;
70 GP_PUD = 2;
71
72 logf("GPIOs set!\n");
73 }
74
75 void reset() {
76 logf("resetting controller ...\n");
77
78 set_power(false);
79
80 SH_CMD = 0;
81 SH_ARG = 0;
82 SH_TOUT = 0xF00000;
83 SH_CDIV = 0;
84 SH_HSTS = 0x7f8;
85 SH_HCFG = 0;
86 SH_HBCT = 0;
87 SH_HBLC = 0;
88
89 uint32_t temp = SH_EDM;
90
91 temp &= ~((SDEDM_THRESHOLD_MASK<<SDEDM_READ_THRESHOLD_SHIFT) |
92 (SDEDM_THRESHOLD_MASK<<SDEDM_WRITE_THRESHOLD_SHIFT));
93 temp |= (SAFE_READ_THRESHOLD << SDEDM_READ_THRESHOLD_SHIFT) |
94 (SAFE_WRITE_THRESHOLD << SDEDM_WRITE_THRESHOLD_SHIFT);
95
96 SH_EDM = temp;
97 udelay(300);
98
99 set_power(true);
100
101 udelay(300);
102 mfence();
103 }
104
105 void init_card() {
106 send(GO_IDLE_STATE, 0);
107 send(SEND_IF_COND, 0x155);
108
109 wait();
110
111 logf("SEND_IF_COND response is: 0x%X\n", SH_RSP0);
112 }
113
114 sdhost_t() {
115 logf("starting up ...\n");
116
117 configure_pinmux();
118 reset();
119
120 SH_HCFG = SH_HCFG_SLOW_CARD_SET | SH_HCFG_WIDE_INT_BUS_SET;
121 SH_CDIV = 0x96;
122
123 udelay(300);
124
125 logf("sdhost controller ready!\n");
126
127 init_card();
128 }
129 };
130
131 sdhost_t STATIC_DRIVER g_SDHostDriver {};
This page took 0.074492 seconds and 4 git commands to generate.