예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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);
}
예제 #8
0
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);
}
예제 #10
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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);
}
예제 #13
0
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;
}
예제 #14
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;
}
예제 #16
0
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;
}
예제 #17
0
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);
}
예제 #18
0
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;
}
예제 #19
0
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;
}
예제 #20
0
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;
}
예제 #21
0
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;
}
예제 #22
0
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;
}
예제 #24
0
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;
}