void mvg_emmc_nanodelay(u32 delay_ns)
{
    //struct timespec t_start,t_end1;
    get_monotonic_boottime(&t_hr_start);

    do {
        get_monotonic_boottime(&t_hr_end1);
        if ( t_hr_end1.tv_nsec< t_hr_start.tv_nsec ) {
            t_hr_end1.tv_nsec=1000000000+t_hr_end1.tv_nsec-t_hr_start.tv_nsec;
        } else {
            t_hr_end1.tv_nsec=t_hr_end1.tv_nsec-t_hr_start.tv_nsec;
        }
        if ( t_hr_end1.tv_nsec>delay_ns ) break;
    } while(1);
}
Beispiel #2
0
static long kfd_ioctl_get_clock_counters(struct file *filep,
				struct kfd_process *p, void __user *arg)
{
	struct kfd_ioctl_get_clock_counters_args args;
	struct kfd_dev *dev;
	struct timespec time;

	if (copy_from_user(&args, arg, sizeof(args)))
		return -EFAULT;

	dev = kfd_device_by_id(args.gpu_id);
	if (dev == NULL)
		return -EINVAL;

	/* Reading GPU clock counter from KGD */
	args.gpu_clock_counter = kfd2kgd->get_gpu_clock_counter(dev->kgd);

	/* No access to rdtsc. Using raw monotonic time */
	getrawmonotonic(&time);
	args.cpu_clock_counter = (uint64_t)timespec_to_ns(&time);

	get_monotonic_boottime(&time);
	args.system_clock_counter = (uint64_t)timespec_to_ns(&time);

	/* Since the counter is in nano-seconds we use 1GHz frequency */
	args.system_clock_freq = 1000000000;

	if (copy_to_user(arg, &args, sizeof(args)))
		return -EFAULT;

	return 0;
}
static int alarm_get_time(enum android_alarm_type alarm_type,
							struct timespec *ts)
{
	int rv = 0;

	switch (alarm_type) {
#ifdef CONFIG_BCM_RTC_ALARM_BOOT
	case ANDROID_ALARM_RTC_POWERON:
#endif
	case ANDROID_ALARM_RTC_WAKEUP:
	case ANDROID_ALARM_RTC:
		getnstimeofday(ts);
		break;
	case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
	case ANDROID_ALARM_ELAPSED_REALTIME:
		get_monotonic_boottime(ts);
		break;
	case ANDROID_ALARM_SYSTEMTIME:
		ktime_get_ts(ts);
		break;
	default:
		rv = -EINVAL;
	}
	return rv;
}
Beispiel #4
0
irqreturn_t stml0xx_isr(int irq, void *dev)
{
	static struct timespec ts;
	static struct stml0xx_work_struct *stm_ws;
	struct stml0xx_data *ps_stml0xx = dev;
	get_monotonic_boottime(&ts);

	if (stml0xx_irq_disable)
		return IRQ_HANDLED;

	stm_ws = kmalloc(
		sizeof(struct stml0xx_work_struct),
		GFP_ATOMIC);
	if (!stm_ws) {
		dev_err(&ps_stml0xx->spi->dev,
			"stml0xx_isr: unable to allocate work struct");
		return IRQ_HANDLED;
	}

	INIT_WORK((struct work_struct *)stm_ws, stml0xx_irq_work_func);
	stm_ws->ts_ns = ts_to_ns(ts);

	queue_work(ps_stml0xx->irq_work_queue, (struct work_struct *)stm_ws);
	return IRQ_HANDLED;
}
Beispiel #5
0
void addTimeAndBusyWait(struct timespec* time, long nanoseconds)
{
    addTime(time, nanoseconds);
    struct timespec actualTime;
    do
    {
        get_monotonic_boottime(&actualTime);
    } while (timespec_compare(time, &actualTime) > 0);
}
static int64_t getCurNS(void)
{
	int64_t ns;
	struct timespec time;

	time.tv_sec = time.tv_nsec = 0;
	get_monotonic_boottime(&time);
	ns = time.tv_sec * 1000000000LL + time.tv_nsec;

	return ns;
}
Beispiel #7
0
static irqreturn_t sensordata_irq_thread_fn(int iIrq, void *dev_id)
{
	struct ssp_data *data = dev_id;
	struct timespec ts;

	get_monotonic_boottime(&ts);
	data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec;

	select_irq_msg(data);
	data->uIrqCnt++;

	return IRQ_HANDLED;
}
static void android_bat_set_charge_time(struct android_bat_data *battery,
					bool enable)
{
	if (enable && !battery->charging_start_time) {
		struct timespec cur_time;

		get_monotonic_boottime(&cur_time);
		/* record start time for charge timeout timer */
		battery->charging_start_time = cur_time.tv_sec;
	} else if (!enable) {
		/* clear charge timeout timer */
		battery->charging_start_time = 0;
	}
}
static bool android_bat_charge_timeout(struct android_bat_data *battery,
				       unsigned long timeout)
{
	struct timespec cur_time;

	if (!battery->charging_start_time)
		return 0;

	get_monotonic_boottime(&cur_time);
	pr_debug("%s: Start time: %ld, End time: %ld, current time: %ld\n",
		 __func__, battery->charging_start_time,
		 battery->charging_start_time + timeout,
		 cur_time.tv_sec);
	return cur_time.tv_sec >= battery->charging_start_time + timeout;
}
static void cw_update_time_member_capacity_change(struct cw_battery *cw_bat)
{
        struct timespec ts;
        int new_run_time;
        int new_sleep_time;

        ktime_get_ts(&ts);
        new_run_time = ts.tv_sec;

        get_monotonic_boottime(&ts);
        new_sleep_time = ts.tv_sec - new_run_time;

        cw_bat->run_time_capacity_change = new_run_time;
        cw_bat->sleep_time_capacity_change = new_sleep_time; 
}
Beispiel #11
0
static int uptime_show(struct seq_file *m, void *v) {
	NsRule *ptr = find_sandbox(current->nsproxy);
	if (ptr) {
		unsigned long long delta;
		struct timespec uptime;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
		do_posix_clock_monotonic_gettime(&uptime);
		monotonic_to_bootbased(&uptime);
#else
		get_monotonic_boottime(&uptime);
#endif
		
		delta =  (unsigned long long) uptime.tv_sec - (unsigned long long) ptr->real_start_time.tv_sec;
		seq_printf(m, "%llu 0\n", delta);
	}
	else
		seq_printf(m, "0 0\n");
	return 0;
}
static int android_power_debug_dump(struct seq_file *s, void *unused)
{
	struct android_bat_data *battery = s->private;
	struct timespec cur_time;

	android_bat_update_data(battery);
	get_monotonic_boottime(&cur_time);
	mutex_lock(&android_bat_state_lock);
	seq_printf(s, "l=%d v=%d c=%d temp=%s%ld.%ld h=%d st=%d%s ct=%lu type=%s\n",
		   battery->batt_soc, battery->batt_vcell/1000,
		   battery->batt_current, battery->batt_temp < 0 ? "-" : "",
		   abs(battery->batt_temp / 10), abs(battery->batt_temp % 10),
		   battery->batt_health, battery->charging_status,
		   battery->recharging ? "r" : "",
		   battery->charging_start_time ?
		   cur_time.tv_sec - battery->charging_start_time : 0,
		   charge_source_str(battery->charge_source));
	mutex_unlock(&android_bat_state_lock);
	return 0;
}
static int get_usb_charge_state(struct cw_battery *cw_bat)
{
        int charge_time;
        int time_from_boot;
        struct timespec ts;

        int gadget_status = get_gadget_connect_flag();
        int usb_status = dwc_vbus_status();

        get_monotonic_boottime(&ts);
        time_from_boot = ts.tv_sec;
        
        if (cw_bat->charger_init_mode) {
 
                if (usb_status == 1 || usb_status == 2) {
                        cw_bat->charger_init_mode = 0;
                } else if (time_from_boot < 8) {
                        usb_status = cw_bat->charger_init_mode;
                } else if (strstr(saved_command_line,"charger")) {
                        cw_bat->charger_init_mode = dwc_otg_check_dpdm();
                        usb_status = cw_bat->charger_init_mode;
                }
        }
#ifdef NO_STANDARD_AC_BIG_CHARGE_MODE 
        if (cw_bat->usb_online == 1) {
                
                charge_time = time_from_boot - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start;
                if (charge_time > 3) {
                        if (gadget_status == 0 && dwc_vbus_status() == 1) {
                                usb_status = 2;
                        }
                }
        }
#endif
        return usb_status;
 
        dev_dbg(&cw_bat->client->dev, "%s usb_status=[%d],cw_bat->charger_mode=[%d],cw_bat->gadget_status=[%d], cw_bat->charger_init_mode = [%d]\n",__func__,usb_status,cw_bat->charger_mode,gadget_status, cw_bat->charger_init_mode);



}
Beispiel #14
0
int stml0xx_ms_data_buffer_write(struct stml0xx_data *ps_stml0xx,
				 unsigned char type, unsigned char *data,
				 int size)
{
	int new_head;
	struct stml0xx_moto_sensor_data *buffer;
	struct timespec ts;
	static bool error_reported;

	new_head = (ps_stml0xx->stml0xx_ms_data_buffer_head + 1)
	    & STML0XX_MS_DATA_QUEUE_MASK;
	if (new_head == ps_stml0xx->stml0xx_ms_data_buffer_tail) {
		if (!error_reported) {
			dev_err(&stml0xx_misc_data->spi->dev,
				"ms data buffer full");
			error_reported = true;
		}
		wake_up(&ps_stml0xx->stml0xx_ms_data_wq);
		return 0;
	}
	buffer = &(ps_stml0xx->stml0xx_ms_data_buffer[new_head]);
	buffer->type = type;
	if (data != NULL && size > 0) {
		if (size > sizeof(buffer->data)) {
			dev_err(&stml0xx_misc_data->spi->dev,
				"size %d exceeds ms buffer", size);
			return 0;
		}
		memcpy(buffer->data, data, size);
	}
	buffer->size = size;

	get_monotonic_boottime(&ts);
	buffer->timestamp = ts.tv_sec * 1000000000LL + ts.tv_nsec;

	ps_stml0xx->stml0xx_ms_data_buffer_head = new_head;
	wake_up(&ps_stml0xx->stml0xx_ms_data_wq);

	error_reported = false;
	return 1;
}
/* Send a single command to the chip.
 *
 * If the SR (suppress response bit) is NOT set, will read the
 * response and cache it the driver object retrieve with escore_resp().
 *
 * Returns:
 * 0 - on success.
 * EITIMEDOUT - if the chip did not respond in within the expected time.
 * E* - any value that can be returned by the underlying HAL.
 */
int escore_cmd(struct escore_priv *escore, u32 cmd)
{
	int sr;
	int err;
	u32 resp;

	BUG_ON(!escore);
	sr = cmd & BIT(28);

	err = escore->cmd(escore, cmd, sr, &resp);
	if (err || sr)
		return err;

	if (resp == 0) {
		err = -ETIMEDOUT;
		dev_err(escore->dev, "no response to command 0x%08x\n", cmd);
	} else {
		escore->last_response = resp;
		get_monotonic_boottime(&escore->last_resp_time);
	}
	return err;
}
Beispiel #16
0
static int stml0xx_resume(struct device *dev)
{
	static struct timespec ts;
	static struct stml0xx_delayed_work_struct *stm_ws;
	struct stml0xx_data *ps_stml0xx = spi_get_drvdata(to_spi_device(dev));

	get_monotonic_boottime(&ts);
	dev_dbg(&stml0xx_misc_data->spi->dev, "%s", __func__);

	mutex_lock(&ps_stml0xx->lock);
	ps_stml0xx->is_suspended = false;
	enable_irq(ps_stml0xx->irq);

	if (ps_stml0xx->pending_wake_work) {
		stm_ws = kmalloc(
			sizeof(struct stml0xx_delayed_work_struct),
			GFP_ATOMIC);
		if (!stm_ws) {
			dev_err(dev, "stml0xx_resume: unable to allocate work struct");
			return 0;
		}
		INIT_DELAYED_WORK((struct delayed_work *)stm_ws,
			stml0xx_irq_wake_work_func);
		stm_ws->ts_ns = ts_to_ns(ts);
		queue_delayed_work(ps_stml0xx->irq_work_queue,
			(struct delayed_work *)stm_ws, 0);
		ps_stml0xx->pending_wake_work = false;
	}

	if (stml0xx_irq_disable == 0)
		queue_work(ps_stml0xx->irq_work_queue,
			   &ps_stml0xx->clear_interrupt_status_work);

	mutex_unlock(&ps_stml0xx->lock);

	return 0;
}
static void android_bat_monitor_work(struct work_struct *work)
{
	struct android_bat_data *battery =
		container_of(work, struct android_bat_data, monitor_work);
	struct timespec cur_time;

	wake_lock(&battery->monitor_wake_lock);
	android_bat_update_data(battery);
	mutex_lock(&android_bat_state_lock);

	switch (battery->charging_status) {
	case POWER_SUPPLY_STATUS_FULL:
		if (battery->batt_vcell < battery->pdata->recharging_voltage &&
		    !battery->recharging) {
			battery->recharging = true;
			android_bat_enable_charging(battery, true);
			pr_info("battery: start recharging, v=%d\n",
				battery->batt_vcell/1000);
		}
		break;
	case POWER_SUPPLY_STATUS_DISCHARGING:
		break;
	case POWER_SUPPLY_STATUS_CHARGING:
		switch (battery->batt_health) {
		case POWER_SUPPLY_HEALTH_OVERHEAT:
		case POWER_SUPPLY_HEALTH_COLD:
		case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
		case POWER_SUPPLY_HEALTH_DEAD:
		case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
			battery->charging_status =
				POWER_SUPPLY_STATUS_NOT_CHARGING;
			android_bat_enable_charging(battery, false);

			pr_info("battery: Not charging, health=%d\n",
				battery->batt_health);
			break;
		default:
			break;
		}
		break;
	case POWER_SUPPLY_STATUS_NOT_CHARGING:
		if (battery->batt_health == POWER_SUPPLY_HEALTH_GOOD) {
			pr_info("battery: battery health recovered\n");
			if (battery->charge_source != CHARGE_SOURCE_NONE) {
				android_bat_enable_charging(battery, true);
				battery->charging_status
					= POWER_SUPPLY_STATUS_CHARGING;
			} else {
				battery->charging_status
					= POWER_SUPPLY_STATUS_DISCHARGING;
			}
		}
		break;
	default:
		pr_err("%s: Undefined battery status: %d\n", __func__,
		       battery->charging_status);
		break;
	}

	android_bat_charging_timer(battery);
	get_monotonic_boottime(&cur_time);
	pr_info("battery: l=%d v=%d c=%d temp=%s%ld.%ld h=%d st=%d%s ct=%lu type=%s\n",
		battery->batt_soc, battery->batt_vcell/1000,
		battery->batt_current, battery->batt_temp < 0 ? "-" : "",
		abs(battery->batt_temp / 10), abs(battery->batt_temp % 10),
		battery->batt_health, battery->charging_status,
		   battery->recharging ? "r" : "",
		   battery->charging_start_time ?
		   cur_time.tv_sec - battery->charging_start_time : 0,
		charge_source_str(battery->charge_source));
	mutex_unlock(&android_bat_state_lock);
	power_supply_changed(&battery->psy_bat);
	battery->last_poll = ktime_get_boottime();
	android_bat_monitor_set_alarm(battery, FAST_POLL);
	wake_unlock(&battery->monitor_wake_lock);
	return;
}
Beispiel #18
0
static int posix_get_boottime(const clockid_t which_clock, struct timespec *tp)
{
	get_monotonic_boottime(tp);
	return 0;
}
Beispiel #19
0
void txSender(unsigned long argument)
{
    GpioUart* uart = (GpioUart*)argument;
    
    spinlock_t locker;
    spin_lock_init(&locker);
    
    struct timespec lastBitTime;
    get_monotonic_boottime(&lastBitTime);
    
    // What is the delay for a bit in nanoseconds?
    long bitDelay = 1000000000L / uart->baudRate;
    
    // We can send multiple bytes at once, if it will not take too long.
    // Let us take up to half a millisecond if our first byte will take less than that
    // (so we will go as long as necessary to get one byte out)
    int bitsFrame = 10 + (uart->secondStopBit ? 1 : 0) + (uart->parityBit ? 1 : 0);
    int bytesToDo = 500000 / bitDelay / bitsFrame;
    // But at least one byte...
    bytesToDo = (bytesToDo == 0) ? 1 : bytesToDo;
    
    for (int i = 0;i < bytesToDo; i++)
    {
        // Have we a byte to send?
        int byteToSend = removeTxByte(uart);
        if (byteToSend != -1)
        {
            // We use the spinlock to disable interrupts so that we can busy-wait exact timing
            // TESTING
            //spin_lock_irqsave(&locker, savedFlags);
            spin_lock_bh(&locker);
            
            // Make sure we have at least the required stop bits before our start bit
            long stopBitNanoseconds = bitDelay + (uart->secondStopBit ? bitDelay : 0);
            
            // Start bit
            holdAndSetTx(uart, false, &lastBitTime, stopBitNanoseconds);
            
            int bits = byteToSend;
            int parity = 0;
            // UART is Least Significant Bit first
            for (int i = 0;i < 8; i++)
            {
                // Keep track of parity
                parity ^= (bits & 1);
                
                // Send the value of the lowest bit
                holdAndSetTx(uart, bits & 1, &lastBitTime, bitDelay);
                // Shift out the just-transmitted bit

                bits >>= 1;
            }
            
            // Parity bit
            if (uart->parityBit)
            {
                holdAndSetTx(uart, parity, &lastBitTime, bitDelay);
            }
            
            // Stop bit(s), though we don't wait for them...
            holdAndSetTx(uart, true, &lastBitTime, bitDelay);
            
            // The byte is done!
            //TESTING
            //spin_unlock_irqrestore(&locker, savedFlags);
            spin_unlock_bh(&locker);
        }
    }
static int cw_get_capacity(struct cw_battery *cw_bat)
{

	int ret;
	u8 reg_val[2];

	struct timespec ts;
	long new_run_time;
	long new_sleep_time;
	long capacity_or_aconline_time;
	int allow_change;
	int allow_capacity;
	static int if_quickstart;
	static int jump_flag;
	static int jump_flag2;
	static int reset_loop;
	int charge_time;
	u8 reset_val;

	ret = cw_i2c_read(cw_bat->client, REG_SOC, reg_val, 2);
	if (ret < 0)
		return ret;

	cw_capacity = reg_val[0];
	if ((cw_capacity < 0) || (cw_capacity > 100)) {
		dev_err(&cw_bat->client->dev, "get cw_capacity error; cw_capacity = %d\n", cw_capacity);
		reset_loop++;

		if (reset_loop > 5) {

			reset_val = MODE_SLEEP;
			ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1);
			if (ret < 0)
				return ret;
			reset_val = MODE_NORMAL;
			msleep(10);
			ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1);
			if (ret < 0)
				return ret;
			dev_dbg(&cw_bat->client->dev, "report battery capacity error");
			ret = cw_update_config_info(cw_bat);
			if (ret)
				return ret;
			reset_loop = 0;

		}

		return cw_capacity;
	} else {
		reset_loop = 0;
	}

	if (cw_capacity == 0)
		dev_dbg(&cw_bat->client->dev, "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__);
	else
		dev_dbg(&cw_bat->client->dev, "the cw201x capacity is %d, funciton: %s\n", cw_capacity, __func__);

	ktime_get_ts(&ts);
	new_run_time = ts.tv_sec;

	get_monotonic_boottime(&ts);
	new_sleep_time = ts.tv_sec - new_run_time;

	if (((cw_bat->charger_mode > 0) && (cw_capacity <= (cw_bat->capacity - 1)) && (cw_capacity > (cw_bat->capacity - 30/*9*/)))
				|| ((cw_bat->charger_mode == 0) && (cw_capacity == (cw_bat->capacity + 1)))) {

		if (!(cw_capacity == 0 && cw_bat->capacity <= 2)) {
			cw_capacity = cw_bat->capacity;
		}
	}

	if ((cw_bat->charger_mode > 0) && (cw_capacity >= 95) && (cw_capacity <= cw_bat->capacity)) {

		capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start;
		capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start;
		allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE;
		if (allow_change > 0) {
			allow_capacity = cw_bat->capacity + allow_change;
			cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100;
			jump_flag = 1;
		} else if (cw_capacity <= cw_bat->capacity) {
			cw_capacity = cw_bat->capacity;
		}

	} else if ((cw_bat->charger_mode == 0) && cw_bat->capacity == 100 && cw_capacity < cw_bat->capacity && jump_flag2 == 0) {
		cw_capacity = cw_bat->capacity;
		jump_flag2 = 1;
	} else if ((cw_bat->charger_mode == 0) && (cw_capacity <= cw_bat->capacity) && (cw_capacity >= 90) && ((jump_flag == 1) || (jump_flag2 == 1))) {
		capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start;
		capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start;
		allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_DOWN_CHANGE;
		if (allow_change > 0) {
			allow_capacity = cw_bat->capacity - allow_change;
			if (cw_capacity >= allow_capacity) {
				jump_flag = 0;
				jump_flag2 = 0;
			} else {
				cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100;
			}
		} else if (cw_capacity <= cw_bat->capacity) {
			cw_capacity = cw_bat->capacity;
		}
	}

	if ((cw_capacity == 0) && (cw_bat->capacity > 1)) {
		allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN);
		allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP);
		allow_capacity = cw_bat->capacity - allow_change;
		cw_capacity = (allow_capacity >= cw_capacity) ? allow_capacity : cw_capacity;
		dev_dbg(&cw_bat->client->dev, "report GGIC POR happened");
		reg_val[0] = MODE_NORMAL;
		ret = cw_i2c_write(cw_bat->client, REG_MODE, reg_val, 1);
		if (ret < 0)
			return ret;
		dev_dbg(&cw_bat->client->dev, "report battery capacity jump 0 ");
	}

#if 1
	if ((cw_bat->charger_mode > 0) && (cw_capacity == 0)) {
		charge_time = new_sleep_time + new_run_time - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start;
		if ((charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE) && (if_quickstart == 0)) {
			cw_quickstart(cw_bat);
			reset_val = MODE_SLEEP;
			ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1);
			if (ret < 0)
				return ret;
				reset_val = MODE_NORMAL;
				msleep(10);
				ret = cw_i2c_write(cw_bat->client, REG_MODE, &reset_val, 1);
				if (ret < 0)
					return ret;
				dev_dbg(&cw_bat->client->dev, "report battery capacity error");
				ret = cw_update_config_info(cw_bat);
				if (ret)
					return ret;
				dev_dbg(&cw_bat->client->dev, "report battery capacity still 0 if in changing");
				if_quickstart = 1;
		}
	} else if ((if_quickstart == 1) && (cw_bat->charger_mode == 0)) {
		if_quickstart = 0;
	}

#endif

#ifdef SYSTEM_SHUTDOWN_VOLTAGE
	if ((cw_bat->charger_mode == 0) && (cw_capacity <= 20) && (cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE)) {
		if (if_quickstart == 10) {

			allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN);
			allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP);

			allow_capacity = cw_bat->capacity - allow_change;
			cw_capacity = (allow_capacity >= 0) ? allow_capacity : 0;

			if (cw_capacity < 1) {
				cw_quickstart(cw_bat);
				if_quickstart = 12;
				cw_capacity = 0;
			}
		} else if (if_quickstart <= 10)
			if_quickstart = if_quickstart+2;
		dev_dbg(&cw_bat->client->dev, "the cw201x voltage is less than SYSTEM_SHUTDOWN_VOLTAGE !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__);
	} else if ((cw_bat->charger_mode > 0) && (if_quickstart <= 12)) {
		if_quickstart = 0;
	}
#endif
	return cw_capacity;
}
Beispiel #21
0
/**
 * write_ipc_from_queue() - try to write ipc msg from Tx queue to device
 * @dev: ishtp device pointer
 *
 * Check if DRBL is cleared. if it is - write the first IPC msg,  then call
 * the callback function (unless it's NULL)
 *
 * Return: 0 for success else failure code
 */
static int write_ipc_from_queue(struct ishtp_device *dev)
{
	struct wr_msg_ctl_info	*ipc_link;
	unsigned long	length;
	unsigned long	rem;
	unsigned long	flags;
	uint32_t	doorbell_val;
	uint32_t	*r_buf;
	uint32_t	reg_addr;
	int	i;
	void	(*ipc_send_compl)(void *);
	void	*ipc_send_compl_prm;
	static int	out_ipc_locked;
	unsigned long	out_ipc_flags;

	if (dev->dev_state == ISHTP_DEV_DISABLED)
		return	-EINVAL;

	spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags);
	if (out_ipc_locked) {
		spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
		return -EBUSY;
	}
	out_ipc_locked = 1;
	if (!ish_is_input_ready(dev)) {
		out_ipc_locked = 0;
		spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);
		return -EBUSY;
	}
	spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags);

	spin_lock_irqsave(&dev->wr_processing_spinlock, flags);
	/*
	 * if tx send list is empty - return 0;
	 * may happen, as RX_COMPLETE handler doesn't check list emptiness.
	 */
	if (list_empty(&dev->wr_processing_list_head.link)) {
		spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags);
		out_ipc_locked = 0;
		return	0;
	}

	ipc_link = list_entry(dev->wr_processing_list_head.link.next,
			      struct wr_msg_ctl_info, link);
	/* first 4 bytes of the data is the doorbell value (IPC header) */
	length = ipc_link->length - sizeof(uint32_t);
	doorbell_val = *(uint32_t *)ipc_link->inline_data;
	r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t));

	/* If sending MNG_SYNC_FW_CLOCK, update clock again */
	if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG &&
		IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) {
		struct timespec ts_system;
		struct timeval tv_utc;
		uint64_t        usec_system, usec_utc;
		struct ipc_time_update_msg time_update;
		struct time_sync_format ts_format;

		get_monotonic_boottime(&ts_system);
		do_gettimeofday(&tv_utc);
		usec_system = (timespec_to_ns(&ts_system)) / NSEC_PER_USEC;
		usec_utc = (uint64_t)tv_utc.tv_sec * 1000000 +
						((uint32_t)tv_utc.tv_usec);
		ts_format.ts1_source = HOST_SYSTEM_TIME_USEC;
		ts_format.ts2_source = HOST_UTC_TIME_USEC;
		ts_format.reserved = 0;

		time_update.primary_host_time = usec_system;
		time_update.secondary_host_time = usec_utc;
		time_update.sync_info = ts_format;

		memcpy(r_buf, &time_update,
		       sizeof(struct ipc_time_update_msg));
	}

	for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++,
			reg_addr += 4)
		ish_reg_write(dev, reg_addr, r_buf[i]);

	rem = length & 0x3;
	if (rem > 0) {
		uint32_t reg = 0;

		memcpy(&reg, &r_buf[length >> 2], rem);
		ish_reg_write(dev, reg_addr, reg);
	}
static int cw_get_capacity(struct cw_battery *cw_bat)
{
        int cw_capacity;
        int ret;
        u8 reg_val[2];

        struct timespec ts;
        long new_run_time;
        long new_sleep_time;
        long capacity_or_aconline_time;
        int allow_change;
        int allow_capacity;
        static int if_quickstart = 0;
        static int jump_flag =0;
        int charge_time;


        // ret = cw_read(cw_bat->client, REG_SOC, &reg_val);
        ret = cw_read_word(cw_bat->client, REG_SOC, reg_val);
        if (ret < 0)
                return ret;

        cw_capacity = reg_val[0];
        if ((cw_capacity < 0) || (cw_capacity > 100)) {
                dev_err(&cw_bat->client->dev, "get cw_capacity error; cw_capacity = %d\n", cw_capacity);
                return cw_capacity;
        } 

        if (cw_capacity == 0) 
                dev_dbg(&cw_bat->client->dev, "the cw201x capacity is 0 !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__);
        else 
                dev_dbg(&cw_bat->client->dev, "the cw201x capacity is %d, funciton: %s\n", cw_capacity, __func__);

        // ret = cw_read(cw_bat->client, REG_SOC + 1, &reg_val);

        ktime_get_ts(&ts);
        new_run_time = ts.tv_sec;

        get_monotonic_boottime(&ts);
        new_sleep_time = ts.tv_sec - new_run_time;

        if ((cw_bat->charger_mode > 0) && (cw_capacity >= 95) && (cw_capacity <= cw_bat->capacity)) {     // avoid no charge full

                capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start;
                capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start;
                allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_UP_MAX_CHANGE;
                if (allow_change > 0) {
                        allow_capacity = cw_bat->capacity + allow_change; 
                        cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100;
                        jump_flag =1;
                } else if (cw_capacity <= cw_bat->capacity) {
                        cw_capacity = cw_bat->capacity; 
                }

        } else if (((cw_bat->charger_mode > 0) && (cw_capacity == (cw_bat->capacity - 1)))
                        || ((cw_bat->charger_mode == 0) && (cw_capacity == (cw_bat->capacity + 1)))) {             // modify battery level swing

                if (!(cw_capacity == 0 && cw_bat->capacity == 1)) {			
		        cw_capacity = cw_bat->capacity;
		}
				

        } else if ((cw_capacity == 0) && (cw_bat->capacity > 1)) {              // avoid battery level jump to 0% at a moment from more than 2%
                allow_change = ((new_run_time - cw_bat->run_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_RUN);
                allow_change += ((new_sleep_time - cw_bat->sleep_time_capacity_change) / BATTERY_DOWN_MIN_CHANGE_SLEEP);

                allow_capacity = cw_bat->capacity - allow_change;
                cw_capacity = (allow_capacity >= cw_capacity) ? allow_capacity: cw_capacity;
                reg_val[0] = MODE_NORMAL;
                ret = cw_write(cw_bat->client, REG_MODE, reg_val);
                if (ret < 0)
                        return ret;

        } else if ((cw_bat->charger_mode == 0) && (cw_capacity <= cw_bat->capacity ) && (cw_capacity >= 90) && (jump_flag == 1)) {     // avoid battery level jump to CW_BAT
                capacity_or_aconline_time = (cw_bat->sleep_time_capacity_change > cw_bat->sleep_time_charge_start) ? cw_bat->sleep_time_capacity_change : cw_bat->sleep_time_charge_start;
                capacity_or_aconline_time += (cw_bat->run_time_capacity_change > cw_bat->run_time_charge_start) ? cw_bat->run_time_capacity_change : cw_bat->run_time_charge_start;
                allow_change = (new_sleep_time + new_run_time - capacity_or_aconline_time) / BATTERY_DOWN_CHANGE;
                if (allow_change > 0) {
                        allow_capacity = cw_bat->capacity - allow_change; 
                        if (cw_capacity >= allow_capacity){
                        	jump_flag =0;
                        }
                        else{
                                cw_capacity = (allow_capacity <= 100) ? allow_capacity : 100;
                        }
                } else if (cw_capacity <= cw_bat->capacity) {
                        cw_capacity = cw_bat->capacity;
                }
        }
 
#if 1	
	if((cw_bat->charger_mode > 0) &&(cw_capacity == 0))
	{		  
                charge_time = new_sleep_time + new_run_time - cw_bat->sleep_time_charge_start - cw_bat->run_time_charge_start;
                if ((charge_time > BATTERY_DOWN_MAX_CHANGE_RUN_AC_ONLINE) && (if_quickstart == 0)) {
        		cw_quickstart(cw_bat);      // if the cw_capacity = 0 the cw2015 will qstrt
                        if_quickstart = 1;
                }
	} else if ((if_quickstart == 1)&&(cw_bat->charger_mode == 0)) {
    		if_quickstart = 0;
        }

#endif

#if 0
        if (cw_bat->plat_data->chg_ok_pin != INVALID_GPIO) {
                if(gpio_get_value(cw_bat->plat_data->chg_ok_pin) != cw_bat->plat_data->chg_ok_level) {
                        if (cw_capacity == 100) {
                                cw_capacity = 99;
                        }
                } else {
                        if (cw_bat->charger_mode > 0) {
                                cw_capacity = 100;
                        }
                }
        }
#endif

#ifdef SYSTEM_SHUTDOWN_VOLTAGE
        if ((cw_bat->charger_mode == 0) && (cw_capacity <= 10) && (cw_bat->voltage <= SYSTEM_SHUTDOWN_VOLTAGE)){      	     
                if (if_quickstart == 10){       	      	
                        cw_quickstart(cw_bat);
                        if_quickstart = 12;
                        cw_capacity = 0;
                } else if (if_quickstart <= 10)
                        if_quickstart =if_quickstart+2;
                dev_info(&cw_bat->client->dev, "the cw201x voltage is less than SYSTEM_SHUTDOWN_VOLTAGE !!!!!!!, funciton: %s, line: %d\n", __func__, __LINE__);
        } else if ((cw_bat->charger_mode > 0)&& (if_quickstart <= 12)) {
                if_quickstart = 0;
        }
#endif
        return cw_capacity;
}
//For non-timer-based busy check
void mvg_emmc_check_busy_and_reset(int delay_ms, int delay_us, u64 addr, u32 len)
{
    struct msdc_host *host=mtk_msdc_host[0];
    volatile unsigned int *reg1=(unsigned int *)(host->base+OFFSET_SDC_STS);
    //volatile unsigned int *reg2 = (unsigned int *)(host->base+OFFSET_MSDC_INT);
    static struct timespec t_start,t_end1;

    //Note: From msdc_response to here: 6571 consume 120us
    get_monotonic_boottime(&t_start);
    if ( delay_ms ) mdelay(delay_ms);
    if ( delay_us ) udelay(delay_us);
    get_monotonic_boottime(&t_end1);
    if ( (*reg1&SDC_STS_SDCBUSY) || (len==0) ) { //len=0 for erase
        //printk(KERN_ERR TAG " emmc_reset_mode %d\n", mvg_spoh_emmc_priv.emmc_reset_mode);
        if ( (mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_RESET_W_POWEROFF) ||
             (mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_RESET_WO_POWEROFF) ) {

            if ( t_end1.tv_nsec< t_start.tv_nsec ) {
                t_end1.tv_nsec=1000000000+t_end1.tv_nsec-t_start.tv_nsec;
            } else {
                t_end1.tv_nsec=t_end1.tv_nsec-t_start.tv_nsec;
            }

            if ( mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_RESET_W_POWEROFF ) {
                hwPowerDown(MT6325_POWER_LDO_VEMC33, "msdc");
                //hwPowerDown(MT6323_POWER_LDO_VIO18, "msdc"); //VIO18 shall not be turned off since system will hang

                #if 0
                if ( mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_RESET_W_POWEROFF ) {
                    while (upmu_get_qi_vemc_3v3_en());
                }
                #else
                mdelay(12); //wait LDO drop to about 0 --> Consult PMIC designer for time to wait.
                #endif
            }

            //Since print itself will add delay to perform wdt_arch_reset(),
            // only enable the next log only for measure planned timing and actual timing.
            if ( mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_RESET_W_POWEROFF ) {
                //printk(KERN_ERR TAG " %d us reset with poweroff, test len %d, addr %x, plan %u us\n", t_end1.tv_nsec/1000, len, (unsigned int)addr, delay_ms*1000+delay_us);
            } else {
                //printk(KERN_ERR TAG " %d us reset without poweroff, test len %d, addr %x, plan %u us\n", t_end1.tv_nsec/1000, len, (unsigned int)addr, delay_ms*1000+delay_us);
            }

            mvg_wdt_reset();

        } else if ( mvg_spoh_emmc_priv.emmc_reset_mode==MVG_EMMC_NO_RESET ) {
            //printk(KERN_ERR TAG " mvg_emmc_check_busy_and_reset wait %u\n", delay);
            if ( t_end1.tv_nsec< t_start.tv_nsec ) {
                t_end1.tv_nsec=1000000000+t_end1.tv_nsec-t_start.tv_nsec;
            } else {
                t_end1.tv_nsec=t_end1.tv_nsec-t_start.tv_nsec;
            }
            printk(KERN_ERR TAG " not reset after %d us, test len %d , addr %x, plan %u us\n", ((int)t_end1.tv_nsec)/1000, len, (unsigned int)addr, delay_ms*1000+delay_us);
            //Not really reset --> for UT/simulation mode
            mvg_spoh_emmc_priv.reset_time_divisor=1;
            return;
        }

    } else {
        printk(KERN_ERR TAG " busy end before %d us, test len %u\n", delay_ms*1000+delay_us, mvg_spoh_emmc_priv.match_len);
        #if 0
        mvg_emmc_reset_planned=0;
        #else
        mvg_emmc_reset_timeout=1;
        mvg_emmc_reset_planned--;
        #endif
        mvg_spoh_emmc_priv.reset_delay_result=1;
        //Fail to reset/poweroff before program finish. Double time divisor to shorten time before reset/poweroff
        mvg_spoh_emmc_priv.reset_time_divisor=mvg_spoh_emmc_priv.reset_time_divisor<<1;
    }
}
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int rv = 0;
    unsigned long flags;
    struct timespec new_alarm_time;
    struct timespec new_rtc_time;
    struct timespec tmp_time;
    struct rtc_time new_rtc_tm;
    struct rtc_device *rtc_dev;
    enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
    uint32_t alarm_type_mask = 1U << alarm_type;

    if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
        return -EINVAL;

    if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
        if ((file->f_flags & O_ACCMODE) == O_RDONLY)
            return -EPERM;
        if (file->private_data == NULL &&
                cmd != ANDROID_ALARM_SET_RTC) {
            spin_lock_irqsave(&alarm_slock, flags);
            if (alarm_opened) {
                spin_unlock_irqrestore(&alarm_slock, flags);
                return -EBUSY;
            }
            alarm_opened = 1;
            file->private_data = (void *)1;
            spin_unlock_irqrestore(&alarm_slock, flags);
        }
    }

    switch (ANDROID_ALARM_BASE_CMD(cmd)) {
    case ANDROID_ALARM_CLEAR(0):
        switch (alarm_type) {
        case ANDROID_ALARM_POWER_UP:
            /* disable power up alarm interrupt */
            rv = alarm_irq_enable(0);
            break;
        case ANDROID_ALARM_RTC_WAKEUP:
        case ANDROID_ALARM_RTC:
        case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
        case ANDROID_ALARM_ELAPSED_REALTIME:
        case ANDROID_ALARM_SYSTEMTIME:
            spin_lock_irqsave(&alarm_slock, flags);
            pr_alarm(IO, "alarm %d clear\n", alarm_type);
            devalarm_try_to_cancel(&alarms[alarm_type]);
            if (alarm_pending) {
                alarm_pending &= ~alarm_type_mask;
                if (!alarm_pending && !wait_pending)
                    wake_unlock(&alarm_wake_lock);
            }
            alarm_enabled &= ~alarm_type_mask;
            spin_unlock_irqrestore(&alarm_slock, flags);
            break;
        default:
            break;
        }
        break;

    case ANDROID_ALARM_SET_OLD:
    case ANDROID_ALARM_SET_AND_WAIT_OLD:
        if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
            rv = -EFAULT;
            goto err1;
        }
        new_alarm_time.tv_nsec = 0;
        goto from_old_alarm_set;
#if defined(CONFIG_RTC_CHN_ALARM_BOOT)
    case ANDROID_ALARM_SET_ALARM:
    {
        char bootalarm_data[14];

        if (copy_from_user(bootalarm_data, (void __user *)arg, 14)) {
            rv = -EFAULT;
            goto err1;
        }

        alarm_set_bootalarm(bootalarm_data);

        break;
    }
#endif
    case ANDROID_ALARM_SET_AND_WAIT(0):
    case ANDROID_ALARM_SET(0):
        if (copy_from_user(&new_alarm_time, (void __user *)arg,
                           sizeof(new_alarm_time))) {
            rv = -EFAULT;
            goto err1;
        }
from_old_alarm_set:
        spin_lock_irqsave(&alarm_slock, flags);
        pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
                 new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
        alarm_enabled |= alarm_type_mask;
        devalarm_start(&alarms[alarm_type],
                       timespec_to_ktime(new_alarm_time));
        spin_unlock_irqrestore(&alarm_slock, flags);
        if (alarm_type == ANDROID_ALARM_POWER_UP)
            alarm_set_rtc_ring(new_alarm_time);
        if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
                && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
            break;
    /* fall though */
    case ANDROID_ALARM_WAIT:
        spin_lock_irqsave(&alarm_slock, flags);
        pr_alarm(IO, "alarm wait\n");
        if (!alarm_pending && wait_pending) {
            wake_unlock(&alarm_wake_lock);
            wait_pending = 0;
        }
        spin_unlock_irqrestore(&alarm_slock, flags);
        rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
        if (rv)
            goto err1;
        spin_lock_irqsave(&alarm_slock, flags);
        rv = alarm_pending;
        wait_pending = 1;
        alarm_pending = 0;
        spin_unlock_irqrestore(&alarm_slock, flags);
        break;
    case ANDROID_ALARM_SET_RTC:
        if (copy_from_user(&new_rtc_time, (void __user *)arg,
                           sizeof(new_rtc_time))) {
            rv = -EFAULT;
            goto err1;
        }
        rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
        rtc_dev = alarmtimer_get_rtcdev();
        rv = do_settimeofday(&new_rtc_time);
        if (rv < 0)
            goto err1;
        if (rtc_dev)
            rv = rtc_set_time(rtc_dev, &new_rtc_tm);

        if (pwr_rtc_dev)
            rv = rtc_set_time(pwr_rtc_dev, &new_rtc_tm);

        spin_lock_irqsave(&alarm_slock, flags);
        alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
        wake_up(&alarm_wait_queue);
        spin_unlock_irqrestore(&alarm_slock, flags);
        if (rv < 0)
            goto err1;
        break;
    case ANDROID_ALARM_GET_TIME(0):
        switch (alarm_type) {
        case ANDROID_ALARM_RTC_WAKEUP:
        case ANDROID_ALARM_POWER_UP:
        case ANDROID_ALARM_RTC:
            getnstimeofday(&tmp_time);
            break;
        case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
        case ANDROID_ALARM_ELAPSED_REALTIME:
            get_monotonic_boottime(&tmp_time);
            break;
        case ANDROID_ALARM_TYPE_COUNT:
        case ANDROID_ALARM_SYSTEMTIME:
            ktime_get_ts(&tmp_time);
            break;
        }
        if (copy_to_user((void __user *)arg, &tmp_time,
                         sizeof(tmp_time))) {
            rv = -EFAULT;
            goto err1;
        }
        break;

    default:
        rv = -EINVAL;
        goto err1;
    }
err1:
    return rv;
}
static void baro_work_func(struct work_struct *work)
{

	struct baro_context *cxt = NULL;
	/* hwm_sensor_data sensor_data; */
	int value, status;
	int64_t pre_ns, cur_ns;
	int64_t delay_ms;
	struct timespec time;
	int err;

	cxt = baro_context_obj;
	delay_ms = atomic_read(&cxt->delay);

	if (NULL == cxt->baro_data.get_data)
		BARO_LOG("baro driver not register data path\n");

	time.tv_sec = time.tv_nsec = 0;
	get_monotonic_boottime(&time);
	cur_ns = time.tv_sec*1000000000LL+time.tv_nsec;

	/* add wake lock to make sure data can be read before system suspend */
	err = cxt->baro_data.get_data(&value, &status);

	if (err) {
		BARO_ERR("get baro data fails!!\n");
		goto baro_loop;
	} else {
		{
			cxt->drv_data.baro_data.values[0] = value;
			cxt->drv_data.baro_data.status = status;
			pre_ns = cxt->drv_data.baro_data.time;
			cxt->drv_data.baro_data.time = cur_ns;
		}
	}

	if (true == cxt->is_first_data_after_enable) {
		pre_ns = cur_ns;
		cxt->is_first_data_after_enable = false;
		/* filter -1 value */
		if (BARO_INVALID_VALUE == cxt->drv_data.baro_data.values[0]) {
			BARO_LOG(" read invalid data\n");
			goto baro_loop;

		}
	}
	/* report data to input device */
	/*BARO_LOG("new baro work run....\n"); */
	/*BARO_LOG("baro data[%d].\n", cxt->drv_data.baro_data.values[0]); */

	while ((cur_ns - pre_ns) >= delay_ms*1800000LL) {
		pre_ns += delay_ms*1000000LL;
		baro_data_report(cxt->idev,
			cxt->drv_data.baro_data.values[0],
			cxt->drv_data.baro_data.status, pre_ns);
	}

	baro_data_report(cxt->idev,
		cxt->drv_data.baro_data.values[0],
		cxt->drv_data.baro_data.status, cxt->drv_data.baro_data.time);

baro_loop:
	if (true == cxt->is_polling_run) {
		{
			startTimer(&cxt->hrTimer, atomic_read(&cxt->delay), false);
		}
	}
}
Beispiel #26
0
static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv = 0;
	unsigned long flags;
	struct timespec new_alarm_time;
	struct timespec new_rtc_time;
	struct timespec tmp_time;
	struct rtc_time new_rtc_tm;
	struct rtc_device *rtc_dev;
	struct rtc_wkalrm pwron_alm;
	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
	uint32_t alarm_type_mask = 1U << alarm_type;

 	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT &&
	    alarm_type != ANDROID_ALARM_POWER_ON &&
	    alarm_type != ANDROID_ALARM_POWER_ON_LOGO) {
		return -EINVAL;
	}
	
	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
			return -EPERM;
		if (file->private_data == NULL &&
		    cmd != ANDROID_ALARM_SET_RTC) {
			spin_lock_irqsave(&alarm_slock, flags);
			if (alarm_opened) {
				spin_unlock_irqrestore(&alarm_slock, flags);
				return -EBUSY;
			}
			alarm_opened = 1;
			file->private_data = (void *)1;
			spin_unlock_irqrestore(&alarm_slock, flags);
		}
	}

	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
	case ANDROID_ALARM_CLEAR(0):
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		if (alarm_type == ANDROID_ALARM_POWER_ON ||
			alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			new_alarm_time.tv_sec = 0;
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm %d clear\n", alarm_type);
		devalarm_try_to_cancel(&alarms[alarm_type]);
		if (alarm_pending) {
			alarm_pending &= ~alarm_type_mask;
			if (!alarm_pending && !wait_pending)
				wake_unlock(&alarm_wake_lock);
		}
		alarm_enabled &= ~alarm_type_mask;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;

	case ANDROID_ALARM_SET_OLD:
	case ANDROID_ALARM_SET_AND_WAIT_OLD:
		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
			rv = -EFAULT;
			goto err1;
		}
		new_alarm_time.tv_nsec = 0;
		goto from_old_alarm_set;

	case ANDROID_ALARM_SET_AND_WAIT(0):
	case ANDROID_ALARM_SET(0):
		if (copy_from_user(&new_alarm_time, (void __user *)arg,
		    sizeof(new_alarm_time))) {
			rv = -EFAULT;
			goto err1;
		}
from_old_alarm_set:
		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);

		if (alarm_type == ANDROID_ALARM_POWER_ON) {
			alarm_set_power_on(new_alarm_time, false);
			break;
		}
		if (alarm_type == ANDROID_ALARM_POWER_ON_LOGO) {
			alarm_set_power_on(new_alarm_time, true);
			break;
		}
		spin_lock_irqsave(&alarm_slock, flags);
	
		alarm_enabled |= alarm_type_mask;
		devalarm_start(&alarms[alarm_type],
			timespec_to_ktime(new_alarm_time));
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
			break;
		/* fall though */
	case ANDROID_ALARM_WAIT:
		spin_lock_irqsave(&alarm_slock, flags);
		pr_alarm(IO, "alarm wait\n");
		if (!alarm_pending && wait_pending) {
			wake_unlock(&alarm_wake_lock);
			wait_pending = 0;
		}
		spin_unlock_irqrestore(&alarm_slock, flags);
		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
		if (rv)
			goto err1;
		spin_lock_irqsave(&alarm_slock, flags);
		rv = alarm_pending;
		wait_pending = 1;
		alarm_pending = 0;
		spin_unlock_irqrestore(&alarm_slock, flags);
		break;
	case ANDROID_ALARM_SET_RTC:
		if (copy_from_user(&new_rtc_time, (void __user *)arg,
		    sizeof(new_rtc_time))) {
			rv = -EFAULT;
			goto err1;
		}
		rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm);
		
		pr_alarm(IO, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
		new_rtc_time.tv_sec, new_rtc_time.tv_nsec,
		new_rtc_tm.tm_hour, new_rtc_tm.tm_min,
		new_rtc_tm.tm_sec, new_rtc_tm.tm_mon + 1,
		new_rtc_tm.tm_mday,
		new_rtc_tm.tm_year + 1900);

		rtc_dev = alarmtimer_get_rtcdev();
		rv = do_settimeofday(&new_rtc_time);
		if (rv < 0)
		{	
			goto err1;
		}
		if (rtc_dev)
		{
			rv = rtc_set_time(rtc_dev, &new_rtc_tm);
		}
		spin_lock_irqsave(&alarm_slock, flags);
		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
		wake_up(&alarm_wait_queue);
		spin_unlock_irqrestore(&alarm_slock, flags);
		if (rv < 0)
			goto err1;
		break;
	case ANDROID_ALARM_GET_TIME(0):
		switch (alarm_type) {
		case ANDROID_ALARM_RTC_WAKEUP:
		case ANDROID_ALARM_RTC:
			getnstimeofday(&tmp_time);
			break;
		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
		case ANDROID_ALARM_ELAPSED_REALTIME:
			get_monotonic_boottime(&tmp_time);
			break;
		case ANDROID_ALARM_TYPE_COUNT:
		case ANDROID_ALARM_SYSTEMTIME:
			ktime_get_ts(&tmp_time);
			break;
		case ANDROID_ALARM_POWER_ON:
		case ANDROID_ALARM_POWER_ON_LOGO:
			break;		
		}
		if (copy_to_user((void __user *)arg, &tmp_time,
		    sizeof(tmp_time))) {
			rv = -EFAULT;
			goto err1;
		}
		break;
	case ANDROID_ALARM_GET_POWER_ON:
		alarm_get_power_on(&pwron_alm);
		if (copy_to_user((void __user *)arg, &pwron_alm,
		    sizeof(struct rtc_wkalrm))) {
			rv = -EFAULT;
			goto err1;
		}
		break;

	default:
		rv = -EINVAL;
		goto err1;
	}
err1:
	return rv;
}