/* 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_lock(unsigned long *flags, unsigned long *hw_flags) { spin_lock_irqsave(&glb_lock, *flags); *hw_flags = hw_local_irq_save(); if (arch_get_hwlock(HWLOCK_GLB)) WARN_ON(IS_ERR_VALUE(hwspin_lock_timeout(arch_get_hwlock(HWLOCK_GLB), -1))); else arch_hwlock_fast(HWLOCK_GLB); }
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 }