18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * SMS/SDRC (SDRAM controller) common code for OMAP2/3 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2005, 2008 Texas Instruments Inc. 68c2ecf20Sopenharmony_ci * Copyright (C) 2005, 2008 Nokia Corporation 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Tony Lindgren <tony@atomide.com> 98c2ecf20Sopenharmony_ci * Paul Walmsley 108c2ecf20Sopenharmony_ci * Richard Woodruff <r-woodruff2@ti.com> 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci#undef DEBUG 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/device.h> 178c2ecf20Sopenharmony_ci#include <linux/list.h> 188c2ecf20Sopenharmony_ci#include <linux/errno.h> 198c2ecf20Sopenharmony_ci#include <linux/delay.h> 208c2ecf20Sopenharmony_ci#include <linux/clk.h> 218c2ecf20Sopenharmony_ci#include <linux/io.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include "common.h" 248c2ecf20Sopenharmony_ci#include "clock.h" 258c2ecf20Sopenharmony_ci#include "sdrc.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_civoid __iomem *omap2_sdrc_base; 308c2ecf20Sopenharmony_civoid __iomem *omap2_sms_base; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistruct omap2_sms_regs { 338c2ecf20Sopenharmony_ci u32 sms_sysconfig; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic struct omap2_sms_regs sms_context; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/* SDRC_POWER register bits */ 398c2ecf20Sopenharmony_ci#define SDRC_POWER_EXTCLKDIS_SHIFT 3 408c2ecf20Sopenharmony_ci#define SDRC_POWER_PWDENA_SHIFT 2 418c2ecf20Sopenharmony_ci#define SDRC_POWER_PAGEPOLICY_SHIFT 0 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/** 448c2ecf20Sopenharmony_ci * omap2_sms_save_context - Save SMS registers 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * Save SMS registers that need to be restored after off mode. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_civoid omap2_sms_save_context(void) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci sms_context.sms_sysconfig = sms_read_reg(SMS_SYSCONFIG); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/** 548c2ecf20Sopenharmony_ci * omap2_sms_restore_context - Restore SMS registers 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * Restore SMS registers that need to be Restored after off mode. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_civoid omap2_sms_restore_context(void) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci sms_write_reg(sms_context.sms_sysconfig, SMS_SYSCONFIG); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/** 648c2ecf20Sopenharmony_ci * omap2_sdrc_get_params - return SDRC register values for a given clock rate 658c2ecf20Sopenharmony_ci * @r: SDRC clock rate (in Hz) 668c2ecf20Sopenharmony_ci * @sdrc_cs0: chip select 0 ram timings ** 678c2ecf20Sopenharmony_ci * @sdrc_cs1: chip select 1 ram timings ** 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * Return pre-calculated values for the SDRC_ACTIM_CTRLA, 708c2ecf20Sopenharmony_ci * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL and SDRC_MR registers in sdrc_cs[01] 718c2ecf20Sopenharmony_ci * structs,for a given SDRC clock rate 'r'. 728c2ecf20Sopenharmony_ci * These parameters control various timing delays in the SDRAM controller 738c2ecf20Sopenharmony_ci * that are expressed in terms of the number of SDRC clock cycles to 748c2ecf20Sopenharmony_ci * wait; hence the clock rate dependency. 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * Supports 2 different timing parameters for both chip selects. 778c2ecf20Sopenharmony_ci * 788c2ecf20Sopenharmony_ci * Note 1: the sdrc_init_params_cs[01] must be sorted rate descending. 798c2ecf20Sopenharmony_ci * Note 2: If sdrc_init_params_cs_1 is not NULL it must be of same size 808c2ecf20Sopenharmony_ci * as sdrc_init_params_cs_0. 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci * Fills in the struct omap_sdrc_params * for each chip select. 838c2ecf20Sopenharmony_ci * Returns 0 upon success or -1 upon failure. 848c2ecf20Sopenharmony_ci */ 858c2ecf20Sopenharmony_ciint omap2_sdrc_get_params(unsigned long r, 868c2ecf20Sopenharmony_ci struct omap_sdrc_params **sdrc_cs0, 878c2ecf20Sopenharmony_ci struct omap_sdrc_params **sdrc_cs1) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci struct omap_sdrc_params *sp0, *sp1; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (!sdrc_init_params_cs0) 928c2ecf20Sopenharmony_ci return -1; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci sp0 = sdrc_init_params_cs0; 958c2ecf20Sopenharmony_ci sp1 = sdrc_init_params_cs1; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci while (sp0->rate && sp0->rate != r) { 988c2ecf20Sopenharmony_ci sp0++; 998c2ecf20Sopenharmony_ci if (sdrc_init_params_cs1) 1008c2ecf20Sopenharmony_ci sp1++; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (!sp0->rate) 1048c2ecf20Sopenharmony_ci return -1; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci *sdrc_cs0 = sp0; 1078c2ecf20Sopenharmony_ci *sdrc_cs1 = sp1; 1088c2ecf20Sopenharmony_ci return 0; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_civoid __init omap2_set_globals_sdrc(void __iomem *sdrc, void __iomem *sms) 1138c2ecf20Sopenharmony_ci{ 1148c2ecf20Sopenharmony_ci omap2_sdrc_base = sdrc; 1158c2ecf20Sopenharmony_ci omap2_sms_base = sms; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * omap2_sdrc_init - initialize SMS, SDRC devices on boot 1208c2ecf20Sopenharmony_ci * @sdrc_cs[01]: pointers to a null-terminated list of struct omap_sdrc_params 1218c2ecf20Sopenharmony_ci * Support for 2 chip selects timings 1228c2ecf20Sopenharmony_ci * 1238c2ecf20Sopenharmony_ci * Turn on smart idle modes for SDRAM scheduler and controller. 1248c2ecf20Sopenharmony_ci * Program a known-good configuration for the SDRC to deal with buggy 1258c2ecf20Sopenharmony_ci * bootloaders. 1268c2ecf20Sopenharmony_ci */ 1278c2ecf20Sopenharmony_civoid __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, 1288c2ecf20Sopenharmony_ci struct omap_sdrc_params *sdrc_cs1) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci u32 l; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci l = sms_read_reg(SMS_SYSCONFIG); 1338c2ecf20Sopenharmony_ci l &= ~(0x3 << 3); 1348c2ecf20Sopenharmony_ci l |= (0x2 << 3); 1358c2ecf20Sopenharmony_ci sms_write_reg(l, SMS_SYSCONFIG); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci l = sdrc_read_reg(SDRC_SYSCONFIG); 1388c2ecf20Sopenharmony_ci l &= ~(0x3 << 3); 1398c2ecf20Sopenharmony_ci l |= (0x2 << 3); 1408c2ecf20Sopenharmony_ci sdrc_write_reg(l, SDRC_SYSCONFIG); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci sdrc_init_params_cs0 = sdrc_cs0; 1438c2ecf20Sopenharmony_ci sdrc_init_params_cs1 = sdrc_cs1; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci /* XXX Enable SRFRONIDLEREQ here also? */ 1468c2ecf20Sopenharmony_ci /* 1478c2ecf20Sopenharmony_ci * PWDENA should not be set due to 34xx erratum 1.150 - PWDENA 1488c2ecf20Sopenharmony_ci * can cause random memory corruption 1498c2ecf20Sopenharmony_ci */ 1508c2ecf20Sopenharmony_ci l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) | 1518c2ecf20Sopenharmony_ci (1 << SDRC_POWER_PAGEPOLICY_SHIFT); 1528c2ecf20Sopenharmony_ci sdrc_write_reg(l, SDRC_POWER); 1538c2ecf20Sopenharmony_ci omap2_sms_save_context(); 1548c2ecf20Sopenharmony_ci} 155