Всё, что было в предыдущих четырёх статьях, работает. Дисплей горит, USB даёт три функции сразу, кнопки листают меню, часы тактируют всё правильно.
SD-карта не работает. И я остановился на этом.
Эту статью напишу честно, без победных формулировок. Здесь не «получилось», здесь — «сорок попыток и таблица того, что точно не является причиной».
Что происходит
Контроллер SD — это MSDC1, база 0x11240000. U-Boot его находит, поднимает, начинает опрашивать карту — и карта молчит.
mmc info
(нет данных о карте)
В логе при этом видно CRCERR и INT = 0x480. Это не «не найдено», это «попробовали и не получилось».
Для сравнения, что должно быть: в работающем Android та же карта отвечает на CMD8 ответом 0x1aa с первой попытки. У меня:
CMD8 → INT=0x400, RSP=0 (ответа нет вообще)
При этом CMD0 — команда, ответа от которой не ожидается — проходит отлично, INT=0x180. То есть контроллер жив, команды отправляются, процесс идёт. Просто карта не отвечает.
Три источника правды, как и с совместимостью
Здесь та же методология, только предмет другой. Спецификаций нет, значит сравниваю:
- Живой Android с вставленной картой. Работает. Все значения снимаю оттуда.
- Дизассемблированный стоковый LK. Инициализация контроллера, разобранная по регистрам.
- Модуль вендора из Android. Раскладка регистров из
mtk-mmc.h.
Первое, что стоит сказать про этот подход: часть найденных расхождений оказалась ложными следами. Например, PATCH_BIT1 = 0xffe64309 отличается от моего значения — но видно это значение только 1–2 мс при reset, это автотюнинг вендора, а не реальная разница. Если бы я не снимал эталон в те же моменты, я бы до сих пор это «чинил».
Сорок попыток
Не буду расписывать все — полный журнал с номерами версий лежит в документации. Вот что реально менялось и к чему привело:
| Версия | Что пробовал | Итог |
|---|---|---|
| v161 | гейты инфраструктуры, маркеры отладки | контроллер затактировался |
| v162–v168 | обход зависания шины infra_ao1 при записи в CLR-регистр |
обошёл, но не помогло |
| v178–v179 | полный pinctrl MSDC1: режим, IES, SMT, подтяжки, drive strength | линии живые, ответа нет |
| v189 | обнаружение карты: гейты через CLR, полярность CD | mmc info перестал врать |
| v191 | pwrap + реальные питания PMIC (2.9 В / 1.8 В), источник 192 МГц | 26 МГц был ошибкой, но не этой |
| v214 | последовательность LK один в один + живые значения Android | CRCERR |
| v218–v219 | 400 кГц, r_smpl=0, отключил LK-handshake, подтянул флаги | CRCERR. Регистры 1:1 с Android |
Два момента из этого списка стоит выделить.
26 МГц — это была ошибка. Я думал, что источник часов MSDC1 надо форсировать в 26 МГц. На деле это давало 2.8 кГц на шине вместо обещанных 26 МГц. Правильный источник — 192 МГц из MSDCPLL, и он точно так же включён в работающем Android.
eMMC-handshake из LK — ловушка. В стоковом LK есть блок, который выглядит как обязательная часть инициализации MSDC1. На самом деле это рукопожатие для режима eMMC-boot, а мы работаем с SD. Переносить его 1:1 на SD — ошибка. В v219 отключил — не помогло, но гипотезу проверена.
Что точно не является причиной
Это главная ценность тридцати с лишним попыток. Таблица, чтобы следующий не повторял:
| Фактор | Проверено | Итог |
|---|---|---|
| Частота инициализации | 100 / 200 / 400 кГц | не влияет |
r_smpl (RSPL) |
0 и 1 | не влияет |
DTOC |
2 и 3 (вендор ставит 3) | не влияет |
PATCH_BIT2 |
три разных значения | не влияет |
| LK eMMC-handshake | включён и выключен | не влияет |
| Пинмux и подтяжки | полный набор + вендорский pinctrl | линии живые |
| Питание PMIC | 2.9 В / 1.8 В по живому дампу | не влияет |
| Частота источника | 26 МГц (ошибка) → 192 МГц | исправлено, не помогло |
Плюс к этому: значения регистров в v219 сведены к эталону Android один в один. Не близко — один в один.
Вывод: статика регистров исчерпана. Проблема не в том, что я записал в регистры. Проблема в том, что происходит между записью команды и ответом.
Два оставшихся объяснения
Первое, что нашёл в v219 с помощью поллера: CMD иногда не поднимается в 1 вообще. Во второй попытке линии прижаты к низу. В первой попытке DAT0 поднимается к сэмплу 2–3 — линия живая, но ответа нет ни битом.
Отсюда два варианта:
- Команда физически не доходит до карты. Прижимается к низу на стороне контроллера или на линии.
- Карта отвечает, но контроллер не защёлкивает ответ. Аппаратная особенность или проблема с тактовым сигналом.
Различить их — вот чем я и занят.
Следующий шаг
У контроллера MSDC есть отладочный мукс, который показывает внутреннее состояние:
MSDC_DBG_SEL = 0xa0 → записать номер
MSDC_DBG_OUT = 0xa4 → прочитать значение
Уже написал команду msdcbg в U-Boot: выводит все регистры MSDC1, значения мукса для sel = 0…0x63 и отдельно режим EMMC50_CFG4. Зеркалит вендорский msdc_dump_dbg_register().
Сейчас в U-Boot картина такая: sel 0x07 = 1, sel 0x19 = 1, остальное ноль.
Чего не хватает: такой же дамп со живого Android с вставленной картой, где она работает. Сравнить по битам — и разница покажет, где именно расходится внутреннее состояние. Всё, что нужно, есть: команда написана, телефон рядом, осталось снять эталон.
Помощь пригодится
Если у вас есть опыт с контроллерами SD на MediaTek, или телефон на том же Helio G99, или просто интересно, как устроен этот блок — буду рад. Нужны:
- люди, у которых есть рабочий U-Boot с SD на MT6789 — чтобы посмотреть, как это выглядит в живом загрузчике, а не в моём;
- снимок
msdcbgс работающего Android на любом MT67xx; - просто мысли: я застрял на двух версиях, и от свежего взгляда всегда что-то находится.
Репозиторий: github.com/mnnoee/u-boot-mtk-g99 ·
журнал всех попыток: docs/hardware/sd-card-msdc1.md ·
заметки и дампы: u-boot-x676b_docs
Образ для прошивки: релиз v219. И да: перед прошивкой сохраните стоковый LK из lk_a и lk_b, без него отката нет.