Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 854d3349 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: Get more info about the memory DIMMs

parent 7dd6953c
Loading
Loading
Loading
Loading
+107 −63
Original line number Diff line number Diff line
@@ -109,14 +109,14 @@
  #define RANKOFFSET(x)		((x & RANKOFFSET_MASK) >> 10)
  #define DIMM_PRESENT_MASK	(1 << 9)
  #define DIMM_PRESENT(x)	(((x) & DIMM_PRESENT_MASK) >> 9)
  #define NUMBANK_MASK		((1 << 8) | (1 << 7))
  #define NUMBANK(x)		(((x) & NUMBANK_MASK) >> 7)
  #define NUMRANK_MASK		((1 << 6) | (1 << 5))
  #define NUMRANK(x)		(((x) & NUMRANK_MASK) >> 5)
  #define NUMROW_MASK		((1 << 4) | (1 << 3))
  #define NUMROW(x)		(((x) & NUMROW_MASK) >> 3)
  #define NUMCOL_MASK		3
  #define NUMCOL(x)		((x) & NUMCOL_MASK)
  #define MC_DOD_NUMBANK_MASK		((1 << 8) | (1 << 7))
  #define MC_DOD_NUMBANK(x)		(((x) & MC_DOD_NUMBANK_MASK) >> 7)
  #define MC_DOD_NUMRANK_MASK		((1 << 6) | (1 << 5))
  #define MC_DOD_NUMRANK(x)		(((x) & MC_DOD_NUMRANK_MASK) >> 5)
  #define MC_DOD_NUMROW_MASK		((1 << 4) | (1 << 3))
  #define MC_DOD_NUMROW(x)		(((x) & MC_DOD_NUMROW_MASK) >> 3)
  #define MC_DOD_NUMCOL_MASK		3
  #define MC_DOD_NUMCOL(x)		((x) & MC_DOD_NUMCOL_MASK)

#define MC_RANK_PRESENT		0x7c

@@ -268,41 +268,41 @@ static struct edac_pci_ctl_info *i7core_pci;
#define CH_DISABLED(pvt, ch)	((pvt)->info.mc_status & (1 << ch))

	/* MC_MAX_DOD read functions */
static inline int maxnumdimms(struct i7core_pvt *pvt)
static inline int numdimms(u32 dimms)
{
	return (pvt->info.max_dod & 0x3) + 1;
	return (dimms & 0x3) + 1;
}

static inline int maxnumrank(struct i7core_pvt *pvt)
static inline int numrank(u32 rank)
{
	static int ranks[4] = { 1, 2, 4, -EINVAL };

	return ranks[(pvt->info.max_dod >> 2) & 0x3];
	return ranks[rank & 0x3];
}

static inline int maxnumbank(struct i7core_pvt *pvt)
static inline int numbank(u32 bank)
{
	static int banks[4] = { 4, 8, 16, -EINVAL };

	return banks[(pvt->info.max_dod >> 4) & 0x3];
	return banks[bank & 0x3];
}

static inline int maxnumrow(struct i7core_pvt *pvt)
static inline int numrow(u32 row)
{
	static int rows[8] = {
		1 << 12, 1 << 13, 1 << 14, 1 << 15,
		1 << 16, -EINVAL, -EINVAL, -EINVAL,
	};

	return rows[((pvt->info.max_dod >> 6) & 0x7)];
	return rows[row & 0x7];
}

static inline int maxnumcol(struct i7core_pvt *pvt)
static inline int numcol(u32 col)
{
	static int cols[8] = {
		1 << 10, 1 << 11, 1 << 12, -EINVAL,
	};
	return cols[((pvt->info.max_dod >> 9) & 0x3) << 12];
	return cols[col & 0x3];
}


@@ -359,10 +359,13 @@ static int get_dimm_config(struct mem_ctl_info *mci)
{
	struct i7core_pvt *pvt = mci->pvt_info;
	struct csrow_info *csr;
	struct pci_dev *pdev = pvt->pci_mcr[0];
	struct pci_dev *pdev;
	int i, j, csrow = 0;
	enum edac_type mode;
	enum mem_type mtype;

	/* Get data from the MC register, function 0 */
	pdev = pvt->pci_mcr[0];
	if (!pdev)
		return -ENODEV;

@@ -388,15 +391,18 @@ static int get_dimm_config(struct mem_ctl_info *mci)
	}

	/* FIXME: need to handle the error codes */
	debugf0("DOD Maximum limits: DIMMS: %d, %d-ranked, %d-banked\n",
		maxnumdimms(pvt), maxnumrank(pvt), maxnumbank(pvt));
	debugf0("DOD Maximum rows x colums = 0x%x x 0x%x\n",
		maxnumrow(pvt), maxnumcol(pvt));
	debugf0("DOD Max limits: DIMMS: %d, %d-ranked, %d-banked\n",
		numdimms(pvt->info.max_dod),
		numrank(pvt->info.max_dod >> 2),
		numbank(pvt->info.max_dod >> 4));
	debugf0("DOD Max rows x colums = 0x%x x 0x%x\n",
		numrow(pvt->info.max_dod >> 6),
		numcol(pvt->info.max_dod >> 9));

	debugf0("Memory channel configuration:\n");

	for (i = 0; i < NUM_CHANS; i++) {
		u32 data, value[8];
		u32 data, dimm_dod[3], value[8];

		if (!CH_ACTIVE(pvt, i)) {
			debugf0("Channel %i is not active\n", i);
@@ -413,26 +419,81 @@ static int get_dimm_config(struct mem_ctl_info *mci)

		pvt->channel[i].ranks = (data & QUAD_RANK_PRESENT)? 4 : 2;

		if (data & REGISTERED_DIMM)
			mtype = MEM_RDDR3;
		else
			mtype = MEM_DDR3;
#if 0
		if (data & THREE_DIMMS_PRESENT)
			pvt->channel[i].dimms = 3;
		else if (data & SINGLE_QUAD_RANK_PRESENT)
			pvt->channel[i].dimms = 1;
		else
			pvt->channel[i].dimms = 2;
#endif

		/* Devices 4-6 function 1 */
		pci_read_config_dword(pvt->pci_ch[i][1],
				MC_DOD_CH_DIMM0, &dimm_dod[0]);
		pci_read_config_dword(pvt->pci_ch[i][1],
				MC_DOD_CH_DIMM1, &dimm_dod[1]);
		pci_read_config_dword(pvt->pci_ch[i][1],
				MC_DOD_CH_DIMM2, &dimm_dod[2]);

		debugf0("Ch%d phy rd%d, wr%d (0x%08x): "
			"%d ranks, %d %cDIMMs, offset = %d\n\t"
			"present: %i, numbank: %#x, numrank: %#x, "
			"numrow: %#x, numcol: %#x\n",
			"%d ranks, %cDIMMs\n",
			i,
			RDLCH(pvt->info.ch_map, i), WRLCH(pvt->info.ch_map, i),
			data,
			pvt->channel[i].ranks, pvt->channel[i].dimms,
			(data & REGISTERED_DIMM)? 'R' : 'U',
			RANKOFFSET(data),
			DIMM_PRESENT(data),
			NUMBANK(data), NUMRANK(data),
			NUMROW(data), NUMCOL(data));
			pvt->channel[i].ranks,
			(data & REGISTERED_DIMM)? 'R' : 'U');

		for (j = 0; j < 3; j++) {
			u32 banks, ranks, rows, cols;

			if (!DIMM_PRESENT(dimm_dod[j]))
				continue;

			banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
			ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
			rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
			cols = numcol(MC_DOD_NUMCOL(dimm_dod[j]));

			pvt->channel[i].dimms++;

			debugf0("\tdimm %d offset: %x, numbank: %#x, "
				"numrank: %#x, numrow: %#x, numcol: %#x\n",
				j,
				RANKOFFSET(dimm_dod[j]),
				banks, ranks, rows, cols);

			csr = &mci->csrows[csrow];
			csr->first_page = 0;
			csr->last_page = 0;
			csr->page_mask = 0;
			csr->nr_pages = 0;
			csr->grain = 0;
			csr->csrow_idx = csrow;

			switch (banks) {
			case 4:
				csr->dtype = DEV_X4;
				break;
			case 8:
				csr->dtype = DEV_X8;
				break;
			case 16:
				csr->dtype = DEV_X16;
				break;
			default:
				csr->dtype = DEV_UNKNOWN;
			}

			csr->edac_mode = mode;
			csr->mtype = mtype;

			csrow++;
		}

		pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
		pci_read_config_dword(pdev, MC_SAG_CH_1, &value[1]);
@@ -448,23 +509,6 @@ static int get_dimm_config(struct mem_ctl_info *mci)
				(value[j] >> 27) & 0x1,
				(value[j] >> 24) & 0x7,
				(value[j] && ((1 << 24) - 1)));

		csr = &mci->csrows[csrow];
		csr->first_page = 0;
		csr->last_page = 0;
		csr->page_mask = 0;
		csr->nr_pages = 0;
		csr->grain = 0;
		csr->csrow_idx = csrow;
		csr->dtype = DEV_X8;	/* FIXME: check this */

		if (data & REGISTERED_DIMM)
			csr->mtype = MEM_RDDR3;
		else
			csr->mtype = MEM_DDR3;
		csr->edac_mode = mode;

		csrow++;
	}

	return 0;