static int sprd_rtc_set_aux_alarm_sec(unsigned long secs) { unsigned sec, min, hour, day; unsigned long temp; sec = secs % 60; temp = (secs - sec)/60; min = temp%60; temp = (temp - min)/60; hour = temp%24; temp = (temp - hour)/24; day = temp; sci_adi_set(ANA_RTC_INT_CLR, RTC_AUXALM_BIT); sci_adi_raw_write(ANA_RTC_AUX_SEC_ALM, sec); sci_adi_raw_write(ANA_RTC_AUX_MIN_ALM, min); sci_adi_raw_write(ANA_RTC_AUX_HOUR_ALM, hour); sci_adi_raw_write(ANA_RTC_AUX_DAY_ALM, day); return 0; }
static int sprd_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { unsigned long secs; unsigned temp; sci_adi_raw_write(ANA_RTC_INT_CLR, RTC_ALARM_BIT); if(alrm->enabled){ rtc_tm_to_time(&alrm->time, &secs); if(secs < secs_start_year_to_1970) return -1; temp = sci_adi_read(ANA_RTC_INT_EN); temp |= RTC_ALARM_BIT; sci_adi_raw_write(ANA_RTC_INT_EN, temp); secs = secs - secs_start_year_to_1970; wake_lock(&rtc_wake_lock); sprd_rtc_set_alarm_sec(secs); sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_UNLOCK); wake_unlock(&rtc_wake_lock); }else{ sci_adi_clr(ANA_RTC_INT_EN, RTC_ALARM_BIT); sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_LOCK); msleep(150); } return 0; }
static u32 adie_efuse_read(int blk_index) { u32 val = 0; pr_debug("adie efuse read %d\n", blk_index); adie_efuse_lock(); __adie_efuse_power_on(); /* enable adie_efuse module clk and power before */ /* FIXME: set read timing, why 0x20 (default value) sci_adi_raw_write(ANA_REG_EFUSE_RD_TIMING_CTRL, BITS_EFUSE_RD_TIMING(0x20)); */ sci_adi_raw_write(ANA_REG_EFUSE_BLOCK_INDEX, BITS_READ_WRITE_INDEX(blk_index)); sci_adi_raw_write(ANA_REG_EFUSE_MODE_CTRL, BIT_RD_START); if (IS_ERR_VALUE(__adie_efuse_wait_clear(BIT_READ_BUSY))) goto out; val = sci_adi_read(ANA_REG_EFUSE_DATA_RD); /* FIXME: reverse the otp value */ val = BITS_EFUSE_DATA_RD(~val); out: __adie_efuse_power_off(); adie_efuse_unlock(); return val; }
/* use ana watchdog to wake up */ void pm_debug_set_apwdt(void) { uint32_t cnt = 0; uint32_t ms = 5000; cnt = (ms * WDG_CLK) / 1000; sci_glb_set(INT_IRQ_ENB, BIT(11)); /*enable interface clk*/ sci_adi_set(ANA_AGEN, AGEN_WDG_EN); /*enable work clk*/ sci_adi_set(ANA_RTC_CLK_EN, AGEN_RTC_WDG_EN); sci_adi_raw_write(WDG_LOCK, WDG_UNLOCK_KEY); sci_adi_set(WDG_CTRL, WDG_NEW_VER_EN); WDG_LOAD_TIMER_VALUE(0x80000); WDG_LOAD_TIMER_INT_VALUE(0x40000); sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_INT_EN_BIT| WDG_RST_EN_BIT); sci_adi_raw_write(WDG_LOCK, (uint16_t) (~WDG_UNLOCK_KEY)); sci_adi_set(ANA_REG_INT_EN, BIT(3)); #if 0 do{ udelay(1000); printk("INTC1 mask:0x%08x raw:0x%08x en:0x%08x\n", __raw_readl(INTCV1_IRQ_MSKSTS),__raw_readl(INTCV1_IRQ_RAW), __raw_readl(INTCV1_IRQ_EN)); printk("INT mask:0x%08x raw:0x%08x en:0x%08x ana 0x%08x\n", __raw_readl(INT_IRQ_STS),__raw_readl(INT_IRQ_RAW), __raw_readl(INT_IRQ_ENB), sci_adi_read(ANA_REG_INT_MASK_STATUS)); printk("ANA mask:0x%08x raw:0x%08x en:0x%08x\n", sci_adi_read(ANA_REG_INT_MASK_STATUS), sci_adi_read(ANA_REG_INT_RAW_STATUS), sci_adi_read(ANA_REG_INT_EN)); printk("wdg cnt low 0x%08x high 0x%08x\n", sci_adi_read(WDG_CNT_LOW), sci_adi_read(WDG_CNT_HIGH)); }while(0); #endif }
static int sprd_rtc_set_sec(unsigned long secs) { unsigned sec, min, hour, day; unsigned set_mask = 0, int_rsts; unsigned long temp; int i = 0; sec = secs % 60; temp = (secs - sec)/60; min = temp%60; temp = (temp - min)/60; hour = temp%24; temp = (temp - hour)/24; day = temp; sci_adi_set(ANA_RTC_INT_CLR, RTC_UPD_TIME_MASK); if(sec != get_sec()){ sci_adi_raw_write(ANA_RTC_SEC_UPDATE, sec); set_mask |= RTC_SEC_ACK_BIT; } if(min != get_min()){ sci_adi_raw_write(ANA_RTC_MIN_UPDATE, min); set_mask |= RTC_MIN_ACK_BIT; } if(hour != get_hour()){ sci_adi_raw_write(ANA_RTC_HOUR_UPDATE, hour); set_mask |= RTC_HOUR_ACK_BIT; } if(day != get_day()){ sci_adi_raw_write(ANA_RTC_DAY_UPDATE, day); set_mask |= RTC_DAY_ACK_BIT; } /* * wait till all update done */ do{ int_rsts = sci_adi_read(ANA_RTC_INT_RSTS) & RTC_UPD_TIME_MASK; if(set_mask == int_rsts) break; if(i < SPRD_RTC_SET_MAX){ msleep(1); i++; }else{ return 1; } }while(1); sci_adi_set(ANA_RTC_INT_CLR, RTC_UPD_TIME_MASK); return 0; }
static void sc8825_power_off(void) { /*ture off all modules ldo*/ sci_adi_raw_write(ANA_REG_GLB_LDO_PD_CTRL1, 0x5555); sci_adi_raw_write(ANA_REG_GLB_LDO_PD_CTRL0, 0x5555); /*ture off all system cores ldo*/ sci_adi_clr(ANA_REG_GLB_LDO_PD_RST, 0x3ff); sci_adi_set(ANA_REG_GLB_LDO_PD_SET, 0x3ff); }
static int sprd_rtc_set_alarm_sec(unsigned long secs) { unsigned sec, min, hour, day; unsigned long temp; unsigned set_mask = 0, int_rsts; int i = 0; sec = secs % 60; temp = (secs - sec)/60; min = temp%60; temp = (temp - min)/60; hour = temp%24; temp = (temp - hour)/24; day = temp; sci_adi_set(ANA_RTC_INT_CLR, RTC_ALM_TIME_MASK); sci_adi_raw_write(ANA_RTC_SEC_ALM, sec); set_mask |= RTC_SEC_ALM_ACK_BIT; sci_adi_raw_write(ANA_RTC_MIN_ALM, min); set_mask |= RTC_MIN_ALM_ACK_BIT; sci_adi_raw_write(ANA_RTC_HOUR_ALM, hour); set_mask |= RTC_HOUR_ALM_ACK_BIT; sci_adi_raw_write(ANA_RTC_DAY_ALM, day); set_mask |= RTC_DAY_ALM_ACK_BIT; /* * wait till all update done */ do{ int_rsts = sci_adi_read(ANA_RTC_INT_RSTS) & RTC_ALM_TIME_MASK; if(set_mask == int_rsts) break; if(i < SPRD_RTC_SET_MAX){ msleep(1); i++; }else{ return 1; } }while(1); sci_adi_set(ANA_RTC_INT_CLR, RTC_ALM_TIME_MASK); #if defined(CONFIG_RTC_CHN_ALARM_BOOT) sprd_rtc_set_bit_spg_counter(SPG_CNT_ALARM_BOOT, 0); #endif return 0; }
static int sprd_rtc_open(struct device *dev) { int temp = 0; /* enable rtc interrupt */ temp = sci_adi_read(ANA_RTC_INT_EN); temp |= RTC_ALARM_BIT; sci_adi_raw_write(ANA_RTC_INT_EN, temp); //add by wbl sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_UNLOCK); printk(KERN_EMERG "sprd_rtc_open is calling!\n"); return 0; }
void sprd_rtc_set_spg_counter(u16 value) { u16 spg_cnt = 0; u32 int_sts = 0; int timeout = SPRD_RTC_SET_MAX; spg_cnt = sci_adi_read(ANA_RTC_SPG_CNT)&RTC_SPG_CNT_MASK; if (spg_cnt == value) return; sci_adi_set(ANA_RTC_INT_CLR, RTC_SPG_CNT_ACK_BIT); sci_adi_raw_write(ANA_RTC_SPG_CNT_UPD, (value&RTC_SPG_CNT_MASK)); for(;;) { if (timeout && int_sts != RTC_SPG_CNT_ACK_BIT) { int_sts = sci_adi_read(ANA_RTC_INT_RSTS)&RTC_SPG_CNT_ACK_BIT; msleep(1); timeout--; } else break; } sci_adi_set(ANA_RTC_INT_CLR, RTC_SPG_CNT_ACK_BIT); }
static int sprd_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { unsigned long secs; unsigned temp; unsigned long read_secs; int i = 0,n; rtc_tm_to_time(&alrm->time, &secs); sci_adi_raw_write(ANA_RTC_INT_CLR, RTC_ALARM_BIT); // printk("sprd_rtc_set_alarm enable : %d, : %lu, secs : %lu\n", alrm->enabled, secs_start_year_to_1970, secs); // printk("sprd_rtc_set_alarm - day [%d] hour [%d] min [%d] sec [%d]\n", alrm->time.tm_mday, alrm->time.tm_hour, alrm->time.tm_min, alrm->time.tm_sec); if(alrm->enabled){ if(secs < secs_start_year_to_1970) return -1; temp = sci_adi_read(ANA_RTC_INT_EN); temp |= RTC_ALARM_BIT; sci_adi_raw_write(ANA_RTC_INT_EN, temp); secs = secs - secs_start_year_to_1970; wake_lock(&rtc_wake_lock); n = 2; while(sprd_rtc_set_alarm_sec(secs)!=0&&(n--)>0); do { if(i!=0){ n = 2; while(sprd_rtc_set_alarm_sec(secs)!=0&&(n--)>0); } read_secs = sprd_rtc_get_alarm_sec(); msleep(1); i++; }while(read_secs != secs && i < SPRD_RTC_SET_MAX); //sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_UNLOCK); wake_unlock(&rtc_wake_lock); }else{ sci_adi_clr(ANA_RTC_INT_EN, RTC_ALARM_BIT); //sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_LOCK); msleep(150); } return 0; }
static int sprd_rtc_open(struct device *dev) { int temp = 0; /* enable rtc interrupt */ temp = sci_adi_read(ANA_RTC_INT_EN); temp |= RTC_ALARM_BIT; sci_adi_raw_write(ANA_RTC_INT_EN, temp); return 0; }
static int sprd_rtc_set_alarm_sec(unsigned long secs) { unsigned sec, min, hour, day; unsigned long temp; u32 timeout = 0; static bool rtc_alarm_in_update = false; sec = secs % 60; temp = (secs - sec)/60; min = temp%60; temp = (temp - min)/60; hour = temp%24; temp = (temp - hour)/24; day = temp; if (rtc_alarm_in_update) { while ((sci_adi_read(ANA_RTC_INT_RSTS) & RTC_ALM_TIME_MASK) != RTC_ALM_TIME_MASK) { msleep(10); if (timeout++ > SPRD_RTC_SET_MAX) { printk("rtc set alarm timeout!\n"); break; } } } printk("++++++rtc set alarm and delay is %d !++++++\n", timeout * 10); sci_adi_set(ANA_RTC_INT_CLR, RTC_ALM_TIME_MASK); sci_adi_raw_write(ANA_RTC_SEC_ALM, sec); sci_adi_raw_write(ANA_RTC_MIN_ALM, min); sci_adi_raw_write(ANA_RTC_HOUR_ALM, hour); sci_adi_raw_write(ANA_RTC_DAY_ALM, day); rtc_alarm_in_update = true; return 0; }
static int sci_open(struct inode *inode, struct file *file) { if (test_and_set_bit(1, &wdt_users)) return -EBUSY; /* started the watchdog when it's openned for the 1st time */ if (wdt_state == 0) { /* start the watchdog */ sci_adi_set(ANA_AGEN, AGEN_WDG_EN | AGEN_RTC_ARCH_EN | AGEN_RTC_WDG_EN); sci_adi_raw_write (WDG_LOCK, WDG_UNLOCK_KEY); sci_adi_clr (WDG_CTRL, WDG_INT_EN_BIT); WDG_LOAD_TIMER_VALUE(margin * WDT_FREQ); #ifdef CONFIG_ARCH_SC8825 sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT | WDG_RST_EN_BIT); #else sci_adi_set(WDG_CTRL, WDG_CNT_EN_BIT); #endif mod_timer(&feeder_timer, jiffies + (feed_period * HZ)); wdt_state = 1; } return nonseekable_open(inode, file); }
static void a_write_reg(uint32_t value, uint32_t addr) { sci_adi_raw_write(addr, value); }
int dcdc_calibrate(int adc_chan, int def_vol, int to_vol) { int i; u32 val[MEASURE_TIMES], sum = 0, adc_vol, ctl_vol, cal_vol; for (i = 0; i < ARRAY_SIZE(val); i++) { sum += val[i] = sci_adc_get_value(adc_chan, true); } sum /= ARRAY_SIZE(val); /* get average value */ info("adc chan %d, value %d\n", adc_chan, sum); adc_vol = sprd_get_adc_to_vol(sum) * (8 * 5) / (30 * 4); if (!def_vol) { switch (adc_chan) { case ADC_CHANNEL_DCDC: def_vol = 1100; cal_vol = sci_adi_read(ANA_DCDC_CTRL_CAL) & 0x1f; i = sci_adi_read(ANA_DCDC_CTRL) & 0x07; break; case ADC_CHANNEL_DCDCARM: def_vol = 1200; cal_vol = sci_adi_read(ANA_DCDCARM_CTRL_CAL) & 0x1f; i = sci_adi_read(ANA_DCDCARM_CTRL) & 0x07; break; default: goto exit; } if (0 != i /* + cal_vol */ ) def_vol = dcdc_ctl_vol[i]; def_vol += cal_vol * 100 / 32; #if 0 if (0 != i + cal_vol) { /* dcdc had been adjusted in uboot-spl */ debug("%s default %dmv, from %dmv to %dmv\n", __FUNCTION__, def_vol, adc_vol, to_vol); goto exit; } #endif } info("%s default %dmv, from %dmv to %dmv\n", __FUNCTION__, def_vol, adc_vol, to_vol); cal_vol = abs(adc_vol - to_vol); if (cal_vol > 200 /* mv */ ) goto exit; else if (cal_vol < to_vol / 100) { info("%s is ok\n", __FUNCTION__); return 0; } ctl_vol = def_vol * to_vol / adc_vol; for (i = 0; i < ARRAY_SIZE(dcdc_ctl_vol) - 1; i++) { if (ctl_vol < dcdc_ctl_vol[i + 1]) break; } if (i >= ARRAY_SIZE(dcdc_ctl_vol) - 1) goto exit; cal_vol = ((ctl_vol - dcdc_ctl_vol[i]) * 32 / 100) % 32; debug("%s cal_vol %dmv: %d, 0x%02x\n", __FUNCTION__, dcdc_ctl_vol[i] + cal_vol * 100 / 32, i, cal_vol); switch (adc_chan) { case ADC_CHANNEL_DCDC: sci_adi_raw_write(ANA_DCDC_CTRL_CAL, cal_vol | (0x1f - cal_vol) << 8); sci_adi_raw_write(ANA_DCDC_CTRL, i | (0x07 - i) << 4); break; case ADC_CHANNEL_DCDCARM: sci_adi_raw_write(ANA_DCDCARM_CTRL_CAL, cal_vol | (0x1f - cal_vol) << 8); sci_adi_raw_write(ANA_DCDCARM_CTRL, i | (0x07 - i) << 4); break; default: break; } return dcdc_ctl_vol[i] + cal_vol * 100 / 32; exit: info("%s failure\n", __FUNCTION__); return -1; }
static int sprd_rtc_probe(struct platform_device *plat_dev) { int err = -ENODEV; struct resource *irq; rtc_data = kzalloc(sizeof(*rtc_data), GFP_KERNEL); if(IS_ERR(rtc_data)){ err = PTR_ERR(rtc_data); return err; }; /*ensure the rtc interrupt don't be send to Adie when there's no *rtc alarm int occur. */ sci_adi_raw_write(ANA_RTC_SPG_UPD, SPRD_RTC_LOCK); /* disable all interrupt */ sci_adi_clr(ANA_RTC_INT_EN, RTC_INT_ALL_MSK); /* enable rtc device */ rtc_data->clk = clk_get(&plat_dev->dev, "ext_32k"); if (IS_ERR(rtc_data->clk)) { err = PTR_ERR(rtc_data->clk); goto kfree_data; } err = clk_enable(rtc_data->clk); if (err < 0) goto put_clk; CLEAR_RTC_INT(RTC_INT_ALL_MSK); rtc_data->rtc = rtc_device_register("sprd_rtc", &plat_dev->dev, &sprd_rtc_ops, THIS_MODULE); if (IS_ERR(rtc_data->rtc)) { err = PTR_ERR(rtc_data->rtc); goto disable_clk; } irq = platform_get_resource(plat_dev, IORESOURCE_IRQ, 0); if(unlikely(!irq)) { dev_err(&plat_dev->dev, "no irq resource specified\n"); goto unregister_rtc; } rtc_data->irq_no = irq->start; platform_set_drvdata(plat_dev, rtc_data); err = request_irq(rtc_data->irq_no, rtc_interrupt_handler, 0, "sprd_rtc", rtc_data->rtc); if(err){ printk(KERN_ERR "RTC regist irq error\n"); goto unregister_rtc; } sprd_creat_caliberate_attr(rtc_data->rtc->dev); sprd_rtc_hwrst_set(1); sprd_rtc_set_bit_spg_counter(SPG_CNT_8SECS_RESET, 1); sprd_rtc_check_power_down(&plat_dev->dev); sprd_rtc_open(&plat_dev->dev);//test return 0; unregister_rtc: rtc_device_unregister(rtc_data->rtc); disable_clk: clk_disable(rtc_data->clk); put_clk: clk_put(rtc_data->clk); kfree_data: kfree(rtc_data); return err; }