Lines Matching +full:ras +full:- +full:to +full:- +full:cas
9 * Intel 5100X Chipset Memory Controller Hub (MCH) - Datasheet
13 * can not reflect this configuration so instead the chip-select
15 * the first half belonging to channel 0, the second half belonging
16 * to channel 1.
64 #define I5100_NERR_NF_MEM 0xa4 /* MC Next Non-Fatal Errors */
68 #define I5100_MTR_0 0x154 /* Memory Technology Registers 0-3 */
71 #define I5100_NRECMEMA 0x190 /* Non-Recoverable Memory Error Log Reg A */
72 #define I5100_NRECMEMB 0x194 /* Non-Recoverable Memory Error Log Reg B */
113 return a & ((1 << 8) - 1); in i5100_spddata_data()
119 return ((dti & ((1 << 4) - 1)) << 28) | in i5100_spdcmd_create()
121 ((sa & ((1 << 3) - 1)) << 24) | in i5100_spdcmd_create()
122 ((ba & ((1 << 8) - 1)) << 16) | in i5100_spdcmd_create()
123 ((data & ((1 << 8) - 1)) << 8) | in i5100_spdcmd_create()
129 return a >> 12 & ((1 << 4) - 1); in i5100_tolm_tolm()
134 return a >> 4 & ((1 << 12) - 1); in i5100_mir_limit()
164 return a >> 16 & ((1 << 11) - 1); in i5100_dmir_limit()
169 return a >> (4 * i) & ((1 << 2) - 1); in i5100_dmir_rank()
194 return a >> 2 & ((1 << 2) - 1); in i5100_mtr_numrow()
199 return a & ((1 << 2) - 1); in i5100_mtr_numcol()
220 return a >> 15 & ((1 << 5) - 1); in i5100_nrecmema_merr()
225 return a >> 12 & ((1 << 3) - 1); in i5100_nrecmema_bank()
230 return a >> 8 & ((1 << 3) - 1); in i5100_nrecmema_rank()
235 return a & ((1 << 8) - 1); in i5100_nrecmema_dm_buf_id()
240 return a >> 16 & ((1 << 13) - 1); in i5100_nrecmemb_cas()
245 return a & ((1 << 16) - 1); in i5100_nrecmemb_ras()
250 return a & ((1 << 18) - 1); in i5100_redmemb_ecc_locator()
287 #define I5100_DIMM_ADDR_LINES (6 - 3) /* 64 bits / 8 bits per byte */
294 /* ranks on each dimm -- 0 maps to not present -- obtained via SPD */
298 * mainboard chip select map -- maps i5100 chip selects to
301 * we map -1 -> NC and assume both channels use the same
343 /* map a rank/chan to a slot number on the mainboard */
347 const struct i5100_priv *priv = mci->pvt_info; in i5100_rank_to_slot()
352 const int numrank = priv->dimm_numrank[chan][i]; in i5100_rank_to_slot()
355 if (priv->dimm_csmap[i][j] == rank) in i5100_rank_to_slot()
359 return -1; in i5100_rank_to_slot()
370 "aliased uncorrectable spare-copy data ECC", /* 5 */ in i5100_err_msg()
375 "non-aliased uncorrectable demand data ECC", /* 10 */ in i5100_err_msg()
376 "non-aliased uncorrectable spare-copy data ECC", /* 11 */ in i5100_err_msg()
377 "non-aliased uncorrectable patrol data ECC", /* 12 */ in i5100_err_msg()
380 "correctable spare-copy data ECC", /* 15 */ in i5100_err_msg()
397 /* convert csrow index into a rank (per channel -- 0..5) */
400 const struct i5100_priv *priv = mci->pvt_info; in i5100_csrow_to_rank()
402 return csrow % priv->ranksperchan; in i5100_csrow_to_rank()
408 const struct i5100_priv *priv = mci->pvt_info; in i5100_csrow_to_chan()
410 return csrow / priv->ranksperchan; in i5100_csrow_to_chan()
416 const struct i5100_priv *priv = mci->pvt_info; in i5100_rank_to_csrow()
418 return chan * priv->ranksperchan + rank; in i5100_rank_to_csrow()
426 unsigned cas, in i5100_handle_ce() argument
427 unsigned ras, in i5100_handle_ce() argument
434 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", in i5100_handle_ce()
435 chan, bank, rank, syndrome, cas, ras, in i5100_handle_ce()
436 csrow, mci->csrows[csrow].channels[0].label, msg); in i5100_handle_ce()
438 mci->ce_count++; in i5100_handle_ce()
439 mci->csrows[csrow].ce_count++; in i5100_handle_ce()
440 mci->csrows[csrow].channels[0].ce_count++; in i5100_handle_ce()
448 unsigned cas, in i5100_handle_ue() argument
449 unsigned ras, in i5100_handle_ue() argument
456 "cas %u, ras %u, csrow %u, label \"%s\": %s\n", in i5100_handle_ue()
457 chan, bank, rank, syndrome, cas, ras, in i5100_handle_ue()
458 csrow, mci->csrows[csrow].channels[0].label, msg); in i5100_handle_ue()
460 mci->ue_count++; in i5100_handle_ue()
461 mci->csrows[csrow].ue_count++; in i5100_handle_ue()
467 struct i5100_priv *priv = mci->pvt_info; in i5100_read_log()
468 struct pci_dev *pdev = (chan) ? priv->ch1mm : priv->ch0mm; in i5100_read_log()
476 unsigned cas; in i5100_read_log() local
477 unsigned ras; in i5100_read_log() local
497 cas = i5100_recmemb_cas(dw2); in i5100_read_log()
498 ras = i5100_recmemb_ras(dw2); in i5100_read_log()
507 i5100_handle_ce(mci, chan, bank, rank, syndrome, cas, ras, msg); in i5100_read_log()
519 cas = i5100_nrecmemb_cas(dw2); in i5100_read_log()
520 ras = i5100_nrecmemb_ras(dw2); in i5100_read_log()
529 i5100_handle_ue(mci, chan, bank, rank, syndrome, cas, ras, msg); in i5100_read_log()
537 struct i5100_priv *priv = mci->pvt_info; in i5100_check_error()
541 pci_read_config_dword(priv->mc, I5100_FERR_NF_MEM, &dw); in i5100_check_error()
545 pci_read_config_dword(priv->mc, I5100_NERR_NF_MEM, &dw2); in i5100_check_error()
547 pci_write_config_dword(priv->mc, I5100_NERR_NF_MEM, in i5100_check_error()
549 pci_write_config_dword(priv->mc, I5100_FERR_NF_MEM, dw); in i5100_check_error()
559 * delayed work to a workqueue, checking every few minutes if
573 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_refresh_scrubbing()
575 if (priv->scrub_enable) { in i5100_refresh_scrubbing()
577 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_refresh_scrubbing()
581 pci_write_config_dword(priv->mc, I5100_MC, dw); in i5100_refresh_scrubbing()
582 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_refresh_scrubbing()
585 schedule_delayed_work(&(priv->i5100_scrubbing), in i5100_refresh_scrubbing()
590 * The bandwidth is based on experimentation, feel free to refine it.
594 struct i5100_priv *priv = mci->pvt_info; in i5100_set_scrub_rate()
597 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_set_scrub_rate()
599 priv->scrub_enable = 1; in i5100_set_scrub_rate()
601 schedule_delayed_work(&(priv->i5100_scrubbing), in i5100_set_scrub_rate()
604 priv->scrub_enable = 0; in i5100_set_scrub_rate()
606 cancel_delayed_work(&(priv->i5100_scrubbing)); in i5100_set_scrub_rate()
608 pci_write_config_dword(priv->mc, I5100_MC, dw); in i5100_set_scrub_rate()
610 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_set_scrub_rate()
619 struct i5100_priv *priv = mci->pvt_info; in i5100_get_scrub_rate()
622 pci_read_config_dword(priv->mc, I5100_MC, &dw); in i5100_get_scrub_rate()
639 if (PCI_FUNC(ret->devfn) == func) in pci_get_device_func()
649 struct i5100_priv *priv = mci->pvt_info; in i5100_npages()
655 if (!priv->mtr[chan][chan_rank].present) in i5100_npages()
660 priv->mtr[chan][chan_rank].numcol + in i5100_npages()
661 priv->mtr[chan][chan_rank].numrow + in i5100_npages()
662 priv->mtr[chan][chan_rank].numbank; in i5100_npages()
670 struct i5100_priv *priv = mci->pvt_info; in i5100_init_mtr()
671 struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; in i5100_init_mtr()
681 I5100_MTR_4 + (j - 4) * 2; in i5100_init_mtr()
686 priv->mtr[i][j].present = i5100_mtr_present(w); in i5100_init_mtr()
687 priv->mtr[i][j].ethrottle = i5100_mtr_ethrottle(w); in i5100_init_mtr()
688 priv->mtr[i][j].width = 4 + 4 * i5100_mtr_width(w); in i5100_init_mtr()
689 priv->mtr[i][j].numbank = 2 + i5100_mtr_numbank(w); in i5100_init_mtr()
690 priv->mtr[i][j].numrow = 13 + i5100_mtr_numrow(w); in i5100_init_mtr()
691 priv->mtr[i][j].numcol = 10 + i5100_mtr_numcol(w); in i5100_init_mtr()
697 * FIXME: make this into a real i2c adapter (so that dimm-decode
703 struct i5100_priv *priv = mci->pvt_info; in i5100_read_spd_byte()
707 pci_read_config_word(priv->mc, I5100_SPDDATA, &w); in i5100_read_spd_byte()
709 return -1; in i5100_read_spd_byte()
711 pci_write_config_dword(priv->mc, I5100_SPDCMD, in i5100_read_spd_byte()
715 /* wait up to 100ms */ in i5100_read_spd_byte()
719 pci_read_config_word(priv->mc, I5100_SPDDATA, &w); in i5100_read_spd_byte()
726 return -1; in i5100_read_spd_byte()
737 * o not the only way to may chip selects to dimm slots
738 * o investigate if there is some way to obtain this map from the bios
742 struct i5100_priv *priv = mci->pvt_info; in i5100_init_dimm_csmap()
749 priv->dimm_csmap[i][j] = -1; /* default NC */ in i5100_init_dimm_csmap()
753 if (priv->ranksperchan == 4) { in i5100_init_dimm_csmap()
754 priv->dimm_csmap[0][0] = 0; in i5100_init_dimm_csmap()
755 priv->dimm_csmap[0][1] = 3; in i5100_init_dimm_csmap()
756 priv->dimm_csmap[1][0] = 1; in i5100_init_dimm_csmap()
757 priv->dimm_csmap[1][1] = 2; in i5100_init_dimm_csmap()
758 priv->dimm_csmap[2][0] = 2; in i5100_init_dimm_csmap()
759 priv->dimm_csmap[3][0] = 3; in i5100_init_dimm_csmap()
761 priv->dimm_csmap[0][0] = 0; in i5100_init_dimm_csmap()
762 priv->dimm_csmap[0][1] = 1; in i5100_init_dimm_csmap()
763 priv->dimm_csmap[1][0] = 2; in i5100_init_dimm_csmap()
764 priv->dimm_csmap[1][1] = 3; in i5100_init_dimm_csmap()
765 priv->dimm_csmap[2][0] = 4; in i5100_init_dimm_csmap()
766 priv->dimm_csmap[2][1] = 5; in i5100_init_dimm_csmap()
773 struct i5100_priv *priv = mci->pvt_info; in i5100_init_dimm_layout()
783 priv->dimm_numrank[i][j] = 0; in i5100_init_dimm_layout()
785 priv->dimm_numrank[i][j] = (rank & 3) + 1; in i5100_init_dimm_layout()
797 struct i5100_priv *priv = mci->pvt_info; in i5100_init_interleaving()
798 struct pci_dev *mms[2] = { priv->ch0mm, priv->ch1mm }; in i5100_init_interleaving()
802 priv->tolm = (u64) i5100_tolm_tolm(w) * 256 * 1024 * 1024; in i5100_init_interleaving()
805 priv->mir[0].limit = (u64) i5100_mir_limit(w) << 28; in i5100_init_interleaving()
806 priv->mir[0].way[1] = i5100_mir_way1(w); in i5100_init_interleaving()
807 priv->mir[0].way[0] = i5100_mir_way0(w); in i5100_init_interleaving()
810 priv->mir[1].limit = (u64) i5100_mir_limit(w) << 28; in i5100_init_interleaving()
811 priv->mir[1].way[1] = i5100_mir_way1(w); in i5100_init_interleaving()
812 priv->mir[1].way[0] = i5100_mir_way0(w); in i5100_init_interleaving()
815 priv->amir[0] = w; in i5100_init_interleaving()
817 priv->amir[1] = w; in i5100_init_interleaving()
827 priv->dmir[i][j].limit = in i5100_init_interleaving()
830 priv->dmir[i][j].rank[k] = in i5100_init_interleaving()
842 struct i5100_priv *priv = mci->pvt_info; in i5100_init_csrows()
844 for (i = 0; i < mci->nr_csrows; i++) { in i5100_init_csrows()
853 * FIXME: these two are totally bogus -- I don't see how to in i5100_init_csrows()
854 * map them correctly to this structure... in i5100_init_csrows()
856 mci->csrows[i].first_page = total_pages; in i5100_init_csrows()
857 mci->csrows[i].last_page = total_pages + npages - 1; in i5100_init_csrows()
858 mci->csrows[i].page_mask = 0UL; in i5100_init_csrows()
860 mci->csrows[i].nr_pages = npages; in i5100_init_csrows()
861 mci->csrows[i].grain = 32; in i5100_init_csrows()
862 mci->csrows[i].csrow_idx = i; in i5100_init_csrows()
863 mci->csrows[i].dtype = in i5100_init_csrows()
864 (priv->mtr[chan][rank].width == 4) ? DEV_X4 : DEV_X8; in i5100_init_csrows()
865 mci->csrows[i].ue_count = 0; in i5100_init_csrows()
866 mci->csrows[i].ce_count = 0; in i5100_init_csrows()
867 mci->csrows[i].mtype = MEM_RDDR2; in i5100_init_csrows()
868 mci->csrows[i].edac_mode = EDAC_SECDED; in i5100_init_csrows()
869 mci->csrows[i].mci = mci; in i5100_init_csrows()
870 mci->csrows[i].nr_channels = 1; in i5100_init_csrows()
871 mci->csrows[i].channels[0].chan_idx = 0; in i5100_init_csrows()
872 mci->csrows[i].channels[0].ce_count = 0; in i5100_init_csrows()
873 mci->csrows[i].channels[0].csrow = mci->csrows + i; in i5100_init_csrows()
874 snprintf(mci->csrows[i].channels[0].label, in i5100_init_csrows()
875 sizeof(mci->csrows[i].channels[0].label), in i5100_init_csrows()
893 if (PCI_FUNC(pdev->devfn) != 1) in i5100_init_one()
894 return -ENODEV; in i5100_init_one()
906 ret = -ENODEV; in i5100_init_one()
923 ret = -ENODEV; in i5100_init_one()
937 ret = -ENODEV; in i5100_init_one()
949 ret = -ENOMEM; in i5100_init_one()
953 mci->dev = &pdev->dev; in i5100_init_one()
955 priv = mci->pvt_info; in i5100_init_one()
956 priv->ranksperchan = ranksperch; in i5100_init_one()
957 priv->mc = pdev; in i5100_init_one()
958 priv->ch0mm = ch0mm; in i5100_init_one()
959 priv->ch1mm = ch1mm; in i5100_init_one()
961 INIT_DELAYED_WORK(&(priv->i5100_scrubbing), i5100_refresh_scrubbing); in i5100_init_one()
966 priv->scrub_enable = 1; in i5100_init_one()
967 schedule_delayed_work(&(priv->i5100_scrubbing), in i5100_init_one()
974 mci->mtype_cap = MEM_FLAG_FB_DDR2; in i5100_init_one()
975 mci->edac_ctl_cap = EDAC_FLAG_SECDED; in i5100_init_one()
976 mci->edac_cap = EDAC_FLAG_SECDED; in i5100_init_one()
977 mci->mod_name = "i5100_edac.c"; in i5100_init_one()
978 mci->mod_ver = "not versioned"; in i5100_init_one()
979 mci->ctl_name = "i5100"; in i5100_init_one()
980 mci->dev_name = pci_name(pdev); in i5100_init_one()
981 mci->ctl_page_to_phys = NULL; in i5100_init_one()
983 mci->edac_check = i5100_check_error; in i5100_init_one()
984 mci->set_sdram_scrub_rate = i5100_set_scrub_rate; in i5100_init_one()
985 mci->get_sdram_scrub_rate = i5100_get_scrub_rate; in i5100_init_one()
989 /* this strange construction seems to be in every driver, dunno why */ in i5100_init_one()
1000 ret = -ENODEV; in i5100_init_one()
1007 priv->scrub_enable = 0; in i5100_init_one()
1008 cancel_delayed_work_sync(&(priv->i5100_scrubbing)); in i5100_init_one()
1035 mci = edac_mc_del_mc(&pdev->dev); in i5100_remove_one()
1040 priv = mci->pvt_info; in i5100_remove_one()
1042 priv->scrub_enable = 0; in i5100_remove_one()
1043 cancel_delayed_work_sync(&(priv->i5100_scrubbing)); in i5100_remove_one()
1046 pci_disable_device(priv->ch0mm); in i5100_remove_one()
1047 pci_disable_device(priv->ch1mm); in i5100_remove_one()
1048 pci_dev_put(priv->ch0mm); in i5100_remove_one()
1049 pci_dev_put(priv->ch1mm); in i5100_remove_one()