int intel_scu_ipc_write_umip(u8 *data, int len, int offset) { int ret, offset_align; int len_align = 0; u32 dptr, sptr, cmd; u8 *buf = NULL; /* Cloverview don't need UMIP access through IPC */ if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW) return -EINVAL; if (!intel_mip_base) return -ENODEV; if (offset + len > IPC_MIP_MAX_ADDR) return -EINVAL; intel_scu_ipc_lock(); offset_align = offset & (~0x3); len_align = (len + (offset - offset_align) + 3) & (~0x3); if (len != len_align) { buf = kzalloc(len_align, GFP_KERNEL); if (!buf) { pr_err("Alloc memory failed\n"); ret = -ENOMEM; goto fail; } ret = read_mip(buf, len_align, offset_align, 0); if (ret) goto fail; memcpy(buf + offset - offset_align, data, len); } else { buf = data; } dptr = offset_align; sptr = len_align / 4; cmd = IPC_CMD_UMIP_WR << 12 | IPCMSG_MIP_ACCESS; memcpy(intel_mip_base, buf, len_align); do { ret = intel_scu_ipc_raw_cmd(cmd, 0, NULL, 0, NULL, 0, dptr, sptr); if (ret == -EIO) msleep(20); } while (ret == -EIO); fail: if (buf && len_align != len) kfree(buf); intel_scu_ipc_unlock(); return ret; }
int intel_scu_ipc_read_mip(u8 *data, int len, int offset, int issigned) { int ret; intel_scu_ipc_lock(); ret = read_mip(data, len, offset, issigned); intel_scu_ipc_unlock(); return ret; }
int intel_scu_ipc_read_mip(u8 *data, int len, int offset, int issigned) { int ret; /* Only SMIP read for Cloverview is supported */ if ((intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW) && (issigned != 1)) return -EINVAL; if (!intel_mip_base) return -ENODEV; if (offset + len > IPC_MIP_MAX_ADDR) return -EINVAL; intel_scu_ipc_lock(); ret = read_mip(data, len, offset, issigned); intel_scu_ipc_unlock(); return ret; }
int intel_scu_ipc_write_umip(u8 *data, int len, int offset) { int i, ret = 0, offset_align; int remainder, len_align = 0; u32 dptr, sptr, cmd; u8 cs, tbl_cs = 0, *buf = NULL; Sector sect; struct block_device *bdev; char *buffer = NULL; int *holderId = NULL; int sect_no; u8 checksum; if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW) { /* Opening the mmcblk0boot0 */ bdev = get_emmc_bdev(); if (bdev == NULL) { pr_err("%s: get_emmc failed!\n", __func__); return -ENODEV; } /* make sure the block device is open rw */ ret = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, holderId); if (ret < 0) { pr_err("%s: blk_dev_get failed!\n", __func__); return -ret; } /* get memmap of the UMIP header */ sect_no = offset / SECTOR_SIZE; remainder = offset % SECTOR_SIZE; buffer = read_dev_sector(bdev, sect_no + UMIP_HEADER_HEADROOM_SECTOR, §); /* Shouldn't need to access UMIP sector 0/1 */ if (sect_no < UMIP_TOTAL_HEADER_SECTOR_NO) { pr_err("invalid umip offset\n"); ret = -EINVAL; goto bd_put; } else if (data == NULL || buffer == NULL) { pr_err("buffer is empty\n"); ret = -ENODEV; goto bd_put; } else if (len > (SECTOR_SIZE - remainder)) { pr_err("too much data to write\n"); ret = -EINVAL; goto bd_put; } lock_page(sect.v); memcpy(buffer + remainder, data, len); checksum = calc_checksum(buffer, SECTOR_SIZE); set_page_dirty(sect.v); unlock_page(sect.v); sync_blockdev(bdev); put_dev_sector(sect); /* * Updating the checksum, sector 0 (starting from UMIP * offset 0x08), we maintains 4 bytes for tracking each of * sector changes individually. For example, the dword at * offset 0x08 is used to checksum data integrity of sector * number 2, and so on so forth. It's worthnoting that only * the first byte in each 4 bytes stores checksum. * For detail, please check CTP FAS UMIP header definition */ buffer = read_dev_sector(bdev, UMIP_HEADER_SECTOR + UMIP_HEADER_HEADROOM_SECTOR, §); if (buffer == NULL) { pr_err("buffer is empty\n"); ret = -ENODEV; goto bd_put; } lock_page(sect.v); memcpy(buffer + 4 * (sect_no - UMIP_TOTAL_HEADER_SECTOR_NO) + UMIP_START_CHKSUM_ADDR, &checksum, 1/* one byte */); /* Change UMIP prologue chksum to zero */ *(buffer + UMIP_HEADER_CHKSUM_ADDR) = 0; for (i = 0; i < UMIP_TOTAL_CHKSUM_ENTRY; i++) { tbl_cs ^= *(u8 *)(buffer + 4 * i + UMIP_START_CHKSUM_ADDR); } /* Finish up with re-calcuating UMIP prologue checksum */ cs = dword_to_byte_chksum(xorblock((u32 *)buffer, SECTOR_SIZE)); *(buffer + UMIP_HEADER_CHKSUM_ADDR) = tbl_cs ^ cs; set_page_dirty(sect.v); unlock_page(sect.v); sync_blockdev(bdev); bd_put: if (buffer) put_dev_sector(sect); blkdev_put(bdev, FMODE_READ|FMODE_WRITE); return ret; } else { if (!intel_mip_base) return -ENODEV; if (offset + len > IPC_MIP_MAX_ADDR) return -EINVAL; rpmsg_global_lock(); offset_align = offset & (~0x3); len_align = (len + (offset - offset_align) + 3) & (~0x3); if (len != len_align) { buf = kzalloc(len_align, GFP_KERNEL); if (!buf) { pr_err("Alloc memory failed\n"); ret = -ENOMEM; goto fail; } ret = read_mip(buf, len_align, offset_align, 0); if (ret) goto fail; memcpy(buf + offset - offset_align, data, len); } else { buf = data; } dptr = offset_align; sptr = len_align / 4; cmd = IPC_CMD_UMIP_WR << 12 | IPCMSG_MIP_ACCESS; memcpy(intel_mip_base, buf, len_align); ret = rpmsg_send_raw_command(mip_instance, cmd, 0, NULL, NULL, 0, 0, sptr, dptr); fail: if (buf && len_align != len) kfree(buf); rpmsg_global_unlock(); return ret; } }
int intel_scu_ipc_read_mip(u8 *data, int len, int offset, int issigned) { int ret = 0; Sector sect; struct block_device *bdev; char *buffer = NULL; int *holderId = NULL; int sect_no, remainder; /* Only SMIP read for Cloverview is supported */ if ((intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_CLOVERVIEW) && (issigned != 1)) { /* CTP read UMIP from eMMC */ /* Opening the mmcblk0boot0 */ bdev = get_emmc_bdev(); if (bdev == NULL) { pr_err("%s: get_emmc failed!\n", __func__); return -ENODEV; } /* make sure the block device is open read only */ ret = blkdev_get(bdev, FMODE_READ, holderId); if (ret < 0) { pr_err("%s: blk_dev_get failed!\n", __func__); return -ret; } /* Get sector number of where data located */ sect_no = offset / SECTOR_SIZE; remainder = offset % SECTOR_SIZE; buffer = read_dev_sector(bdev, sect_no + UMIP_HEADER_HEADROOM_SECTOR, §); /* Shouldn't need to access UMIP sector 0/1 */ if (sect_no < UMIP_TOTAL_HEADER_SECTOR_NO) { pr_err("invalid umip offset\n"); ret = -EINVAL; goto bd_put; } else if (data == NULL || buffer == NULL) { pr_err("buffer is empty\n"); ret = -ENODEV; goto bd_put; } else if (len > (SECTOR_SIZE - remainder)) { pr_err("not enough data to read\n"); ret = -EINVAL; goto bd_put; } memcpy(data, buffer + remainder, len); bd_put: if (buffer) put_dev_sector(sect); blkdev_put(bdev, FMODE_READ); return ret; } else { if (!intel_mip_base) return -ENODEV; if (offset + len > IPC_MIP_MAX_ADDR) return -EINVAL; rpmsg_global_lock(); ret = read_mip(data, len, offset, issigned); rpmsg_global_unlock(); return ret; } }