int check_fwbl(struct ssp_data *data) { unsigned int fw_revision; fw_revision = SSP_FIRMWARE_REVISION_STM; data->uCurFirmRev = get_firmware_rev(data); if ((data->uCurFirmRev == SSP_INVALID_REVISION) || (data->uCurFirmRev == SSP_INVALID_REVISION2)) { data->uCurFirmRev = SSP_INVALID_REVISION; ssp_err("SSP_INVALID_REVISION"); return FW_DL_STATE_NEED_TO_SCHEDULE; } else { if (data->uCurFirmRev != fw_revision) { ssp_info("MCU Firm Rev : Old = %8u, New = %8u", data->uCurFirmRev, fw_revision); return FW_DL_STATE_NEED_TO_SCHEDULE; } ssp_info("MCU Firm Rev : Old = %8u, New = %8u", data->uCurFirmRev, fw_revision); } return FW_DL_STATE_NONE; }
int initialize_mcu(struct ssp_data *data) { int iRet = 0; clean_pending_list(data); iRet = get_chipid(data); ssp_info("MCU device ID = %d, reading ID = %d", DEVICE_ID, iRet); if (iRet != DEVICE_ID) { if (iRet < 0) { ssp_errf("MCU is not working : 0x%x", iRet); } else { ssp_errf("MCU identification failed"); iRet = -ENODEV; } goto out; } iRet = set_sensor_position(data); if (iRet < 0) { ssp_errf("set_sensor_position failed"); goto out; } #ifdef CONFIG_SENSORS_MULTIPLE_GLASS_TYPE iRet = set_glass_type(data); if (iRet < 0) { pr_err("[SSP]: %s - set_sensor_position failed\n", __func__); goto out; } #endif data->uSensorState = get_sensor_scanning_info(data); if (data->uSensorState == 0) { ssp_errf("get_sensor_scanning_info failed"); iRet = ERROR; goto out; } iRet = initialize_magnetic_sensor(data); if (iRet < 0) ssp_errf("initialize magnetic sensor failed"); data->uCurFirmRev = get_firmware_rev(data); ssp_info("MCU Firm Rev : New = %8u", data->uCurFirmRev); out: return iRet; }
int gyro_open_calibration(struct ssp_data *data) { int iRet = 0; mm_segment_t old_fs; struct file *cal_filp = NULL; old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CALIBRATION_FILE_PATH, O_RDONLY | O_NOFOLLOW, 0660); if (IS_ERR(cal_filp)) { set_fs(old_fs); iRet = PTR_ERR(cal_filp); data->gyrocal.x = 0; data->gyrocal.y = 0; data->gyrocal.z = 0; return iRet; } iRet = cal_filp->f_op->read(cal_filp, (char *)&data->gyrocal, sizeof(data->gyrocal), &cal_filp->f_pos); if (iRet != sizeof(data->gyrocal)) iRet = -EIO; filp_close(cal_filp, current->files); set_fs(old_fs); ssp_info("open gyro calibration %d, %d, %d", data->gyrocal.x, data->gyrocal.y, data->gyrocal.z); return iRet; }
void sync_sensor_state(struct ssp_data *data) { unsigned char uBuf[9] = {0,}; unsigned int uSensorCnt; int iRet = 0; iRet = set_gyro_cal(data); if (iRet < 0) ssp_errf("set_gyro_cal failed"); iRet = set_accel_cal(data); if (iRet < 0) ssp_errf("set_accel_cal failed"); udelay(10); for (uSensorCnt = 0; uSensorCnt < SENSOR_MAX; uSensorCnt++) { if (atomic64_read(&data->aSensorEnable) & (1 << uSensorCnt)) { s32 dMsDelay = get_msdelay(data->adDelayBuf[uSensorCnt]); memcpy(&uBuf[0], &dMsDelay, 4); memcpy(&uBuf[4], &data->batchLatencyBuf[uSensorCnt], 4); uBuf[8] = data->batchOptBuf[uSensorCnt]; send_instruction(data, ADD_SENSOR, uSensorCnt, uBuf, 9); udelay(10); } } if (data->bProximityRawEnabled == true) { s32 dMsDelay = 20; memcpy(&uBuf[0], &dMsDelay, 4); send_instruction(data, ADD_SENSOR, PROXIMITY_RAW, uBuf, 4); } set_proximity_threshold(data, data->uProxHiThresh, data->uProxLoThresh); data->buf[PROXIMITY_SENSOR].prox = 0; report_sensordata(data, PROXIMITY_SENSOR, &data->buf[PROXIMITY_SENSOR]); #if 1 if(sec_debug_get_debug_level() > 0) { data->bMcuDumpMode = true; ssp_info("Mcu Dump Enabled"); } iRet = ssp_send_cmd(data, MSG2SSP_AP_MCU_SET_DUMPMODE, data->bMcuDumpMode); if (iRet < 0) ssp_errf("MSG2SSP_AP_MCU_SET_DUMPMODE failed"); #else #if CONFIG_SEC_DEBUG data->bMcuDumpMode = sec_debug_is_enabled(); iRet = ssp_send_cmd(data, MSG2SSP_AP_MCU_SET_DUMPMODE, data->bMcuDumpMode); if (iRet < 0) ssp_errf("MSG2SSP_AP_MCU_SET_DUMPMODE failed"); #endif #endif }
static int change_to_bootmode(struct ssp_data *data) { int iCnt; int ret; char syncb = BL_SPI_SOF; int ncount = 5; struct stm32fwu_spi_cmd dummy_cmd; ssp_dbgf(); /* dummy_cmd.timeout = DEF_ACKCMD_NUMBER; */ dummy_cmd.timeout = ncount; gpio_set_value_cansleep(data->rst, 0); usleep_range(4000, 4400); gpio_set_value_cansleep(data->rst, 1); usleep_range(45000, 47000); for (iCnt = 0; iCnt < 9; iCnt++) { gpio_set_value_cansleep(data->rst, 0); usleep_range(4000, 4400); gpio_set_value_cansleep(data->rst, 1); usleep_range(15000, 15500); } data->spi->mode = SPI_MODE_0; if (spi_setup(data->spi)) ssp_err("failed to setup spi mode for boot"); usleep_range(1000, 1100); msleep(30); while (ncount-- >= 0) { ret = stm32fwu_spi_write(data->spi, &syncb, 1); #if SSP_STM_DEBUG ssp_info("stm32fwu_spi_write(sync byte) returned %d", ret); #endif ret = stm32fwu_spi_wait_for_ack(data->spi, &dummy_cmd, BL_DUMMY); #if SSP_STM_DEBUG ssp_info("stm32fwu_spi_wait_for_ack returned %d (0x%x)", ret, ret); #endif if (ret == BL_ACK) break; } return ret; }
static int update_mcu_bin(struct ssp_data *data, int iBinType) { int retry = BLMODE_RETRYCOUNT; int iRet = SUCCESS; struct stm32fwu_spi_cmd cmd; cmd.cmd = GO_COMMAND; cmd.xor_cmd = XOR_GO_COMMAND; cmd.timeout = 1000; cmd.ack_pad = (u8)((STM_APP_ADDR >> 24) & 0xFF); /* 1. Start system boot mode */ do { iRet = change_to_bootmode(data); ssp_info("bootmode %d retry: %d", iRet, 3 - retry); } while (retry-- > 0 && iRet != BL_ACK); if (iRet != BL_ACK) { ssp_errf("change_to_bootmode %d", iRet); return iRet; } /* 2. Flash erase all */ iRet = fw_erase_stm(data->spi); if (iRet < 0) { ssp_errf("fw_erase_stm %d", iRet); return iRet; } switch (iBinType) { case KERNEL_BINARY: /* HW request: I2C line is reversed */ iRet = load_kernel_fw_bootmode(data->spi, BL_FW_NAME); break; case KERNEL_CRASHED_BINARY: iRet = load_kernel_fw_bootmode(data->spi, BL_CRASHED_FW_NAME); break; case UMS_BINARY: iRet = load_ums_fw_bootmode(data->spi, BL_UMS_FW_NAME); break; default: ssp_err("binary type error!!"); } /* STM : GO USER ADDR */ stm32fwu_spi_send_cmd(data->spi, &cmd); send_addr(data->spi, STM_APP_ADDR, 0); data->spi->mode = SPI_MODE_1; if (spi_setup(data->spi)) ssp_err("failed to setup spi mode for app"); usleep_range(1000, 1100); return iRet; }
static ssize_t proximity_cancel_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ssp_data *data = dev_get_drvdata(dev); ssp_info("uProxThresh : hi : %u lo : %u, uProxCanc = %u", data->uProxHiThresh, data->uProxLoThresh, data->uProxCanc); return sprintf(buf, "%u,%u,%u\n", data->uProxCanc, data->uProxHiThresh, data->uProxLoThresh); }
static ssize_t proximity_thresh_low_show(struct device *dev, struct device_attribute *attr, char *buf) { struct ssp_data *data = dev_get_drvdata(dev); ssp_info("uProxThresh = hi - %u, lo - %u", data->uProxHiThresh, data->uProxLoThresh); return sprintf(buf, "%u,%u\n", data->uProxHiThresh, data->uProxLoThresh); }
static ssize_t accel_calibration_show(struct device *dev, struct device_attribute *attr, char *buf) { int iRet; struct ssp_data *data = dev_get_drvdata(dev); iRet = accel_open_calibration(data); if (iRet < 0) pr_err("[SSP]: %s - calibration open failed(%d)\n", __func__, iRet); ssp_info("Cal data : %d %d %d - %d", data->accelcal.x, data->accelcal.y, data->accelcal.z, iRet); return sprintf(buf, "%d %d %d %d\n", iRet, data->accelcal.x, data->accelcal.y, data->accelcal.z); }
static irqreturn_t sensordata_irq_thread_fn(int iIrq, void *dev_id) { struct ssp_data *data = dev_id; struct timespec ts; ts = ktime_to_timespec(ktime_get_boottime()); data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; if (gpio_get_value(data->mcu_int1)) { ssp_info("MCU int HIGH"); return IRQ_HANDLED; } select_irq_msg(data); data->uIrqCnt++; return IRQ_HANDLED; }
int forced_to_download_binary(struct ssp_data *data, int iBinType) { int iRet = 0; int retry = 3; ssp_infof("mcu binany update!"); ssp_enable(data, false); data->fw_dl_state = FW_DL_STATE_DOWNLOADING; ssp_infof("DL state = %d", data->fw_dl_state); data->spi->max_speed_hz = BOOT_SPI_HZ; if (spi_setup(data->spi)) ssp_err("failed to setup spi for ssp_boot"); do { ssp_info("%d try", 3 - retry); iRet = update_mcu_bin(data, iBinType); } while (retry-- > 0 && iRet < 0); data->spi->max_speed_hz = NORM_SPI_HZ; if (spi_setup(data->spi)) ssp_err("failed to setup spi for ssp_norm"); if (iRet < 0) { ssp_infof("update_mcu_bin failed!"); goto out; } data->fw_dl_state = FW_DL_STATE_SYNC; ssp_infof("DL state = %d", data->fw_dl_state); ssp_enable(data, true); get_proximity_threshold(data); proximity_open_calibration(data); accel_open_calibration(data); gyro_open_calibration(data); pressure_open_calibration(data); data->fw_dl_state = FW_DL_STATE_DONE; ssp_infof("DL state = %d", data->fw_dl_state); iRet = SUCCESS; out: return iRet; }
void print_dataframe(struct ssp_data *data, char *dataframe, int frame_len) { char *raw_data; int size = 0; int i = 0; raw_data = kzalloc(frame_len*4, GFP_KERNEL); if (raw_data == NULL) return; for (i = 0; i < frame_len; i++) { size += snprintf(raw_data+size, PAGE_SIZE, "%d ", *(dataframe + i)); } ssp_info("%s", raw_data); kfree(raw_data); }
int print_mcu_debug(char *pchRcvDataFrame, int *pDataIdx, int iRcvDataFrameLength) { u16 length = 0; int cur = *pDataIdx; memcpy(&length, pchRcvDataFrame + *pDataIdx, 1); *pDataIdx += 1; if (length > iRcvDataFrameLength - *pDataIdx || length <= 0) { ssp_infof("[M] invalid debug length(%u/%d/%d)", length, iRcvDataFrameLength, cur); return length ? length : ERROR; } ssp_info("[M] %s", &pchRcvDataFrame[*pDataIdx]); *pDataIdx += length; return 0; }
int save_gyro_caldata(struct ssp_data *data, s16 *iCalData) { int iRet = 0; struct file *cal_filp = NULL; mm_segment_t old_fs; if (data->bSspShutdown) return -EIO; data->gyrocal.x = iCalData[0]; data->gyrocal.y = iCalData[1]; data->gyrocal.z = iCalData[2]; ssp_info("do gyro calibrate %d, %d, %d", data->gyrocal.x, data->gyrocal.y, data->gyrocal.z); old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CALIBRATION_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY | O_NOFOLLOW, 0660); if (IS_ERR(cal_filp)) { pr_err("[SSP]: %s - Can't open calibration file\n", __func__); set_fs(old_fs); iRet = PTR_ERR(cal_filp); return -EIO; } iRet = cal_filp->f_op->write(cal_filp, (char *)&data->gyrocal, sizeof(data->gyrocal), &cal_filp->f_pos); if (iRet != sizeof(data->gyrocal)) { pr_err("[SSP]: %s - Can't write gyro cal to file\n", __func__); iRet = -EIO; } filp_close(cal_filp, current->files); set_fs(old_fs); return iRet; }
static ssize_t accel_lowpassfilter_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { int iRet = 0, new_enable = 1; struct ssp_data *data = dev_get_drvdata(dev); struct ssp_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL); if (msg == NULL) { pr_err("[SSP] %s, failed to alloc memory\n", __func__); goto exit; } if (sysfs_streq(buf, "1")) new_enable = 1; else if (sysfs_streq(buf, "0")) new_enable = 0; else ssp_info(" invalid value!"); msg->cmd = MSG2SSP_AP_SENSOR_LPF; msg->length = 1; msg->options = AP2HUB_WRITE; msg->buffer = (char*) kzalloc(1, GFP_KERNEL); if (msg->buffer == NULL) { pr_err("[SSP] %s, failed to alloc memory\n", __func__); kfree(msg); goto exit; } *msg->buffer = new_enable; msg->free_buffer = 1; iRet = ssp_spi_async(data, msg); if (iRet != SUCCESS) pr_err("[SSP] %s - fail %d\n", __func__, iRet); else pr_info("[SSP] %s - %d\n", __func__, new_enable); exit: return size; }
static int initialize_irq(struct ssp_data *data) { int iRet, iIrq; iIrq = gpio_to_irq(data->mcu_int1); ssp_info("requesting IRQ %d", iIrq); iRet = request_threaded_irq(iIrq, NULL, sensordata_irq_thread_fn, IRQF_TRIGGER_FALLING|IRQF_ONESHOT, "SSP_Int", data); if (iRet < 0) { ssp_errf("request_irq(%d) failed for gpio %d (%d)", iIrq, iIrq, iRet); goto err_request_irq; } /* start with interrupts disabled */ data->iIrq = iIrq; disable_irq(data->iIrq); return 0; err_request_irq: gpio_free(data->mcu_int1); return iRet; }
static void ssp_sensorhub_log(const char *func_name, const char *data, int length) { char buf[6]; char *log_str; int log_size; int i; if (likely(length <= BIG_DATA_SIZE)) log_size = length; else log_size = PRINT_TRUNCATE * 2 + 1; log_size = sizeof(buf) * log_size + 1; log_str = kzalloc(log_size, GFP_ATOMIC); if (unlikely(!log_str)) { ssp_errf("allocate memory for data log err"); return; } for (i = 0; i < length; i++) { if (length < BIG_DATA_SIZE || i < PRINT_TRUNCATE || i >= length - PRINT_TRUNCATE) { snprintf(buf, sizeof(buf), "%d", (signed char)data[i]); strlcat(log_str, buf, log_size); if (i < length - 1) strlcat(log_str, ", ", log_size); } if (length > BIG_DATA_SIZE && i == PRINT_TRUNCATE) strlcat(log_str, "..., ", log_size); } ssp_info("%s(%d): %s", func_name, length, log_str); kfree(log_str); }
static int fw_write_stm(struct spi_device *spi, u32 fw_addr, int len, const u8 *buffer) { int res; struct stm32fwu_spi_cmd cmd; struct stm32fwu_spi_cmd dummy_cmd; int i; u8 xor = 0; u8 send_buff[STM_MAX_BUFFER_SIZE] = {0,}; cmd.cmd = WMEM_COMMAND; cmd.xor_cmd = XOR_WMEM_COMMAND; cmd.timeout = DEF_ACKCMD_NUMBER; cmd.ack_pad = (u8)((fw_addr >> 24) & 0xFF); ssp_dbgf(); #if SSP_STM_DEBUG ssp_info("sending WMEM_COMMAND"); #endif if (len > STM_MAX_XFER_SIZE) { ssp_err("Can't send more than 256 bytes per transaction"); return -EINVAL; } send_buff[0] = len - 1; memcpy(&send_buff[1], buffer, len); for (i = 0; i < (len + 1); i++) xor ^= send_buff[i]; send_buff[len + 1] = xor; res = stm32fwu_spi_send_cmd(spi, &cmd); if (res != BL_ACK) { ssp_err("Error %d sending read_mem cmd", res); return res; } res = send_addr(spi, fw_addr, 0); if (res != 0) { ssp_err("Error %d sending write_mem Address", res); return res; } res = stm32fwu_spi_write(spi, send_buff, len + 2); if (res < len) { ssp_err("Error writing to flash. res = %d", res); return (res > 0) ? -EIO : res; } ssp_dbgf("2"); dummy_cmd.timeout = DEF_ACKROOF_NUMBER; usleep_range(100, 150); /* Samsung added */ res = stm32fwu_spi_wait_for_ack(spi, &dummy_cmd, BL_ACK); if (res == BL_ACK) return len; if (res == BL_NACK) { ssp_err("Got NAK waiting for WRITE_MEM to complete"); return -EPROTO; } ssp_err("timeout waiting for ACK for WRITE_MEM command"); return -ETIME; }
static int load_ums_fw_bootmode(struct spi_device *spi, const char *pFn) { const u8 *buff = NULL; char fw_path[BL_UMS_FW_PATH+1]; unsigned int uFSize = 0, uNRead = 0; unsigned int uPos = 0; int iRet = SUCCESS; int remaining; int block = STM_MAX_XFER_SIZE; unsigned int fw_addr = STM_APP_ADDR; int retry_count = 0; int err_count = 0; int count = 0; struct file *fp = NULL; mm_segment_t old_fs = get_fs(); ssp_info("ssp_load_ums_fw start!!"); old_fs = get_fs(); set_fs(get_ds()); snprintf(fw_path, BL_UMS_FW_PATH, "/sdcard/ssp/%s", pFn); fp = filp_open(fw_path, O_RDONLY, 0); if (IS_ERR(fp)) { iRet = ERROR; ssp_err("file %s open error", fw_path); goto err_open; } uFSize = (unsigned int)fp->f_path.dentry->d_inode->i_size; ssp_info("ssp_load_ums firmware size: %u", uFSize); buff = kzalloc((size_t)STM_MAX_XFER_SIZE, GFP_KERNEL); if (!buff) { iRet = ERROR; ssp_err("fail to alloc buffer for fw"); goto err_alloc; } remaining = uFSize; while (remaining > 0) { if (block > remaining) block = remaining; uNRead = (unsigned int)vfs_read(fp, (char __user *)buff, (unsigned int)block, &fp->f_pos); if (uNRead != block) { iRet = ERROR; ssp_err("fail to read file %s (nread = %u)", fw_path, uNRead); goto err_fw_size; } while (retry_count < 3) { iRet = fw_write_stm(spi, fw_addr, block, buff); if (iRet < block) { ssp_err("Err writing to addr 0x%08X", fw_addr); if (iRet < 0) { ssp_err("Error was %d", iRet); } else { ssp_err("Incomplete write of %d bytes", iRet); iRet = -EIO; } retry_count++; err_count++; } else { retry_count = 0; break; } } if (iRet < 0) { ssp_err("Writing MEM failed: %d, retry cont: %d", iRet, err_count); goto out; } remaining -= block; uPos += block; fw_addr += block; if (count++ == 50) { ssp_info("Updated %u bytes / %u bytes", uPos, uFSize); count = 0; } } ssp_info("Firm up(UMS) success(%d bytes, retry %d)", uPos, err_count); out: err_fw_size: kfree(buff); err_alloc: filp_close(fp, NULL); err_open: set_fs(old_fs); return iRet; }
static int ssp_probe(struct spi_device *spi) { int iRet = 0; struct ssp_data *data; ssp_infof(); /* if (poweroff_charging == 1 || boot_mode_recovery == 1) { ssp_err("probe exit : lpm %d, recovery %d", poweroff_charging, boot_mode_recovery); return -ENODEV; } */ data = kzalloc(sizeof(*data), GFP_KERNEL); if (data == NULL) { ssp_errf("failed to allocate memory for data"); iRet = -ENOMEM; goto exit; } if (spi->dev.of_node) { iRet = ssp_parse_dt(&spi->dev, data); if (iRet) { ssp_errf("Failed to parse DT"); goto err_setup; } } else { ssp_errf("failed to get device node"); iRet = -ENODEV; goto err_setup; } spi->mode = SPI_MODE_1; if (spi_setup(spi)) { ssp_errf("failed to setup spi"); iRet = -ENODEV; goto err_setup; } data->fw_dl_state = FW_DL_STATE_NONE; data->spi = spi; spi_set_drvdata(spi, data); mutex_init(&data->comm_mutex); mutex_init(&data->pending_mutex); pr_info("\n#####################################################\n"); INIT_DELAYED_WORK(&data->work_firmware, work_function_firmware_update); wake_lock_init(&data->ssp_wake_lock, WAKE_LOCK_SUSPEND, "ssp_wake_lock"); iRet = initialize_indio_dev(data); if (iRet < 0) { ssp_errf("could not create input device"); goto err_input_register_device; } iRet = initialize_debug_timer(data); if (iRet < 0) { ssp_errf("could not create workqueue"); goto err_create_workqueue; } iRet = initialize_irq(data); if (iRet < 0) { ssp_errf("could not create irq"); goto err_setup_irq; } iRet = initialize_sysfs(data); if (iRet < 0) { ssp_errf("could not create sysfs"); goto err_sysfs_create; } initialize_variable(data); /* init sensorhub device */ iRet = ssp_sensorhub_initialize(data); if (iRet < 0) { ssp_errf("ssp_sensorhub_initialize err(%d)", iRet); ssp_sensorhub_remove(data); } ssp_enable(data, true); /* check boot loader binary */ data->fw_dl_state = check_fwbl(data); if (data->fw_dl_state == FW_DL_STATE_NONE) { iRet = initialize_mcu(data); if (iRet == ERROR) { toggle_mcu_reset(data); } else if (iRet < ERROR) { ssp_errf("initialize_mcu failed"); goto err_read_reg; } } ssp_infof("probe success!"); enable_debug_timer(data); if (data->fw_dl_state == FW_DL_STATE_NEED_TO_SCHEDULE) { ssp_info("Firmware update is scheduled"); schedule_delayed_work(&data->work_firmware, msecs_to_jiffies(1000)); data->fw_dl_state = FW_DL_STATE_SCHEDULED; } else if (data->fw_dl_state == FW_DL_STATE_FAIL) { data->bSspShutdown = true; } data->bProbeIsDone = true; iRet = 0; goto exit; err_read_reg: remove_sysfs(data); err_sysfs_create: free_irq(data->iIrq, data); gpio_free(data->mcu_int1); err_setup_irq: destroy_workqueue(data->debug_wq); err_create_workqueue: remove_indio_dev(data); err_input_register_device: wake_lock_destroy(&data->ssp_wake_lock); mutex_destroy(&data->comm_mutex); mutex_destroy(&data->pending_mutex); err_setup: kfree(data); ssp_errf("probe failed!"); exit: pr_info("#####################################################\n\n"); return iRet; }
static int ssp_parse_dt(struct device *dev, struct ssp_data *data) { struct device_node *np = dev->of_node; enum of_gpio_flags flags; int errorno = 0; /* gpio pins */ data->mcu_int1 = of_get_named_gpio_flags(np, "ssp,mcu_int1-gpio", 0, &flags); if (data->mcu_int1 < 0) { errorno = data->mcu_int1; goto dt_exit; } data->mcu_int2 = of_get_named_gpio_flags(np, "ssp,mcu_int2-gpio", 0, &flags); if (data->mcu_int2 < 0) { errorno = data->mcu_int2; goto dt_exit; } data->ap_int = of_get_named_gpio_flags(np, "ssp,ap_int-gpio", 0, &flags); if (data->ap_int < 0) { errorno = data->ap_int; goto dt_exit; } data->rst = of_get_named_gpio_flags(np, "ssp,rst-gpio", 0, &flags); if (data->rst < 0) { errorno = data->rst; goto dt_exit; } /* sensor positions */ if (of_property_read_u32(np, "ssp,acc-position", &data->accel_position)) data->accel_position = 0; if (of_property_read_u32(np, "ssp,mag-position", &data->mag_position)) data->mag_position = 0; ssp_info("acc-posi[%d] mag-posi[%d]", data->accel_position, data->mag_position); /* prox thresh */ if (of_property_read_u32(np, "ssp,prox-hi_thresh", &data->uProxHiThresh_default)) data->uProxHiThresh_default = DEFUALT_HIGH_THRESHOLD; if (of_property_read_u32(np, "ssp,prox-low_thresh", &data->uProxLoThresh_default)) data->uProxLoThresh_default = DEFUALT_LOW_THRESHOLD; ssp_info("hi-thresh[%u] low-thresh[%u]", data->uProxHiThresh_default, data->uProxLoThresh_default); #ifdef CONFIG_SENSORS_MULTIPLE_GLASS_TYPE if (of_property_read_u32(np, "ssp-glass-type", &data->glass_type)) data->glass_type = 0; #endif /* mag matrix */ if (of_property_read_u8_array(np, "ssp,mag-array", data->pdc_matrix, sizeof(data->pdc_matrix))) { ssp_err("no mag-array, set as 0"); } /* set off gpio pins */ errorno = gpio_request(data->mcu_int1, "mcu_ap_int1"); if (errorno) { ssp_err("failed to request MCU_INT1 for SSP"); goto dt_exit; } errorno = gpio_direction_input(data->mcu_int1); if (errorno) { ssp_err("failed to set mcu_int1 as input"); goto dt_exit; } errorno = gpio_request(data->mcu_int2, "MCU_INT2"); if (errorno) { ssp_err("failed to request MCU_INT2 for SSP"); goto dt_exit; } gpio_direction_input(data->mcu_int2); errorno = gpio_request(data->ap_int, "AP_MCU_INT"); if (errorno) { ssp_err("failed to request AP_INT for SSP"); goto dt_exit; } gpio_direction_output(data->ap_int, 1); errorno = gpio_request(data->rst, "MCU_RST"); if (errorno) { ssp_err("failed to request MCU_RST for SSP"); goto dt_exit; } gpio_direction_output(data->rst, 1); dt_exit: return errorno; }
static void print_sensordata(struct ssp_data *data, unsigned int uSensor) { switch (uSensor) { case ACCELEROMETER_SENSOR: case GYROSCOPE_SENSOR: ssp_info("%u : %d, %d, %d (%ums, %dms)", uSensor, data->buf[uSensor].x, data->buf[uSensor].y, data->buf[uSensor].z, get_msdelay(data->adDelayBuf[uSensor]), data->batchLatencyBuf[uSensor]); break; case GEOMAGNETIC_SENSOR: ssp_info("%u : %d, %d, %d, %d (%ums)", uSensor, data->buf[uSensor].cal_x, data->buf[uSensor].cal_y, data->buf[uSensor].cal_y, data->buf[uSensor].accuracy, get_msdelay(data->adDelayBuf[uSensor])); break; case GEOMAGNETIC_UNCALIB_SENSOR: ssp_info("%u : %d, %d, %d, %d, %d, %d (%ums)", uSensor, data->buf[uSensor].uncal_x, data->buf[uSensor].uncal_y, data->buf[uSensor].uncal_z, data->buf[uSensor].offset_x, data->buf[uSensor].offset_y, data->buf[uSensor].offset_z, get_msdelay(data->adDelayBuf[uSensor])); break; case PRESSURE_SENSOR: ssp_info("%u : %d, %d (%ums, %dms)", uSensor, data->buf[uSensor].pressure, data->buf[uSensor].temperature, get_msdelay(data->adDelayBuf[uSensor]), data->batchLatencyBuf[uSensor]); break; case GESTURE_SENSOR: ssp_info("%u : %d, %d, %d, %d (%ums)", uSensor, data->buf[uSensor].data[3], data->buf[uSensor].data[4], data->buf[uSensor].data[5], data->buf[uSensor].data[6], get_msdelay(data->adDelayBuf[uSensor])); break; case LIGHT_SENSOR: ssp_info("%u : %u, %u, %u, %u, %u, %u (%ums)", uSensor, data->buf[uSensor].r, data->buf[uSensor].g, data->buf[uSensor].b, data->buf[uSensor].w, data->buf[uSensor].a_time, data->buf[uSensor].a_gain, get_msdelay(data->adDelayBuf[uSensor])); break; case PROXIMITY_SENSOR: ssp_info("%u : %d, %d (%ums)", uSensor, data->buf[uSensor].prox, data->buf[uSensor].prox_ex, get_msdelay(data->adDelayBuf[uSensor])); break; case STEP_DETECTOR: ssp_info("%u : %u (%ums, %dms)", uSensor, data->buf[uSensor].step_det, get_msdelay(data->adDelayBuf[uSensor]), data->batchLatencyBuf[uSensor]); break; case GAME_ROTATION_VECTOR: case ROTATION_VECTOR: ssp_info("%u : %d, %d, %d, %d, %d (%ums, %dms)", uSensor, data->buf[uSensor].quat_a, data->buf[uSensor].quat_b, data->buf[uSensor].quat_c, data->buf[uSensor].quat_d, data->buf[uSensor].acc_rot, get_msdelay(data->adDelayBuf[uSensor]), data->batchLatencyBuf[uSensor]); break; case SIG_MOTION_SENSOR: ssp_info("%u : %u(%ums)", uSensor, data->buf[uSensor].sig_motion, get_msdelay(data->adDelayBuf[uSensor])); break; case GYRO_UNCALIB_SENSOR: ssp_info("%u : %d, %d, %d, %d, %d, %d (%ums)", uSensor, data->buf[uSensor].uncal_x, data->buf[uSensor].uncal_y, data->buf[uSensor].uncal_z, data->buf[uSensor].offset_x, data->buf[uSensor].offset_y, data->buf[uSensor].offset_z, get_msdelay(data->adDelayBuf[uSensor])); break; case STEP_COUNTER: ssp_info("%u : %u(%ums)", uSensor, data->buf[uSensor].step_diff, get_msdelay(data->adDelayBuf[uSensor])); break; case LIGHT_IR_SENSOR: ssp_info("%u : %u, %u, %u, %u, %u, %u, %u(%ums)", uSensor, data->buf[uSensor].irdata, data->buf[uSensor].ir_r, data->buf[uSensor].ir_g, data->buf[uSensor].ir_b, data->buf[uSensor].ir_w, data->buf[uSensor].ir_a_time, data->buf[uSensor].ir_a_gain, get_msdelay(data->adDelayBuf[uSensor])); break; case INTERRUPT_GYRO_SENSOR: ssp_info("%u : %d, %d, %d (%ums)", uSensor, data->buf[uSensor].x, data->buf[uSensor].y, data->buf[uSensor].z, get_msdelay(data->adDelayBuf[uSensor])); break; default: ssp_info("Wrong sensorCnt: %u", uSensor); break; } }
static int accel_do_calibrate(struct ssp_data *data, int iEnable) { int iSum[3] = { 0, }; int iRet = 0, iCount; struct file *cal_filp = NULL; mm_segment_t old_fs; if (iEnable) { data->accelcal.x = 0; data->accelcal.y = 0; data->accelcal.z = 0; set_accel_cal(data); iRet = enable_accel_for_cal(data); msleep(300); for (iCount = 0; iCount < CALIBRATION_DATA_AMOUNT; iCount++) { iSum[0] += data->buf[ACCELEROMETER_SENSOR].x; iSum[1] += data->buf[ACCELEROMETER_SENSOR].y; iSum[2] += data->buf[ACCELEROMETER_SENSOR].z; mdelay(10); } disable_accel_for_cal(data, iRet); data->accelcal.x = (iSum[0] / CALIBRATION_DATA_AMOUNT); data->accelcal.y = (iSum[1] / CALIBRATION_DATA_AMOUNT); data->accelcal.z = (iSum[2] / CALIBRATION_DATA_AMOUNT); if (data->accelcal.z > 0) data->accelcal.z -= MAX_ACCEL_1G; else if (data->accelcal.z < 0) data->accelcal.z += MAX_ACCEL_1G; } else { data->accelcal.x = 0; data->accelcal.y = 0; data->accelcal.z = 0; } ssp_info("do accel calibrate %d, %d, %d", data->accelcal.x, data->accelcal.y, data->accelcal.z); old_fs = get_fs(); set_fs(KERNEL_DS); cal_filp = filp_open(CALIBRATION_FILE_PATH, O_CREAT | O_TRUNC | O_WRONLY, 0660); if (IS_ERR(cal_filp)) { pr_err("[SSP]: %s - Can't open calibration file\n", __func__); set_fs(old_fs); iRet = PTR_ERR(cal_filp); return iRet; } iRet = cal_filp->f_op->write(cal_filp, (char *)&data->accelcal, 3 * sizeof(int), &cal_filp->f_pos); if (iRet != 3 * sizeof(int)) { pr_err("[SSP]: %s - Can't write the accelcal to file\n", __func__); iRet = -EIO; } filp_close(cal_filp, current->files); set_fs(old_fs); set_accel_cal(data); return iRet; }
static int load_kernel_fw_bootmode(struct spi_device *spi, const char *pFn) { const struct firmware *fw = NULL; int remaining; unsigned int uPos = 0; unsigned int fw_addr = STM_APP_ADDR; int iRet; int block = STM_MAX_XFER_SIZE; int count = 0; int err_count = 0; int retry_count = 0; ssp_info("ssp_load_fw start!!"); iRet = request_firmware(&fw, pFn, &spi->dev); if (iRet) { ssp_err("Unable to open firmware %s", pFn); return iRet; } remaining = fw->size; while (remaining > 0) { if (block > remaining) block = remaining; while (retry_count < 3) { iRet = fw_write_stm(spi, fw_addr, block, fw->data+uPos); if (iRet < block) { ssp_err("Err writing to addr 0x%08X", fw_addr); if (iRet < 0) { ssp_err("Error was %d", iRet); } else { ssp_err("Incomplete write of %d bytes", iRet); iRet = -EIO; } retry_count++; err_count++; } else { retry_count = 0; break; } } if (iRet < 0) { ssp_err("Writing MEM failed: %d, retry cont: %d", iRet, err_count); goto out_load_kernel; } remaining -= block; uPos += block; fw_addr += block; if (count++ == 20) { ssp_info("Updated %u bytes / %u bytes", uPos, (unsigned int)fw->size); count = 0; } } ssp_info("Firmware download is success(%d bytes, retry %d)", uPos, err_count); out_load_kernel: release_firmware(fw); return iRet; }