Example #1
0
/* brief
 * arg0: command type as TEE_SMC_PLAFORM_OPERATION
 * arg1: set standby status mode.(clear or get or set)
 * arg2: standby reg physical address.
 * arg3: value to set when set.
 */
static u32 sunxi_sec_set_standby_status(u32 command_type, u32 setting_type, u32 addr, u32 val)
{
	u32 ret_val = 0;
	u32 phys_addr;

	phys_addr = (u32)addr > (u32)IO_ADDRESS(0) ? ((u32)addr - (u32)IO_ADDRESS(0)) : (u32)addr;
	switch(setting_type){
		case TE_SMC_STANDBY_STATUS_CLEAR:
			ret_val = sunxi_do_smc(TEE_SMC_PLAFORM_OPERATION, TE_SMC_READ_REG, phys_addr, 0);
			if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
				ret_val = sunxi_do_smc(TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_CLEAR, phys_addr, ret_val);
				hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
			}
			break;
		case TE_SMC_STANDBY_STATUS_SET:
			if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
				ret_val = sunxi_do_smc(TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_SET, phys_addr, val);
				hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
			}
			asm volatile ("dsb");
			asm volatile ("isb");

			break;
		case TE_SMC_STANDBY_STATUS_GET:
			if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
				ret_val = sunxi_do_smc(TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_GET, phys_addr, val);
				hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
			}
			break;
		default:
			break;
	}

	return ret_val;
}
Example #2
0
void show_pm_secure_mem_status(void)
{
	int i = 1;
	int val = 0;
	
#ifndef CONFIG_SUNXI_TRUSTZONE
	while(i < STANDBY_STATUS_REG_NUM) {
		pm_secure_status_reg_tmp.bits.reg_sel = i;
		if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
			(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
			pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval;
			hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
		}
		val = pm_secure_status_reg_tmp.bits.data_rd;
		printk("addr %x, value = %x. \n", (i), val);
		i++;
	}
#else
	while(i < STANDBY_STATUS_REG_NUM){
		val = call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_GET, (u32)pm_secure_status_reg, i);
		printk("addr %x, value = %x. \n", (i), val);
		i++;
	}
#endif

}
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
	unsigned long flags;
	unsigned char gpiodir;

	if (offset >= gc->ngpio)
		return -EINVAL;

	spin_lock_irqsave(&chip->lock, flags);

	if (hwspin_lock_timeout(gpio_hwlock, LOCK_TIMEOUT)) {
		pr_err("%s: hwspinlock timeout!\n", __func__);
		spin_unlock_irqrestore(&chip->lock, flags);
		return -EBUSY;
	}

	gpiodir = readb(chip->base + GPIODIR);
	gpiodir &= ~(1 << offset);
	writeb(gpiodir, chip->base + GPIODIR);

	hwspin_unlock(gpio_hwlock);
	spin_unlock_irqrestore(&chip->lock, flags);

	return 0;
}
static int pl061_direction_output(struct gpio_chip *gc, unsigned offset,
		int value)
{
	struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
	unsigned long flags;
	unsigned char gpiodir;

	if (offset >= gc->ngpio)
		return -EINVAL;

	spin_lock_irqsave(&chip->lock, flags);

	if (hwspin_lock_timeout(gpio_hwlock, LOCK_TIMEOUT)) {
		pr_err("%s: hwspinlock timeout!\n", __func__);
		spin_unlock_irqrestore(&chip->lock, flags);
		return -EBUSY;
	}

	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
	gpiodir = readb(chip->base + GPIODIR);
	gpiodir |= 1 << offset;
	writeb(gpiodir, chip->base + GPIODIR);

	/*
	 * gpio value is set again, because pl061 doesn't allow to set value of
	 * a gpio pin before configuring it in OUT mode.
	 */
	writeb(!!value << offset, chip->base + (1 << (offset + 2)));
	hwspin_unlock(gpio_hwlock);
	spin_unlock_irqrestore(&chip->lock, flags);

	return 0;
}
/*hwspin_trylock()
* Returns 0 if we successfully locked the hwspinlock, -EBUSY if
* the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
* hwspin_lock_timeout()
* Returns 0 when the @hwlock was successfully taken, and an appropriate
* error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
* busy after @timeout msecs). The function will never sleep.
*/
static int debugfs_hwspinlock_trylock_timeout(int id, int timeout, int unlock)
{
	struct hwspinlock_hisi *hwlockinfo, *hwunlockinfo;
	int ret = 0;
	int val0, val1 = 0;

	if (0 == timeout)
		ret = hwspin_trylock(hwlock);
	else if (timeout > 0) {
		ret = hwspin_lock_timeout(hwlock, timeout);
		if (ret) {
			pr_err("%s: hwspinlock timeout!\n", __func__);
			goto _timout;
		}
	}
	hwlockinfo = (struct hwspinlock_hisi *)(hwlock->priv);
	val0 = readl(hwlockinfo->address + RESOURCE_LOCK_STAT_OFFSET);
	locked = 1;
	if (unlock) {
		hwspin_unlock(hwlock);
		hwunlockinfo = (struct hwspinlock_hisi *)(hwlock->priv);
		val1 = readl(hwunlockinfo->address + RESOURCE_LOCK_STAT_OFFSET);
		locked = 0;
	} else
		val1 = readl(hwlockinfo->address + RESOURCE_LOCK_STAT_OFFSET);
	pr_info("[debug]the ResourceLock %d locked val= 0x%x,unlock val=0x%x\n", id, val0, val1);

_timout:
	return ret;
}
static void sci_glb_unlock(unsigned long *flags, unsigned long *hw_flags)
{
	if (arch_get_hwlock(HWLOCK_GLB))
		hwspin_unlock(arch_get_hwlock(HWLOCK_GLB));
	else
		arch_hwunlock_fast(HWLOCK_GLB);
	hw_local_irq_restore(*hw_flags);
	spin_unlock_irqrestore(&glb_lock, *flags);
}
static int pl061_irq_type(struct irq_data *d, unsigned trigger)
{
	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
	int offset = irqd_to_hwirq(d);
	unsigned long flags;
	u8 gpiois, gpioibe, gpioiev;

	if (offset < 0 || offset >= PL061_GPIO_NR)
		return -EINVAL;

	spin_lock_irqsave(&chip->lock, flags);

	if (hwspin_lock_timeout(gpio_hwlock, LOCK_TIMEOUT)) {
		pr_err("%s: hwspinlock timeout!\n", __func__);
		spin_unlock_irqrestore(&chip->lock, flags);
		return -EBUSY;
	}

	gpioiev = readb(chip->base + GPIOIEV);

	gpiois = readb(chip->base + GPIOIS);
	if (trigger & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
		gpiois |= 1 << offset;
		if (trigger & IRQ_TYPE_LEVEL_HIGH)
			gpioiev |= 1 << offset;
		else
			gpioiev &= ~(1 << offset);
	} else
		gpiois &= ~(1 << offset);
	writeb(gpiois, chip->base + GPIOIS);

	gpioibe = readb(chip->base + GPIOIBE);
	if ((trigger & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
		gpioibe |= 1 << offset;
	else {
		gpioibe &= ~(1 << offset);
		if (trigger & IRQ_TYPE_EDGE_RISING)
			gpioiev |= 1 << offset;
		else if (trigger & IRQ_TYPE_EDGE_FALLING)
			gpioiev &= ~(1 << offset);
	}
	writeb(gpioibe, chip->base + GPIOIBE);

	writeb(gpioiev, chip->base + GPIOIEV);

	hwspin_unlock(gpio_hwlock);
	spin_unlock_irqrestore(&chip->lock, flags);

	return 0;
}
Example #8
0
__u32 get_pm_secure_mem_status(void)
{
	int val = 0;

#ifndef CONFIG_SUNXI_TRUSTZONE
	pm_secure_status_reg_tmp.bits.reg_sel = 1;
	if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
		(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
		pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval;
		hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
	}

	val = pm_secure_status_reg_tmp.bits.data_rd;
	return (val);
#else
	val = call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_GET, (u32)pm_secure_status_reg, 1);
	return (val);
#endif
}
static void pl061_irq_unmask(struct irq_data *d)
{
	struct pl061_gpio *chip = irq_data_get_irq_chip_data(d);
	u8 mask = 1 << (irqd_to_hwirq(d) % PL061_GPIO_NR);
	u8 gpioie;
	unsigned long flags;

	spin_lock_irqsave(&chip->lock, flags);

	if (hwspin_lock_timeout(gpio_hwlock, LOCK_TIMEOUT)) {
		pr_err("%s: hwspinlock timeout!\n!", __func__);
		spin_unlock_irqrestore(&chip->lock, flags);
		return ;
	}

	gpioie = readb(chip->base + GPIOIE) | mask;
	writeb(gpioie, chip->base + GPIOIE);

	hwspin_unlock(gpio_hwlock);
	spin_unlock_irqrestore(&chip->lock, flags);
}
Example #10
0
void save_pm_secure_mem_status(volatile __u32 val)
{
#ifndef CONFIG_SUNXI_TRUSTZONE
	if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
		pm_secure_status_reg_tmp.bits.reg_sel = 1;
		pm_secure_status_reg_tmp.bits.data_wr = val;
		(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
		pm_secure_status_reg_tmp.bits.wr_pulse = 0;
		(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
		pm_secure_status_reg_tmp.bits.wr_pulse = 1;
		(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
		pm_secure_status_reg_tmp.bits.wr_pulse = 0;
		(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
		hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
	}
	asm volatile ("dsb");
	asm volatile ("isb");
	return;
#else
	call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_SET, (u32)pm_secure_status_reg, val);
	return;
#endif
}
Example #11
0
void pm_secure_mem_status_clear(void)
{
#ifndef CONFIG_SUNXI_TRUSTZONE
	int i = 1;
	pm_secure_status_reg_tmp.dwval = (*pm_secure_status_reg).dwval;
	if (!hwspin_lock_timeout(MEM_RTC_REG_HWSPINLOCK, 20000)) {
		while(i < STANDBY_STATUS_REG_NUM){
			pm_secure_status_reg_tmp.bits.reg_sel = i;
			pm_secure_status_reg_tmp.bits.data_wr = 0;
			(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
			pm_secure_status_reg_tmp.bits.wr_pulse = 0;
			(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
			pm_secure_status_reg_tmp.bits.wr_pulse = 1;
			(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
			pm_secure_status_reg_tmp.bits.wr_pulse = 0;
			(*pm_secure_status_reg).dwval = pm_secure_status_reg_tmp.dwval;
			i++;
	    	}
		hwspin_unlock(MEM_RTC_REG_HWSPINLOCK);
	}
#else
	call_firmware_op(set_standby_status,TEE_SMC_PLAFORM_OPERATION, TE_SMC_STANDBY_STATUS_CLEAR, (u32)pm_secure_status_reg, 0);
#endif
}
static ssize_t
debugfs_write(struct file *filp, const char __user *ubuf, size_t cnt, loff_t *ppos)
{
	struct hwspinlock *__hwlock;
	char buf[128];
	char *cmd = NULL;
	char *_cmd = NULL;
	int id;
	int timeout;
	int unlock;
	int ret ;

	if (NULL == ubuf || 0 == cnt){
		pr_err("buf is null !\n");
		return (-EINVAL);
	}
	if(cnt > sizeof(buf))
	{
		pr_err("input count larger! \n");
		return (-ENOMEM);
	}

	if (copy_from_user(buf, ubuf, cnt - 1)) {
		pr_err("[Hwspinlock Debugfs] can not copy from user\n");
		cnt = -EINVAL;
		goto out;
	}

	buf[cnt - 1] = '\0';
	cmd = buf;
	_cmd = buf;
	pr_debug("[Hwspinlock Debugfs] [cmd: %s[cnt: %d]]\n", cmd, (int)cnt);

	if (!strncmp("request ", _cmd, strlen("request "))) {
		cmd = cmd + strlen("request ");
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;
		*_cmd = '\0';

		if (kstrtos32(cmd, 10, &id)) {
			pr_err("Hwspinlock Debugfs cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

		hwlock = hwspin_lock_request_specific(id);
		if (!hwlock)
			pr_err("hwspinlock %u is already in use\n", id);
		else
			pr_info("[debug] Request hwspinlock %d sucess!",id);
	} else if (!strncmp("free_lock ", _cmd, strlen("free_lock "))) {
		cmd = cmd + strlen("free_lock ");
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;
		*_cmd = '\0';
		if (kstrtos32(cmd, 10, &id)) {
			pr_err("Hwspinlock Debugfs cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

		if (!hwlock){
			__hwlock = hwspin_lock_lookup(id);
			if (__hwlock){
				debugfs_hwspinlock_lock_free(__hwlock);
				__hwlock = NULL;
			}else{
				pr_err("Current haven't requested the hwspinlock %d\n",id);
				goto out;
			}
		}else if (hwlock_to_id(hwlock) == id){
			debugfs_hwspinlock_lock_free(hwlock);
			hwlock = NULL;
		}else
			pr_err("[debug] please freelock the correct lock!\n");
	} else if (!strncmp("trylock ", _cmd, strlen("trylock "))) {
		cmd = cmd + strlen("trylock ");
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;

		if ('\0' == *_cmd) {
			pr_err("[debug] cmd error\n");
			cnt = -EINVAL;
			goto out;
		}
		*_cmd = '\0';

		if (kstrtos32(cmd, 10, &id)) {
			pr_err("[debug] cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

		cmd = _cmd + 1;
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;
		*_cmd = '\0';
		if (kstrtos32(cmd, 10, &timeout)) {
			pr_err("[debug] cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

		cmd = _cmd + 1;
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;
		*_cmd = '\0';

		if (kstrtos32(cmd, 10, &unlock)) {
			pr_err("[debug] cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

		if (!hwlock){
			pr_err("Current haven't requested the hwspinlock %d\n",id);
			goto out;
		}else if (hwlock_to_id(hwlock) == id && timeout >= 0){
			ret =debugfs_hwspinlock_trylock_timeout(id, timeout, unlock);
			if (!ret){
				if (0 == timeout)
					pr_info("[debug] hwspin_trylock %d sucess!\n",id);
				else
					pr_info("[debug] hwspin_trylock_timout %d sucess!\n",id);
			}
		}else if(timeout < 0)
			pr_err("[debug] cmd err! timeout must > 0\n");
		else
			pr_err("[debug] please trylock the correct lock!\n");
	}else if (!strncmp("unlock ", _cmd, strlen("unlock "))) {
		cmd = cmd + strlen("unlock ");
		_cmd = cmd;
		while ((' ' != *_cmd) && ('\0' != *_cmd))
			_cmd++;
		*_cmd = '\0';
		if (kstrtos32(cmd, 10, &id)) {
			pr_err("Hwspinlock Debugfs cmd error\n");
			cnt = -EINVAL;
			goto out;
		}

                if (!hwlock){
			pr_err("Current don't echo request the hwspinlock %d\n",id);
			goto out;
		}else if(hwlock_to_id(hwlock) == id && locked == 1){
			hwspin_unlock(hwlock);
			pr_info("[debug] hwspin_unlock id=%d sucess!\n",id);
		}else
			pr_err("[debug] please free the correct request lock!\n");
	} else {
		pr_err("Hwspinlock Debugfs cmd error\n");
		cnt = -EINVAL;
	}
out:
	return cnt;
}