/**
 * notify security component of hdcp and hdmi cable status
 *
 * @hdcp	HDCP status: true if phase1 is enabled
 * @cable	HDMI connection status: true if connected
 *
 * Returns:	none
 */
void ps_hdmi_update_security_hdmi_hdcp_status(bool hdcp, bool cable)
{
#define IA_SCU_CMD      0XE8
#define SCU_CHAABI_CMD  0X85
#define CHAABI_MSG_SIZE 16

	uint8_t  in_buf[CHAABI_MSG_SIZE];
	uint32_t out_buf[CHAABI_MSG_SIZE/sizeof(uint32_t)];

	pr_debug("hdcp: enter %s\n", __func__);

	/* init
	 * do not care about out_buf.
	 */
	memset(in_buf, 0, CHAABI_MSG_SIZE);

	/* chaabi msg use byte 3 for command */
	in_buf[3] = SCU_CHAABI_CMD;

	/* chaabi msg use bits 1:0 of byte 4 for status */
	if (cable)
		in_buf[4] |= 1 << 0;
	if (hdcp)
		in_buf[4] |= 1 << 1;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
	/* no sub-cmd, so set "sub" argument to 0 */
	intel_scu_ipc_command(IA_SCU_CMD, 0, in_buf, sizeof(in_buf),
			out_buf, sizeof(out_buf)/sizeof(uint32_t));
#else
        intel_scu_ipc_command(IA_SCU_CMD, 0, (u32 *)in_buf, sizeof(in_buf),
                        out_buf, sizeof(out_buf)/sizeof(uint32_t));
#endif
	pr_debug("hdcp: leave %s\n", __func__);
	return;
}
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++;
	}

	iounmap(oshob_addr);
exit:
	return ret;
}
Пример #3
0
static void __iomem *get_oshob_addr(void)
{
	int ret;
	u32 oshob_base;
	u16 oshob_size;
	void __iomem *oshob_addr;

	ret = intel_scu_ipc_command(IPCMSG_GET_HOBADDR, 0, NULL,
					0, &oshob_base, 1);

	if (ret < 0) {
		pr_err("ipc_read_oshob address failed!!\n");
		return NULL;
	}

	oshob_size = intel_scu_ipc_get_oshob_size();

	pr_debug("OSHOB addr is 0x%x size is %d\n", oshob_base, oshob_size);

	if (oshob_size == 0) {
		pr_err("size of oshob is null!!\n");
		return NULL;
	}

	oshob_addr = ioremap_nocache(oshob_base, oshob_size);

	if (!oshob_addr) {
		pr_err("ioremap of oshob address failed!!\n");
		return NULL;
	}

	return oshob_addr; /* Return OSHOB base address */
}
static int pmic_scu_ipc_battery_property_get(struct battery_property *prop)
{
	u32 data[3];
	u8 *p = (u8 *)&data[1];
	int err = intel_scu_ipc_command(IPCMSG_BATTERY,
				IPC_CMD_BATTERY_PROPERTY, NULL, 0, data, 3);

	prop->capacity = data[0];
	prop->crnt = *p++;
	prop->volt = *p++;
	prop->prot = *p++;
	prop->prot2 = *p++;
	prop->timer = *p++;

	return err;
}
Пример #5
0
u32 bi_scu_version(void)
{
	int ret = 0;
	u32 fw_version;


	ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0,
			&fw_version, 1);
	if (ret < 0) {
		printk(KERN_ERR "%s[%d] ret=0x%08x ", __FILE__, __LINE__, ret);
		return (u32)ret;
	}

	scu_version = fw_version;

	return scu_version;
}
Пример #6
0
u32 bi_ifw_version(void)
{
	int ret = 0;
	struct scu_ipc_version version;

	version.count = 16;

	ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0, NULL, 0,
				(u32 *)version.data, 4);
	if (ret < 0) {
		printk(KERN_ERR "%s[%d] ret=0x%08x ", __FILE__, __LINE__, ret);
		return (u32)ret;
	}

	ifw_version = version.data[15];
	ifw_version = (ifw_version << 8) + version.data[14];

	return ifw_version;
}
int intel_scu_ipc_osc_clk(u8 clk, unsigned int khz)
{
	/* SCU IPC COMMAND(osc clk on/off) definition:
	 * ipc_wbuf[0] = clock to act on {0, 1, 2, 3}
	 * ipc_wbuf[1] =
	 * bit 0 - 1:on  0:off
	 * bit 1 - if 1, read divider setting from bits 3:2 as follows:
	 * bit [3:2] - 00: clk/1, 01: clk/2, 10: clk/4, 11: reserved
	 */
	unsigned int base_freq;
	unsigned int div;
	u8 ipc_wbuf[16];
	int ipc_ret;

	if (clk > 3)
		return -EINVAL;

	ipc_wbuf[0] = clk;
	ipc_wbuf[1] = 0;
	if (khz) {
#ifdef CONFIG_CTP_CRYSTAL_38M4
		base_freq = 38400;
#else
		base_freq = 19200;
#endif
		div = fls(base_freq / khz) - 1;
		if (div >= 3 || (1 << div) * khz != base_freq)
			return -EINVAL;	/* Allow only exact frequencies */
		ipc_wbuf[1] = 0x03 | (div << 2);
	}

	ipc_ret = intel_scu_ipc_command(IPCMSG_OSC_CLK, 0,
					(u32 *)ipc_wbuf, 2, NULL, 0);
	if (ipc_ret != 0)
		pr_err("%s: failed to set osc clk(%d) output\n", __func__, clk);

	return ipc_ret;
}
Пример #8
0
/*
 * IPC operations
 */
static int watchdog_set_ipc(int soft_threshold, int threshold)
{
	u32	*ipc_wbuf;
	u8	 cbuf[16] = { '\0' };
	int	 ipc_ret = 0;

	ipc_wbuf = (u32 *)&cbuf;
	ipc_wbuf[0] = soft_threshold;
	ipc_wbuf[1] = threshold;

	ipc_ret = intel_scu_ipc_command(
			IPC_SET_WATCHDOG_TIMER,
			0,
			ipc_wbuf,
			2,
			NULL,
			0);

	if (ipc_ret != 0)
		pr_err("Error setting SCU watchdog timer: %x\n", ipc_ret);

	return ipc_ret;
};
Пример #9
0
static void __iomem *get_oshob_addr(void)
{
	int ret;
	u32 oshob_base;
	void __iomem *oshob_addr;

	ret = intel_scu_ipc_command(IPCMSG_GET_HOBADDR, 0, NULL,
					0, &oshob_base, 1);

	if (ret < 0) {
		pr_err("ipc_read_oshob address failed!!\n");
		return NULL;
	}

	pr_debug("OSHOB addr is 0x%x\n", oshob_base);
	oshob_addr = ioremap_nocache(oshob_base, OSHOB_SIZE);

	if (!oshob_addr) {
		pr_err("ioremap of oshob address failed!!\n");
		return NULL;
	}

	return oshob_addr; /* Return OSHOB base address */
}
Пример #10
0
static inline int wdt_command(int sub, u32 *in, int inlen)
{
	return intel_scu_ipc_command(IPC_WATCHDOG, sub, in, inlen, NULL, 0);
}
static int pmic_scu_ipc_battery_cc_read(u32 *value)
{
	return intel_scu_ipc_command(IPCMSG_BATTERY, IPC_CMD_CC_RD,
					NULL, 0, value, 1);
}
int intel_scu_ipc_write_osnib(u8 *data, int len, int offset)
{
	int i;
	int ret = 0;
	u32 posnibw, oshob_base;
	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);
	if (ret < 0) {
		pr_err("ipc_get_hobaddr failed!!\n");
		goto exit;
	}

	pr_info("OSHOB addr values is %x\n", oshob_base);

	intel_scu_ipc_lock();

	oshob_addr = ioremap_nocache(oshob_base, OSHOB_SIZE);
	if (!oshob_addr) {
		pr_err("ioremap failed!\n");
		ret = -ENOMEM;
		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;
		pr_err("ERR: posnibw from oshob is 0, manually set it here\n");
	}

	pr_info("POSNIB: %x\n", posnibw);

	osnibw_addr = ioremap_nocache(posnibw, OSNIB_SIZE);
	if (!osnibw_addr) {
		pr_err("ioremap failed!\n");
		ret = -ENOMEM;
		goto unmap_oshob_addr;
	}

	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, 0xFFFFFFFF);
	if (ret < 0)
		pr_err("ipc_write_osnib failed!!\n");

	iounmap(osnibw_addr);

unmap_oshob_addr:
	iounmap(oshob_addr);
exit:
	intel_scu_ipc_unlock();

	return ret;
}
/**
 *	scu_ipc_ioctl		-	control ioctls for the SCU
 *	@fp: file handle of the SCU device
 *	@cmd: ioctl coce
 *	@arg: pointer to user passed structure
 *
 *	Support the I/O and firmware flashing interfaces of the SCU
 */
static long scu_ipc_ioctl(struct file *fp, unsigned int cmd,
							unsigned long arg)
{
	int ret = -EINVAL;
	struct scu_ipc_data  data;
	void __user *argp = (void __user *)arg;
	int platform;

	/* Only IOCTL cmd allowed to pass through without capability check */
	/* is getting fw version info, all others need to check to prevent */
	/* arbitrary access to all sort of bit of the hardware exposed here*/

	if (cmd != INTEL_SCU_IPC_FW_REVISION_GET && !capable(CAP_SYS_RAWIO))
		return -EPERM;

	platform = intel_mid_identify_cpu();
	switch (cmd) {
	case INTEL_SCU_IPC_READ_FBMODE_FROM_OSNIB:
	{
		u8 fb_mode;
		ret = intel_scu_ipc_read_osnib_fb_mode(&fb_mode);
		if (ret < 0) {
			pr_err("read fb_mode from ipc failed!!\n");
			return ret;
		}
		ret = copy_to_user(argp, &fb_mode, 1);
		break;
	}
	case INTEL_SCU_IPC_WRITE_FBMODE_TO_OSNIB:
	{
		u8 fb_mode;

		ret = copy_from_user(&fb_mode, (u8 *)arg, 1);
		if (ret < 0) {
			pr_err("copy fb_mode from user failed!!\n");
			return ret;
		}
		ret = intel_scu_ipc_write_osnib_fb_mode(fb_mode);
		break;
	}
	case INTEL_SCU_IPC_READ_BOS_FROM_OSNIB:
	{
		u8 resync_reason;
		ret = intel_scu_ipc_read_osnib_bos(&resync_reason);
		if (ret < 0)
			return ret;
		ret = copy_to_user(argp, &resync_reason, 1);
		break;
	}
	case INTEL_SCU_IPC_WRITE_BOS_TO_OSNIB:
	{
		u8 data;

		ret = copy_from_user(&data, (u8 *)arg, 1);
		if (ret < 0) {
			pr_err("copy from user failed!!\n");
			return ret;
		}
		ret = intel_scu_ipc_write_osnib_bos(data);
		break;
	}
	case INTEL_SCU_IPC_READ_RR_FROM_OSNIB:
	{
		u8 reboot_reason;
		ret = intel_scu_ipc_read_osnib_rr(&reboot_reason);
		if (ret < 0)
			return ret;
		ret = copy_to_user(argp, &reboot_reason, 1);
		break;
	}
	case INTEL_SCU_IPC_WRITE_RR_TO_OSNIB:
	{
		u8 data;

		ret = copy_from_user(&data, (u8 *)arg, 1);
		if (ret < 0) {
			pr_err("copy from user failed!!\n");
			return ret;
		}
		ret = intel_scu_ipc_write_osnib_rr(data);
		break;
	}
	case INTEL_SCU_IPC_WRITE_ALARM_FLAG_TO_OSNIB:
	{
		u8 flag, data;
		ret = copy_from_user(&flag, (u8 *)arg, 1);
		if (ret < 0) {
			pr_err("copy from user failed!!\n");
			return ret;
		}
		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, OSNIB_ALARM_OFFSET);
		break;
	}
	case INTEL_SCU_IPC_READ_VBATTCRIT:
	{
		u32 value;

		pr_debug("cmd = INTEL_SCU_IPC_READ_VBATTCRIT");
		ret = intel_scu_ipc_read_mip((u8 *)&value, 4, 0x318, 1);
		if (ret < 0)
			return ret;
		pr_debug("VBATTCRIT VALUE = %x\n", value);
		ret = copy_to_user(argp, &value, 4);
		break;
	}
	case INTEL_SCU_IPC_FW_REVISION_GET:
	{
		struct scu_ipc_version version;

		if (copy_from_user(&version, argp, sizeof(u32)))
			return -EFAULT;

		if (version.count > 16)
			return -EINVAL;

		ret = intel_scu_ipc_command(IPCMSG_FW_REVISION, 0,
					NULL, 0, (u32 *)version.data, 4);
		if (ret < 0)
			return ret;

		if (copy_to_user(argp + sizeof(u32),
					version.data, version.count))
			ret = -EFAULT;
		break;
	}
	case INTEL_SCU_IPC_OSC_CLK_CNTL:
	{
		struct osc_clk_t osc_clk;

		if (copy_from_user(&osc_clk, argp, sizeof(struct osc_clk_t)))
			return -EFAULT;

		ret = intel_scu_ipc_osc_clk(osc_clk.id, osc_clk.khz);
		if (ret)
			pr_err("%s: failed to set osc clk\n", __func__);

		break;
	}
	case INTEL_SCU_IPC_READ_BYTE_IN_OSNIB:
	{
		struct osnib_data read_data;

		ret = copy_from_user(&read_data, (u8 *)arg,
					sizeof(struct scu_ipc_data));
		if (ret < 0) {
			pr_err("copy from user failed!!\n");
			return ret;
		}
		if ((read_data.offset-OSNIB_OFFSET) >= 32)
			return -EINVAL;
		ret = intel_scu_ipc_read_osnib_byte(read_data.offset,
							&read_data.data);
		if (ret < 0)
			return ret;
		ret = copy_to_user(argp, &read_data,
					sizeof(struct scu_ipc_data));
		break;
	}
	case INTEL_SCU_IPC_WRITE_BYTE_IN_OSNIB:
	{
		struct osnib_data write_data;

		ret = copy_from_user(&write_data, (u8 *)arg,
					sizeof(struct scu_ipc_data));
		if (ret < 0) {
			pr_err("copy from user failed!!\n");
			return ret;
		}
		if ((write_data.offset-OSNIB_OFFSET) >= 32)
			return -EINVAL;
		ret = intel_scu_ipc_write_osnib_byte(write_data.offset,
							write_data.data);
		if (ret < 0)
			return ret;
		break;
	}
	default:
		if (copy_from_user(&data, argp, sizeof(struct scu_ipc_data)))
			return -EFAULT;
		ret = scu_reg_access(cmd, &data);
		if (ret < 0)
			return ret;
		if (copy_to_user(argp, &data, sizeof(struct scu_ipc_data)))
			return -EFAULT;
		return 0;
	}

	return ret;
}