1f2ab9977SPaul Walmsley /* 2f2ab9977SPaul Walmsley * SMS/SDRC (SDRAM controller) common code for OMAP2/3 3f2ab9977SPaul Walmsley * 4f2ab9977SPaul Walmsley * Copyright (C) 2005, 2008 Texas Instruments Inc. 5f2ab9977SPaul Walmsley * Copyright (C) 2005, 2008 Nokia Corporation 6f2ab9977SPaul Walmsley * 7f2ab9977SPaul Walmsley * Tony Lindgren <tony@atomide.com> 8f2ab9977SPaul Walmsley * Paul Walmsley 9f2ab9977SPaul Walmsley * Richard Woodruff <r-woodruff2@ti.com> 10f2ab9977SPaul Walmsley * 11f2ab9977SPaul Walmsley * This program is free software; you can redistribute it and/or modify 12f2ab9977SPaul Walmsley * it under the terms of the GNU General Public License version 2 as 13f2ab9977SPaul Walmsley * published by the Free Software Foundation. 14f2ab9977SPaul Walmsley */ 1587246b75SPaul Walmsley #undef DEBUG 16f2ab9977SPaul Walmsley 17f2ab9977SPaul Walmsley #include <linux/module.h> 18f2ab9977SPaul Walmsley #include <linux/kernel.h> 19f2ab9977SPaul Walmsley #include <linux/device.h> 20f2ab9977SPaul Walmsley #include <linux/list.h> 21f2ab9977SPaul Walmsley #include <linux/errno.h> 22f2ab9977SPaul Walmsley #include <linux/delay.h> 23f2ab9977SPaul Walmsley #include <linux/clk.h> 24f2ab9977SPaul Walmsley #include <linux/io.h> 25f2ab9977SPaul Walmsley 264e65331cSTony Lindgren #include "common.h" 27ce491cf8STony Lindgren #include <plat/clock.h> 28622297fdSTony Lindgren #include "../plat-omap/sram.h" 29f2ab9977SPaul Walmsley 30f2ab9977SPaul Walmsley #include "sdrc.h" 31f2ab9977SPaul Walmsley 3258cda884SJean Pihet static struct omap_sdrc_params *sdrc_init_params_cs0, *sdrc_init_params_cs1; 3387246b75SPaul Walmsley 34f2ab9977SPaul Walmsley void __iomem *omap2_sdrc_base; 35f2ab9977SPaul Walmsley void __iomem *omap2_sms_base; 36f2ab9977SPaul Walmsley 378a917d2fSKalle Jokiniemi struct omap2_sms_regs { 388a917d2fSKalle Jokiniemi u32 sms_sysconfig; 398a917d2fSKalle Jokiniemi }; 408a917d2fSKalle Jokiniemi 418a917d2fSKalle Jokiniemi static struct omap2_sms_regs sms_context; 428a917d2fSKalle Jokiniemi 4398cfe5abSPaul Walmsley /* SDRC_POWER register bits */ 4498cfe5abSPaul Walmsley #define SDRC_POWER_EXTCLKDIS_SHIFT 3 4598cfe5abSPaul Walmsley #define SDRC_POWER_PWDENA_SHIFT 2 4698cfe5abSPaul Walmsley #define SDRC_POWER_PAGEPOLICY_SHIFT 0 4787246b75SPaul Walmsley 4887246b75SPaul Walmsley /** 498a917d2fSKalle Jokiniemi * omap2_sms_save_context - Save SMS registers 508a917d2fSKalle Jokiniemi * 518a917d2fSKalle Jokiniemi * Save SMS registers that need to be restored after off mode. 528a917d2fSKalle Jokiniemi */ 538a917d2fSKalle Jokiniemi void omap2_sms_save_context(void) 548a917d2fSKalle Jokiniemi { 558a917d2fSKalle Jokiniemi sms_context.sms_sysconfig = sms_read_reg(SMS_SYSCONFIG); 568a917d2fSKalle Jokiniemi } 578a917d2fSKalle Jokiniemi 588a917d2fSKalle Jokiniemi /** 598a917d2fSKalle Jokiniemi * omap2_sms_restore_context - Restore SMS registers 608a917d2fSKalle Jokiniemi * 618a917d2fSKalle Jokiniemi * Restore SMS registers that need to be Restored after off mode. 628a917d2fSKalle Jokiniemi */ 638a917d2fSKalle Jokiniemi void omap2_sms_restore_context(void) 648a917d2fSKalle Jokiniemi { 658a917d2fSKalle Jokiniemi sms_write_reg(sms_context.sms_sysconfig, SMS_SYSCONFIG); 668a917d2fSKalle Jokiniemi } 678a917d2fSKalle Jokiniemi 688a917d2fSKalle Jokiniemi /** 6987246b75SPaul Walmsley * omap2_sdrc_get_params - return SDRC register values for a given clock rate 7087246b75SPaul Walmsley * @r: SDRC clock rate (in Hz) 7158cda884SJean Pihet * @sdrc_cs0: chip select 0 ram timings ** 7258cda884SJean Pihet * @sdrc_cs1: chip select 1 ram timings ** 7387246b75SPaul Walmsley * 7487246b75SPaul Walmsley * Return pre-calculated values for the SDRC_ACTIM_CTRLA, 7558cda884SJean Pihet * SDRC_ACTIM_CTRLB, SDRC_RFR_CTRL and SDRC_MR registers in sdrc_cs[01] 7658cda884SJean Pihet * structs,for a given SDRC clock rate 'r'. 7758cda884SJean Pihet * These parameters control various timing delays in the SDRAM controller 7858cda884SJean Pihet * that are expressed in terms of the number of SDRC clock cycles to 7958cda884SJean Pihet * wait; hence the clock rate dependency. 8058cda884SJean Pihet * 8158cda884SJean Pihet * Supports 2 different timing parameters for both chip selects. 8258cda884SJean Pihet * 8358cda884SJean Pihet * Note 1: the sdrc_init_params_cs[01] must be sorted rate descending. 8458cda884SJean Pihet * Note 2: If sdrc_init_params_cs_1 is not NULL it must be of same size 8558cda884SJean Pihet * as sdrc_init_params_cs_0. 8658cda884SJean Pihet * 8758cda884SJean Pihet * Fills in the struct omap_sdrc_params * for each chip select. 8858cda884SJean Pihet * Returns 0 upon success or -1 upon failure. 8987246b75SPaul Walmsley */ 9058cda884SJean Pihet int omap2_sdrc_get_params(unsigned long r, 9158cda884SJean Pihet struct omap_sdrc_params **sdrc_cs0, 9258cda884SJean Pihet struct omap_sdrc_params **sdrc_cs1) 9387246b75SPaul Walmsley { 9458cda884SJean Pihet struct omap_sdrc_params *sp0, *sp1; 9587246b75SPaul Walmsley 9658cda884SJean Pihet if (!sdrc_init_params_cs0) 9758cda884SJean Pihet return -1; 988bd22949SKevin Hilman 9958cda884SJean Pihet sp0 = sdrc_init_params_cs0; 10058cda884SJean Pihet sp1 = sdrc_init_params_cs1; 10187246b75SPaul Walmsley 10258cda884SJean Pihet while (sp0->rate && sp0->rate != r) { 10358cda884SJean Pihet sp0++; 10458cda884SJean Pihet if (sdrc_init_params_cs1) 10558cda884SJean Pihet sp1++; 10658cda884SJean Pihet } 10787246b75SPaul Walmsley 10858cda884SJean Pihet if (!sp0->rate) 10958cda884SJean Pihet return -1; 11087246b75SPaul Walmsley 11158cda884SJean Pihet *sdrc_cs0 = sp0; 11258cda884SJean Pihet *sdrc_cs1 = sp1; 11358cda884SJean Pihet return 0; 11487246b75SPaul Walmsley } 11587246b75SPaul Walmsley 11687246b75SPaul Walmsley 117f2ab9977SPaul Walmsley void __init omap2_set_globals_sdrc(struct omap_globals *omap2_globals) 118f2ab9977SPaul Walmsley { 1194c3cf901STony Lindgren if (omap2_globals->sdrc) 1204c3cf901STony Lindgren omap2_sdrc_base = omap2_globals->sdrc; 1214c3cf901STony Lindgren if (omap2_globals->sms) 1224c3cf901STony Lindgren omap2_sms_base = omap2_globals->sms; 123f2ab9977SPaul Walmsley } 124f2ab9977SPaul Walmsley 12598cfe5abSPaul Walmsley /** 12698cfe5abSPaul Walmsley * omap2_sdrc_init - initialize SMS, SDRC devices on boot 12758cda884SJean Pihet * @sdrc_cs[01]: pointers to a null-terminated list of struct omap_sdrc_params 12858cda884SJean Pihet * Support for 2 chip selects timings 12998cfe5abSPaul Walmsley * 13098cfe5abSPaul Walmsley * Turn on smart idle modes for SDRAM scheduler and controller. 13198cfe5abSPaul Walmsley * Program a known-good configuration for the SDRC to deal with buggy 13298cfe5abSPaul Walmsley * bootloaders. 13398cfe5abSPaul Walmsley */ 13458cda884SJean Pihet void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0, 13558cda884SJean Pihet struct omap_sdrc_params *sdrc_cs1) 136f2ab9977SPaul Walmsley { 137f2ab9977SPaul Walmsley u32 l; 138f2ab9977SPaul Walmsley 139f2ab9977SPaul Walmsley l = sms_read_reg(SMS_SYSCONFIG); 140f2ab9977SPaul Walmsley l &= ~(0x3 << 3); 141f2ab9977SPaul Walmsley l |= (0x2 << 3); 142f2ab9977SPaul Walmsley sms_write_reg(l, SMS_SYSCONFIG); 143f2ab9977SPaul Walmsley 144f2ab9977SPaul Walmsley l = sdrc_read_reg(SDRC_SYSCONFIG); 145f2ab9977SPaul Walmsley l &= ~(0x3 << 3); 146f2ab9977SPaul Walmsley l |= (0x2 << 3); 147f2ab9977SPaul Walmsley sdrc_write_reg(l, SDRC_SYSCONFIG); 14887246b75SPaul Walmsley 14958cda884SJean Pihet sdrc_init_params_cs0 = sdrc_cs0; 15058cda884SJean Pihet sdrc_init_params_cs1 = sdrc_cs1; 15198cfe5abSPaul Walmsley 15298cfe5abSPaul Walmsley /* XXX Enable SRFRONIDLEREQ here also? */ 15375f251e3SPaul Walmsley /* 15475f251e3SPaul Walmsley * PWDENA should not be set due to 34xx erratum 1.150 - PWDENA 15575f251e3SPaul Walmsley * can cause random memory corruption 15675f251e3SPaul Walmsley */ 15798cfe5abSPaul Walmsley l = (1 << SDRC_POWER_EXTCLKDIS_SHIFT) | 15898cfe5abSPaul Walmsley (1 << SDRC_POWER_PAGEPOLICY_SHIFT); 15998cfe5abSPaul Walmsley sdrc_write_reg(l, SDRC_POWER); 1608a917d2fSKalle Jokiniemi omap2_sms_save_context(); 161f2ab9977SPaul Walmsley } 162