/* * SDRC register values for the Samsung K4X1G323PC * * Copyright (C) 2008 Nokia Corporation * * Lauri Leukkunen * * Original code by Juha Yrjölä * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include #include #include /* In picoseconds, except for tREF */ struct sdram_timings { u32 casl; u32 tDAL; u32 tDPL; u32 tRRD; u32 tRCD; u32 tRP; u32 tRAS; u32 tRC; u32 tRFC; u32 tXSR; u32 tREF; /* in ms */ }; struct sdram_info { u8 row_lines; }; struct omap_sdrc_params rx51_sdrc_params[2]; static const struct sdram_timings rx51_timings[] = { { .casl = 3, .tDAL = 15000 + 18000, .tDPL = 15000, .tRRD = 12000, .tRCD = 18000, .tRP = 18000, .tRAS = 42000, .tRC = 66000, .tRFC = 97500, .tXSR = 120000, .tREF = 64, }, }; static const struct sdram_info rx51_info = { .row_lines = 13, }; #define CM_BASE 0x48004000 #define CM_CLKSEL_CORE 0x0a40 #define CM_CLKSEL1_PLL 0x0d40 #define PRM_CLKSEL 0x48306d40 #define PRM_CLKSRC_CTRL 0x48307270 static u32 cm_base = CM_BASE; static inline u32 cm_read_reg(int idx) { return *(u32 *)OMAP2_IO_ADDRESS(cm_base + idx); } static const unsigned long sys_clk_rate_table[] = { 12000, 13000, 19200, 26000, 38400, 16800 }; static unsigned long get_sys_clk_rate(void) { unsigned long rate; rate = sys_clk_rate_table[*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSEL) & 0x07]; if (((*(u32 *)OMAP2_IO_ADDRESS(PRM_CLKSRC_CTRL) >> 6) & 0x03) == 0x02) rate /= 2; return rate; } static unsigned long get_core_rate(void) { unsigned long rate; u32 l; l = cm_read_reg(CM_CLKSEL1_PLL); rate = get_sys_clk_rate(); rate *= ((l >> 16) & 0x7ff); rate /= ((l >> 8) & 0x7f) + 1; rate /= (l >> 27) & 0x1f; return rate; } static unsigned long get_l3_rate(void) { u32 l; l = cm_read_reg(CM_CLKSEL_CORE); return get_core_rate() / (l & 0x03); } static unsigned long sdrc_get_fclk_period(void) { /* In picoseconds */ return 1000000000 / get_l3_rate(); } static unsigned int sdrc_ps_to_ticks(unsigned int time_ps) { unsigned long tick_ps; /* Calculate in picosecs to yield more exact results */ tick_ps = sdrc_get_fclk_period(); return (time_ps + tick_ps - 1) / tick_ps; } #undef DEBUG #ifdef DEBUG static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, int time, const char *name) #else static int set_sdrc_timing_regval(u32 *regval, int st_bit, int end_bit, int time) #endif { int ticks, mask, nr_bits; if (time == 0) ticks = 0; else ticks = sdrc_ps_to_ticks(time); nr_bits = end_bit - st_bit + 1; if (ticks >= 1 << nr_bits) return -1; mask = (1 << nr_bits) - 1; *regval &= ~(mask << st_bit); *regval |= ticks << st_bit; #ifdef DEBUG printk("SDRC %s: %i ticks %i ns\n", name, ticks, (unsigned int)sdrc_get_fclk_period() * ticks / 1000); #endif return 0; } #ifdef DEBUG #define SDRC_SET_ONE(reg, st, end, field) \ if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field, #field) < 0) \ err = -1 #else #define SDRC_SET_ONE(reg, st, end, field) \ if (set_sdrc_timing_regval((reg), (st), (end), rx51_timings->field) < 0) \ err = -1 #endif struct omap_sdrc_params *rx51_get_sdram_timings(void) { u32 ticks_per_ms; u32 rfr, l; u32 actim_ctrla, actim_ctrlb; u32 rfr_ctrl; int err = 0; SDRC_SET_ONE(&actim_ctrla, 0, 4, tDAL); SDRC_SET_ONE(&actim_ctrla, 6, 8, tDPL); SDRC_SET_ONE(&actim_ctrla, 9, 11, tRRD); SDRC_SET_ONE(&actim_ctrla, 12, 14, tRCD); SDRC_SET_ONE(&actim_ctrla, 15, 17, tRP); SDRC_SET_ONE(&actim_ctrla, 18, 21, tRAS); SDRC_SET_ONE(&actim_ctrla, 22, 26, tRC); SDRC_SET_ONE(&actim_ctrla, 27, 31, tRFC); SDRC_SET_ONE(&actim_ctrlb, 0, 7, tXSR); ticks_per_ms = sdrc_ps_to_ticks(1000000000); rfr = rx51_timings[0].tREF * ticks_per_ms / (1 << rx51_info.row_lines); if (rfr > 65535 + 50) rfr = 65535; else rfr -= 50; l = rfr << 8; rfr_ctrl = l | 0x3; /* autorefresh, reload counter with 8xARCV */ rx51_sdrc_params[0].rate = 133333333; rx51_sdrc_params[0].actim_ctrla = actim_ctrla; rx51_sdrc_params[0].actim_ctrlb = actim_ctrlb; rx51_sdrc_params[0].rfr_ctrl = rfr_ctrl; rx51_sdrc_params[0].mr = 0x32; rx51_sdrc_params[1].rate = 0; if (err < 0) return NULL; return &rx51_sdrc_params[0]; }