/*============================================================================= Copyright (C) 2016 Kristina Brooks All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. FILE DESCRIPTION SDHOST driver. This used to be known as ALTMMC. =============================================================================*/ #include #include #include "sd2.hpp" #define SDEDM_WRITE_THRESHOLD_SHIFT 9 #define SDEDM_READ_THRESHOLD_SHIFT 14 #define SDEDM_THRESHOLD_MASK 0x1f #define SAFE_READ_THRESHOLD 4 #define SAFE_WRITE_THRESHOLD 4 #define logf(fmt, ...) printf("[sdhost::%s]: " fmt, __FUNCTION__, ##__VA_ARGS__); struct sdhost_t { void set_power(bool on) { SH_VDD = on ? SH_VDD_POWER_ON_SET : 0x0; } bool wait(uint32_t timeout = 10000) { uint32_t t = timeout; while(SH_CMD & SH_CMD_NEW_FLAG_SET) { if (t == 0) { logf("timed out after %dus!\n", timeout) return false; } t--; udelay(10); } return true; } bool send(uint32_t command, uint32_t arg) { if (!wait()) return false; SH_ARG = arg; SH_CMD = (command & SH_CMD_COMMAND_SET) | SH_CMD_NEW_FLAG_SET; udelay(300); mfence(); return true; } void configure_pinmux() { GP_FSEL4 = 0x24000000; GP_FSEL5 = 0x924; GP_PUD = 2; logf("GPIOs set!\n"); } void reset() { logf("resetting controller ...\n"); set_power(false); SH_CMD = 0; SH_ARG = 0; SH_TOUT = 0xF00000; SH_CDIV = 0; SH_HSTS = 0x7f8; SH_HCFG = 0; SH_HBCT = 0; SH_HBLC = 0; uint32_t temp = SH_EDM; temp &= ~((SDEDM_THRESHOLD_MASK<