/* * CPC925 registers are of 32 bits with bit0 defined at the * most significant bit and bit31 at that of least significant.
*/ #define CPC925_BITS_PER_REG 32 #define CPC925_BIT(nr) (1UL << (CPC925_BITS_PER_REG - 1 - nr))
/* * EDAC device names for the error detections of * CPU Interface and Hypertransport Link.
*/ #define CPC925_CPU_ERR_DEV "cpu" #define CPC925_HT_LINK_DEV "htlink"
/* Disable memory controller ECC detection */ staticvoid cpc925_mc_exit(struct mem_ctl_info *mci)
{ /* * WARNING: * We are supposed to clear the ECC error detection bits, * and it will be no problem to do so. However, once they * are cleared here if we want to re-install CPC925 EDAC * module later, setting them up in cpc925_mc_init() will * trigger machine check exception. * Also, it's ok to leave ECC error detection bits enabled, * since they are reset to 1 by default or by boot loader.
*/
return;
}
/* * Revert DDR column/row/bank addresses into page frame number and * offset in page. * * Suppose memory mode is 0x0111(128-bit mode, identical DIMM pairs), * physical address(PA) bits to column address(CA) bits mappings are: * CA 0 1 2 3 4 5 6 7 8 9 10 * PA 59 58 57 56 55 54 53 52 51 50 49 * * physical address(PA) bits to bank address(BA) bits mappings are: * BA 0 1 * PA 43 44 * * physical address(PA) bits to row address(RA) bits mappings are: * RA 0 1 2 3 4 5 6 7 8 9 10 11 12 * PA 36 35 34 48 47 46 45 40 41 42 39 38 37
*/ staticvoid cpc925_mc_get_pfn(struct mem_ctl_info *mci, u32 mear, unsignedlong *pfn, unsignedlong *offset, int *csrow)
{
u32 bcnt, rank, col, bank, row;
u32 c; unsignedlong pa; int i;
/* use cached value if available */ if (mask != 0) return mask;
mask = APIMASK_ADI0 | APIMASK_ADI1;
for_each_of_cpu_node(cpunode) { const u32 *reg = of_get_property(cpunode, "reg", NULL); if (reg == NULL || *reg > 2) {
cpc925_printk(KERN_ERR, "Bad reg value at %pOF\n", cpunode); continue;
}
mask &= ~APIMASK_ADI(*reg);
}
if (mask != (APIMASK_ADI0 | APIMASK_ADI1)) { /* We assume that each CPU sits on it's own PI and that * for present CPUs the reg property equals to the PI
* interface id */
cpc925_printk(KERN_WARNING, "Assuming PI id is equal to CPU MPIC id!\n");
}
/* Disable CPU Errors detection */ staticvoid cpc925_cpu_exit(struct cpc925_dev_info *dev_info)
{ /* * WARNING: * We are supposed to clear the CPU error detection bits, * and it will be no problem to do so. However, once they * are cleared here if we want to re-install CPC925 EDAC * module later, setting them up in cpc925_cpu_init() will * trigger machine check exception. * Also, it's ok to leave CPU error detection bits enabled, * since they are reset to 1 by default.
*/
return;
}
/* Check for CPU Errors */ staticvoid cpc925_cpu_check(struct edac_device_ctl_info *edac_dev)
{ struct cpc925_dev_info *dev_info = edac_dev->pvt_info;
u32 apiexcp;
u32 apimask;
/* APIEXCP is cleared when read */
apiexcp = __raw_readl(dev_info->vbase + REG_APIEXCP_OFFSET); if ((apiexcp & CPU_EXCP_DETECTED) == 0) return;
if ((apiexcp & ~cpc925_cpu_mask_disabled()) == 0) return;
/* Clear by write 1 */ if (brgctrl & BRGCTRL_DETSERR)
__raw_writel(BRGCTRL_DETSERR,
dev_info->vbase + REG_BRGCTRL_OFFSET);
if (linkctrl & HT_LINKCTRL_DETECTED)
__raw_writel(HT_LINKCTRL_DETECTED,
dev_info->vbase + REG_LINKCTRL_OFFSET);
/* Initiate Secondary Bus Reset to clear the chain failure */ if (errctrl & ERRCTRL_CHN_FAL)
__raw_writel(BRGCTRL_SECBUSRESET,
dev_info->vbase + REG_BRGCTRL_OFFSET);
if (errctrl & ERRCTRL_RSP_ERR)
__raw_writel(ERRCTRL_RSP_ERR,
dev_info->vbase + REG_ERRCTRL_OFFSET);
if (linkerr & HT_LINKERR_DETECTED)
__raw_writel(HT_LINKERR_DETECTED,
dev_info->vbase + REG_LINKERR_OFFSET);
/* * Add CPU Err detection and HyperTransport Link Err detection * as common "edac_device", they have no corresponding device * nodes in the Open Firmware DTB and we have to add platform * devices for them. Also, they will share the MMIO with that * of memory controller.
*/ staticvoid cpc925_add_edac_devices(void __iomem *vbase)
{ struct cpc925_dev_info *dev_info;
if (!vbase) {
cpc925_printk(KERN_ERR, "MMIO not established yet\n"); return;
}
for (dev_info = &cpc925_devs[0]; dev_info->init; dev_info++) {
dev_info->vbase = vbase;
dev_info->pdev = platform_device_register_simple(
dev_info->ctl_name, 0, NULL, 0); if (IS_ERR(dev_info->pdev)) {
cpc925_printk(KERN_ERR, "Can't register platform device for %s\n",
dev_info->ctl_name); continue;
}
/* * Don't have to allocate private structure but * make use of cpc925_devs[] instead.
*/
dev_info->edac_idx = edac_device_alloc_index();
dev_info->edac_dev =
edac_device_alloc_ctl_info(0, dev_info->ctl_name,
1, NULL, 0, 0, dev_info->edac_idx); if (!dev_info->edac_dev) {
cpc925_printk(KERN_ERR, "No memory for edac device\n"); goto err1;
}
if (edac_op_state == EDAC_OPSTATE_POLL)
dev_info->edac_dev->edac_check = dev_info->check;
if (dev_info->init)
dev_info->init(dev_info);
if (edac_device_add_device(dev_info->edac_dev) > 0) {
cpc925_printk(KERN_ERR, "Unable to add edac device for %s\n",
dev_info->ctl_name); goto err2;
}
edac_dbg(0, "Successfully added edac device for %s\n",
dev_info->ctl_name);
continue;
err2: if (dev_info->exit)
dev_info->exit(dev_info);
edac_device_free_ctl_info(dev_info->edac_dev);
err1:
platform_device_unregister(dev_info->pdev);
}
}
/* * Delete the common "edac_device" for CPU Err Detection * and HyperTransport Link Err Detection
*/ staticvoid cpc925_del_edac_devices(void)
{ struct cpc925_dev_info *dev_info;
for (dev_info = &cpc925_devs[0]; dev_info->init; dev_info++) { if (dev_info->edac_dev) {
edac_device_del_device(dev_info->edac_dev->dev);
edac_device_free_ctl_info(dev_info->edac_dev);
platform_device_unregister(dev_info->pdev);
}
if (dev_info->exit)
dev_info->exit(dev_info);
edac_dbg(0, "Successfully deleted edac device for %s\n",
dev_info->ctl_name);
}
}
/* Convert current back-ground scrub rate into byte/sec bandwidth */ staticint cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
{ struct cpc925_mc_pdata *pdata = mci->pvt_info; int bw;
u32 mscr;
u8 si;
if (!devres_open_group(&pdev->dev, cpc925_probe, GFP_KERNEL)) {
res = -ENOMEM; goto out;
}
r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) {
cpc925_printk(KERN_ERR, "Unable to get resource\n");
res = -ENOENT; goto err1;
}
if (!devm_request_mem_region(&pdev->dev,
r->start,
resource_size(r),
pdev->name)) {
cpc925_printk(KERN_ERR, "Unable to request mem region\n");
res = -EBUSY; goto err1;
}
vbase = devm_ioremap(&pdev->dev, r->start, resource_size(r)); if (!vbase) {
cpc925_printk(KERN_ERR, "Unable to ioremap device\n");
res = -ENOMEM; goto err2;
}
nr_channels = cpc925_mc_get_channels(vbase) + 1;
layers[0].type = EDAC_MC_LAYER_CHIP_SELECT;
layers[0].size = CPC925_NR_CSROWS;
layers[0].is_virt_csrow = true;
layers[1].type = EDAC_MC_LAYER_CHANNEL;
layers[1].size = nr_channels;
layers[1].is_virt_csrow = false;
mci = edac_mc_alloc(edac_mc_idx, ARRAY_SIZE(layers), layers, sizeof(struct cpc925_mc_pdata)); if (!mci) {
cpc925_printk(KERN_ERR, "No memory for mem_ctl_info\n");
res = -ENOMEM; goto err2;
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Cao Qingtao ");
MODULE_DESCRIPTION("IBM CPC925 Bridge and MC EDAC kernel module");
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.18Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.