LINUX.ORG.RU

Инициализация ram на Rockchip rk356x, теперь opensource

 ,


4

4

По скольку Рокчип как-то не топропился открывать исходники бинаря для инициализации контроллера оперативной памяти на rk356x, я, потратив прилично времени на реверс, сделал это за них.

На данный момент поддерживаются rk3568 и rk3566 (rk3566 сам не проверял, не обладаю). Из опреративки поддерживается только LPDDR4 (опять же, по скольку отладками с другими типами DDR не обладаю).

Сам тестировал вариант с 4GB оперативной памяти.

Понимаю что not my personal army, но заинтересованных прошу попробовать собрать и потестировать. Буду рад услышать что оно работает на rk3566, ну и с объёмами памяти отличными от 4GB.

Ссылка на нсходники, собирать generic-rk3568_defconfig. Хотя и на остальных поддерживаемых u-boot моделях должно заработать, если включить CONFIG_RAM_ROCKCHIP_LPDDR4.

Частота оперативки намеренно задушена до 1056 Mhz, чтобы заработало на rk3566. Чтобы сделать 1560 Mhz нужно откатить последний коммит.



Последнее исправление: Dimez (всего исправлений: 1)

Добавил в избранное.

Если будет время потестирую на паре плат на RK3568.

Только просьба не использовать merge с основным деревом. А держать как патч-сет. Можно даже с периодическим rebase как делают тут https://gitlab.collabora.com/hardware-enablement/rockchip-3588

Или пачкой веток. Каждая из которых будет версионным патч-сетом (аля 2026.07.01-rc1-rockchip-rkinit-v0.1-dev).

Главное, что бы можно было всегда взять и создать набор патчей для Buildroot/Yocto только из верхних коммитов.

И это будет полезно, в случае интереса к отправке патчей в Mainline U-Boot.

AlexVR ★★★★★
()

Немного оффтопный вопрос: а почему инициализация контроллера вообще целых 50кб занимает? Там же должно быть прописывание каких-то чисел в его регистры по списку и всё, разве нет? С ним же не надо потом работать никак.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 1)
Ответ на: комментарий от AlexVR

Отправить в upstream интересно, только надо сначала понять что оно работает. В идеале ещё добавить DDR4, но для этого надо сесть и посчитать тайминги, да поотлаживаться. Не уверен что сходу заработает.

Патчсет практически ничего не трогает кроме clock controller (вырезал вообще всё управление clock’ами из TPL, по скольку SDRAM всего 59,5Кб на всё про всё), да добавил пару syscon. Вообще, можно было ограничиться только кодом в drivers/ram/rockchip, как сделано в инициализаторе для rv1126, но в итоге всё равно придётся завязываться на dts, чтобы сделать выбор разных частот для rk3568 и rk3566. По другому никак, по скольку конфиг u-boot ничего про rk3566 как чип не знает.

com
() автор топика
Последнее исправление: com (всего исправлений: 1)
Ответ на: комментарий от firkax

Ну, не совсем. Для начала надо определить что за оперативка к тебе подоткнута. У неё могут быть разные конфигурации по размеру и по количеству рангов.

Дальше история в том что там есть DFS. То есть, динамическое управление частотой памяти. Условно, когда не смотришь видео в 4к, частоту можно и подзанизить чтобы поберечь батарейку.

Ещё современную оперативку нужно тренировать. По скольку частоты высокие, длинна дорог до чипа имеет значение. А каждый инженер может на своей плате развести дороги по-своему. Ну и на заводе где-то поднакосячить могут.

Поэтом алгоритм такой: определить что за оперативка, а дальше натренировать её на 4х частотах чтобы уметь переключаться между ними в рантайме.

Правда, opesource поддержки DFS нету. Она должна быть в ARM trusted firmware. Но там (наверное) уже как раз проще: всё на тренировано на 4 частоты, просто щёлкай между ними когда тебя попросят.

Не забываем ещё про размер указателя в 64 бита, который ужирняет бинарь.

com
() автор топика

Поскольку «Рокчип» как-то не торопился открывать исходники бинаря для инициализации контроллера оперативной памяти на rk356x, я, потратив прилично времени на реверс, сделал это за них.

А техническое описание микропроцессора «рокчиповцы» не дают по запросу? Если прочитать техописание самого микропроцессора, то по описанию его регистров, отвечающих за взаимодействие с оперативной памятью, можно же самому написать заново начальную настройку и калибровку оперативной памяти и не заниматься дизассемблированием чужого исполняемого файла.

Enthusiast ★★★★
()
Ответ на: комментарий от Enthusiast

Полагаю что увы.

Чтобы правильно рассчитать задержки нужно иметь полную документацию на DDR PHY. Думаю, Innosilicon даёт её только тем кто купил у них эту PHY. А в описании «рокчиповцов» только сухие регисты.

Вот ты звапустил тренировку write leveling для опреативки, оно дало тебе какие-то значения в регистрах. А как правильно это дело пересчитать c учётом текущей частоты и остальных задержек знает только «рокчип» да Innosilicon.

Не говоря уже об особенностях взаимодействия контроллера DDR с DDR PHY.

com
() автор топика
Ответ на: комментарий от com

Вот ты звапустил тренировку write leveling для опреативки, оно дало тебе какие-то значения в регистрах. А как правильно это дело пересчитать c учётом текущей частоты и остальных задержек знает только «рокчип» да Innosilicon.

Если поставить себя на место производителя микропроцессоров «Рокчипа» и принять твои слова за текущее положение дел, то кто по-твоему будет покупать микросхемы у «Рокчипа»? Разработчики электронной аппаратуры изготовят свои устройства на процессорах «Рокчипа», а откалибровать микросхемы оперативной памяти не смогут?

Обычно данные для калибровки оперативной памяти выдаёт производитель микропроцессоров, чтобы его микросхемы хоть кто-то купил. Если производитель микросхем не выдаёт эти технические документы по запросу радиолюбителя, то эти документы вполне можно получить у оптового продавца микросхем в твоей местности. То есть всего-то нужно узнать кто именно является рукопожатным продавцом микросхем «Рокчипа» в нашей стране и обратиться к этому продавцу за документацией.

Что-то там дизассемблировать это несерьёзно же. Гораздо лучше работать с документами производителя электронных компонентов - так ошибок будет гораздо меньше.

Enthusiast ★★★★
()
Ответ на: комментарий от Enthusiast

Разработчики электронной аппаратуры изготовят свои устройства на процессорах «Рокчипа», а откалибровать микросхемы оперативной памяти не смогут?

Дела обстоят так, что «Рокчип» выдаёт список поддерживаемых микросхем оперативной памяти, и бинарный файл который умеет эти поддерживаемые микросхемы калибровать.

И действительно, если микросхема заявлена как поддерживаемая, но при этом не калибруется бинарным файлом, то можно написать в «Рокчип», и они исправят проблему в этом бинаром файле.

А вот инструкций для самостоятельной инициализации оперативной памяти, полагаю, не существует. По крайней мере за 6 лет никто открытую реализацию не написал.

com
() автор топика
Ответ на: комментарий от Enthusiast

А техническое описание микропроцессора «рокчиповцы» не дают по запросу?

Ничего они не дают, если ты не клиент, заказывающий процессоры миллионами. По интернету если пошариться, какие-то пдфки найти можно, в которых инфы кот наплакал, и это всё. Уродская контора, как и 99% остальных эмбедщиков.

vbr ★★★★★
()
Последнее исправление: vbr (всего исправлений: 2)

Интересно послушать про сам процесс исследования бинаря. Какой формат? Какие инструменты для декомпиляции/дизассемблер использовали? Как найти точку начала исполнения и т.п.

UPD: Но сама работа - огонь! Спасибо!

dsl ★★
()
Последнее исправление: dsl (всего исправлений: 1)
Ответ на: комментарий от dsl

На удивление, там ничего сверхъестественного.

Начал с bootrom. Сдампить было довольно просто, bootrom доступен для чтения в u-boot SPL, так что написал код который выплёвывает его в hex на UART. На этом этапе мыслей лезть в бинарь с инициализацией оперативки ещё не возникало. Однако, в bootrom нашлась очень интересная деталь: на самом деле bootrom ищет дальнейшие стадии загрузки не по фиксированному смещению на флешке, а делает аж 5 попыток по разным. Ну, то есть, сначала смотрит 64й сектор флешки в поисках заголовка следующего загрузчика, и, если не находит, прибавляет 1024 сектора и смотрит на 1088й.

И тут я подумал: есть же замечательная инициатива прикрутить Verified Boot For Embedded к u-boot. Это про то как обновлять u-boot из Linux не задумываясь о том чтобы превратить устройство в кирпич. И в этом документе Simon пишет:

For SoCs with more SRAM (such as RK3588) it would be possible to put everything in one FIT. For SoCs with a lot less SRAM, probably the only option would be to init the SDRAM early in boot, living with the inability to safely update that code later.

Но почему бы тогда не воспользоваться механизмом поиска дальнейших загрузчиков в bootrom, и не сделать нормальное A/B обновление для инициализации оперативки в том числе? Алгоритм должен быть таким: первым делом запускаем VPL, тот смотрит какой слот нам надо горузить, A или B, сохраняет где-то то что он насмотрел. 60Кб SRAM должно хватить на драйвер для SD/eMMC и немного обвязки. Дальше VPL вываливается с ошибкой. Bootrom находит следующий валидный заголовок, из которого запускается инициализация оперативки. Инициализация оперативки смотрит на результат работы VPL, и, если понимает что должна отработать (слот A), то отрабатывает, если нет, то вываливается с ошибкой чтобы bootrom искал дальше то что должно быть в слоту B.

Но для того чтобы это работало нам нужен opensource код для инициализации оперативки, чтобы добавить туда проверку на результат работы VPL…

Бинарь с оперативкой на самом деле просто bare arm64. u-boot при сборке заботливо оборачивает его в заголовок который понимает bootrom. Так что заменить бинарь на собранный из исходников u-boot TPL проблем не составило. Куда в SRAM грузится бинарь стало понятно из bootrom. Ещё сильно помог код инициализации оперативки для RV1126. Там инкарнация той же PHY, только она сильно размазана по регистрам. Но CA Training там вообще не реализован. К слову, инициализацию для RV1126 выложил сам Rockchip как часть своего форка u-boot. Описание регистров контроллера и PHY в TRM для RK3568 сильно куцее, поэтому пришлось половину додумывать и угадывать. Но самое обидное что нормальное описание есть в TRM к RK3562, и наткнулся я на него только тогда когда инициализация оперативки заработала. Так что пришлось переименовывать все свои догадки в соответствие с нормальным описанием регистров.

Из инструментов – Ghidra.

com
() автор топика
Ответ на: комментарий от com

Сходу нашел Rockchip_RK3568_TRM_Part1_V1.3-20220930P.pdf на 852 страницы и Rockchip_RV1126B_TRM_Part_1_V1.0_20250427_(public).pdf на 1365. Они?

Жаль только потестить не смогу - у меня только PinePhone Pro на RK3399S.

Про гидру какие-то страшилки слышал, но сам не пробовал. А почему кстати не Radare2, например? Удобнее или фичи какие в гидре есть?

UPD: Иииии я открыл для себя Паленый мед. Спасибо и за это!

dsl ★★
()
Последнее исправление: dsl (всего исправлений: 1)
Ответ на: комментарий от dsl

Скорее RK3568 TRM Part 2, глава про DMC, начиная с 16й страницы, RV1109-RV1126 TRM Part 2, тоже про DMC, с 17й страницы, RK3562 TRM Part 1, опять про DMC, 760я страница (там регистров побольше чем у rk3566/8, чего-то нового досыпали, у rk3566/8 BYTE секции начинаются с 0x300), ну и на закуску примерное описание interconnect (memory scheduler) в RK3588 TRM Part 2, страница 16.

com
() автор топика
Ответ на: комментарий от dsl

Про гидру какие-то страшилки слышал, но сам не пробовал.

Там в отличие от radre есть достаточно достойный декомпилятор.

com
() автор топика
Ответ на: комментарий от Enthusiast

Что-то там дизассемблировать это несерьёзно же. Гораздо лучше работать с документами производителя

Для дизассемблирования нужны одни навыки, для добывания документации абсолютно другие. Тут уж кто что умеет.

watchcat382 ★★
()
Ответ на: комментарий от com

А bootrom - это стартовый код, который прошит на заводе где-то в сам чип, и запускается непосредственно после подачи питания (в доках ARM, насколько я помню, он называется BROM)? А откуда ты его читал, т.е. по каким адресам?

zloy_starper ★★★
()
Ответ на: комментарий от zloy_starper

Он самый.

RK3568 TRM Part 1, стр. 13. Таблица 1-2 Address Remapping.

Так что 0xffff0000. Его там 32 килобайта. В конце после нулей некая ASCII последовательность. Видимо, версия bootrom. Мой заканчивается на 350A20210322V300

com
() автор топика
Ответ на: комментарий от dsl

Есть <Rockchip-RK3568-TRM-Part2-V1_1-20210301.pdf> на 2579 страниц, есть вроде и посвежее. Если не найдете, могу куда-то выложить. Там стр.16-182 2 главы:

Chapter 1 DMC (Dynamic Memory Interface)

Chapter 2 DDR Converter of Frequency (DCF)

И в документации масса пробелов, что с чем связано и как оно работает, а что-то вообще не описано, как ISP v2.1 (Image Processor). Конкретно памятью не занимался, сейчас голова пухнет как запустить камеру RPi v2.1 на MIPI-CSI. Вот кстати рокчиповское ядро https://github.com/rockchip-linux/kernel/tree/develop-6.6 . Они уже такого там понаваяли, что влить их изменения в ваниль практически невозможно, и их патчи отклоняются. Но, кое-что по их исходникам посмотреть можно, что-то утащить.

bugs-bunny
()
Ответ на: комментарий от bugs-bunny

Ну да, я выше уже оставлял ссылку на этот TRM.

Опять же, как писал выше, полное описание регистров DMC есть в TRM для rk3562. Вроде бы с DPLL в CRU там что-то сделали чтобы можно было выставлять любую частоту оперативке, а не только ту что присутствует в списке. Ну и address space перетосовали конкретно.

DCF для инициализации оперативки не используется.

Так или иначе, LPDDR4 4GB на rk3568 успешно инициализируется и работает с моими патчами.

Конкретно памятью не занимался, сейчас голова пухнет как запустить камеру RPi v2.1 на MIPI-CSI.

Обидно что нет обратной связи. Видимо, никто кроме меня пока это не пытался запустить. Подожду ещё немного, если никто не ответит, то, видимо, буду пробовать отправлять в mainline u-boot как RFC. Может, там кому-нибудь будет интересно пощупать.

com
() автор топика
Последнее исправление: com (всего исправлений: 1)
Ответ на: комментарий от com

Ну да, я выше уже оставлял ссылку на этот TRM.

В Part1 только половина блоков, в Part2 еще 33 раздела. Около 200 страниц как раз про общее описание и регистры DMC и DCF, конкретно у rk3568.

bugs-bunny
()
Ответ на: комментарий от bugs-bunny

Ещё выше.

Скорее RK3568 TRM Part 2, глава про DMC, начиная с 16й страницы, RV1109-RV1126 TRM Part 2, тоже про DMC, с 17й страницы, RK3562 TRM Part 1, опять про DMC, 760я страница (там регистров побольше чем у rk3566/8, чего-то нового досыпали, у rk3566/8 BYTE секции начинаются с 0x300), ну и на закуску примерное описание interconnect (memory scheduler) в RK3588 TRM Part 2, страница 16.

com
() автор топика
Ответ на: комментарий от com

У меня работает вот так:

U-Boot TPL 2026.07-rc1 (May 28 2026 - 09:25:28) PHY drv:clk:38,ca:38,DQ:30,odt:0 vrefinner:41%, vrefout:41% dram drv:40,odt:0 read gate training failed LPDDR4, 324MHz DRAM init failed! -1

ERROR ### Please RESET the board

Есть ли какие то мысли что может быть не так?

yarlus
()
Ответ на: комментарий от com

Да, точно, это я нашел, попробовал, к сожалению все равно не работает :(

Нашел для тестов вторую плату, там память LPDDR4X. Если в .inc файлах для LPDDR4 поменять тип памяти это может сработать или это глупость и там все сильно сложнее?

yarlus
()
Ответ на: комментарий от yarlus

Если в .inc файлах для LPDDR4 поменять тип памяти это может сработать или это глупость и там все сильно сложнее?

Сложнее. Там для DDR4 свои inc файлы. Разный набор inc файлов подключается в зависимости от типа памяти выбранного при компиляции.

А не работает каким образом?

read gate training failed LPDDR4, 324MHz DRAM init failed! -1

Всё так же пишет что пытается инициализировать LPDDR4 вместо DDR4?

Собрался сейчас с DDR4, у меня пишет

U-Boot TPL 2026.07-rc3-ge39964c734f3-dirty (Jun 02 2026 - 20:55:33)
PHY drv:clk:37,ca:37,DQ:37,odt:0
vrefinner:50%, vrefout:50%
dram drv:34,odt:0
read gate training failed
DDR4, 324MHz
DRAM init failed: -1

Что логично. Пытается инициализировать DDR4, хотя у меня LPDDR4, и падает.

com
() автор топика
Ответ на: комментарий от yarlus

По поводу LPDDR4X: там и правда должно (скорее всего) заработать если поменять LPDDR на LPDDR4X и ещё один бит. Убрать 16й бит во втором значении в строчке с /* INIT4 */ в каждом inc файле.

diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1056.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1056.inc
index fe9b5d92d08..34c447345fa 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1056.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1056.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00690000},	/* INIT1 */
 			{0x000000d8, 0x00000206},	/* INIT2 */
 			{0x000000dc, 0x0034001b},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00230000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1184.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1184.inc
index 506871f27ce..f8505044f62 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1184.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1184.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00750000},	/* INIT1 */
 			{0x000000d8, 0x00000206},	/* INIT2 */
 			{0x000000dc, 0x00440024},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00230000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1332.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1332.inc
index 1d2bc4c22f1..c2c20b13bd3 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1332.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1332.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00840000},	/* INIT1 */
 			{0x000000d8, 0x00000207},	/* INIT2 */
 			{0x000000dc, 0x00440024},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00230000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1560.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1560.inc
index 1afaec6fe11..3d1ff371036 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1560.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-1560.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x009a0000},	/* INIT1 */
 			{0x000000d8, 0x00000208},	/* INIT2 */
 			{0x000000dc, 0x0054002d},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00230000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-324.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-324.inc
index 0b796f8a0ae..41ff56678cc 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-324.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-324.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00210000},	/* INIT1 */
 			{0x000000d8, 0x00000202},	/* INIT2 */
 			{0x000000dc, 0x00240012},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00000000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-396.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-396.inc
index 8f2a3191329..0f7ae204607 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-396.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-396.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00280000},	/* INIT1 */
 			{0x000000d8, 0x00000202},	/* INIT2 */
 			{0x000000dc, 0x00240012},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00000000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-528.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-528.inc
index 51c786e0ada..9281da45f00 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-528.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-528.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x00350000},	/* INIT1 */
 			{0x000000d8, 0x00000203},	/* INIT2 */
 			{0x000000dc, 0x00240012},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00000000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-630.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-630.inc
index 70084613475..db109f98b75 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-630.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-630.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x003f0000},	/* INIT1 */
 			{0x000000d8, 0x00000204},	/* INIT2 */
 			{0x000000dc, 0x00240012},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00000000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-780.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-780.inc
index 2df058f06fa..3217432551f 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-780.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-780.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x004e0000},	/* INIT1 */
 			{0x000000d8, 0x00000204},	/* INIT2 */
 			{0x000000dc, 0x00240012},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00000000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */
diff --git a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-920.inc b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-920.inc
index f253e4ccf5b..a104462e77f 100644
--- a/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-920.inc
+++ b/drivers/ram/rockchip/sdram-rk3568-lpddr4-detect-920.inc
@@ -39,7 +39,7 @@
 			{0x000000d4, 0x005b0000},	/* INIT1 */
 			{0x000000d8, 0x00000205},	/* INIT2 */
 			{0x000000dc, 0x0034001b},	/* INIT3 */
-			{0x000000e0, 0x00310000},	/* INIT4 */
+			{0x000000e0, 0x00300000},	/* INIT4 */
 			{0x000000e8, 0x00230000},	/* INIT6 */
 			{0x000000ec, 0x00000000},	/* INIT7 */
 			{0x000000f4, 0x000f022f},	/* RANKCTL */

Ещё вот этот патч положить сверху для надёжности.

com
() автор топика
Ответ на: комментарий от com

На плате с DDR4 не работает следующим образом:


U-Boot TPL 2026.07-rc1 (Jun 03 2026 - 08:06:44)

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

read gate training failed

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

ddrconfig: 9

DDR4, 324MHz

BW=16 Col=10 Bk=4 BG=2 CS0 Row=16 CS=1 Die BW=16 Size=1024MB

tdqss: cs0 dqs0: 144ps, dqs1: 144ps

change to: 324MHz

clk skew:0x8d

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

error: read training failed

DRAM init failed! -1

### ERROR ### Please RESET the board ###

Меня смущает «odt:0». Бинарник от рокчипа пишет 60.

В ближайшее время попробую поковырять плату с LPDDR4X, может с ней что то получится.

yarlus
()
Ответ на: комментарий от yarlus

Меня смущает «odt:0». Бинарник от рокчипа пишет 60.

Это он для последней частоты пишет, которая 1560MHz(final freq). odt должен включаться после 625 MHz. А инициализация развалилась на самой первой частоте (324 MHz). Ну, хоть оперативка определилась, что радует.

BW=16 Col=10 Bk=4 BG=2 CS0 Row=16 CS=1 Die BW=16 Size=1024MB

А количество оперативки он правильно определил?

ddrconfig: 9

А ddrconfig (можно сравнить с тем что пишет блоб)?

Хотелось бы попробовать сделать блоб поразговорчивее и посмотреть что он пишет.

Для того чтобы сделать блоб порзаговорчивее, надо взять этот блоб и его пропатчить:

printf '\xbb' | dd of=rk3568_ddr_1560MHz_v1.18.bin bs=1 seek=38820 conv=notrunc

Ну и собраться, запуститься, и выложить лог (до строчки out, дальше не интересно) либо сюда, либо на какую-нибудь хранилку текстов (аналог pastebin).

com
() автор топика
Ответ на: комментарий от com

Количество оперативки не то и ddrconfig тоже другой.

Вот результат работы после патча:


DDR V1.18 f366f69a7d typ 23/07/17-15:48:58

In

LP4/4x derate en, other dram:1x trefi

ddrconfig:15

DDR4, 324MHz

BW=32 Col=10 Bk=4 BG=2 CS0 Row=16 CS=1 Die BW=16 Size=2048MB

tdqss: cs0 dqs0: 144ps, dqs1: 144ps, dqs2: 96ps, dqs3: 48ps, 



change to: 324MHz

clk skew:0x8d

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

cs 0:

the read training result:

DQS0:0x70, DQS1:0x71, DQS2:0x6f, DQS3:0x71, 

min  : 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 , 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 ,

       0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 , 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 ,

mid  :0x3f 0x3e 0x3d 0x3c 0x3a 0x3a 0x3b 0x3a ,0x3e 0x3f 0x39 0x3d 0x3d 0x3e 0x3e 0x3d ,

      0x3d 0x3d 0x3f 0x3f 0x3d 0x3c 0x3d 0x3b ,0x3f 0x3d 0x3c 0x3a 0x3d 0x3f 0x3f 0x3e ,

max  :0x7e 0x7c 0x7b 0x78 0x74 0x75 0x76 0x74 ,0x7d 0x7e 0x73 0x7a 0x7b 0x7d 0x7c 0x7b ,

      0x7a 0x7b 0x7e 0x7e 0x7a 0x78 0x7a 0x77 ,0x7e 0x7b 0x79 0x75 0x7b 0x7e 0x7e 0x7c ,

range:0x7e 0x7c 0x7b 0x78 0x74 0x75 0x76 0x74 ,0x7d 0x7e 0x73 0x7a 0x7b 0x7d 0x7c 0x7b ,

      0x7a 0x7b 0x7e 0x7e 0x7a 0x78 0x7a 0x77 ,0x7e 0x7b 0x79 0x75 0x7b 0x7e 0x7e 0x7c ,

the write training result:

DQS0:0x92, DQS1:0x92, DQS2:0x90, DQS3:0x8e, 

min  :0x74 0x74 0x75 0x74 0x72 0x72 0x72 0x71 0x73 ,0x74 0x74 0x72 0x74 0x73 0x74 0x74 0x73 0x72 ,

      0x72 0x73 0x73 0x73 0x72 0x72 0x72 0x72 0x71 ,0x70 0x70 0x70 0x6f 0x70 0x70 0x6f 0x6f 0x6f ,

mid  :0x92 0x93 0x93 0x92 0x90 0x90 0x90 0x8f 0x91 ,0x92 0x92 0x90 0x92 0x91 0x92 0x93 0x92 0x90 ,

      0x91 0x92 0x91 0x92 0x90 0x90 0x90 0x90 0x90 ,0x8e 0x8e 0x8e 0x8d 0x8e 0x8f 0x8d 0x8e 0x8e ,

max  :0xb1 0xb2 0xb2 0xb1 0xaf 0xaf 0xaf 0xae 0xb0 ,0xb1 0xb1 0xaf 0xb1 0xb0 0xb1 0xb2 0xb1 0xaf ,

      0xb0 0xb1 0xb0 0xb1 0xaf 0xaf 0xaf 0xaf 0xaf ,0xad 0xac 0xad 0xac 0xad 0xae 0xac 0xad 0xad ,

range:0x3d 0x3e 0x3d 0x3d 0x3d 0x3d 0x3d 0x3d 0x3d ,0x3d 0x3d 0x3d 0x3d 0x3d 0x3d 0x3e 0x3e 0x3d ,

      0x3e 0x3e 0x3d 0x3e 0x3d 0x3d 0x3d 0x3d 0x3e ,0x3d 0x3c 0x3d 0x3d 0x3d 0x3e 0x3d 0x3e 0x3e ,



change to: 528MHz

clk skew:0x8d

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

cs 0:

the read training result:

DQS0:0x70, DQS1:0x71, DQS2:0x6f, DQS3:0x72, 

min  : 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 , 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 ,

       0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 , 0x0  0x0  0x0  0x0  0x0  0x0  0x0  0x0 ,

mid  :0x3f 0x3e 0x3d 0x3c 0x3a 0x3a 0x3a 0x3a ,0x3e 0x3f 0x39 0x3d 0x3d 0x3e 0x3e 0x3d ,

      0x3c 0x3d 0x3f 0x3f 0x3c 0x3b 0x3c 0x3b ,0x3f 0x3d 0x3c 0x3a 0x3d 0x3f 0x3e 0x3e ,

max  :0x7e 0x7c 0x7b 0x78 0x74 0x75 0x75 0x74 ,0x7d 0x7e 0x73 0x7a 0x7a 0x7d 0x7c 0x7a ,

      0x79 0x7a 0x7e 0x7e 0x79 0x77 0x79 0x77 ,0x7e 0x7b 0x79 0x74 0x7b 0x7e 0x7d 0x7c ,

range:0x7e 0x7c 0x7b 0x78 0x74 0x75 0x75 0x74 ,0x7d 0x7e 0x73 0x7a 0x7a 0x7d 0x7c 0x7a ,

      0x79 0x7a 0x7e 0x7e 0x79 0x77 0x79 0x77 ,0x7e 0x7b 0x79 0x74 0x7b 0x7e 0x7d 0x7c ,

the write training result:

DQS0:0x96, DQS1:0x96, DQS2:0x93, DQS3:0x90, 

min  :0x7a 0x7a 0x7b 0x79 0x75 0x76 0x76 0x74 0x77 ,0x79 0x79 0x76 0x79 0x77 0x79 0x79 0x79 0x76 ,

      0x76 0x77 0x77 0x77 0x76 0x76 0x75 0x76 0x76 ,0x72 0x72 0x72 0x70 0x72 0x73 0x71 0x72 0x71 ,

mid  :0x98 0x98 0x99 0x97 0x93 0x94 0x93 0x92 0x95 ,0x97 0x97 0x94 0x97 0x95 0x97 0x97 0x97 0x94 ,

      0x94 0x95 0x95 0x95 0x94 0x93 0x93 0x93 0x94 ,0x91 0x90 0x90 0x8f 0x90 0x91 0x8f 0x90 0x8f ,

max  :0xb6 0xb6 0xb7 0xb5 0xb1 0xb2 0xb1 0xb1 0xb4 ,0xb5 0xb5 0xb2 0xb5 0xb4 0xb5 0xb6 0xb5 0xb2 ,

      0xb2 0xb4 0xb4 0xb4 0xb2 0xb1 0xb1 0xb1 0xb2 ,0xb0 0xae 0xaf 0xae 0xaf 0xb0 0xad 0xae 0xae ,

range:0x3c 0x3c 0x3c 0x3c 0x3c 0x3c 0x3b 0x3d 0x3d ,0x3c 0x3c 0x3c 0x3c 0x3d 0x3c 0x3d 0x3c 0x3c ,

      0x3c 0x3d 0x3d 0x3d 0x3c 0x3b 0x3c 0x3b 0x3c ,0x3e 0x3c 0x3d 0x3e 0x3d 0x3d 0x3c 0x3c 0x3d ,



change to: 780MHz

clk skew:0x8d

PHY drv:clk:37,ca:37,DQ:37,odt:139

vrefinner:50%, vrefout:61%

dram drv:34,odt:120

cs 0:

the read training result:

DQS0:0x59, DQS1:0x57, DQS2:0x4e, DQS3:0x53, 

min  : 0xb  0xd  0xa  0x8  0x4  0x3  0x6  0x2 , 0xb  0xc  0x1  0x8  0x8  0xd  0xa  0x9 ,

       0x4  0x6  0x8  0x7  0x4  0x2  0x2  0x3 , 0x4  0x5  0x4  0x1  0x5  0x7  0x4  0x6 ,

mid  :0x38 0x38 0x37 0x34 0x30 0x30 0x32 0x2f ,0x37 0x38 0x2d 0x34 0x34 0x38 0x36 0x34 ,

      0x2e 0x30 0x32 0x32 0x2d 0x2c 0x2d 0x2c ,0x31 0x30 0x2e 0x2b 0x30 0x33 0x31 0x31 ,

max  :0x66 0x64 0x64 0x60 0x5c 0x5e 0x5e 0x5c ,0x63 0x64 0x5a 0x60 0x60 0x64 0x62 0x60 ,

      0x58 0x5a 0x5c 0x5d 0x57 0x56 0x59 0x56 ,0x5e 0x5c 0x59 0x56 0x5c 0x60 0x5e 0x5d ,

range:0x5b 0x57 0x5a 0x58 0x58 0x5b 0x58 0x5a ,0x58 0x58 0x59 0x58 0x58 0x57 0x58 0x57 ,

      0x54 0x54 0x54 0x56 0x53 0x54 0x57 0x53 ,0x5a 0x57 0x55 0x55 0x57 0x59 0x5a 0x57 ,

the write training result:

DQS0:0x9b, DQS1:0x9b, DQS2:0x96, DQS3:0x91, 

min  :0x80 0x80 0x80 0x7f 0x7a 0x7c 0x7a 0x79 0x7c ,0x7f 0x7f 0x7c 0x80 0x7d 0x80 0x80 0x7f 0x7a ,

      0x7c 0x7d 0x7c 0x7d 0x7a 0x7a 0x7a 0x7a 0x79 ,0x74 0x74 0x74 0x72 0x74 0x75 0x71 0x74 0x72 ,

mid  :0x9d 0x9d 0x9e 0x9c 0x97 0x98 0x97 0x96 0x9a ,0x9c 0x9c 0x99 0x9d 0x9a 0x9d 0x9d 0x9c 0x97 ,

      0x99 0x9a 0x99 0x9a 0x97 0x97 0x96 0x97 0x97 ,0x92 0x91 0x92 0x90 0x91 0x93 0x8f 0x91 0x90 ,

max  :0xbb 0xbb 0xbc 0xba 0xb5 0xb5 0xb5 0xb3 0xb8 ,0xba 0xba 0xb6 0xba 0xb8 0xba 0xbb 0xb9 0xb5 ,

      0xb6 0xb7 0xb7 0xb8 0xb5 0xb4 0xb3 0xb4 0xb5 ,0xb1 0xae 0xb0 0xae 0xaf 0xb1 0xad 0xaf 0xae ,

range:0x3b 0x3b 0x3c 0x3b 0x3b 0x39 0x3b 0x3a 0x3c ,0x3b 0x3b 0x3a 0x3a 0x3b 0x3a 0x3b 0x3a 0x3b ,

      0x3a 0x3a 0x3b 0x3b 0x3b 0x3a 0x39 0x3a 0x3c ,0x3d 0x3a 0x3c 0x3c 0x3b 0x3c 0x3c 0x3b 0x3c ,



change to: 1560MHz(final freq)

clk skew:0x8d

PHY drv:clk:37,ca:37,DQ:37,odt:139

vrefinner:50%, vrefout:61%

dram drv:34,odt:120

cs 0:

the read training result:

DQS0:0x35, DQS1:0x31, DQS2:0x29, DQS3:0x30, 

min  :0x10 0x11  0xe  0xb  0x6  0x4  0x8  0x2 , 0xe  0xe  0x1  0x8  0xb 0x10  0xe  0xb ,

       0x4  0x8  0xb  0xa  0x4  0x2  0x2  0x4 , 0x8  0x6  0x6  0x2  0x8  0xa  0x8  0x8 ,

mid  :0x2b 0x2b 0x29 0x25 0x20 0x1f 0x22 0x1e ,0x27 0x28 0x1b 0x23 0x24 0x29 0x27 0x24 ,

      0x1e 0x20 0x24 0x23 0x1d 0x1b 0x1d 0x1c ,0x23 0x22 0x20 0x1b 0x22 0x24 0x23 0x22 ,

max  :0x47 0x45 0x45 0x3f 0x3a 0x3a 0x3c 0x3a ,0x41 0x43 0x35 0x3e 0x3d 0x42 0x40 0x3e ,

      0x38 0x39 0x3e 0x3d 0x37 0x34 0x38 0x34 ,0x3e 0x3e 0x3a 0x35 0x3c 0x3f 0x3e 0x3d ,

range:0x37 0x34 0x37 0x34 0x34 0x36 0x34 0x38 ,0x33 0x35 0x34 0x36 0x32 0x32 0x32 0x33 ,

      0x34 0x31 0x33 0x33 0x33 0x32 0x36 0x30 ,0x36 0x38 0x34 0x33 0x34 0x35 0x36 0x35 ,

the write training result:

DQS0:0xa9, DQS1:0xa9, DQS2:0xa0, DQS3:0x96, 

min  :0x91 0x92 0x94 0x90 0x86 0x8a 0x86 0x86 0x8c ,0x90 0x90 0x8a 0x90 0x8d 0x90 0x93 0x91 0x87 ,

      0x8a 0x8c 0x8c 0x8c 0x87 0x87 0x87 0x88 0x86 ,0x7c 0x7d 0x7b 0x78 0x7e 0x7f 0x77 0x7c 0x78 ,

mid  :0xac 0xae 0xaf 0xab 0x9f 0xa3 0xa1 0x9f 0xa7 ,0xab 0xab 0xa3 0xab 0xa8 0xab 0xae 0xac 0xa1 ,

      0xa5 0xa7 0xa7 0xa8 0xa1 0xa0 0x9f 0xa1 0xa1 ,0x99 0x96 0x97 0x94 0x97 0x99 0x92 0x97 0x94 ,

max  :0xc8 0xca 0xca 0xc7 0xb9 0xbc 0xbc 0xb8 0xc3 ,0xc7 0xc7 0xbd 0xc7 0xc3 0xc7 0xc9 0xc7 0xbc ,

      0xc1 0xc3 0xc3 0xc4 0xbc 0xba 0xb8 0xbb 0xbc ,0xb6 0xb0 0xb3 0xb0 0xb1 0xb4 0xad 0xb2 0xb1 ,

range:0x37 0x38 0x36 0x37 0x33 0x32 0x36 0x32 0x37 ,0x37 0x37 0x33 0x37 0x36 0x37 0x36 0x36 0x35 ,

      0x37 0x37 0x37 0x38 0x35 0x33 0x31 0x33 0x36 ,0x3a 0x33 0x38 0x38 0x33 0x35 0x36 0x36 0x39 ,

out
yarlus
()
Ответ на: комментарий от yarlus

Количество оперативки не то и ddrconfig тоже другой.

Накосячл с проверкой типа памяти при определении её количества.

diff --git a/drivers/ram/rockchip/sdram_rk3568.c b/drivers/ram/rockchip/sdram_rk3568.c
index 91ec7300af4..8a641dab585 100644
--- a/drivers/ram/rockchip/sdram_rk3568.c
+++ b/drivers/ram/rockchip/sdram_rk3568.c
@@ -3152,7 +3152,7 @@ static u64 dram_detect_cap(struct dram_info *dram, struct rk3568_sdram_params *s
 	}
 	cap_info->rank = cs + 1;
 
-	if (dram_type == LPDDR4X) {
+	if (dram_type != LPDDR4 && dram_type != LPDDR4X) {
 		clrsetbits_le32(&phy->reg0, CHANNEL_EN_MASK,
 				((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)) << CHANNEL_EN_SHIFT);
 		if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)

Вот так должна найтись вся. Ну и LPDDR4X должно полегчать, если ей было плохо.

com
() автор топика
Ответ на: комментарий от com

Да, память теперь определяется полностью, но ddrconfig 14, а не 15.

И самое главное, что теперь оно в итоге виснет.

U-Boot TPL 2026.07-rc1 (Jun 05 2026 - 07:19:03)

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

read gate training failed

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

ddrconfig: 14

DDR4, 324MHz

BW=32 Col=10 Bk=4 BG=2 CS0 Row=16 CS=1 Die BW=16 Size=2048MB
yarlus
()
Ответ на: комментарий от yarlus

но ddrconfig 14, а не 15.

Досадная опечатка.

diff --git a/drivers/ram/rockchip/sdram_rk3568.c b/drivers/ram/rockchip/sdram_rk3568.c
index 91ec7300af4..a0ce73d9dca 100644
--- a/drivers/ram/rockchip/sdram_rk3568.c
+++ b/drivers/ram/rockchip/sdram_rk3568.c
@@ -424,7 +424,7 @@ static unsigned int calculate_ddrconfig(struct rk3568_sdram_params *sdram_params
 			if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
 			    ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
 			    ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
-				if (i < 4) {
+				if (i < 14) {
 					ddrconf = i;
 					goto out;
 				} else if (i == 14) {
@@ -3152,7 +3152,7 @@ static u64 dram_detect_cap(struct dram_info *dram, struct rk3568_sdram_params *s
 	}
 	cap_info->rank = cs + 1;
 
-	if (dram_type == LPDDR4X) {
+	if (dram_type != LPDDR4 && dram_type != LPDDR4X) {
 		clrsetbits_le32(&phy->reg0, CHANNEL_EN_MASK,
 				((1 << 3) | (1 << 2) | (1 << 1) | (1 << 0)) << CHANNEL_EN_SHIFT);
 		if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)

Это вместе с предыдущим фиксом. Не знаю, правда, перестанет ли оно виснуть от правильного ddrconfig, но до этого оно пыталось применить конфиг который к DDR4 не применим. Так что вполне могло.

com
() автор топика
Ответ на: комментарий от com

Виснуть перестал, теперь опять ошибка. Зато ddrconfig правильный и количество памяти тоже правильно определилось:

U-Boot TPL 2026.07-rc1 (Jun 08 2026 - 09:04:39)

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

read gate training failed

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

ddrconfig: 15

DDR4, 324MHz

BW=32 Col=10 Bk=4 BG=2 CS0 Row=16 CS=1 Die BW=16 Size=2048MB

tdqss: cs0 dqs0: 144ps, dqs1: 144ps, dqs2: 96ps, dqs3: 48ps

change to: 324MHz

clk skew:0x94

PHY drv:clk:37,ca:37,DQ:37,odt:0

vrefinner:50%, vrefout:50%

dram drv:34,odt:0

error: read training failed

DRAM init failed! -1

### ERROR ### Please RESET the board ###
yarlus
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария