SD-карта, которая не отвечает / The SD card that does not answer

Всё, что было в предыдущих четырёх статьях, работает. Дисплей горит, USB даёт три функции сразу, кнопки листают меню, часы тактируют всё правильно.

SD-карта не работает. И я остановился на этом.

Эту статью напишу честно, без победных формулировок. Здесь не «получилось», здесь — «сорок попыток и таблица того, что точно не является причиной».

Что происходит

Контроллер SD — это MSDC1, база 0x11240000. U-Boot его находит, поднимает, начинает опрашивать карту — и карта молчит.

mmc info
(нет данных о карте)

В логе при этом видно CRCERR и INT = 0x480. Это не «не найдено», это «попробовали и не получилось».

Для сравнения, что должно быть: в работающем Android та же карта отвечает на CMD8 ответом 0x1aa с первой попытки. У меня:

CMD8  →  INT=0x400, RSP=0     (ответа нет вообще)

При этом CMD0 — команда, ответа от которой не ожидается — проходит отлично, INT=0x180. То есть контроллер жив, команды отправляются, процесс идёт. Просто карта не отвечает.

Три источника правды, как и с совместимостью

Здесь та же методология, только предмет другой. Спецификаций нет, значит сравниваю:

  1. Живой Android с вставленной картой. Работает. Все значения снимаю оттуда.
  2. Дизассемблированный стоковый LK. Инициализация контроллера, разобранная по регистрам.
  3. Модуль вендора из 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 — линия живая, но ответа нет ни битом.

Отсюда два варианта:

  1. Команда физически не доходит до карты. Прижимается к низу на стороне контроллера или на линии.
  2. Карта отвечает, но контроллер не защёлкивает ответ. Аппаратная особенность или проблема с тактовым сигналом.

Различить их — вот чем я и занят.

Следующий шаг

У контроллера 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, без него отката нет.