📄 articias.c
字号:
/* * (C) Copyright 2002 * Hyperion Entertainment, ThomasF@hyperion-entertainment.com * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <pci.h>#include <asm/processor.h>#include "memio.h"#include "articiaS.h"#include "smbus.h"#include "via686.h"#undef DEBUGstruct dimm_bank { uint8 used; /* Bank is populated */ uint32 rows; /* Number of row addresses */ uint32 columns; /* Number of column addresses */ uint8 registered; /* SIMM is registered */ uint8 ecc; /* SIMM has ecc */ uint8 burst_len; /* Supported burst lengths */ uint32 cas_lat; /* Supported CAS latencies */ uint32 cas_used; /* CAS to use (not set by user) */ uint32 trcd; /* RAS to CAS latency */ uint32 trp; /* Precharge latency */ uint32 tclk_hi; /* SDRAM cycle time (highest CAS latency) */ uint32 tclk_2hi; /* SDRAM second highest CAS latency */ uint32 size; /* Size of bank in bytes */ uint8 auto_refresh; /* Module supports auto refresh */ uint32 refresh_time; /* Refresh time (in ns) */};/*** Based in part on the evb64260 code*//* * translate ns.ns/10 coding of SPD timing values * into 10 ps unit values */static inline unsigned short NS10to10PS (unsigned char spd_byte){ unsigned short ns, ns10; /* isolate upper nibble */ ns = (spd_byte >> 4) & 0x0F; /* isolate lower nibble */ ns10 = (spd_byte & 0x0F); return (ns * 100 + ns10 * 10);}/* * translate ns coding of SPD timing values * into 10 ps unit values */static inline unsigned short NSto10PS (unsigned char spd_byte){ return (spd_byte * 100);}long detect_sdram (uint8 * rom, int dimmNum, struct dimm_bank *banks){ DECLARE_GLOBAL_DATA_PTR; int dimm_address = (dimmNum == 0) ? SM_DIMM0_ADDR : SM_DIMM1_ADDR; uint32 busclock = gd->bus_clk; uint32 memclock = busclock; uint32 tmemclock = 1000000000 / (memclock / 100); uint32 datawidth; if (sm_get_data (rom, dimm_address) == 0) { /* Nothing in slot, make both banks empty */ debug ("Slot %d: vacant\n", dimmNum); banks[0].used = 0; banks[1].used = 0; return 0; } if (rom[2] != 0x04) { debug ("Slot %d: No SDRAM\n", dimmNum); banks[0].used = 0; banks[1].used = 0; return 0; } /* Determine number of banks/rows */ if (rom[5] == 1) { banks[0].used = 1; banks[1].used = 0; } else { banks[0].used = 1; banks[1].used = 1; } /* Determine number of row addresses */ if (rom[3] & 0xf0) { /* Different banks sizes */ banks[0].rows = rom[3] & 0x0f; banks[1].rows = (rom[3] & 0xf0) >> 4; } else { /* Equal sized banks */ banks[0].rows = rom[3] & 0x0f; banks[1].rows = banks[0].rows; } /* Determine number of column addresses */ if (rom[4] & 0xf0) { /* Different bank sizes */ banks[0].columns = rom[4] & 0x0f; banks[1].columns = (rom[4] & 0xf0) >> 4; } else { banks[0].columns = rom[4] & 0x0f; banks[1].columns = banks[0].columns; } /* Check Jedec revision, and modify row/column accordingly */ if (rom[62] > 0x10) { if (banks[0].rows <= 3) banks[0].rows += 15; if (banks[1].rows <= 3) banks[1].rows += 15; if (banks[0].columns <= 3) banks[0].columns += 15; if (banks[0].columns <= 3) banks[0].columns += 15; } /* Check registered/unregisterd */ if (rom[21] & 0x12) { banks[0].registered = 1; banks[1].registered = 1; } else { banks[0].registered = 0; banks[1].registered = 0; }#ifdef CONFIG_ECC /* Check parity/ECC */ banks[0].ecc = (rom[11] == 0x02); banks[1].ecc = (rom[11] == 0x02);#endif /* Find burst lengths supported */ banks[0].burst_len = rom[16] & 0x8f; banks[1].burst_len = rom[16] & 0x8f; /* Find possible cas latencies */ banks[0].cas_lat = rom[18] & 0x7F; banks[1].cas_lat = rom[18] & 0x7F; /* RAS/CAS latency */ banks[0].trcd = (NSto10PS (rom[29]) + (tmemclock - 1)) / tmemclock; banks[1].trcd = (NSto10PS (rom[29]) + (tmemclock - 1)) / tmemclock; /* Precharge latency */ banks[0].trp = (NSto10PS (rom[27]) + (tmemclock - 1)) / tmemclock; banks[1].trp = (NSto10PS (rom[27]) + (tmemclock - 1)) / tmemclock; /* highest CAS latency */ banks[0].tclk_hi = NS10to10PS (rom[9]); banks[1].tclk_hi = NS10to10PS (rom[9]); /* second highest CAS latency */ banks[0].tclk_2hi = NS10to10PS (rom[23]); banks[1].tclk_2hi = NS10to10PS (rom[23]); /* bank sizes */ datawidth = rom[13] & 0x7f; banks[0].size = (1L << (banks[0].rows + banks[0].columns)) * /* FIXME datawidth */ 8 * rom[17]; if (rom[13] & 0x80) banks[1].size = 2 * banks[0].size; else banks[1].size = (1L << (banks[1].rows + banks[1].columns)) * /* FIXME datawidth */ 8 * rom[17]; /* Refresh */ if (rom[12] & 0x80) { banks[0].auto_refresh = 1; banks[1].auto_refresh = 1; } else { banks[0].auto_refresh = 0; banks[1].auto_refresh = 0; } switch (rom[12] & 0x7f) { case 0: banks[0].refresh_time = (1562500 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (1562500 + (tmemclock - 1)) / tmemclock; break; case 1: banks[0].refresh_time = (390600 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (390600 + (tmemclock - 1)) / tmemclock; break; case 2: banks[0].refresh_time = (781200 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (781200 + (tmemclock - 1)) / tmemclock; break; case 3: banks[0].refresh_time = (3125000 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (3125000 + (tmemclock - 1)) / tmemclock; break; case 4: banks[0].refresh_time = (6250000 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (6250000 + (tmemclock - 1)) / tmemclock; break; case 5: banks[0].refresh_time = (12500000 + (tmemclock - 1)) / tmemclock; banks[1].refresh_time = (12500000 + (tmemclock - 1)) / tmemclock; break; default: banks[0].refresh_time = 0x100; /* Default of Articia S */ banks[1].refresh_time = 0x100; break; }#ifdef DEBUG printf ("\nInformation for SIMM bank %ld:\n", dimmNum); printf ("Number of banks: %ld\n", banks[0].used + banks[1].used); printf ("Number of row addresses: %ld\n", banks[0].rows); printf ("Number of coumns addresses: %ld\n", banks[0].columns); printf ("SIMM is %sregistered\n", banks[0].registered == 0 ? "not " : "");#ifdef CONFIG_ECC printf ("SIMM %s ECC\n", banks[0].ecc == 1 ? "supports" : "doesn't support");#endif printf ("Supported burst lenghts: %s %s %s %s %s\n", banks[0].burst_len & 0x08 ? "8" : " ", banks[0].burst_len & 0x04 ? "4" : " ", banks[0].burst_len & 0x02 ? "2" : " ", banks[0].burst_len & 0x01 ? "1" : " ", banks[0].burst_len & 0x80 ? "PAGE" : " "); printf ("Supported CAS latencies: %s %s %s\n", banks[0].cas_lat & 0x04 ? "CAS 3" : " ", banks[0].cas_lat & 0x02 ? "CAS 2" : " ", banks[0].cas_lat & 0x01 ? "CAS 1" : " "); printf ("RAS to CAS latency: %ld\n", banks[0].trcd); printf ("Precharge latency: %ld\n", banks[0].trp); printf ("SDRAM highest CAS latency: %ld\n", banks[0].tclk_hi); printf ("SDRAM 2nd highest CAS latency: %ld\n", banks[0].tclk_2hi); printf ("SDRAM data width: %ld\n", datawidth); printf ("Auto Refresh %ssupported\n", banks[0].auto_refresh ? "" : "not "); printf ("Refresh time: %ld clocks\n", banks[0].refresh_time); if (banks[0].used) printf ("Bank 0 size: %ld MB\n", banks[0].size / 1024 / 1024); if (banks[1].used) printf ("Bank 1 size: %ld MB\n", banks[1].size / 1024 / 1024); printf ("\n");#endif sm_term (); return 1;}void select_cas (struct dimm_bank *banks, uint8 fast){ if (!banks[0].used) { banks[0].cas_used = 0; banks[0].cas_used = 0; return; } if (fast) { /* Search for fast CAS */ uint32 i; uint32 c = 0x01; for (i = 1; i < 5; i++) { if (banks[0].cas_lat & c) { banks[0].cas_used = i; banks[1].cas_used = i; debug ("Using CAS %d (fast)\n", i); return; } c <<= 1; } /* Default to CAS 3 */ banks[0].cas_used = 3; banks[1].cas_used = 3; debug ("Using CAS 3 (fast)\n"); return; } else { /* Search for slow cas */ uint32 i; uint32 c = 0x08; for (i = 4; i > 1; i--) { if (banks[0].cas_lat & c) { banks[0].cas_used = i; banks[1].cas_used = i; debug ("Using CAS %d (slow)\n", i); return; } c >>= 1; } /* Default to CAS 3 */ banks[0].cas_used = 3; banks[1].cas_used = 3; debug ("Using CAS 3 (slow)\n"); return; } banks[0].cas_used = 3; banks[1].cas_used = 3; debug ("Using CAS 3\n"); return;}uint32 get_reg_setting (uint32 banks, uint32 rows, uint32 columns, uint32 size){ uint32 i; struct RowColumnSize { uint32 banks; uint32 rows; uint32 columns; uint32 size; uint32 register_value; }; struct RowColumnSize rcs_map[] = { /* Sbk Radr Cadr MB Value */ {1, 11, 8, 8, 0x00840f00},
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -