/* 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; }
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; }
__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); }
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 }
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; }