123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- /*
- *
- * Modified from unicore-mx SDRAM support
- *
- * Copyright (C) 2014 Chuck McManis <cmcmanis@mcmanis.com>
- * Copyright (C) 2016 Maxime Vincent <maxime.vince@gmail.com>
- * Copyright (C) 2016-2023 Daniele Lacamera <root@danielinux.net>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
- /*
- * Original authors:
- * Maxime Vincent <maxime.vince@gmail.com>
- * Chuck McManis <cmcmanis@mcmanis.com>
- * Daniele Lacamera <root@danielinux.net>
- *
- *
- */
- #include <stdint.h>
- #include <unicore-mx/stm32/gpio.h>
- #include <unicore-mx/stm32/rcc.h>
- #include <unicore-mx/stm32/fsmc.h>
- extern volatile uint32_t jiffies;
- #define SDRAM_BASE_ADDRESS ((uint8_t *)(0xC0000000))
- /*
- * This is just syntactic sugar but it helps, all of these
- * GPIO pins get configured in exactly the same way.
- */
- static const struct {
- uint32_t gpio;
- uint16_t pins;
- } sdram_pins[6] = {
- {GPIOC, GPIO3 },
- {GPIOD, GPIO0 | GPIO1 | GPIO3 | GPIO8 | GPIO9 | GPIO10 | GPIO14 | GPIO15},
- {GPIOE, GPIO0 | GPIO1 | GPIO7 | GPIO8 | GPIO9 | GPIO10 |
- GPIO11 | GPIO12 | GPIO13 | GPIO14 | GPIO15 },
- {GPIOF, GPIO0 | GPIO1 | GPIO2 | GPIO3 | GPIO4 | GPIO5 | GPIO11 |
- GPIO12 | GPIO13 | GPIO14 | GPIO15 },
- {GPIOG, GPIO0 | GPIO1 | GPIO4 | GPIO5 | GPIO8 | GPIO15},
- {GPIOH, GPIO3 | GPIO5 }
- };
- static struct sdram_timing timing = {
- .trcd = 2, /* RCD Delay */
- .trp = 2, /* RP Delay */
- .twr = 2, /* Write Recovery Time */
- .trc = 7, /* Row Cycle Delay */
- .tras = 4, /* Self Refresh Time */
- .txsr = 7, /* Exit Self Refresh Time */
- .tmrd = 2, /* Load to Active Delay */
- };
- /*
- * Initialize the SD RAM controller.
- */
- void sdram_init(void)
- {
- int i, now;
- uint32_t cr_tmp, tr_tmp; /* control, timing registers */
- /*
- * First all the GPIO pins that end up as SDRAM pins
- */
- rcc_periph_clock_enable(RCC_GPIOC);
- rcc_periph_clock_enable(RCC_GPIOD);
- rcc_periph_clock_enable(RCC_GPIOE);
- rcc_periph_clock_enable(RCC_GPIOF);
- rcc_periph_clock_enable(RCC_GPIOG);
- rcc_periph_clock_enable(RCC_GPIOH);
- for (i = 0; i < 6; i++) {
- gpio_mode_setup(sdram_pins[i].gpio,
- GPIO_MODE_AF, GPIO_PUPD_NONE,
- sdram_pins[i].pins);
- gpio_set_output_options(sdram_pins[i].gpio, GPIO_OTYPE_PP,
- GPIO_OSPEED_100MHZ, sdram_pins[i].pins);
- gpio_set_af(sdram_pins[i].gpio, GPIO_AF12, sdram_pins[i].pins);
- }
- /* Enable the SDRAM Controller */
- #if 1
- rcc_periph_clock_enable(RCC_FMC);
- #else
- rcc_peripheral_enable_clock(&RCC_AHB3ENR, RCC_AHB3ENR_FMCEN);
- #endif
- /* Note the STM32F746G-DISCO board has the ram attached to bank 1 */
- /* Timing parameters computed for a ~200 MHz clock */
- /* These parameters are specific to the SDRAM chip on the board */
- cr_tmp = FMC_SDCR_RPIPE_NONE;
- cr_tmp |= FMC_SDCR_SDCLK_2HCLK;
- cr_tmp |= FMC_SDCR_CAS_2CYC;
- cr_tmp |= FMC_SDCR_NB4;
- cr_tmp |= FMC_SDCR_MWID_16b;
- cr_tmp |= FMC_SDCR_NR_12;
- cr_tmp |= FMC_SDCR_NC_8;
- /* We're programming BANK 1
- * Per the manual some of the parameters only work in CR1 and TR1
- * So when using BANK2: we need pull those off and put them in the right place.
- * FMC_SDCR1 |= (cr_tmp); // & FMC_SDCR_DNC_MASK);
- * FMC_SDCR2 = cr_tmp;
- */
- FMC_SDCR1 = (cr_tmp);
- tr_tmp = sdram_timing(&timing);
- FMC_SDTR1 = (tr_tmp);
- /* Now start up the Controller per the manual
- * - Clock config enable
- * - PALL state
- * - set auto refresh
- * - Load the Mode Register
- */
- sdram_command(SDRAM_BANK1, SDRAM_CLK_CONF, 1, 0);
- /* sleep at least 100uS */
- now = jiffies;
- //while (now + 2 > jiffies) {};
- sdram_command(SDRAM_BANK1, SDRAM_PALL, 1, 0);
- sdram_command(SDRAM_BANK1, SDRAM_AUTO_REFRESH, 8, 0);
- tr_tmp = SDRAM_MODE_BURST_LENGTH_1 |
- SDRAM_MODE_BURST_TYPE_SEQUENTIAL |
- SDRAM_MODE_CAS_LATENCY_2 |
- SDRAM_MODE_OPERATING_MODE_STANDARD |
- SDRAM_MODE_WRITEBURST_MODE_SINGLE;
- sdram_command(SDRAM_BANK1, SDRAM_LOAD_MODE, 1, tr_tmp);
- /*
- * set the refresh counter to insure we kick off an
- * auto refresh often enough to prevent data loss.
- */
- FMC_SDRTR = ((uint32_t)0x0603); /* SDRAM refresh counter (100Mhz SD clock) */
- /* and Poof! a 8 megabytes of ram shows up in the address space */
- /* Disable write protection */
- FMC_SDCR1 &= ~FMC_SDCR_WP_ENABLE;
- }
|