Lines Matching +full:interleave +full:- +full:mode

50 #include <sys/mc-us3i.h>
55 * pm-hardware-state value
57 #define NO_SUSPEND_RESUME "no-suspend-resume"
134 "Memory-controller", /* module name */
238 softsp->dip = devi; in mc_attach()
240 if ((softsp->portid = (int)ddi_getprop(DDI_DEV_T_ANY, softsp->dip, in mc_attach()
241 DDI_PROP_DONTPASS, "portid", -1)) == -1) { in mc_attach()
248 instance, softsp->portid, CPU->cpu_id)); in mc_attach()
252 if ((ddi_getlongprop_buf(DDI_DEV_T_ANY, softsp->dip, DDI_PROP_DONTPASS, in mc_attach()
253 "memory-control-register-1", (caddr_t)&(softsp->mcreg1), in mc_attach()
256 softsp->mcr_read_ok = 1; in mc_attach()
258 instance, softsp->mcreg1)); in mc_attach()
262 if (!softsp->mcr_read_ok) { in mc_attach()
270 "pm-hardware-state", NO_SUSPEND_RESUME, in mc_attach()
275 * memory-layout property of the memory controller. in mc_attach()
277 err = ddi_getlongprop(DDI_DEV_T_ANY, softsp->dip, DDI_PROP_DONTPASS, in mc_attach()
278 "memory-layout", (caddr_t)&dimminfop, &len); in mc_attach()
279 if (err == DDI_PROP_SUCCESS && dimminfop->table_width == 1) { in mc_attach()
281 softsp->memlayoutp = dimminfop; in mc_attach()
282 softsp->memlayoutlen = len; in mc_attach()
285 * memory-layout property was not found or some other in mc_attach()
289 softsp->memlayoutp = NULL; in mc_attach()
290 softsp->memlayoutlen = 0; in mc_attach()
292 ("mc %d: missing or unsupported memory-layout property\n", in mc_attach()
316 if (ddi_create_minor_node(devi, "mc-us3i", S_IFCHR, instance, in mc_attach()
329 mc_delete(softsp->portid); in mc_attach()
331 if (softsp->memlayoutp != NULL) in mc_attach()
332 kmem_free(softsp->memlayoutp, softsp->memlayoutlen); in mc_attach()
335 cmn_err(CE_WARN, "mc-us3i: attach failed for instance %d\n", instance); in mc_attach()
365 softsp->portid)); in mc_detach()
370 mc_delete(softsp->portid); in mc_detach()
372 if (softsp->memlayoutp != NULL) in mc_detach()
373 kmem_free(softsp->memlayoutp, softsp->memlayoutlen); in mc_detach()
494 size = sizeof (*mcmem) + (nsegments - 1) * in mc_ioctl()
495 sizeof (mcmem->segmentids[0]); in mc_ioctl()
498 mcmem->size = memsize; in mc_ioctl()
499 mcmem->nsegments = nsegments; in mc_ioctl()
503 mcmem->segmentids[i].globalid = seg->seg_node.id; in mc_ioctl()
504 mcmem->segmentids[i].localid = seg->seg_node.id; in mc_ioctl()
505 seg = (struct seg_info *)seg->seg_node.next; in mc_ioctl()
538 if (mcseg_in.nbanks < seg->nbanks) { in mc_ioctl()
539 mcseg_in.nbanks = seg->nbanks; in mc_ioctl()
549 size = sizeof (*mcseg) + (seg->nbanks - 1) * in mc_ioctl()
550 sizeof (mcseg->bankids[0]); in mc_ioctl()
553 mcseg->id = seg->seg_node.id; in mc_ioctl()
554 mcseg->ifactor = seg->ifactor; in mc_ioctl()
555 mcseg->base = seg->base; in mc_ioctl()
556 mcseg->size = seg->size; in mc_ioctl()
557 mcseg->nbanks = seg->nbanks; in mc_ioctl()
559 bank = seg->head; in mc_ioctl()
562 seg->nbanks, (void *) seg, (void *) bank)); in mc_ioctl()
567 i, bank->bank_node.id)); in mc_ioctl()
568 mcseg->bankids[i].globalid = bank->bank_node.id; in mc_ioctl()
569 mcseg->bankids[i++].localid = bank->local_id; in mc_ioctl()
570 bank = bank->next; in mc_ioctl()
572 ASSERT(i == seg->nbanks); in mc_ioctl()
603 mcbank.mask = bank->mask; in mc_ioctl()
604 mcbank.match = bank->match; in mc_ioctl()
605 mcbank.size = bank->size; in mc_ioctl()
606 mcbank.devgrpid.globalid = bank->devgrp_id; in mc_ioctl()
608 bank->bank_node.id % NLOGBANKS_PER_SEG; in mc_ioctl()
636 mcdevgrp.ndevices = dgrp->ndevices; in mc_ioctl()
637 mcdevgrp.size = dgrp->size; in mc_ioctl()
677 size = sizeof (*mcctrlconf) + ((nmcs - 1) * in mc_ioctl()
678 sizeof (mcctrlconf->mcids[0])); in mc_ioctl()
681 mcctrlconf->nmcs = nmcs; in mc_ioctl()
687 mcctrlconf->mcids[i].globalid = mctrl->id; in mc_ioctl()
688 mcctrlconf->mcids[i].localid = mctrl->id; in mc_ioctl()
690 mctrl = mctrl->next; in mc_ioctl()
726 * mcport->ndevgrps zero means Memory Controller is disable. in mc_ioctl()
728 if ((mccontrol_in.ndevgrps < mcport->ndevgrps) || in mc_ioctl()
729 (mcport->ndevgrps == 0)) { in mc_ioctl()
730 mccontrol_in.ndevgrps = mcport->ndevgrps; in mc_ioctl()
735 else if (mcport->ndevgrps != 0) in mc_ioctl()
741 size = sizeof (*mccontrol) + (mcport->ndevgrps - 1) * in mc_ioctl()
742 sizeof (mccontrol->devgrpids[0]); in mc_ioctl()
745 mccontrol->id = mcport->mctrl_node.id; in mc_ioctl()
746 mccontrol->ndevgrps = mcport->ndevgrps; in mc_ioctl()
747 for (i = 0; i < mcport->ndevgrps; i++) { in mc_ioctl()
748 mccontrol->devgrpids[i].globalid = mcport->devgrpids[i]; in mc_ioctl()
749 mccontrol->devgrpids[i].localid = in mc_ioctl()
750 mcport->devgrpids[i] % NDGRPS_PER_MC; in mc_ioctl()
787 * memory segments, at bank-boundries, dimm-pair boundries, in the form
790 * Returns 0 for success and -1 for failure.
802 if ((devi = ddi_find_devinfo("memory", -1, 0)) == NULL) { in mc_get_memory_reg_info()
804 ("mc-us3i: cannot find memory node under root\n")); in mc_get_memory_reg_info()
805 return (-1); in mc_get_memory_reg_info()
811 ("mc-us3i: reg undefined under memory\n")); in mc_get_memory_reg_info()
812 return (-1); in mc_get_memory_reg_info()
825 mregi->base, mregi->size)); in mc_get_memory_reg_info()
849 banki->bank_node.id = bankid; in mc_add_bank()
850 banki->devgrp_id = dgrpid; in mc_add_bank()
851 banki->mask = mask; in mc_add_bank()
852 banki->match = match; in mc_add_bank()
853 banki->base = match; in mc_add_bank()
854 banki->size = size; in mc_add_bank()
860 banki->base, banki->size)); in mc_add_bank()
883 tb = segi->tail; in mc_add_segment()
885 if (banki->base > (tb->base + tb->size)) { in mc_add_segment()
891 segi->nbanks++; in mc_add_segment()
892 tb->next = banki; in mc_add_segment()
894 banki->seg_id = segi->seg_node.id; in mc_add_segment()
895 banki->local_id = tb->local_id + 1; in mc_add_segment()
898 if (banki->base != (tb->base + tb->size)) in mc_add_segment()
899 segi->ifactor++; in mc_add_segment()
901 segi->size += banki->size; in mc_add_segment()
902 segi->tail = banki; in mc_add_segment()
904 memsize += banki->size; in mc_add_segment()
907 "size 0x%lx\n", segi->seg_node.id, banki->bank_node.id, in mc_add_segment()
908 banki->size)); in mc_add_segment()
915 segi->seg_node.id = seg_id; in mc_add_segment()
916 segi->nbanks = 1; in mc_add_segment()
917 segi->ifactor = 1; in mc_add_segment()
918 segi->base = banki->base; in mc_add_segment()
919 segi->size = banki->size; in mc_add_segment()
920 segi->head = banki; in mc_add_segment()
921 segi->tail = banki; in mc_add_segment()
923 banki->seg_id = segi->seg_node.id; in mc_add_segment()
924 banki->local_id = 0; in mc_add_segment()
929 memsize += banki->size; in mc_add_segment()
932 "size 0x%lx\n", segi->seg_node.id, banki->bank_node.id, in mc_add_segment()
933 banki->size)); in mc_add_segment()
938 * bank assignment in interleave of kind internal-external same dimm-pair,
939 * internal-external both dimm-pair. This is done by using the dimm-densities
940 * and part-type.
947 switch (dgrp->base_device) { in get_row_shift()
960 if (dgrp->part_type == PART_TYPE_X4) in get_row_shift()
970 get_device_select(int interleave, struct dgrp_info *dgrp, in get_device_select() argument
974 switch (interleave) { in get_device_select()
980 if (dgrp->nlogbanks == 2) { in get_device_select()
988 if (dgrp->nlogbanks == 2) { in get_device_select()
994 if (dgrp->nlogbanks == 2) { in get_device_select()
1010 uint64_t mask, uint64_t match, int interleave) in mc_add_xor_banks() argument
1015 int ds_shift = -1, bs_shift = -1; in mc_add_xor_banks()
1020 /* xor mode - assume 2 identical dimm-pairs */ in mc_add_xor_banks()
1021 if ((dgrp = mc_node_get(mctrl->devgrpids[0], dgrp_head)) == NULL) { in mc_add_xor_banks()
1025 get_device_select(interleave, dgrp, &ds_shift, &bs_shift); in mc_add_xor_banks()
1027 mask |= (ds_shift == -1 ? 0 : (1ULL << ds_shift)); in mc_add_xor_banks()
1028 mask |= (bs_shift == -1 ? 0 : (1ULL << bs_shift)); in mc_add_xor_banks()
1030 /* xor enable means, bit 21 is used for dimm-pair select */ in mc_add_xor_banks()
1032 if (dgrp->nlogbanks == NLOGBANKS_PER_DGRP) { in mc_add_xor_banks()
1049 size = (dgrp->size * 2)/nbanks; in mc_add_xor_banks()
1051 bankid = mctrl->mctrl_node.id * NLOGBANKS_PER_MC; in mc_add_xor_banks()
1057 xmatch |= (i & (1ULL << j)) << (dselect[j] - j); in mc_add_xor_banks()
1059 /* xor ds bits to get the dimm-pair */ in mc_add_xor_banks()
1064 mctrl->devgrpids[id]); in mc_add_xor_banks()
1071 * Based on interleave, dimm-densities, part-type determine the mask
1077 uint64_t mask, uint64_t match, int interleave) in mc_add_dgrp_banks() argument
1082 int ds_shift = -1, bs_shift = -1; in mc_add_dgrp_banks()
1090 get_device_select(interleave, dgrp, &ds_shift, &bs_shift); in mc_add_dgrp_banks()
1092 mask |= (ds_shift == -1 ? 0 : (1ULL << ds_shift)); in mc_add_dgrp_banks()
1093 mask |= (bs_shift == -1 ? 0 : (1ULL << bs_shift)); in mc_add_dgrp_banks()
1094 match |= (ds_shift == -1 ? 0 : ((dgrpid & 1) << ds_shift)); in mc_add_dgrp_banks()
1096 size = dgrp->size/dgrp->nlogbanks; in mc_add_dgrp_banks()
1099 match |= (bs_shift == -1 ? 0 : ((bankid & 1) << bs_shift)); in mc_add_dgrp_banks()
1100 DPRINTF(MC_CNSTRC_DEBUG, ("mc_add_segments: interleave %d" in mc_add_dgrp_banks()
1102 interleave, mask, bs_shift, match)); in mc_add_dgrp_banks()
1107 if (dgrp->nlogbanks == 2) { in mc_add_dgrp_banks()
1114 match |= (bs_shift == -1 ? 0 : ((bankid & 1) << bs_shift)); in mc_add_dgrp_banks()
1115 DPRINTF(MC_CNSTRC_DEBUG, ("mc_add_segments: interleave %d" in mc_add_dgrp_banks()
1117 interleave, mask, bs_shift, match)); in mc_add_dgrp_banks()
1133 uint64_t mcid, bankid, interleave, mask, match; in mc_logical_layout() local
1135 if (mctrl->ndevgrps == 0) in mc_logical_layout()
1138 mcid = mctrl->mctrl_node.id; in mc_logical_layout()
1142 interleave = (softsp->mcreg1 & MCREG1_INTERLEAVE_MASK) >> in mc_logical_layout()
1146 if (mctrl->ndevgrps == NDGRPS_PER_MC && in mc_logical_layout()
1147 (softsp->mcreg1 & MCREG1_XOR_ENABLE)) { in mc_logical_layout()
1148 mc_add_xor_banks(mctrl, mask, match, interleave); in mc_logical_layout()
1160 for (i = 0; i < mctrl->ndevgrps; i++) { in mc_logical_layout()
1161 bankid += mc_add_dgrp_banks(bankid, mctrl->devgrpids[i], in mc_logical_layout()
1162 mask, match, interleave); in mc_logical_layout()
1167 * Get the dimm-pair's size from the reg_info
1178 end = start + DGRP_SIZE_MAX - 1; in get_devgrp_size()
1183 reg_start = regi->base; in get_devgrp_size()
1184 reg_end = regi->base + regi->size - 1; in get_devgrp_size()
1199 size = regi->size - (start - reg_start); in get_devgrp_size()
1205 size += regi->size; in get_devgrp_size()
1213 * Each device group is a pair (dimm-pair) of identical single/dual dimms.
1214 * Determine the dimm-pair's dimm-densities and part-type using the MCR-I.
1222 struct dimm_info *dimmp = (struct dimm_info *)softsp->memlayoutp; in mc_add_devgrp()
1224 mcid = softsp->portid; in mc_add_devgrp()
1235 dgrp->dgrp_node.id = dgrpid; in mc_add_devgrp()
1239 /* dimm-pair 0, 2, 4, 6 */ in mc_add_devgrp()
1240 if (softsp->mcreg1 & MCREG1_DIMM1_BANK1) in mc_add_devgrp()
1241 dgrp->nlogbanks = 2; in mc_add_devgrp()
1243 dgrp->nlogbanks = 1; in mc_add_devgrp()
1244 dgrp->base_device = (softsp->mcreg1 & MCREG1_ADDRGEN1_MASK) >> in mc_add_devgrp()
1246 dgrp->part_type = (softsp->mcreg1 & MCREG1_X4DIMM1_MASK) >> in mc_add_devgrp()
1249 /* dimm-pair 1, 3, 5, 7 */ in mc_add_devgrp()
1250 if (softsp->mcreg1 & MCREG1_DIMM2_BANK3) in mc_add_devgrp()
1251 dgrp->nlogbanks = 2; in mc_add_devgrp()
1253 dgrp->nlogbanks = 1; in mc_add_devgrp()
1254 dgrp->base_device = (softsp->mcreg1 & MCREG1_ADDRGEN2_MASK) >> in mc_add_devgrp()
1256 dgrp->part_type = (softsp->mcreg1 & MCREG1_X4DIMM2_MASK) >> in mc_add_devgrp()
1260 dgrp->base = MC_BASE(mcid) + DGRP_BASE(dgrpid); in mc_add_devgrp()
1261 dgrp->size = get_devgrp_size(dgrp->base); in mc_add_devgrp()
1264 " base_device %d part_type %d\n", dgrpid, dgrp->size, in mc_add_devgrp()
1265 dgrp->nlogbanks, dgrp->base_device, dgrp->part_type)); in mc_add_devgrp()
1268 dgrp->ndevices = NDIMMS_PER_DGRP; in mc_add_devgrp()
1272 dgrp->deviceids[i] = devid; in mc_add_devgrp()
1282 dev->dev_node.id = devid; in mc_add_devgrp()
1284 dev->size = dgrp->size/2; in mc_add_devgrp()
1287 (void) strncpy(dev->label, (char *)dimmp->label[ in mc_add_devgrp()
1292 dev->dev_node.id, dev->label)); in mc_add_devgrp()
1310 mcid = softsp->portid; in mc_construct()
1313 mcid, softsp->mcreg1)); in mc_construct()
1330 mctrl->mctrl_node.id = mcid; in mc_construct()
1334 if (softsp->mcreg1 & MCREG1_DIMM1_BANK0) { in mc_construct()
1336 mctrl->devgrpids[i] = dgrpid; in mc_construct()
1337 mctrl->ndevgrps++; in mc_construct()
1341 if (softsp->mcreg1 & MCREG1_DIMM2_BANK2) { in mc_construct()
1344 mctrl->devgrpids[i] = dgrpid; in mc_construct()
1345 mctrl->ndevgrps++; in mc_construct()
1350 mctrl->dimminfop = (struct dimm_info *)softsp->memlayoutp; in mc_construct()
1382 nmcs--; in mc_delete()
1416 if ((segi = mc_node_get(banki->seg_id, seg_head)) != NULL) { in mc_delete()
1419 nsegments--; in mc_delete()
1442 DPRINTF(MC_LIST_DEBUG, ("mc_node_add: node->id %d head %p tail %p\n", in mc_node_add()
1443 node->id, (void *) *head, (void *) *tail)); in mc_node_add()
1446 node->prev = *tail; in mc_node_add()
1447 node->next = (*tail)->next; in mc_node_add()
1448 (*tail)->next = node; in mc_node_add()
1451 node->next = node->prev = NULL; in mc_node_add()
1469 if (node->next == NULL) { in mc_node_del()
1471 *tail = node->prev; in mc_node_del()
1473 node->next->prev = node->prev; in mc_node_del()
1476 if (node->prev == NULL) { in mc_node_del()
1478 *head = node->next; in mc_node_del()
1480 node->prev->next = node->next; in mc_node_del()
1497 node->id, id)); in mc_node_get()
1498 if (node->id == id) in mc_node_get()
1500 node = node->next; in mc_node_get()
1508 * to a specific DIMM pin is described by the memory-layout property
1511 * Memory-layout property arranges data/ecc bits in the following order:
1529 * logical bit position assigned above by the memory-layout property.
1562 * Enforce old Openboot requirement for synd code, either a single-bit in mc_get_mem_unum()
1563 * code from 0..QWORD_SIZE-1 or -1 (multi-bit error). in mc_get_mem_unum()
1565 if (qwlayout < -1 || qwlayout >= QWORD_SIZE) in mc_get_mem_unum()
1586 if ((paddr & bank->mask) != bank->match) { in mc_get_mem_unum()
1587 bank = (struct bank_info *)bank->bank_node.next; in mc_get_mem_unum()
1591 mcid = bank->bank_node.id / NLOGBANKS_PER_MC; in mc_get_mem_unum()
1596 "dgrp %d\n", mcid, bank->bank_node.id, bank->devgrp_id)); in mc_get_mem_unum()
1598 mcdgrpid = bank->devgrp_id % NDGRPS_PER_MC; in mc_get_mem_unum()
1601 dimmp = (struct dimm_info *)mctrl->dimminfop; in mc_get_mem_unum()
1609 * single-bit error handling, we can identify specific in mc_get_mem_unum()
1613 pinp = (struct pin_info *)&dimmp->data[0]; in mc_get_mem_unum()
1616 position = 143 - pos_cacheline; in mc_get_mem_unum()
1618 offset = 7 - (position % 8); in mc_get_mem_unum()
1623 * Trade-off: We cound't add pin number to in mc_get_mem_unum()
1627 * pinp->pintable[pos_cacheline]); in mc_get_mem_unum()
1630 "%1u\n", (uint_t)pinp->pintable[pos_cacheline])); in mc_get_mem_unum()
1631 data = pinp->dimmtable[index]; in mc_get_mem_unum()
1635 (char *)dimmp->label[dimmoffset + idx4dimm], in mc_get_mem_unum()
1650 * multi-bit error handling, we can only identify in mc_get_mem_unum()
1657 (char *)dimmp->label[dimmoffset + i]); in mc_get_mem_unum()
1658 res -= strlen(p); in mc_get_mem_unum()
1666 mc_add_mem_unum_label(unum, mcid, mcdgrpid, -1); in mc_get_mem_unum()
1690 if (synd_code < -1 || synd_code >= QWORD_SIZE) in mc_get_mem_info()
1707 if ((paddr & bankp->mask) != bankp->match) { in mc_get_mem_info()
1708 bankp = (struct bank_info *)bankp->bank_node.next; in mc_get_mem_info()
1712 mcid = bankp->bank_node.id / NLOGBANKS_PER_MC; in mc_get_mem_info()
1717 if ((segp = (struct seg_info *)mc_node_get(bankp->seg_id, in mc_get_mem_info()
1724 *seg_sizep = segp->size; in mc_get_mem_info()
1725 *bank_sizep = bankp->size; in mc_get_mem_info()
1727 *banksp = segp->nbanks; in mc_get_mem_info()
1739 * mc-us3i driver allows a platform to add extra label