From 0dfe956a1686eb24fd381ecfce2dbb8698d92310 Mon Sep 17 00:00:00 2001 From: lwan89x Date: Fri, 23 Mar 2012 16:13:17 +0800 Subject: [PATCH] intel_scu_ipc.c: Write chksum data when writing osnib data. BZ: 24109 Change-Id: I1c102eed594b4b661fefdf989ff95d4e60488800 Signed-off-by: lwan89x Reviewed-on: http://android.intel.com:8080/40435 Reviewed-by: Puech, Yann Reviewed-by: Romieu, Benoit Tested-by: Romieu, Benoit Reviewed-by: buildbot Tested-by: buildbot --- arch/x86/include/asm/intel_scu_ipcutil.h | 3 +- drivers/platform/x86/intel_scu_ipcutil.c | 92 +++++++++++++++++++++++--------- drivers/watchdog/intel_scu_watchdog.c | 4 +- 3 files changed, 72 insertions(+), 27 deletions(-) diff --git a/arch/x86/include/asm/intel_scu_ipcutil.h b/arch/x86/include/asm/intel_scu_ipcutil.h index 3dc3b19..253e28c 100644 --- a/arch/x86/include/asm/intel_scu_ipcutil.h +++ b/arch/x86/include/asm/intel_scu_ipcutil.h @@ -62,7 +62,8 @@ int intel_scu_ipc_msic_vprog2(int on); int intel_scu_ipc_read_oshob(u8 *data, int len, int offset); /* OSNIB-OS No Init Buffer write */ #define OSNIB_OFFSET 0x0C -int intel_scu_ipc_write_osnib(u8 *data, int len, int offset, u32 mask); +int intel_scu_ipc_write_osnib(u8 *data, int len, int offset); +int intel_scu_ipc_read_osnib(u8 *data, int len, int offset); int intel_scu_ipc_write_osnib_rr(u8 rr); int intel_scu_ipc_read_osnib_rr(u8 *rr); diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c index 9bdc3c6..e696bc8 100644 --- a/drivers/platform/x86/intel_scu_ipcutil.c +++ b/drivers/platform/x86/intel_scu_ipcutil.c @@ -36,18 +36,12 @@ #define MAX_FW_SIZE 264192 #define OSHOB_PMIT_OFFSET 0x0000002c -#define OSNIB_RR_OFFSET OSNIB_OFFSET -#define OSNIB_WD_OFFSET (OSNIB_OFFSET + 1) -#define OSNIB_ALARM_OFFSET (OSNIB_OFFSET + 2) -#define OSNIB_WAKESRC_OFFSET (OSNIB_OFFSET + 3) -#define OSNIB_RESETIRQ1_OFFSET (OSNIB_OFFSET + 4) -#define OSNIB_RESETIRQ2_OFFSET (OSNIB_OFFSET + 5) -#define OSNIB_RR_MASK 0x00000001 -#define OSNIB_WD_MASK 0x00000002 -#define OSNIB_ALARM_MASK 0x00000004 -#define OSNIB_WAKESRC_MASK 0x00000008 -#define OSNIB_RESETIRQ1_MASK 0x00000010 -#define OSNIB_RESETIRQ2_MASK 0x00000020 +#define OSNIB_RR_OFFSET 0 +#define OSNIB_WD_OFFSET 1 +#define OSNIB_ALARM_OFFSET 2 +#define OSNIB_WAKESRC_OFFSET 3 +#define OSNIB_RESETIRQ1_OFFSET 4 +#define OSNIB_RESETIRQ2_OFFSET 5 #define PMIT_RESETIRQ1_OFFSET 14 #define PMIT_RESETIRQ2_OFFSET 15 @@ -264,14 +258,14 @@ static long scu_ipc_ioctl(struct file *fp, unsigned int cmd, pr_err("copy from user failed!!\n"); return ret; } - ret = intel_scu_ipc_read_oshob(&data, 1, OSNIB_ALARM_OFFSET); + ret = intel_scu_ipc_read_osnib(&data, 1, OSNIB_ALARM_OFFSET); if (ret < 0) return ret; if (flag) data = data | 0x1; /* set alarm flag */ else data = data & 0xFE; /* clear alarm flag */ - ret = intel_scu_ipc_write_osnib(&data, 1, 2, OSNIB_ALARM_MASK); + ret = intel_scu_ipc_write_osnib(&data, 1, OSNIB_ALARM_OFFSET); break; } case INTEL_SCU_IPC_READ_VBATTCRIT: @@ -389,12 +383,51 @@ EXPORT_SYMBOL_GPL(intel_scu_ipc_read_oshob); #define IPCMSG_WRITE_OSNIB 0xE4 #define POSNIBW_OFFSET 0x34 -int intel_scu_ipc_write_osnib(u8 *data, int len, int offset, u32 mask) +int intel_scu_ipc_read_osnib(u8 *data, int len, int offset) +{ + int i, ret = 0; + u32 oshob_base; + u8 *ptr; + void __iomem *oshob_addr; + void __iomem *osnibr_addr; + ret = intel_scu_ipc_command(IPCMSG_GET_HOBADDR, + 0, NULL, 0, &oshob_base, 1); + if (ret < 0) { + pr_err("ipc_read_osnib failed!\n"); + goto exit; + } + pr_info("OSHOB addr values is %x\n", oshob_base); + oshob_addr = ioremap_nocache(oshob_base, OSHOB_SIZE); + if (!oshob_addr) { + pr_err("ioremap failed!\n"); + ret = -ENOMEM; + goto exit; + } + osnibr_addr = oshob_addr + OSNIB_OFFSET; + + ptr = data; + for (i = 0; i < len; i++) { + *ptr = readb(osnibr_addr + offset + i); + pr_info("addr=%8x, offset=%2x, value=%2x\n", + (u32)(osnibr_addr+offset+i), offset+i, *ptr); + ptr++; + } + +unmap_oshob_addr: + iounmap(oshob_addr); +exit: + return ret; +} +EXPORT_SYMBOL_GPL(intel_scu_ipc_read_osnib); + +int intel_scu_ipc_write_osnib(u8 *data, int len, int offset) { int i; int ret = 0; u32 posnibw, oshob_base; - void __iomem *oshob_addr, *osnibw_addr; + u8 osnib_data[OSNIB_SIZE]; + u8 chksum = 0; + void __iomem *oshob_addr, *osnibw_addr, *osnibr_addr; ret = intel_scu_ipc_command(IPCMSG_GET_HOBADDR, 0, NULL, 0, &oshob_base, 1); @@ -414,6 +447,18 @@ int intel_scu_ipc_write_osnib(u8 *data, int len, int offset, u32 mask) goto exit; } + /*Dump osnib data for generate chksum */ + osnibr_addr = oshob_addr + OSNIB_OFFSET; + for (i = 0; i < OSNIB_SIZE; i++) + osnib_data[i] = readb(osnibr_addr + i); + + memcpy(osnib_data + offset, data, len); + + /* generate chksum */ + for (i = 0; i < OSNIB_SIZE - 1; i++) + chksum += osnib_data[i]; + osnib_data[OSNIB_SIZE - 1] = ~chksum + 1; + posnibw = readl(oshob_addr + POSNIBW_OFFSET); if (posnibw == 0) { /* workaround here for BZ 2914 */ posnibw = 0xFFFF3400; @@ -429,11 +474,11 @@ int intel_scu_ipc_write_osnib(u8 *data, int len, int offset, u32 mask) goto unmap_oshob_addr; } - for (i = 0; i < len; i++) - writeb(*(data + i), (osnibw_addr + offset + i)); + for (i = 0; i < OSNIB_SIZE; i++) + writeb(*(osnib_data + i), (osnibw_addr + i)); ret = intel_scu_ipc_raw_cmd(IPCMSG_WRITE_OSNIB, 0, NULL, 0, NULL, - 0, 0, mask); + 0, 0, 0xFFFFFFFF); if (ret < 0) pr_err("ipc_write_osnib failed!!\n"); @@ -453,8 +498,7 @@ EXPORT_SYMBOL_GPL(intel_scu_ipc_write_osnib); */ int intel_scu_ipc_write_osnib_rr(u8 rr) { - return intel_scu_ipc_write_osnib(&rr, 1, OSNIB_RR_OFFSET-OSNIB_OFFSET, - OSNIB_RR_MASK); + return intel_scu_ipc_write_osnib(&rr, 1, OSNIB_RR_OFFSET); } EXPORT_SYMBOL_GPL(intel_scu_ipc_write_osnib_rr); @@ -463,7 +507,7 @@ EXPORT_SYMBOL_GPL(intel_scu_ipc_write_osnib_rr); */ int intel_scu_ipc_read_osnib_rr(u8 *rr) { - return intel_scu_ipc_read_oshob(rr, 1, OSNIB_RR_OFFSET); + return intel_scu_ipc_read_osnib(rr, 1, OSNIB_RR_OFFSET); } EXPORT_SYMBOL_GPL(intel_scu_ipc_read_osnib_rr); @@ -483,7 +527,7 @@ static int intel_scu_ipc_read_oshob_it_tree(u32 *ptr) #ifdef DUMP_OSNIB static int intel_scu_ipc_read_osnib_resetirq1(u8 *rirq1) { - return intel_scu_ipc_read_oshob(rirq1, 1, OSNIB_RESETIRQ1_OFFSET); + return intel_scu_ipc_read_osnib(rirq1, 1, OSNIB_RESETIRQ1_OFFSET); } #endif @@ -493,7 +537,7 @@ static int intel_scu_ipc_read_osnib_resetirq1(u8 *rirq1) #ifdef DUMP_OSNIB static int intel_scu_ipc_read_osnib_resetirq2(u8 *rirq2) { - return intel_scu_ipc_read_oshob(rirq2, 1, OSNIB_RESETIRQ2_OFFSET); + return intel_scu_ipc_read_osnib(rirq2, 1, OSNIB_RESETIRQ2_OFFSET); } #endif diff --git a/drivers/watchdog/intel_scu_watchdog.c b/drivers/watchdog/intel_scu_watchdog.c index 32f90ed..655325f 100644 --- a/drivers/watchdog/intel_scu_watchdog.c +++ b/drivers/watchdog/intel_scu_watchdog.c @@ -404,8 +404,8 @@ static int intel_scu_open(struct inode *inode, struct file *file) /* Let shared OSNIB (sram) know we are open */ /* To publish a proc and ioctl to do this and leave userland decide */ /* when it is sensible to do it (boot completed intent) */ - ret = intel_scu_ipc_write_osnib(&osnib_reset, OSNIB_WRITE_SIZE, - OSNIB_WDOG_OFFSET, OSNIB_WRITE_MASK); + ret = intel_scu_ipc_write_osnib(&osnib_reset, + OSNIB_WRITE_SIZE, OSNIB_WDOG_OFFSET); if (ret != 0) { pr_err(PFX "cannot write OSNIB\n"); -- 2.7.4