int pm_reg_write(uint32_t value, mic_ctx_t *mic_ctx, uint32_t regoffset) { int err = 0; if (mic_ctx->bi_family == FAMILY_ABR) DBOX_WRITE(value, mic_ctx->mmio.va, regoffset); else if (mic_ctx->bi_family == FAMILY_KNC) SBOX_WRITE(value, mic_ctx->mmio.va, regoffset); return err; }
int send_flash_cmd(mic_ctx_t *mic_ctx, MIC_FLASH_CMD_TYPE type, void *data, uint32_t len) { int32_t status = 0; uint8_t *mmio_va = mic_ctx->mmio.va; sbox_scratch1_reg_t scratch1reg = {0}; sbox_scratch2_reg_t scratch2reg = {0}; uint32_t ret = 0; void *src; struct timeval t; struct flash_stat *statbuf = NULL; uint64_t temp; uint32_t i = 0; struct version_struct *verbuf = NULL; int32_t offset = 0; uint8_t cmddata = 0; scratch1reg.bits.status = FLASH_CMD_INVALID; switch (type) { case FLASH_CMD_READ: /* * image address = the upper 20 bits of the 32-bit of scracth2 register * is card side physical address where the flash image resides * program scratch2 register to notify the image address */ scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); /* set command */ scratch1reg.bits.command = FLASH_CMD_READ; SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); mic_send_bootstrap_intr(mic_ctx); break; case FLASH_CMD_READ_DATA: /* * flash read_data command : set pci aperture to 128MB * read the value of scratch2 in a variable */ ret = SBOX_READ(mmio_va, SBOX_SCRATCH2); scratch2reg.value = ret; /* * convert physical to virtual address * image address = the upper 20 bits of the 32-bit KNC side physical * address where the flash image resides */ offset = scratch2reg.bits.image_addr << 12 ; if (len == 0) { status = -EINVAL; goto exit; } if (len > (mic_ctx->aper.len - offset)) { status = -EINVAL; goto exit; } src = mic_ctx->aper.va + offset; temp = copy_to_user(data, src, len); if (temp > 0) { printk("error while copy to user \n"); status = -EFAULT; goto exit; } break; case FLASH_CMD_ABORT: scratch1reg.bits.command = FLASH_CMD_ABORT; SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); mic_send_bootstrap_intr(mic_ctx); break; case FLASH_CMD_VERSION: /* * image address = the upper 20 bits of the 32-bit of scracth2 register * is card side physical address where the flash image resides */ scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); /* * flash version command : similar to read_data command. * Instead of get_user_pages(), use kmalloc() as we are allocating * buffer of lesser size */ scratch1reg.bits.command = FLASH_CMD_VERSION; SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); mic_send_bootstrap_intr(mic_ctx); /* poll for completion */ while(scratch1reg.bits.status != FLASH_CMD_COMPLETED) { ret = SBOX_READ(mmio_va, SBOX_SCRATCH1); scratch1reg.value = ret; msleep(1); i++; printk("Looping for status (time = %d ms)\n", i); if(i > 3000) { status = -ETIME; goto exit; } } src = mic_ctx->aper.va + RASMM_DEFAULT_OFFSET; if (len == 0) { status = -EINVAL; goto exit; } verbuf = kmalloc(len, GFP_KERNEL); if (!verbuf) { status = -ENOMEM; goto exit; } memcpy(verbuf, src, len); printk("header verbuf is : %x\n", verbuf->hdr_ver); printk("odm verbuf is : %x\n", verbuf->odm_ver); printk("uptd time bcd is : %llu\n", verbuf->upd_time_bcd); printk("updated verbuf is : %d\n", *((int*)(&verbuf->upd_ver))); printk("mfg time bcd is : %llu\n", verbuf->mfg_time_bcd); printk("mfg verbuf is : %d\n", *((int*)(&verbuf->mfg_ver))); temp = copy_to_user(data, verbuf, len); if(temp > 0) { printk("error while copy to user \n"); status = -EFAULT; if(verbuf) { kfree(verbuf); } goto exit; } if(verbuf) { kfree(verbuf); } break; case FLASH_CMD_WRITE: /* flash write command : pin user pages for the data buffer which contains * the image. * For the write command, we provide the offset for writing. * GTT is set to 64MB and offset = 0. */ if (len > (mic_ctx->aper.len - RASMM_DEFAULT_OFFSET)) { status = -EINVAL; goto exit; } src = mic_ctx->aper.va + RASMM_DEFAULT_OFFSET; if (len == 0) { status = -EINVAL; goto exit; } temp = copy_from_user(src, data, len); if (temp > 0) { printk("error while copying from user \n"); status = -EFAULT; goto exit; } /* image address = the upper 20 bits of the 32-bit KNC side physical * address where the flash image resides */ scratch2reg.bits.image_addr = RASMM_DEFAULT_OFFSET >> 12; SBOX_WRITE(scratch2reg.value, mmio_va, SBOX_SCRATCH2); scratch1reg.bits.command = FLASH_CMD_WRITE; SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); mic_send_bootstrap_intr(mic_ctx); break; case RAS_CMD_CORE_DISABLE: case RAS_CMD_CORE_ENABLE: if (copy_from_user(&cmddata, data, sizeof(cmddata))) { status = -EFAULT; goto exit; } scratch1reg.bits.cmd_data = cmddata; if (cmddata > MAX_CORE_INDEX) { printk("Parameter given is greater than physical core index\n"); status = -EINVAL; goto exit; } case RAS_CMD: case RAS_CMD_INJECT_REPAIR: case RAS_CMD_ECC_DISABLE: case RAS_CMD_ECC_ENABLE: case RAS_CMD_EXIT: do_gettimeofday(&t); SBOX_WRITE(t.tv_sec, mmio_va, SBOX_SCRATCH3); scratch1reg.bits.command = type; SBOX_WRITE(scratch1reg.value, mmio_va, SBOX_SCRATCH1); mic_send_bootstrap_intr(mic_ctx); break; case FLASH_CMD_STATUS: /* status command : mmio read of SCRATCH1 register * The percentage completion is only updated on the * Flash Write function as currently implemented. * The other functions are expected to complete almost instantly */ if(len != sizeof(struct flash_stat)) { status = -EINVAL; goto exit; } if (len == 0) { status = -EINVAL; goto exit; } statbuf = kmalloc(len, GFP_KERNEL); if(!statbuf) { status = -ENOMEM; goto exit; } temp = SBOX_READ(mmio_va, SBOX_SCRATCH1); scratch1reg.value = (uint32_t)temp; statbuf->status = scratch1reg.bits.status; statbuf->percent = scratch1reg.bits.percent; statbuf->smc_status = scratch1reg.bits.smc_status; statbuf->cmd_data = scratch1reg.bits.cmd_data; statbuf->mm_debug = scratch1reg.bits.mm_debug; temp = copy_to_user(data, statbuf, len); if(temp > 0) { printk("Error copying data to user buffer\n"); status = -EFAULT; if(statbuf) { kfree(statbuf); } goto exit; } if(statbuf) { kfree(statbuf); } break; default: printk(KERN_ERR "Unknown command\n"); status = -EOPNOTSUPP; break; } exit : return status; }