コード例 #1
0
void stm401_irq_wake_work_func(struct work_struct *work)
{
	int err;
	unsigned short irq_status;
	u32 irq2_status;
	uint8_t irq3_status;
	struct stm401_data *ps_stm401 = container_of(work,
			struct stm401_data, irq_wake_work);
	unsigned char cmdbuff[STM401_MAXDATA_LENGTH];
	unsigned char readbuff[STM401_MAXDATA_LENGTH];

	dev_dbg(&ps_stm401->client->dev, "stm401_irq_wake_work_func\n");
	mutex_lock(&ps_stm401->lock);

	if (ps_stm401->mode == BOOTMODE)
		goto EXIT_NO_WAKE;

	/* This is to handle the case of receiving an interrupt after
	   suspend_late, but before interrupts were globally disabled. If this
	   is the case, interrupts might be disabled now, so we cannot handle
	   this at this time. suspend_noirq will return BUSY if this happens
	   so that we can handle these interrupts. */
	if (ps_stm401->ignore_wakeable_interrupts) {
		dev_info(&ps_stm401->client->dev,
			"Deferring interrupt work\n");
		ps_stm401->ignored_interrupts++;
		goto EXIT_NO_WAKE;
	}

	stm401_wake(ps_stm401);

	/* read interrupt mask register */
	cmdbuff[0] = WAKESENSOR_STATUS;
	err = stm401_i2c_write_read(ps_stm401, cmdbuff, readbuff, 1, 2);
	if (err < 0) {
		dev_err(&ps_stm401->client->dev, "Reading from stm401 failed\n");
		goto EXIT;
	}
	irq_status = (readbuff[IRQ_WAKE_MED] << 8)
				| readbuff[IRQ_WAKE_LO];

	/* read algorithm interrupt status register */
	cmdbuff[0] = ALGO_INT_STATUS;
	err = stm401_i2c_write_read(ps_stm401, cmdbuff, readbuff, 1, 3);
	if (err < 0) {
		dev_err(&ps_stm401->client->dev, "Reading from stm401 failed\n");
		goto EXIT;
	}
	irq2_status = (readbuff[IRQ_WAKE_HI] << 16) |
		(readbuff[IRQ_WAKE_MED] << 8) |
		readbuff[IRQ_WAKE_LO];

	/* read generic interrupt register */
	cmdbuff[0] = GENERIC_INT_STATUS;
	err = stm401_i2c_write_read(ps_stm401, cmdbuff, readbuff, 1, 1);
	if (err < 0) {
		dev_err(&ps_stm401->client->dev, "Reading from stm failed\n");
		goto EXIT;
	}
	irq3_status = readbuff[0];

	if (ps_stm401->qw_irq_status) {
		irq_status |= ps_stm401->qw_irq_status;
		ps_stm401->qw_irq_status = 0;
	}

	/* First, check for error messages */
	if (irq_status & M_LOG_MSG) {
		cmdbuff[0] = ERROR_STATUS;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, ESR_SIZE);
		if (err >= 0) {
			memcpy(stat_string, readbuff, ESR_SIZE);
			stat_string[ESR_SIZE] = 0;
			dev_err(&ps_stm401->client->dev,
				"STM401 Error: %s\n", stat_string);
		} else
			dev_err(&ps_stm401->client->dev,
				"Failed to read error message %d\n", err);
	}

	/* Second, check for a reset request */
	if (irq_status & M_HUB_RESET) {
		unsigned char status;

		if (strnstr(stat_string, "modality", ESR_SIZE))
			status = 0x01;
		else if (strnstr(stat_string, "Algo", ESR_SIZE))
			status = 0x02;
		else if (strnstr(stat_string, "Watchdog", ESR_SIZE))
			status = 0x03;
		else
			status = 0x04;

		stm401_as_data_buffer_write(ps_stm401, DT_RESET, &status, 1, 0);

		stm401_reset_and_init();
		dev_err(&ps_stm401->client->dev, "STM401 requested a reset\n");
		goto EXIT;
	}

	/* Check all other status bits */
	if (irq_status & M_DOCK) {
		int state;

		dev_err(&ps_stm401->client->dev,
			"Invalid M_DOCK bit set. irq_status = 0x%06x\n",
			irq_status);

		cmdbuff[0] = DOCK_DATA;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Dock state failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_DOCK,
			readbuff, 1, 0);
		state = readbuff[DOCK_STATE];
		if (ps_stm401->dsdev.dev != NULL)
			switch_set_state(&ps_stm401->dsdev, state);
		if (ps_stm401->edsdev.dev != NULL)
			switch_set_state(&ps_stm401->edsdev, state);

		dev_dbg(&ps_stm401->client->dev, "Dock status:%d\n", state);
	}
	if (irq_status & M_PROXIMITY) {
		cmdbuff[0] = PROXIMITY;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading prox from stm401 failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_PROX,
			readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Proximity distance %d\n",
			readbuff[PROX_DISTANCE]);
	}
	if (irq_status & M_TOUCH) {
		if (stm401_display_handle_touch_locked(ps_stm401) < 0)
			goto EXIT;
	}
	if (irq_status & M_COVER) {
		int state;
		cmdbuff[0] = COVER_DATA;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Cover state failed\n");
			goto EXIT;
		}

		state = readbuff[COVER_STATE];
		if (state > 0)
			state = 1;

		input_report_switch(ps_stm401->input_dev, SW_LID, state);
		input_sync(ps_stm401->input_dev);

		dev_dbg(&ps_stm401->client->dev, "Cover status: %d\n", state);
	}
	if (irq_status & M_QUICKPEEK) {
		if (stm401_display_handle_quickpeek_locked(ps_stm401,
			irq_status == M_QUICKPEEK) < 0)
			goto EXIT;
	}
	if (irq_status & M_FLATUP) {
		cmdbuff[0] = FLAT_DATA;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading flat data from stm401 failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_FLAT_UP,
			readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev, "Sending Flat up %d\n",
			readbuff[FLAT_UP]);
	}
	if (irq_status & M_FLATDOWN) {
		cmdbuff[0] = FLAT_DATA;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading flat data from stm401 failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_FLAT_DOWN,
			readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev, "Sending Flat down %d\n",
			readbuff[FLAT_DOWN]);
	}
	if (irq_status & M_STOWED) {
		cmdbuff[0] = STOWED;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading stowed from stm401 failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_STOWED,
			readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Stowed status %d\n", readbuff[STOWED]);
	}
	if (irq_status & M_CAMERA_ACT) {
		cmdbuff[0] = CAMERA;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 2);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading camera data from stm failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_CAMERA_ACT,
			readbuff, 2, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Camera: %d\n",
			STM16_TO_HOST(CAMERA_VALUE, readbuff));

		input_report_key(ps_stm401->input_dev, KEY_CAMERA, 1);
		input_report_key(ps_stm401->input_dev, KEY_CAMERA, 0);
		input_sync(ps_stm401->input_dev);
		dev_dbg(&ps_stm401->client->dev,
			"Report camkey toggle\n");
	}
	if (irq_status & M_NFC) {
		cmdbuff[0] = NFC;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading nfc data from stm failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_NFC,
				readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending NFC value: %d\n", readbuff[NFC_VALUE]);

	}
	if (irq_status & M_SIM) {
		cmdbuff[0] = SIM;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 2);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading sig_motion data from stm failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_SIM,
				readbuff, 2, 0);

		/* This is one shot sensor */
		stm401_g_wake_sensor_state &= (~M_SIM);

		dev_dbg(&ps_stm401->client->dev, "Sending SIM Value=%d\n",
					STM16_TO_HOST(SIM_DATA, readbuff));
	}
	if (irq_status & M_CHOPCHOP) {
		cmdbuff[0] = CHOPCHOP;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 2);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading chopchop data from stm failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_CHOPCHOP,
						readbuff, 2, 0);

		dev_dbg(&ps_stm401->client->dev, "ChopChop triggered. Gyro aborts=%d\n",
				STM16_TO_HOST(CHOPCHOP_DATA, readbuff));
	}
	if (irq_status & M_LIFT) {
		cmdbuff[0] = LIFT;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1, 12);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading lift data from stm failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_LIFT,
						readbuff, 12, 0);

		dev_dbg(&ps_stm401->client->dev, "Lift triggered. Dist=%d. ZRot=%d. GravDiff=%d.\n",
				STM32_TO_HOST(LIFT_DISTANCE, readbuff),
				STM32_TO_HOST(LIFT_ROTATION, readbuff),
				STM32_TO_HOST(LIFT_GRAV_DIFF, readbuff));
	}
	if (irq2_status & M_MMOVEME) {
		unsigned char status;
		/* Client recieving action will be upper 2 most significant */
		/* bits of the least significant byte of status. */
		status = (irq2_status & STM401_CLIENT_MASK) | M_MMOVEME;
		stm401_ms_data_buffer_write(ps_stm401, DT_MMMOVE, &status, 1);

		dev_dbg(&ps_stm401->client->dev,
			"Sending meaningful movement event\n");
	}
	if (irq2_status & M_NOMMOVE) {
		unsigned char status;
		/* Client recieving action will be upper 2 most significant */
		/* bits of the least significant byte of status. */
		status = (irq2_status & STM401_CLIENT_MASK) | M_NOMMOVE;
		stm401_ms_data_buffer_write(ps_stm401, DT_NOMOVE, &status, 1);

		dev_dbg(&ps_stm401->client->dev,
			"Sending no meaningful movement event\n");
	}
	if (irq2_status & M_ALGO_MODALITY) {
		cmdbuff[0] =
			stm401_algo_info[STM401_IDX_MODALITY].evt_register;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1,
			STM401_EVT_SZ_TRANSITION);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading modality event failed\n");
			goto EXIT;
		}
		readbuff[ALGO_TYPE] = STM401_IDX_MODALITY;
		stm401_ms_data_buffer_write(ps_stm401, DT_ALGO_EVT,
			readbuff, 8);
		dev_dbg(&ps_stm401->client->dev, "Sending modality event\n");
	}
	if (irq2_status & M_ALGO_ORIENTATION) {
		cmdbuff[0] =
			stm401_algo_info[STM401_IDX_ORIENTATION].evt_register;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1,
			STM401_EVT_SZ_TRANSITION);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading orientation event failed\n");
			goto EXIT;
		}
		readbuff[ALGO_TYPE] = STM401_IDX_ORIENTATION;
		stm401_ms_data_buffer_write(ps_stm401, DT_ALGO_EVT,
			readbuff, 8);
		dev_dbg(&ps_stm401->client->dev, "Sending orientation event\n");
	}
	if (irq2_status & M_ALGO_STOWED) {
		cmdbuff[0] =
			stm401_algo_info[STM401_IDX_STOWED].evt_register;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1,
			STM401_EVT_SZ_TRANSITION);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading stowed event failed\n");
			goto EXIT;
		}
		readbuff[ALGO_TYPE] = STM401_IDX_STOWED;
		stm401_ms_data_buffer_write(ps_stm401, DT_ALGO_EVT,
			readbuff, 8);
		dev_dbg(&ps_stm401->client->dev, "Sending stowed event\n");
	}
	if (irq2_status & M_ALGO_ACCUM_MODALITY) {
		cmdbuff[0] =
			stm401_algo_info[STM401_IDX_ACCUM_MODALITY]
				.evt_register;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1,
			STM401_EVT_SZ_ACCUM_STATE);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading accum modality event failed\n");
			goto EXIT;
		}
		readbuff[ALGO_TYPE] = STM401_IDX_ACCUM_MODALITY;
		stm401_ms_data_buffer_write(ps_stm401, DT_ALGO_EVT,
			readbuff, 8);
		dev_dbg(&ps_stm401->client->dev, "Sending accum modality event\n");
	}
	if (irq2_status & M_ALGO_ACCUM_MVMT) {
		cmdbuff[0] =
			stm401_algo_info[STM401_IDX_ACCUM_MVMT].evt_register;
		err = stm401_i2c_write_read(
			ps_stm401,
			cmdbuff,
			readbuff,
			1,
			STM401_EVT_SZ_ACCUM_MVMT);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading accum mvmt event failed\n");
			goto EXIT;
		}
		readbuff[ALGO_TYPE] = STM401_IDX_ACCUM_MVMT;
		stm401_ms_data_buffer_write(ps_stm401, DT_ALGO_EVT,
			readbuff, 8);
		dev_dbg(&ps_stm401->client->dev, "Sending accum mvmt event\n");
	}
	if (irq2_status & M_IR_WAKE_GESTURE) {
		err = stm401_process_ir_gesture(ps_stm401);
		if (err < 0)
			goto EXIT;
	}
	if (irq3_status & M_GENERIC_INTRPT) {

		dev_err(&ps_stm401->client->dev,
			"Invalid M_GENERIC_INTRPT bit set. irq_status = 0x%06x\n",
			irq_status);

		/* x (data1) : irq3_status */
		stm401_ms_data_buffer_write(ps_stm401, DT_GENERIC_INT,
			&irq3_status, 1);
		dev_dbg(&ps_stm401->client->dev,
			"Sending generic interrupt event:%d\n", irq3_status);
	}

EXIT:
	stm401_sleep(ps_stm401);
EXIT_NO_WAKE:
	mutex_unlock(&ps_stm401->lock);
}
コード例 #2
0
void stm401_irq_work_func(struct work_struct *work)
{
	int err;
	u32 irq_status;
	struct stm401_data *ps_stm401 = container_of(work,
			struct stm401_data, irq_work);

	dev_dbg(&ps_stm401->client->dev, "stm401_irq_work_func\n");
	mutex_lock(&ps_stm401->lock);

	/* read interrupt mask register */
	stm401_cmdbuff[0] = INTERRUPT_STATUS;
	err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 3);
	if (err < 0) {
		dev_err(&ps_stm401->client->dev,
			"Reading from stm401 failed\n");
		goto EXIT;
	}
	irq_status = (stm401_readbuff[IRQ_NOWAKE_HI] << 16) |
		(stm401_readbuff[IRQ_NOWAKE_MED] << 8) |
		stm401_readbuff[IRQ_NOWAKE_LO];

	if (irq_status & M_ACCEL) {
		/* read accelerometer values from STM401 */
		stm401_cmdbuff[0] = ACCEL_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 6);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Accel from stm401 failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_ACCEL,
			stm401_readbuff, 6, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending acc(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(ACCEL_RD_X), STM16_TO_HOST(ACCEL_RD_Y),
			STM16_TO_HOST(ACCEL_RD_Z));
	}
	if (irq_status & M_LIN_ACCEL) {
		/* read linear accelerometer values from STM401 */
		stm401_cmdbuff[0] = LIN_ACCEL_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 6);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Linear Accel from stm401 failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_LIN_ACCEL,
					stm401_readbuff, 6, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending lin_acc(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(ACCEL_RD_X), STM16_TO_HOST(ACCEL_RD_Y),
			STM16_TO_HOST(ACCEL_RD_Z));
	}
	if (irq_status & M_ECOMPASS) {
		unsigned char status;
		/*Read orientation values */
		stm401_cmdbuff[0] = MAG_HX;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 13);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev, "Reading Ecompass failed\n");
			goto EXIT;
		}
		status = stm401_readbuff[COMPASS_STATUS];
		stm401_as_data_buffer_write(ps_stm401, DT_MAG,
			stm401_readbuff, 6, status);

		dev_dbg(&ps_stm401->client->dev,
			"Sending mag(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(MAG_X), STM16_TO_HOST(MAG_Y),
			STM16_TO_HOST(MAG_Z));

		stm401_as_data_buffer_write(ps_stm401, DT_ORIENT,
					    stm401_readbuff + 6, 6, status);

		dev_dbg(&ps_stm401->client->dev,
			"Sending orient(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(ORIENT_X), STM16_TO_HOST(ORIENT_Y),
			STM16_TO_HOST(ORIENT_Z));
	}
	if (irq_status & M_GYRO) {
		stm401_cmdbuff[0] = GYRO_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 6);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Gyroscope failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_GYRO,
			stm401_readbuff, 6, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending gyro(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(GYRO_RD_X), STM16_TO_HOST(GYRO_RD_Y),
			STM16_TO_HOST(GYRO_RD_Z));
	}
	/*MODIFIED UNCALIBRATED GYRO*/
	if (irq_status & M_UNCALIB_GYRO) {
		stm401_cmdbuff[0] = UNCALIB_GYRO_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 12);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Gyroscope failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_UNCALIB_GYRO,
			stm401_readbuff, 12, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Gyro uncalib(x,y,z)values:%d,%d,%d;%d,%d,%d\n",
			STM16_TO_HOST(GYRO_RD_X), STM16_TO_HOST(GYRO_RD_Y),
			STM16_TO_HOST(GYRO_RD_Z), STM16_TO_HOST(GYRO_UNCALIB_X),
			STM16_TO_HOST(GYRO_UNCALIB_Y),
			STM16_TO_HOST(GYRO_UNCALIB_Z));
	}
	if (irq_status & M_UNCALIB_MAG) {
		stm401_cmdbuff[0] = UNCALIB_MAG_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 12);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Gyroscope failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_UNCALIB_MAG,
			stm401_readbuff, 12, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Gyro uncalib(x,y,z)values:%d,%d,%d;%d,%d,%d\n",
			STM16_TO_HOST(MAG_X), STM16_TO_HOST(MAG_Y),
			STM16_TO_HOST(MAG_Z), STM16_TO_HOST(MAG_UNCALIB_X),
			STM16_TO_HOST(MAG_UNCALIB_Y),
			STM16_TO_HOST(MAG_UNCALIB_Z));
	}
	if (irq_status & M_STEP_COUNTER) {
		stm401_cmdbuff[0] = STEP_COUNTER;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 8);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading step counter failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_STEP_COUNTER,
			stm401_readbuff, 8, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending step counter %X %X %X %X\n",
			STM16_TO_HOST(STEP64_DATA), STM16_TO_HOST(STEP32_DATA),
			STM16_TO_HOST(STEP16_DATA), STM16_TO_HOST(STEP8_DATA));
	}
	if (irq_status & M_STEP_DETECTOR) {
		unsigned short detected_steps = 0;
		stm401_cmdbuff[0] = STEP_DETECTOR;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading step detector  failed\n");
			goto EXIT;
		}
		detected_steps = stm401_readbuff[STEP_DETECT];
		while (detected_steps-- != 0) {
			stm401_as_data_buffer_write(ps_stm401, DT_STEP_DETECTOR,
				stm401_readbuff, 1, 0);

			dev_dbg(&ps_stm401->client->dev,
				"Sending step detector\n");
		}
	}
	if (irq_status & M_ALS) {
		stm401_cmdbuff[0] = ALS_LUX;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 2);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading ALS from stm401 failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_ALS,
			stm401_readbuff, 2, 0);

		dev_dbg(&ps_stm401->client->dev, "Sending ALS %d\n",
			STM16_TO_HOST(ALS_VALUE));
	}
	if (irq_status & M_TEMPERATURE) {
		/*Read temperature value */
		stm401_cmdbuff[0] = TEMPERATURE_DATA;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 2);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Temperature failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_TEMP,
					    stm401_readbuff, 2, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending temp(x)value:%d\n", STM16_TO_HOST(TEMP_VALUE));
	}
	if (irq_status & M_PRESSURE) {
		/*Read pressure value */
		stm401_cmdbuff[0] = CURRENT_PRESSURE;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 4);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Pressure failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_PRESSURE,
			stm401_readbuff, 4, 0);

		dev_dbg(&ps_stm401->client->dev, "Sending pressure %d\n",
			STM32_TO_HOST(PRESSURE_VALUE));
	}
	if (irq_status & M_GRAVITY) {
		/* read gravity values from STM401 */
		stm401_cmdbuff[0] = GRAVITY_X;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 6);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Gravity from stm401 failed\n");
			goto EXIT;
		}

		stm401_as_data_buffer_write(ps_stm401, DT_GRAVITY,
			stm401_readbuff, 6, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending gravity(x,y,z)values:x=%d,y=%d,z=%d\n",
			STM16_TO_HOST(GRAV_X), STM16_TO_HOST(GRAV_Y),
			STM16_TO_HOST(GRAV_Z));
	}
	if (irq_status & M_DISP_ROTATE) {
		/*Read Display Rotate value */
		stm401_cmdbuff[0] = DISP_ROTATE_DATA;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading disp_rotate failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_DISP_ROTATE,
			stm401_readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending disp_rotate(x)value: %d\n",
			stm401_readbuff[DISP_VALUE]);
	}
	if (irq_status & M_DISP_BRIGHTNESS) {
		stm401_cmdbuff[0] = DISPLAY_BRIGHTNESS;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1, 1);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev,
				"Reading Display Brightness failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_DISP_BRIGHT,
			stm401_readbuff, 1, 0);

		dev_dbg(&ps_stm401->client->dev,
			"Sending Display Brightness %d\n",
			stm401_readbuff[DISP_VALUE]);
	}
	if (irq_status & M_IR_GESTURE) {
		err = stm401_process_ir_gesture(ps_stm401);
		if (err < 0)
			goto EXIT;
	}
	if (irq_status & M_IR_RAW) {
		stm401_cmdbuff[0] = IR_RAW;
		err = stm401_i2c_write_read(ps_stm401, stm401_cmdbuff, 1,
			STM401_IR_SZ_RAW);
		if (err < 0) {
			dev_err(&ps_stm401->client->dev, "Reading IR data failed\n");
			goto EXIT;
		}
		stm401_as_data_buffer_write(ps_stm401, DT_IR_RAW,
			stm401_readbuff, STM401_IR_SZ_RAW, 0);
		dev_dbg(&ps_stm401->client->dev, "Sending raw IR data\n");
	}

EXIT:
	/* For now HAE needs events even if the activity is still */
	mutex_unlock(&ps_stm401->lock);
}
コード例 #3
0
void stml0xx_irq_work_func(struct work_struct *work)
{
    int err;
    u32 irq_status;
    struct stml0xx_data *ps_stml0xx = stml0xx_misc_data;
    unsigned char buf[SPI_MSG_SIZE];

    dev_dbg(&stml0xx_misc_data->spi->dev, "stml0xx_irq_work_func");
    mutex_lock(&ps_stml0xx->lock);

    stml0xx_wake(ps_stml0xx);

    if (ps_stml0xx->mode == BOOTMODE)
        goto EXIT;

    if (ps_stml0xx->is_suspended)
        goto EXIT;

    /* read interrupt mask register */
    err = stml0xx_spi_send_read_reg(INTERRUPT_STATUS, buf, 3);
    if (err < 0) {
        dev_err(&stml0xx_misc_data->spi->dev,
                "Reading from stml0xx failed");
        goto EXIT;
    }
    irq_status = (buf[IRQ_NOWAKE_HI] << 16) |
                 (buf[IRQ_NOWAKE_MED] << 8) | buf[IRQ_NOWAKE_LO];

    if (irq_status & M_ACCEL) {
        /* read accelerometer values from STML0XX */
        err = stml0xx_spi_send_read_reg(ACCEL_X, buf, 6);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Accel from stml0xx failed");
            goto EXIT;
        }

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_ACCEL, buf, 6, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending acc(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(ACCEL_RD_X), STM16_TO_HOST(ACCEL_RD_Y),
                STM16_TO_HOST(ACCEL_RD_Z));
    }
    if (irq_status & M_ACCEL2) {
        /* read 2nd accelerometer values from STML0XX */
        err = stml0xx_spi_send_read_reg(ACCEL2_X, buf, 6);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading 2nd Accel from stml0xx failed");
            goto EXIT;
        }

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_ACCEL2, buf, 6, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending acc2(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(ACCEL_RD_X), STM16_TO_HOST(ACCEL_RD_Y),
                STM16_TO_HOST(ACCEL_RD_Z));
    }
    if (irq_status & M_LIN_ACCEL) {
        dev_err(&stml0xx_misc_data->spi->dev,
                "Invalid M_LIN_ACCEL bit set. irq_status = 0x%06x",
                irq_status);

        /* read linear accelerometer values from STML0XX */
        err = stml0xx_spi_send_read_reg(LIN_ACCEL_X, buf, 6);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Linear Accel from stml0xx failed");
            goto EXIT;
        }

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_LIN_ACCEL,
                                     buf, 6, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending lin_acc(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(ACCEL_RD_X), STM16_TO_HOST(ACCEL_RD_Y),
                STM16_TO_HOST(ACCEL_RD_Z));
    }
    if (irq_status & M_ECOMPASS) {
        unsigned char status;
        /*Read orientation values */
        err = stml0xx_spi_send_read_reg(MAG_HX, buf, 13);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Ecompass failed");
            goto EXIT;
        }
        status = buf[COMPASS_STATUS];
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_MAG,
                                     buf, 6, status);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending mag(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(MAG_X), STM16_TO_HOST(MAG_Y),
                STM16_TO_HOST(MAG_Z));

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_ORIENT,
                                     buf + 6, 6, status);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending orient(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(ORIENT_X), STM16_TO_HOST(ORIENT_Y),
                STM16_TO_HOST(ORIENT_Z));
    }
    if (irq_status & M_GYRO) {
        err = stml0xx_spi_send_read_reg(GYRO_X, buf, 6);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Gyroscope failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_GYRO, buf, 6, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending gyro(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(GYRO_RD_X), STM16_TO_HOST(GYRO_RD_Y),
                STM16_TO_HOST(GYRO_RD_Z));
    }
    /*MODIFIED UNCALIBRATED GYRO */
    if (irq_status & M_UNCALIB_GYRO) {
        err = stml0xx_spi_send_read_reg(UNCALIB_GYRO_X, buf, 12);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Gyroscope failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_UNCALIB_GYRO,
                                     buf, 12, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending Gyro uncalib(x,y,z)values:%d,%d,%d;%d,%d,%d",
                STM16_TO_HOST(GYRO_RD_X), STM16_TO_HOST(GYRO_RD_Y),
                STM16_TO_HOST(GYRO_RD_Z),
                STM16_TO_HOST(GYRO_UNCALIB_X),
                STM16_TO_HOST(GYRO_UNCALIB_Y),
                STM16_TO_HOST(GYRO_UNCALIB_Z));
    }
    if (irq_status & M_UNCALIB_MAG) {
        err = stml0xx_spi_send_read_reg(UNCALIB_MAG_X, buf, 12);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Gyroscope failed");
            goto EXIT;
        }

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_UNCALIB_MAG,
                                     buf, 12, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending Gyro uncalib(x,y,z)values:%d,%d,%d;%d,%d,%d",
                STM16_TO_HOST(MAG_X), STM16_TO_HOST(MAG_Y),
                STM16_TO_HOST(MAG_Z), STM16_TO_HOST(MAG_UNCALIB_X),
                STM16_TO_HOST(MAG_UNCALIB_Y),
                STM16_TO_HOST(MAG_UNCALIB_Z));
    }
    if (irq_status & M_ALS) {
        err = stml0xx_spi_send_read_reg(ALS_LUX, buf, 2);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading ALS from stml0xx failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_ALS, buf, 2, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending ALS %d", STM16_TO_HOST(ALS_VALUE));
    }
    if (irq_status & M_TEMPERATURE) {
        /* Read temperature value */
        err = stml0xx_spi_send_read_reg(TEMPERATURE_DATA, buf, 2);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Temperature failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_TEMP, buf, 2, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending temp(x)value:%d", STM16_TO_HOST(TEMP_VALUE));
    }
    if (irq_status & M_PRESSURE) {
        dev_err(&stml0xx_misc_data->spi->dev,
                "Invalid M_PRESSURE bit set. irq_status = 0x%06x",
                irq_status);
        /* Read pressure value */
        err = stml0xx_spi_send_read_reg(CURRENT_PRESSURE, buf, 4);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Pressure failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_PRESSURE,
                                     buf, 4, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending pressure %d", STM32_TO_HOST(PRESSURE_VALUE));
    }
    if (irq_status & M_GRAVITY) {
        dev_err(&stml0xx_misc_data->spi->dev,
                "Invalid M_GRAVITY bit set. irq_status = 0x%06x",
                irq_status);

        /* read gravity values from STML0XX */
        err = stml0xx_spi_send_read_reg(GRAVITY_X, buf, 6);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Gravity from stml0xx failed");
            goto EXIT;
        }

        stml0xx_as_data_buffer_write(ps_stml0xx, DT_GRAVITY, buf, 6, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending gravity(x,y,z)values:x=%d,y=%d,z=%d",
                STM16_TO_HOST(GRAV_X), STM16_TO_HOST(GRAV_Y),
                STM16_TO_HOST(GRAV_Z));
    }
    if (irq_status & M_DISP_ROTATE) {
        /* Read Display Rotate value */
        err = stml0xx_spi_send_read_reg(DISP_ROTATE_DATA, buf, 1);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading disp_rotate failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_DISP_ROTATE,
                                     buf, 1, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending disp_rotate(x)value: %d", buf[DISP_VALUE]);
    }
    if (irq_status & M_DISP_BRIGHTNESS) {
        err = stml0xx_spi_send_read_reg(DISPLAY_BRIGHTNESS, buf, 1);
        if (err < 0) {
            dev_err(&stml0xx_misc_data->spi->dev,
                    "Reading Display Brightness failed");
            goto EXIT;
        }
        stml0xx_as_data_buffer_write(ps_stml0xx, DT_DISP_BRIGHT,
                                     buf, 1, 0);

        dev_dbg(&stml0xx_misc_data->spi->dev,
                "Sending Display Brightness %d", buf[DISP_VALUE]);
    }
EXIT:
    stml0xx_sleep(ps_stml0xx);
    /* For now HAE needs events even if the activity is still */
    mutex_unlock(&ps_stml0xx->lock);
    wake_unlock(&ps_stml0xx->wakelock);
}