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 146c9a1003SVikas Manocha DECLARE_GLOBAL_DATA_PTR; 156c9a1003SVikas Manocha 169242ece1SPatrice Chotard struct stm32_fmc_regs { 171421e0a3SPatrice Chotard /* 0x0 */ 181421e0a3SPatrice Chotard u32 bcr1; /* NOR/PSRAM Chip select control register 1 */ 191421e0a3SPatrice Chotard u32 btr1; /* SRAM/NOR-Flash Chip select timing register 1 */ 201421e0a3SPatrice Chotard u32 bcr2; /* NOR/PSRAM Chip select Control register 2 */ 211421e0a3SPatrice Chotard u32 btr2; /* SRAM/NOR-Flash Chip select timing register 2 */ 221421e0a3SPatrice Chotard u32 bcr3; /* NOR/PSRAMChip select Control register 3 */ 231421e0a3SPatrice Chotard u32 btr3; /* SRAM/NOR-Flash Chip select timing register 3 */ 241421e0a3SPatrice Chotard u32 bcr4; /* NOR/PSRAM Chip select Control register 4 */ 251421e0a3SPatrice Chotard u32 btr4; /* SRAM/NOR-Flash Chip select timing register 4 */ 261421e0a3SPatrice Chotard u32 reserved1[24]; 279242ece1SPatrice Chotard 281421e0a3SPatrice Chotard /* 0x80 */ 291421e0a3SPatrice Chotard u32 pcr; /* NAND Flash control register */ 301421e0a3SPatrice Chotard u32 sr; /* FIFO status and interrupt register */ 311421e0a3SPatrice Chotard u32 pmem; /* Common memory space timing register */ 321421e0a3SPatrice Chotard u32 patt; /* Attribute memory space timing registers */ 331421e0a3SPatrice Chotard u32 reserved2[1]; 341421e0a3SPatrice Chotard u32 eccr; /* ECC result registers */ 351421e0a3SPatrice Chotard u32 reserved3[27]; 361421e0a3SPatrice Chotard 371421e0a3SPatrice Chotard /* 0x104 */ 381421e0a3SPatrice Chotard u32 bwtr1; /* SRAM/NOR-Flash write timing register 1 */ 391421e0a3SPatrice Chotard u32 reserved4[1]; 401421e0a3SPatrice Chotard u32 bwtr2; /* SRAM/NOR-Flash write timing register 2 */ 411421e0a3SPatrice Chotard u32 reserved5[1]; 421421e0a3SPatrice Chotard u32 bwtr3; /* SRAM/NOR-Flash write timing register 3 */ 431421e0a3SPatrice Chotard u32 reserved6[1]; 441421e0a3SPatrice Chotard u32 bwtr4; /* SRAM/NOR-Flash write timing register 4 */ 451421e0a3SPatrice Chotard u32 reserved7[8]; 461421e0a3SPatrice Chotard 471421e0a3SPatrice Chotard /* 0x140 */ 481421e0a3SPatrice Chotard u32 sdcr1; /* SDRAM Control register 1 */ 491421e0a3SPatrice Chotard u32 sdcr2; /* SDRAM Control register 2 */ 501421e0a3SPatrice Chotard u32 sdtr1; /* SDRAM Timing register 1 */ 511421e0a3SPatrice Chotard u32 sdtr2; /* SDRAM Timing register 2 */ 521421e0a3SPatrice Chotard u32 sdcmr; /* SDRAM Mode register */ 531421e0a3SPatrice Chotard u32 sdrtr; /* SDRAM Refresh timing register */ 541421e0a3SPatrice Chotard u32 sdsr; /* SDRAM Status register */ 551421e0a3SPatrice Chotard }; 569242ece1SPatrice Chotard 579242ece1SPatrice Chotard /* Control register SDCR */ 589242ece1SPatrice Chotard #define FMC_SDCR_RPIPE_SHIFT 13 /* RPIPE bit shift */ 599242ece1SPatrice Chotard #define FMC_SDCR_RBURST_SHIFT 12 /* RBURST bit shift */ 609242ece1SPatrice Chotard #define FMC_SDCR_SDCLK_SHIFT 10 /* SDRAM clock divisor shift */ 619242ece1SPatrice Chotard #define FMC_SDCR_WP_SHIFT 9 /* Write protection shift */ 629242ece1SPatrice Chotard #define FMC_SDCR_CAS_SHIFT 7 /* CAS latency shift */ 639242ece1SPatrice Chotard #define FMC_SDCR_NB_SHIFT 6 /* Number of banks shift */ 649242ece1SPatrice Chotard #define FMC_SDCR_MWID_SHIFT 4 /* Memory width shift */ 659242ece1SPatrice Chotard #define FMC_SDCR_NR_SHIFT 2 /* Number of row address bits shift */ 669242ece1SPatrice Chotard #define FMC_SDCR_NC_SHIFT 0 /* Number of col address bits shift */ 679242ece1SPatrice Chotard 689242ece1SPatrice Chotard /* Timings register SDTR */ 699242ece1SPatrice Chotard #define FMC_SDTR_TMRD_SHIFT 0 /* Load mode register to active */ 709242ece1SPatrice Chotard #define FMC_SDTR_TXSR_SHIFT 4 /* Exit self-refresh time */ 719242ece1SPatrice Chotard #define FMC_SDTR_TRAS_SHIFT 8 /* Self-refresh time */ 729242ece1SPatrice Chotard #define FMC_SDTR_TRC_SHIFT 12 /* Row cycle delay */ 739242ece1SPatrice Chotard #define FMC_SDTR_TWR_SHIFT 16 /* Recovery delay */ 749242ece1SPatrice Chotard #define FMC_SDTR_TRP_SHIFT 20 /* Row precharge delay */ 759242ece1SPatrice Chotard #define FMC_SDTR_TRCD_SHIFT 24 /* Row-to-column delay */ 769242ece1SPatrice Chotard 779242ece1SPatrice Chotard #define FMC_SDCMR_NRFS_SHIFT 5 789242ece1SPatrice Chotard 799242ece1SPatrice Chotard #define FMC_SDCMR_MODE_NORMAL 0 809242ece1SPatrice Chotard #define FMC_SDCMR_MODE_START_CLOCK 1 819242ece1SPatrice Chotard #define FMC_SDCMR_MODE_PRECHARGE 2 829242ece1SPatrice Chotard #define FMC_SDCMR_MODE_AUTOREFRESH 3 839242ece1SPatrice Chotard #define FMC_SDCMR_MODE_WRITE_MODE 4 849242ece1SPatrice Chotard #define FMC_SDCMR_MODE_SELFREFRESH 5 859242ece1SPatrice Chotard #define FMC_SDCMR_MODE_POWERDOWN 6 869242ece1SPatrice Chotard 879242ece1SPatrice Chotard #define FMC_SDCMR_BANK_1 BIT(4) 889242ece1SPatrice Chotard #define FMC_SDCMR_BANK_2 BIT(3) 899242ece1SPatrice Chotard 909242ece1SPatrice Chotard #define FMC_SDCMR_MODE_REGISTER_SHIFT 9 919242ece1SPatrice Chotard 929242ece1SPatrice Chotard #define FMC_SDSR_BUSY BIT(5) 939242ece1SPatrice Chotard 941421e0a3SPatrice Chotard #define FMC_BUSY_WAIT(regs) do { \ 959242ece1SPatrice Chotard __asm__ __volatile__ ("dsb" : : : "memory"); \ 961421e0a3SPatrice Chotard while (regs->sdsr & FMC_SDSR_BUSY) \ 979242ece1SPatrice Chotard ; \ 989242ece1SPatrice Chotard } while (0) 999242ece1SPatrice Chotard 1006c9a1003SVikas Manocha struct stm32_sdram_control { 1016c9a1003SVikas Manocha u8 no_columns; 1026c9a1003SVikas Manocha u8 no_rows; 1036c9a1003SVikas Manocha u8 memory_width; 1046c9a1003SVikas Manocha u8 no_banks; 1056c9a1003SVikas Manocha u8 cas_latency; 106bfea69adSVikas Manocha u8 sdclk; 1076c9a1003SVikas Manocha u8 rd_burst; 1086c9a1003SVikas Manocha u8 rd_pipe_delay; 1096c9a1003SVikas Manocha }; 1106c9a1003SVikas Manocha 1116c9a1003SVikas Manocha struct stm32_sdram_timing { 1126c9a1003SVikas Manocha u8 tmrd; 1136c9a1003SVikas Manocha u8 txsr; 1146c9a1003SVikas Manocha u8 tras; 1156c9a1003SVikas Manocha u8 trc; 1166c9a1003SVikas Manocha u8 trp; 117bfea69adSVikas Manocha u8 twr; 1186c9a1003SVikas Manocha u8 trcd; 1196c9a1003SVikas Manocha }; 1206c9a1003SVikas Manocha struct stm32_sdram_params { 1211421e0a3SPatrice Chotard struct stm32_fmc_regs *base; 1226c9a1003SVikas Manocha u8 no_sdram_banks; 123*f39b90dcSPatrice Chotard struct stm32_sdram_control *sdram_control; 124*f39b90dcSPatrice Chotard struct stm32_sdram_timing *sdram_timing; 125bfea69adSVikas Manocha u32 sdram_ref_count; 1266c9a1003SVikas Manocha }; 127bf1ae442SVikas Manocha 128bf1ae442SVikas Manocha #define SDRAM_MODE_BL_SHIFT 0 129bf1ae442SVikas Manocha #define SDRAM_MODE_CAS_SHIFT 4 130bf1ae442SVikas Manocha #define SDRAM_MODE_BL 0 1316c9a1003SVikas Manocha 1326c9a1003SVikas Manocha int stm32_sdram_init(struct udevice *dev) 133bf1ae442SVikas Manocha { 1346c9a1003SVikas Manocha struct stm32_sdram_params *params = dev_get_platdata(dev); 1351421e0a3SPatrice Chotard struct stm32_fmc_regs *regs = params->base; 136*f39b90dcSPatrice Chotard struct stm32_sdram_control *control = params->sdram_control; 137*f39b90dcSPatrice Chotard struct stm32_sdram_timing *timing = params->sdram_timing; 138bf1ae442SVikas Manocha 139*f39b90dcSPatrice Chotard writel(control->sdclk << FMC_SDCR_SDCLK_SHIFT 140*f39b90dcSPatrice Chotard | control->cas_latency << FMC_SDCR_CAS_SHIFT 141*f39b90dcSPatrice Chotard | control->no_banks << FMC_SDCR_NB_SHIFT 142*f39b90dcSPatrice Chotard | control->memory_width << FMC_SDCR_MWID_SHIFT 143*f39b90dcSPatrice Chotard | control->no_rows << FMC_SDCR_NR_SHIFT 144*f39b90dcSPatrice Chotard | control->no_columns << FMC_SDCR_NC_SHIFT 145*f39b90dcSPatrice Chotard | control->rd_pipe_delay << FMC_SDCR_RPIPE_SHIFT 146*f39b90dcSPatrice Chotard | control->rd_burst << FMC_SDCR_RBURST_SHIFT, 1471421e0a3SPatrice Chotard ®s->sdcr1); 148bf1ae442SVikas Manocha 149*f39b90dcSPatrice Chotard writel(timing->trcd << FMC_SDTR_TRCD_SHIFT 150*f39b90dcSPatrice Chotard | timing->trp << FMC_SDTR_TRP_SHIFT 151*f39b90dcSPatrice Chotard | timing->twr << FMC_SDTR_TWR_SHIFT 152*f39b90dcSPatrice Chotard | timing->trc << FMC_SDTR_TRC_SHIFT 153*f39b90dcSPatrice Chotard | timing->tras << FMC_SDTR_TRAS_SHIFT 154*f39b90dcSPatrice Chotard | timing->txsr << FMC_SDTR_TXSR_SHIFT 155*f39b90dcSPatrice Chotard | timing->tmrd << FMC_SDTR_TMRD_SHIFT, 1561421e0a3SPatrice Chotard ®s->sdtr1); 157bf1ae442SVikas Manocha 158bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_START_CLOCK, 1591421e0a3SPatrice Chotard ®s->sdcmr); 160bf1ae442SVikas Manocha udelay(200); /* 200 us delay, page 10, "Power-Up" */ 1611421e0a3SPatrice Chotard FMC_BUSY_WAIT(regs); 162bf1ae442SVikas Manocha 163bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_PRECHARGE, 1641421e0a3SPatrice Chotard ®s->sdcmr); 165bf1ae442SVikas Manocha udelay(100); 1661421e0a3SPatrice Chotard FMC_BUSY_WAIT(regs); 167bf1ae442SVikas Manocha 168bf1ae442SVikas Manocha writel((FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_AUTOREFRESH 1691421e0a3SPatrice Chotard | 7 << FMC_SDCMR_NRFS_SHIFT), ®s->sdcmr); 170bf1ae442SVikas Manocha udelay(100); 1711421e0a3SPatrice Chotard FMC_BUSY_WAIT(regs); 172bf1ae442SVikas Manocha 173bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | (SDRAM_MODE_BL << SDRAM_MODE_BL_SHIFT 174*f39b90dcSPatrice Chotard | control->cas_latency << SDRAM_MODE_CAS_SHIFT) 175bf1ae442SVikas Manocha << FMC_SDCMR_MODE_REGISTER_SHIFT | FMC_SDCMR_MODE_WRITE_MODE, 1761421e0a3SPatrice Chotard ®s->sdcmr); 177bf1ae442SVikas Manocha udelay(100); 1781421e0a3SPatrice Chotard FMC_BUSY_WAIT(regs); 179bf1ae442SVikas Manocha 180bf1ae442SVikas Manocha writel(FMC_SDCMR_BANK_1 | FMC_SDCMR_MODE_NORMAL, 1811421e0a3SPatrice Chotard ®s->sdcmr); 1821421e0a3SPatrice Chotard FMC_BUSY_WAIT(regs); 183bf1ae442SVikas Manocha 184bf1ae442SVikas Manocha /* Refresh timer */ 1851421e0a3SPatrice Chotard writel((params->sdram_ref_count) << 1, ®s->sdrtr); 186bf1ae442SVikas Manocha 187bf1ae442SVikas Manocha return 0; 188bf1ae442SVikas Manocha } 189910a52edSVikas Manocha 1906c9a1003SVikas Manocha static int stm32_fmc_ofdata_to_platdata(struct udevice *dev) 1916c9a1003SVikas Manocha { 192*f39b90dcSPatrice Chotard ofnode bank_node; 1936c9a1003SVikas Manocha struct stm32_sdram_params *params = dev_get_platdata(dev); 1946c9a1003SVikas Manocha 195*f39b90dcSPatrice Chotard params->no_sdram_banks = dev_read_u32_default(dev, "mr-nbanks", 1); 1966c9a1003SVikas Manocha debug("%s, no of banks = %d\n", __func__, params->no_sdram_banks); 1976c9a1003SVikas Manocha 198*f39b90dcSPatrice Chotard dev_for_each_subnode(bank_node, dev) { 199*f39b90dcSPatrice Chotard params->sdram_control = (struct stm32_sdram_control *) 200*f39b90dcSPatrice Chotard ofnode_read_u8_array_ptr(bank_node, 201*f39b90dcSPatrice Chotard "st,sdram-control", 202*f39b90dcSPatrice Chotard sizeof(struct stm32_sdram_control)); 203bfea69adSVikas Manocha 204*f39b90dcSPatrice Chotard if (!params->sdram_control) { 205*f39b90dcSPatrice Chotard error("st,sdram-control not found for device: %s", 206*f39b90dcSPatrice Chotard dev->name); 207*f39b90dcSPatrice Chotard return -EINVAL; 208*f39b90dcSPatrice Chotard } 209*f39b90dcSPatrice Chotard 210*f39b90dcSPatrice Chotard params->sdram_timing = (struct stm32_sdram_timing *) 211*f39b90dcSPatrice Chotard ofnode_read_u8_array_ptr(bank_node, 212*f39b90dcSPatrice Chotard "st,sdram-timing", 213*f39b90dcSPatrice Chotard sizeof(struct stm32_sdram_timing)); 214*f39b90dcSPatrice Chotard 215*f39b90dcSPatrice Chotard if (!params->sdram_timing) { 216*f39b90dcSPatrice Chotard error("st,sdram-timing not found for device: %s", 217*f39b90dcSPatrice Chotard dev->name); 218*f39b90dcSPatrice Chotard return -EINVAL; 219*f39b90dcSPatrice Chotard } 220*f39b90dcSPatrice Chotard 221*f39b90dcSPatrice Chotard params->sdram_ref_count = ofnode_read_u32_default(bank_node, 222bfea69adSVikas Manocha "st,sdram-refcount", 8196); 2236c9a1003SVikas Manocha } 2246c9a1003SVikas Manocha 2256c9a1003SVikas Manocha return 0; 2266c9a1003SVikas Manocha } 2276c9a1003SVikas Manocha 228910a52edSVikas Manocha static int stm32_fmc_probe(struct udevice *dev) 229910a52edSVikas Manocha { 2301421e0a3SPatrice Chotard struct stm32_sdram_params *params = dev_get_platdata(dev); 231d0b24c1aSVikas Manocha int ret; 2321421e0a3SPatrice Chotard fdt_addr_t addr; 2331421e0a3SPatrice Chotard 2341421e0a3SPatrice Chotard addr = dev_read_addr(dev); 2351421e0a3SPatrice Chotard if (addr == FDT_ADDR_T_NONE) 2361421e0a3SPatrice Chotard return -EINVAL; 2371421e0a3SPatrice Chotard 2381421e0a3SPatrice Chotard params->base = (struct stm32_fmc_regs *)addr; 2391421e0a3SPatrice Chotard 24014a50e37SPatrice Chotard #ifdef CONFIG_CLK 241d0b24c1aSVikas Manocha struct clk clk; 2426c9a1003SVikas Manocha 243d0b24c1aSVikas Manocha ret = clk_get_by_index(dev, 0, &clk); 244d0b24c1aSVikas Manocha if (ret < 0) 245d0b24c1aSVikas Manocha return ret; 246d0b24c1aSVikas Manocha 247d0b24c1aSVikas Manocha ret = clk_enable(&clk); 248d0b24c1aSVikas Manocha 249d0b24c1aSVikas Manocha if (ret) { 250d0b24c1aSVikas Manocha dev_err(dev, "failed to enable clock\n"); 251d0b24c1aSVikas Manocha return ret; 252d0b24c1aSVikas Manocha } 253d0b24c1aSVikas Manocha #endif 2546c9a1003SVikas Manocha ret = stm32_sdram_init(dev); 2556c9a1003SVikas Manocha if (ret) 2566c9a1003SVikas Manocha return ret; 2576c9a1003SVikas Manocha 258910a52edSVikas Manocha return 0; 259910a52edSVikas Manocha } 260910a52edSVikas Manocha 261910a52edSVikas Manocha static int stm32_fmc_get_info(struct udevice *dev, struct ram_info *info) 262910a52edSVikas Manocha { 263910a52edSVikas Manocha return 0; 264910a52edSVikas Manocha } 265910a52edSVikas Manocha 266910a52edSVikas Manocha static struct ram_ops stm32_fmc_ops = { 267910a52edSVikas Manocha .get_info = stm32_fmc_get_info, 268910a52edSVikas Manocha }; 269910a52edSVikas Manocha 270910a52edSVikas Manocha static const struct udevice_id stm32_fmc_ids[] = { 271910a52edSVikas Manocha { .compatible = "st,stm32-fmc" }, 272910a52edSVikas Manocha { } 273910a52edSVikas Manocha }; 274910a52edSVikas Manocha 275910a52edSVikas Manocha U_BOOT_DRIVER(stm32_fmc) = { 276910a52edSVikas Manocha .name = "stm32_fmc", 277910a52edSVikas Manocha .id = UCLASS_RAM, 278910a52edSVikas Manocha .of_match = stm32_fmc_ids, 279910a52edSVikas Manocha .ops = &stm32_fmc_ops, 2806c9a1003SVikas Manocha .ofdata_to_platdata = stm32_fmc_ofdata_to_platdata, 281910a52edSVikas Manocha .probe = stm32_fmc_probe, 2826c9a1003SVikas Manocha .platdata_auto_alloc_size = sizeof(struct stm32_sdram_params), 283910a52edSVikas Manocha }; 284