1bf1ae442SVikas Manocha /* 2bf1ae442SVikas Manocha * (C) Copyright 2017 3bf1ae442SVikas Manocha * Vikas Manocha, <vikas.manocha@st.com> 4bf1ae442SVikas Manocha * 5bf1ae442SVikas Manocha * SPDX-License-Identifier: GPL-2.0+ 6bf1ae442SVikas Manocha */ 7bf1ae442SVikas Manocha 8bf1ae442SVikas Manocha #include <common.h> 9d0b24c1aSVikas Manocha #include <clk.h> 10910a52edSVikas Manocha #include <dm.h> 11910a52edSVikas Manocha #include <ram.h> 12bf1ae442SVikas Manocha #include <asm/io.h> 13bf1ae442SVikas Manocha #include <asm/arch/fmc.h> 14bf1ae442SVikas Manocha #include <asm/arch/stm32.h> 15bf1ae442SVikas Manocha 166c9a1003SVikas Manocha DECLARE_GLOBAL_DATA_PTR; 176c9a1003SVikas Manocha 186c9a1003SVikas Manocha struct stm32_sdram_control { 196c9a1003SVikas Manocha u8 no_columns; 206c9a1003SVikas Manocha u8 no_rows; 216c9a1003SVikas Manocha u8 memory_width; 226c9a1003SVikas Manocha u8 no_banks; 236c9a1003SVikas Manocha u8 cas_latency; 24bfea69adSVikas Manocha u8 sdclk; 256c9a1003SVikas Manocha u8 rd_burst; 266c9a1003SVikas Manocha u8 rd_pipe_delay; 276c9a1003SVikas Manocha }; 286c9a1003SVikas Manocha 296c9a1003SVikas Manocha struct stm32_sdram_timing { 306c9a1003SVikas Manocha u8 tmrd; 316c9a1003SVikas Manocha u8 txsr; 326c9a1003SVikas Manocha u8 tras; 336c9a1003SVikas Manocha u8 trc; 346c9a1003SVikas Manocha u8 trp; 35bfea69adSVikas Manocha u8 twr; 366c9a1003SVikas Manocha u8 trcd; 376c9a1003SVikas Manocha }; 386c9a1003SVikas Manocha struct stm32_sdram_params { 396c9a1003SVikas Manocha u8 no_sdram_banks; 406c9a1003SVikas Manocha struct stm32_sdram_control sdram_control; 416c9a1003SVikas Manocha struct stm32_sdram_timing sdram_timing; 42bfea69adSVikas Manocha u32 sdram_ref_count; 436c9a1003SVikas Manocha }; 44bf1ae442SVikas Manocha 45bf1ae442SVikas Manocha #define SDRAM_MODE_BL_SHIFT 0 46bf1ae442SVikas Manocha #define SDRAM_MODE_CAS_SHIFT 4 47bf1ae442SVikas Manocha #define SDRAM_MODE_BL 0 486c9a1003SVikas Manocha 496c9a1003SVikas Manocha int stm32_sdram_init(struct udevice *dev) 50bf1ae442SVikas Manocha { 516c9a1003SVikas Manocha struct stm32_sdram_params *params = dev_get_platdata(dev); 52bf1ae442SVikas Manocha 53bfea69adSVikas Manocha writel(params->sdram_control.sdclk << FMC_SDCR_SDCLK_SHIFT 546c9a1003SVikas Manocha | params->sdram_control.cas_latency << FMC_SDCR_CAS_SHIFT 556c9a1003SVikas Manocha | params->sdram_control.no_banks << FMC_SDCR_NB_SHIFT 566c9a1003SVikas Manocha | params->sdram_control.memory_width << FMC_SDCR_MWID_SHIFT 576c9a1003SVikas Manocha | params->sdram_control.no_rows << FMC_SDCR_NR_SHIFT 586c9a1003SVikas Manocha | params->sdram_control.no_columns << FMC_SDCR_NC_SHIFT 596c9a1003SVikas Manocha | params->sdram_control.rd_pipe_delay << FMC_SDCR_RPIPE_SHIFT 606c9a1003SVikas Manocha | params->sdram_control.rd_burst << FMC_SDCR_RBURST_SHIFT, 61bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdcr1); 62bf1ae442SVikas Manocha 63bfea69adSVikas Manocha writel(params->sdram_timing.trcd << FMC_SDTR_TRCD_SHIFT 64bfea69adSVikas Manocha | params->sdram_timing.trp << FMC_SDTR_TRP_SHIFT 65bfea69adSVikas Manocha | params->sdram_timing.twr << FMC_SDTR_TWR_SHIFT 66bfea69adSVikas Manocha | params->sdram_timing.trc << FMC_SDTR_TRC_SHIFT 67bfea69adSVikas Manocha | params->sdram_timing.tras << FMC_SDTR_TRAS_SHIFT 68bfea69adSVikas Manocha | params->sdram_timing.txsr << FMC_SDTR_TXSR_SHIFT 69bfea69adSVikas Manocha | params->sdram_timing.tmrd << FMC_SDTR_TMRD_SHIFT, 70bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdtr1); 71bf1ae442SVikas Manocha 72bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_START_CLOCK, 73bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdcmr); 74bf1ae442SVikas Manocha udelay(200); /* 200 us delay, page 10, "Power-Up" */ 75bf1ae442SVikas Manocha FMC_BUSY_WAIT(); 76bf1ae442SVikas Manocha 77bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_PRECHARGE, 78bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdcmr); 79bf1ae442SVikas Manocha udelay(100); 80bf1ae442SVikas Manocha FMC_BUSY_WAIT(); 81bf1ae442SVikas Manocha 82bf1ae442SVikas Manocha writel((FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_AUTOREFRESH 83bf1ae442SVikas Manocha | 7 << FMC_SDCMR_NRFS_SHIFT), &STM32_SDRAM_FMC->sdcmr); 84bf1ae442SVikas Manocha udelay(100); 85bf1ae442SVikas Manocha FMC_BUSY_WAIT(); 86bf1ae442SVikas Manocha 87bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | (SDRAM_MODE_BL << SDRAM_MODE_BL_SHIFT 88bfea69adSVikas Manocha | params->sdram_control.cas_latency << SDRAM_MODE_CAS_SHIFT) 89bf1ae442SVikas Manocha << FMC_SDCMR_MODE_REGISTER_SHIFT | FMC_SDCMR_MODE_WRITE_MODE, 90bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdcmr); 91bf1ae442SVikas Manocha udelay(100); 92bf1ae442SVikas Manocha FMC_BUSY_WAIT(); 93bf1ae442SVikas Manocha 94bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_NORMAL, 95bf1ae442SVikas Manocha &STM32_SDRAM_FMC->sdcmr); 96bf1ae442SVikas Manocha FMC_BUSY_WAIT(); 97bf1ae442SVikas Manocha 98bf1ae442SVikas Manocha /* Refresh timer */ 99bfea69adSVikas Manocha writel((params->sdram_ref_count) << 1, &STM32_SDRAM_FMC->sdrtr); 100bf1ae442SVikas Manocha 101bf1ae442SVikas Manocha return 0; 102bf1ae442SVikas Manocha } 103910a52edSVikas Manocha 1046c9a1003SVikas Manocha static int stm32_fmc_ofdata_to_platdata(struct udevice *dev) 1056c9a1003SVikas Manocha { 1066c9a1003SVikas Manocha int ret; 107da409cccSSimon Glass int node = dev_of_offset(dev); 1086c9a1003SVikas Manocha const void *blob = gd->fdt_blob; 1096c9a1003SVikas Manocha struct stm32_sdram_params *params = dev_get_platdata(dev); 1106c9a1003SVikas Manocha 1116c9a1003SVikas Manocha params->no_sdram_banks = fdtdec_get_uint(blob, node, "mr-nbanks", 1); 1126c9a1003SVikas Manocha debug("%s, no of banks = %d\n", __func__, params->no_sdram_banks); 1136c9a1003SVikas Manocha 1146c9a1003SVikas Manocha fdt_for_each_subnode(node, blob, node) { 1156c9a1003SVikas Manocha ret = fdtdec_get_byte_array(blob, node, "st,sdram-control", 1166c9a1003SVikas Manocha (u8 *)¶ms->sdram_control, 1176c9a1003SVikas Manocha sizeof(params->sdram_control)); 1186c9a1003SVikas Manocha if (ret) 1196c9a1003SVikas Manocha return ret; 1206c9a1003SVikas Manocha ret = fdtdec_get_byte_array(blob, node, "st,sdram-timing", 1216c9a1003SVikas Manocha (u8 *)¶ms->sdram_timing, 1226c9a1003SVikas Manocha sizeof(params->sdram_timing)); 1236c9a1003SVikas Manocha if (ret) 1246c9a1003SVikas Manocha return ret; 125bfea69adSVikas Manocha 126bfea69adSVikas Manocha params->sdram_ref_count = fdtdec_get_int(blob, node, 127bfea69adSVikas Manocha "st,sdram-refcount", 8196); 1286c9a1003SVikas Manocha } 1296c9a1003SVikas Manocha 1306c9a1003SVikas Manocha return 0; 1316c9a1003SVikas Manocha } 1326c9a1003SVikas Manocha 133910a52edSVikas Manocha static int stm32_fmc_probe(struct udevice *dev) 134910a52edSVikas Manocha { 135d0b24c1aSVikas Manocha int ret; 136*14a50e37SPatrice Chotard #ifdef CONFIG_CLK 137d0b24c1aSVikas Manocha struct clk clk; 1386c9a1003SVikas Manocha 139d0b24c1aSVikas Manocha ret = clk_get_by_index(dev, 0, &clk); 140d0b24c1aSVikas Manocha if (ret < 0) 141d0b24c1aSVikas Manocha return ret; 142d0b24c1aSVikas Manocha 143d0b24c1aSVikas Manocha ret = clk_enable(&clk); 144d0b24c1aSVikas Manocha 145d0b24c1aSVikas Manocha if (ret) { 146d0b24c1aSVikas Manocha dev_err(dev, "failed to enable clock\n"); 147d0b24c1aSVikas Manocha return ret; 148d0b24c1aSVikas Manocha } 149d0b24c1aSVikas Manocha #endif 1506c9a1003SVikas Manocha ret = stm32_sdram_init(dev); 1516c9a1003SVikas Manocha if (ret) 1526c9a1003SVikas Manocha return ret; 1536c9a1003SVikas Manocha 154910a52edSVikas Manocha return 0; 155910a52edSVikas Manocha } 156910a52edSVikas Manocha 157910a52edSVikas Manocha static int stm32_fmc_get_info(struct udevice *dev, struct ram_info *info) 158910a52edSVikas Manocha { 159910a52edSVikas Manocha return 0; 160910a52edSVikas Manocha } 161910a52edSVikas Manocha 162910a52edSVikas Manocha static struct ram_ops stm32_fmc_ops = { 163910a52edSVikas Manocha .get_info = stm32_fmc_get_info, 164910a52edSVikas Manocha }; 165910a52edSVikas Manocha 166910a52edSVikas Manocha static const struct udevice_id stm32_fmc_ids[] = { 167910a52edSVikas Manocha { .compatible = "st,stm32-fmc" }, 168910a52edSVikas Manocha { } 169910a52edSVikas Manocha }; 170910a52edSVikas Manocha 171910a52edSVikas Manocha U_BOOT_DRIVER(stm32_fmc) = { 172910a52edSVikas Manocha .name = "stm32_fmc", 173910a52edSVikas Manocha .id = UCLASS_RAM, 174910a52edSVikas Manocha .of_match = stm32_fmc_ids, 175910a52edSVikas Manocha .ops = &stm32_fmc_ops, 1766c9a1003SVikas Manocha .ofdata_to_platdata = stm32_fmc_ofdata_to_platdata, 177910a52edSVikas Manocha .probe = stm32_fmc_probe, 1786c9a1003SVikas Manocha .platdata_auto_alloc_size = sizeof(struct stm32_sdram_params), 179910a52edSVikas Manocha }; 180