Jump to content

    

doom13

Свой
  • Content Count

    1479
  • Joined

  • Last visited

Community Reputation

0 Обычный

About doom13

  • Rank
    Профессионал
  • Birthday 02/09/1982

Контакты

  • Сайт
    http://
  • ICQ
    0

Информация

  • Город
    Минск, Беларусь

Recent Profile Visitors

6293 profile views
  1. Приветствую. Нужен совет по реализации загрузчика для ZynqMP. На данный момент всю систему разруливает FreeRTOS на A53 #0. Далее будут задействованы ещё одно A53 и одно R5 (возможно все) c BareMetal или FreeRTOS. Удалённое обновление ПО по Ethernet (TFTP server) и запись в QSPI, тут вроде всё просто. Ещё думаю над возможностью в целях отладки реализовать загрузку в RAM (PS DDR) и тут вопросы. Может попробовать как-то использовать u-boot, флэху писать он умеет, грузить RAM тож умеет (вопрос только как быть, если загрузили прошивки под разные ядра, как их тут стартануть) или писать свой загрузчик? Но тут тот же вопрос, прошивки разложили, как их все стартануть? Спасибо.
  2. Здравствуйте. Подскажите, что почитать по теме. Пока прошёлся по докам FreeRTOS.
  3. Т.е. ваш Linux крутится на одном ядре
  4. Спасибо, посмотрел, получается device-tree она не парсит. И что тогда, кривой драйвер?
  5. Исходники для dev_get_platdata найти не могу, поэтому пока не понимаю, могла ли она помочь достать поддержку для 8 бит из device-tree
  6. Нет, если перед ней не ставлю mmc_of_parse(dev, &plat->cfg);// ТУТ ДОБАВИТ ПОДДЕРЖКУ 8-бит , то поддержку 8ми бит не получу int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, u32 f_max, u32 f_min) { u32 caps, caps_1 = 0; #ifdef __DOOM13_DEBUG printf("-----------------------------------\n"); printf("RUN: int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host, u32 f_max, u32 f_min)\n"); printf("cfg->host_caps = %x\n", cfg->host_caps); printf("\n"); #endif caps = sdhci_readl(host, SDHCI_CAPABILITIES); #ifdef CONFIG_MMC_SDHCI_SDMA if (!(caps & SDHCI_CAN_DO_SDMA)) { printf("%s: Your controller doesn't support SDMA!!\n", __func__); return -EINVAL; } #endif if (host->quirks & SDHCI_QUIRK_REG32_RW) host->version = sdhci_readl(host, SDHCI_HOST_VERSION - 2) >> 16; else host->version = sdhci_readw(host, SDHCI_HOST_VERSION); cfg->name = host->name; #ifndef CONFIG_DM_MMC cfg->ops = &sdhci_ops; #endif /* Check whether the clock multiplier is supported or not */ if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); host->clk_mul = (caps_1 & SDHCI_CLOCK_MUL_MASK) >> SDHCI_CLOCK_MUL_SHIFT; } if (host->max_clk == 0) { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) host->max_clk = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; else host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; host->max_clk *= 1000000; if (host->clk_mul) host->max_clk *= host->clk_mul; } if (host->max_clk == 0) { printf("%s: Hardware doesn't specify base clock frequency\n", __func__); return -EINVAL; } if (f_max && (f_max < host->max_clk)) cfg->f_max = f_max; else cfg->f_max = host->max_clk; if (f_min) cfg->f_min = f_min; else { if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300; else cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200; } cfg->voltages = 0; if (caps & SDHCI_CAN_VDD_330) cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; if (caps & SDHCI_CAN_VDD_300) cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; if (caps & SDHCI_CAN_VDD_180) cfg->voltages |= MMC_VDD_165_195; if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE) cfg->voltages |= host->voltages; #ifdef __DOOM13_DEBUG printf("cfg->host_caps = %x\n", cfg->host_caps); printf("\n"); #endif cfg->host_caps |= MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT; #ifdef __DOOM13_DEBUG printf("cfg->host_caps = %x\n", cfg->host_caps); printf("\n"); #endif /* Since Host Controller Version3.0 */ if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { if (!(caps & SDHCI_CAN_DO_8BIT)) cfg->host_caps &= ~MMC_MODE_8BIT; } if (host->quirks & SDHCI_QUIRK_BROKEN_HISPD_MODE) { cfg->host_caps &= ~MMC_MODE_HS; cfg->host_caps &= ~MMC_MODE_HS_52MHz; } if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) caps_1 = sdhci_readl(host, SDHCI_CAPABILITIES_1); if (!(cfg->voltages & MMC_VDD_165_195) || (host->quirks & SDHCI_QUIRK_NO_1_8_V)) caps_1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); if (caps_1 & (SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50)) cfg->host_caps |= MMC_CAP(UHS_SDR12) | MMC_CAP(UHS_SDR25); if (caps_1 & SDHCI_SUPPORT_SDR104) { cfg->host_caps |= MMC_CAP(UHS_SDR104) | MMC_CAP(UHS_SDR50); /* * SD3.0: SDR104 is supported so (for eMMC) the caps2 * field can be promoted to support HS200. */ cfg->host_caps |= MMC_CAP(MMC_HS_200); } else if (caps_1 & SDHCI_SUPPORT_SDR50) { cfg->host_caps |= MMC_CAP(UHS_SDR50); } if (caps_1 & SDHCI_SUPPORT_DDR50) cfg->host_caps |= MMC_CAP(UHS_DDR50); if (host->host_caps) cfg->host_caps |= host->host_caps; cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; return 0; } Получается, что в static int arasan_sdhci_probe(struct udevice *dev) { конфиг 8бит из device-tree могла достать только struct arasan_sdhci_plat *plat = dev_get_platdata(dev); но она этого не сделала (может ещё какой-то конфиг не установлен), а больше некому, только если править драйвер, добавляя парсер для device-tree
  7. Нашёл следующее: 1. параметер bus_width достаётся из device-tree функцией 2. В драйвере zynq_sdhci.c она не вызывается вообще 3. В файле mmc-uclass.c есть функция int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg) { int val; #ifdef __DOOM13_DEBUG printf("------------------------------------------------------------------\n"); printf("RUN: int mmc_of_parse(struct udevice *dev, struct mmc_config *cfg)\n"); printf("\n"); #endif val = dev_read_u32_default(dev, "bus-width", 1); switch (val) { case 0x8: cfg->host_caps |= MMC_MODE_8BIT; /* fall through */ case 0x4: cfg->host_caps |= MMC_MODE_4BIT; /* fall through */ case 0x1: cfg->host_caps |= MMC_MODE_1BIT; break; default: dev_err(dev, "Invalid \"bus-width\" value %u!\n", val); return -EINVAL; } /* f_max is obtained from the optional "max-frequency" property */ dev_read_u32(dev, "max-frequency", &cfg->f_max); if (dev_read_bool(dev, "cap-sd-highspeed")) cfg->host_caps |= MMC_CAP(SD_HS); if (dev_read_bool(dev, "cap-mmc-highspeed")) cfg->host_caps |= MMC_CAP(MMC_HS); if (dev_read_bool(dev, "sd-uhs-sdr12")) cfg->host_caps |= MMC_CAP(UHS_SDR12); if (dev_read_bool(dev, "sd-uhs-sdr25")) cfg->host_caps |= MMC_CAP(UHS_SDR25); if (dev_read_bool(dev, "sd-uhs-sdr50")) cfg->host_caps |= MMC_CAP(UHS_SDR50); if (dev_read_bool(dev, "sd-uhs-sdr104")) cfg->host_caps |= MMC_CAP(UHS_SDR104); if (dev_read_bool(dev, "sd-uhs-ddr50")) cfg->host_caps |= MMC_CAP(UHS_DDR50); if (dev_read_bool(dev, "mmc-ddr-1_8v")) cfg->host_caps |= MMC_CAP(MMC_DDR_52); if (dev_read_bool(dev, "mmc-ddr-1_2v")) cfg->host_caps |= MMC_CAP(MMC_DDR_52); if (dev_read_bool(dev, "mmc-hs200-1_8v")) cfg->host_caps |= MMC_CAP(MMC_HS_200); if (dev_read_bool(dev, "mmc-hs200-1_2v")) cfg->host_caps |= MMC_CAP(MMC_HS_200); if (dev_read_bool(dev, "mmc-hs400-1_8v")) cfg->host_caps |= MMC_CAP(MMC_HS_400); if (dev_read_bool(dev, "mmc-hs400-1_2v")) cfg->host_caps |= MMC_CAP(MMC_HS_400); return 0; } , но она тож нигде по коду не вызывается, получаю, что мои правки в device-tree /include/ "system-conf.dtsi" / { }; /* SD0 eMMC, 8-bit wide data bus */ /* non-removable; */ /* broken-mmc-highspeed; */ &sdhci0 { max-frequency = <200000000>; bus-width = <8>; }; не применяются. Получаю, что если подправить функцию static int arasan_sdhci_probe(struct udevice *dev), то контроллер SD переключит шину и eMMC память в режим 8-бит. static int arasan_sdhci_probe(struct udevice *dev) { struct arasan_sdhci_plat *plat = dev_get_platdata(dev); struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct arasan_sdhci_priv *priv = dev_get_priv(dev); struct sdhci_host *host; struct clk clk; unsigned long clock; int ret; #ifdef __DOOM13_DEBUG printf("-----------------------------------\n"); printf("RUN: static int arasan_sdhci_probe(struct udevice *dev)\n"); printf("1. plat->mmc.cfg->host_caps = %x\n", plat->mmc.cfg->host_caps); // printf --> 0 printf("\n"); #endif host = priv->host; ret = clk_get_by_index(dev, 0, &clk); if (ret < 0) { dev_err(dev, "failed to get clock\n"); return ret; } clock = clk_get_rate(&clk); if (IS_ERR_VALUE(clock)) { dev_err(dev, "failed to get rate\n"); return clock; } debug("%s: CLK %ld\n", __func__, clock); ret = clk_enable(&clk); if (ret && ret != -ENOSYS) { dev_err(dev, "failed to enable clock\n"); return ret; } host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; #ifdef CONFIG_ZYNQ_HISPD_BROKEN host->quirks |= SDHCI_QUIRK_BROKEN_HISPD_MODE; #endif if (priv->no_1p8) host->quirks |= SDHCI_QUIRK_NO_1_8_V; host->max_clk = clock; #ifdef __DOOM13_DEBUG printf("1.2. plat->mmc.cfg->host_caps = %x\n", plat->mmc.cfg->host_caps); // printf --> 0 mmc_of_parse(dev, &plat->cfg);// ТУТ ДОБАВИТ ПОДДЕРЖКУ 8-бит printf("2. plat->mmc.cfg->host_caps = %x\n", plat->mmc.cfg->host_caps); // printf --> 70000000 printf("\n"); #endif ret = sdhci_setup_cfg(&plat->cfg, host, plat->f_max, CONFIG_ZYNQ_SDHCI_MIN_FREQ); #ifdef __DOOM13_DEBUG printf("3. plat->mmc.cfg->host_caps = %x\n", plat->mmc.cfg->host_caps); printf("\n"); #endif host->mmc = &plat->mmc; if (ret) return ret; host->mmc->priv = host; host->mmc->dev = dev; upriv->mmc = host->mmc; #ifdef __DOOM13_DEBUG printf("upriv->mmc->cfg->host_caps = %x\n", upriv->mmc->cfg->host_caps); printf("\n"); #endif return sdhci_probe(dev); } Вопрос - что это, кривой драйвер? Или я ещё что-то должен включить в файле конфига?
  8. Попробовал SD_MODE, не повлияло никак
  9. Да, в дефолтном ничего не сказано про bus_width:
  10. Считал, что u-boot не пользует eMMC в нужном режиме, т.к. в дефолтном состоянии выбран QSPI_BOOT режим, и он криво инициализирует eMMC (но ему фиолетово в какой режим загрузки выбран, изменение никак не повлияло на eMMC bus_width). Поэтому попробовал при завершении FSBL перекинуть режим загрузки в EMMC_BOOT: Xil_Out32(0xff5e0200, 0x6100); Переключение режима загрузки расписано тут.
  11. Это? Можно попробовать. Эт в конце программы FSBL переключает режим загрузки в EMMC_BOOT, резисторами вообще выбран режим QSPI_BOOT.
  12. Спасибо, сейчас гляну, но я уже столько обыскал, а "воз и ныне там"
  13. Предлагаете обновить Vivado и SDK? На данный момент пользуюсь 2018.2 По моему *.hdf можете ведь попробовать сгенерить pmufw для моей системы? Хотя может на версию SDK ругнётся. xczu9eg.hdf
  14. Это я сделал. Стандартные примеры в SDK для PMU и FSBL добавляются в BOOT.BIN. Пытаюсь разобраться в работе функции static int mmc_select_mode_and_width(struct mmc *mmc, uint card_caps) из исходников u-boot-xlnx (/../u-boot-xlnx /drivers/mmc/mmc.c), предположительно именно здесь происходит переключение шины eMMC. mmc.c
  15. Для u-boot, собранного из исходников Xilinx, добавил галку mmcdebug, стало выводить в консоль обмен между eMMC чипом и контроллером SD: Смущают значения аргумента для CMD6 (выделил жирным), когда-то давно инициализацию eMMC v4.51 выполнял немного по другому: 1. В начале было переключение в HS mode - CMD6 и arg = 0x03B90100 2. Далее переключение BUS_WIDTH - CMD6 и arg = 0x03B70200 Может косяк в этом, u-boot неправильно гонит инициализацию памяти?