/* interrupt work handler */ static void stmvl6180_work_handler(struct work_struct *work) { struct stmvl6180_data *data = gp_vl6180_data; int ret = 0; uint8_t to_startPS = 0; uint8_t range_status=0, range_start=0; mutex_lock(&data->work_mutex); if (data->enable_ps_sensor == 1) { /* vl6180_dbgmsg("Enter\n"); */ data->rangeData.errorStatus = 0xFF; /* to reset the data, should be set by API */ VL6180x_RdByte(vl6180x_dev, RESULT_RANGE_STATUS, &range_status); VL6180x_RdByte(vl6180x_dev, SYSRANGE_START, &range_start); if (data->enableDebug) { vl6180_errmsg("RangeStatus as 0x%x,RangeStart: 0x%x\n",range_status,range_start); } if (range_start == 0 && (range_status & 0x01) == 0x01) { ret = VL6180x_RangeGetMeasurementIfReady(vl6180x_dev, &(data->rangeData)); if (!ret && data->rangeData.errorStatus !=DataNotReady ) { if (data->ps_is_singleshot) to_startPS = 1; if (data->rangeData.errorStatus == 17) data->rangeData.errorStatus = 16; stmvl6180_ps_read_measurement(); /* to update data */ } } //if (!ret) // stmvl6180_ps_read_measurement(); /* to update data */ if (to_startPS) VL6180x_RangeSetSystemMode(vl6180x_dev, MODE_START_STOP | MODE_SINGLESHOT); /* restart timer */ schedule_delayed_work(&data->dwork, msecs_to_jiffies((data->delay_ms))); /* vl6180_dbgmsg("End\n"); */ } mutex_unlock(&data->work_mutex); return; }
/* * Initialization function */ static int stmvl6180_init_client(struct stmvl6180_data *data) { uint8_t id = 0, module_major = 0, module_minor = 0; uint8_t model_major = 0, model_minor = 0; uint8_t i = 0, val; vl6180_dbgmsg("Enter\n"); /* Read Model ID */ VL6180x_RdByte(vl6180x_dev, VL6180_MODEL_ID_REG, &id); vl6180_errmsg("read MODLE_ID: 0x%x\n", id); if (id == 0xb4) { vl6180_errmsg("STM VL6180 Found\n"); } else if (id == 0) { vl6180_errmsg("Not found STM VL6180\n"); } /* Read Model Version */ VL6180x_RdByte(vl6180x_dev, VL6180_MODEL_REV_MAJOR_REG, &model_major); model_major &= 0x07; VL6180x_RdByte(vl6180x_dev, VL6180_MODEL_REV_MINOR_REG, &model_minor); model_minor &= 0x07; vl6180_errmsg("STM VL6180 Model Version : %d.%d\n", model_major, model_minor); /* Read Module Version */ VL6180x_RdByte(vl6180x_dev, VL6180_MODULE_REV_MAJOR_REG, &module_major); VL6180x_RdByte(vl6180x_dev, VL6180_MODULE_REV_MINOR_REG, &module_minor); vl6180_errmsg("STM VL6180 Module Version : %d.%d\n", module_major, module_minor); /* Read Identification */ printk("STM VL6180 Serial Numbe: "); for (i = 0; i <= (VL6180_FIRMWARE_REVISION_ID_REG - VL6180_REVISION_ID_REG); i++) { VL6180x_RdByte(vl6180x_dev, (VL6180_REVISION_ID_REG + i), &val); printk("0x%x-", val); } printk("\n"); /* intialization */ if (data->reset) { /* no need vl6180_dbgmsg("WaitDeviceBoot"); VL6180x_WaitDeviceBooted(vl6180x_dev); */ /* only called if device being reset, otherwise data being overwrite */ vl6180_dbgmsg("Init data!"); VL6180x_InitData(vl6180x_dev); /* only called if device being reset */ data->reset = 0; } /* set user calibration data - need to be called after VL6180x_InitData */ #ifdef CALIBRATION_FILE stmvl6180_read_calibration_file(); #endif vl6180_dbgmsg("End\n"); return 0; }
/** * call in the main loop * when running under debugger it enable doing direct vl6180x reg access * After breaking at entrance * change the the local index/data and cmd variable to do what needed * reg_cmd -1 wr byte -2wr word -3 wr dword * reg_cmd 1 rd byte 2 rd word 3 rd dword * step to last statement before return and read variable to get rd result exit */ void debug_stuff(void) { int reg_cmd = 0; static uint32_t reg_data; static uint16_t reg_index; if (reg_cmd) { switch (reg_cmd) { case -1: VL6180x_WrByte(theVL6180xDev, reg_index, reg_data); debug("Wr B 0x%X = %d", reg_index, (int)reg_data); break; case -2: VL6180x_WrWord(theVL6180xDev, reg_index, reg_data); debug("Wr W 0x%X = %d", reg_index, (int) reg_data); break; case -3: VL6180x_WrDWord(theVL6180xDev, reg_index, reg_data); debug("WrDW 0x%X = %d", reg_index, (int)reg_data); break; case 1: reg_data = 0; VL6180x_RdByte(theVL6180xDev, reg_index, (uint8_t*) ®_data); debug("RD B 0x%X = %d", reg_index, (int)reg_data); break; case 2: reg_data = 0; VL6180x_RdWord(theVL6180xDev, reg_index, (uint16_t*) ®_data); debug("RD W 0x%X = %d", reg_index, (int)reg_data); break; case 3: VL6180x_RdDWord(theVL6180xDev, reg_index, ®_data); debug("RD DW 0x%X = %d", reg_index, (int)reg_data); break; default: debug("Invalid command %d", reg_cmd); /* nothing to do*/ ; } } }
/* * misc device file operation functions */ static int stmvl6180_ioctl_handler(struct file *file, unsigned int cmd, unsigned long arg, void __user *p) { int rc = 0; unsigned int xtalkint = 0; int8_t offsetint = 0; struct stmvl6180_data *data = gp_vl6180_data; struct stmvl6180_register reg; if (!data) return -EINVAL; vl6180_dbgmsg("Enter enable_ps_sensor:%d\n", data->enable_ps_sensor); switch (cmd) { /* enable */ case VL6180_IOCTL_INIT: pr_err("%s: VL6180_IOCTL_INIT\n", __func__); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, NORMAL_MODE); } else rc = -EINVAL; break; /* crosstalk calibration */ case VL6180_IOCTL_XTALKCALB: vl6180_dbgmsg("VL6180_IOCTL_XTALKCALB\n"); /* turn on tof sensor only if it's not enabled by other client */ if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, XTALKCALIB_MODE); } else rc = -EINVAL; break; /* set up Xtalk value */ case VL6180_IOCTL_SETXTALK: vl6180_dbgmsg("VL6180_IOCTL_SETXTALK\n"); if (copy_from_user(&xtalkint, (unsigned int *)p, sizeof(unsigned int))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETXTALK as 0x%x\n", xtalkint); #ifdef CALIBRATION_FILE xtalk_calib = xtalkint; stmvl6180_write_xtalk_calibration_file(); #endif VL6180x_SetXTalkCompensationRate(vl6180x_dev, xtalkint); break; /* offset calibration */ case VL6180_IOCTL_OFFCALB: vl6180_dbgmsg("VL6180_IOCTL_OFFCALB\n"); if (data->enable_ps_sensor == 0) { /* to start */ stmvl6180_start(data, 3, OFFSETCALIB_MODE); } else rc = -EINVAL; break; /* set up offset value */ case VL6180_IOCTL_SETOFFSET: vl6180_dbgmsg("VL6180_IOCTL_SETOFFSET\n"); if (copy_from_user(&offsetint, (int8_t *)p, sizeof(int8_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } vl6180_dbgmsg("SETOFFSET as %d\n", offsetint); #ifdef CALIBRATION_FILE offset_calib = offsetint; stmvl6180_write_offset_calibration_file(); #endif VL6180x_SetOffsetCalibrationData(vl6180x_dev, offsetint); break; /* disable */ case VL6180_IOCTL_STOP: vl6180_errmsg("VL6180_IOCTL_STOP\n"); /* turn off tof sensor only if it's enabled by other client */ if (data->enable_ps_sensor == 1) { data->enable_ps_sensor = 0; /* to stop */ stmvl6180_stop(data); } break; /* Get all range data */ case VL6180_IOCTL_GETDATAS: vl6180_dbgmsg("VL6180_IOCTL_GETDATAS\n"); if (copy_to_user((VL6180x_RangeData_t *)p, &(data->rangeData), sizeof(VL6180x_RangeData_t))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; case VL6180_IOCTL_REGISTER: vl6180_dbgmsg("VL6180_IOCTL_REGISTER\n"); if (copy_from_user(®, (struct stmvl6180_register *)p, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } reg.status = 0; switch (reg.reg_bytes) { case(4): if (reg.is_read) reg.status = VL6180x_RdDWord(vl6180x_dev, (uint16_t)reg.reg_index, ®.reg_data); else reg.status = VL6180x_WrDWord(vl6180x_dev, (uint16_t)reg.reg_index, reg.reg_data); break; case(2): if (reg.is_read) reg.status = VL6180x_RdWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t *)®.reg_data); else reg.status = VL6180x_WrWord(vl6180x_dev, (uint16_t)reg.reg_index, (uint16_t)reg.reg_data); break; case(1): if (reg.is_read) reg.status = VL6180x_RdByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t *)®.reg_data); else reg.status = VL6180x_WrByte(vl6180x_dev, (uint16_t)reg.reg_index, (uint8_t)reg.reg_data); break; default: reg.status = -1; } if (copy_to_user((struct stmvl6180_register *)p, ®, sizeof(struct stmvl6180_register))) { vl6180_errmsg("%d, fail\n", __LINE__); return -EFAULT; } break; default: rc = -EINVAL; break; } return rc; }