Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: common: ssp_sensors: Add sensorhub driver

Sensorhub is MCU dedicated to collect data and manage several sensors.
Sensorhub is a spi device which provides a layer for IIO devices. It provides
some data parsing and common mechanism for sensorhub sensors.

Adds common sensorhub library for sensorhub driver and iio drivers
which uses sensorhub MCU to communicate with sensors.

Signed-off-by: Karol Wrona <k.wrona@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Karol Wrona and committed by
Jonathan Cameron
50dd64d5 1664f6a5

+1683
+1
drivers/iio/common/Kconfig
··· 3 3 # 4 4 5 5 source "drivers/iio/common/hid-sensors/Kconfig" 6 + source "drivers/iio/common/ssp_sensors/Kconfig" 6 7 source "drivers/iio/common/st_sensors/Kconfig"
+1
drivers/iio/common/Makefile
··· 8 8 9 9 # When adding new entries keep the list in alphabetical order 10 10 obj-y += hid-sensors/ 11 + obj-y += ssp_sensors/ 11 12 obj-y += st_sensors/
+16
drivers/iio/common/ssp_sensors/Kconfig
··· 1 + # 2 + # SSP sensor drivers and commons configuration 3 + # 4 + menu "SSP Sensor Common" 5 + 6 + config IIO_SSP_SENSORHUB 7 + tristate "Samsung Sensorhub driver" 8 + depends on SPI 9 + select MFD_CORE 10 + help 11 + SSP driver for sensorhub. 12 + If you say yes here you get ssp support for sensorhub. 13 + To compile this driver as a module, choose M here: the 14 + module will be called sensorhub. 15 + 16 + endmenu
+6
drivers/iio/common/ssp_sensors/Makefile
··· 1 + # 2 + # Makefile for SSP sensor drivers and commons. 3 + # 4 + 5 + sensorhub-objs := ssp_dev.o ssp_spi.o 6 + obj-$(CONFIG_IIO_SSP_SENSORHUB) += sensorhub.o
+257
drivers/iio/common/ssp_sensors/ssp.h
··· 1 + /* 2 + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + */ 15 + 16 + #ifndef __SSP_SENSORHUB_H__ 17 + #define __SSP_SENSORHUB_H__ 18 + 19 + #include <linux/delay.h> 20 + #include <linux/gpio.h> 21 + #include <linux/iio/common/ssp_sensors.h> 22 + #include <linux/iio/iio.h> 23 + #include <linux/spi/spi.h> 24 + 25 + #define SSP_DEVICE_ID 0x55 26 + 27 + #ifdef SSP_DBG 28 + #define ssp_dbg(format, ...) pr_info("[SSP] "format, ##__VA_ARGS__) 29 + #else 30 + #define ssp_dbg(format, ...) 31 + #endif 32 + 33 + #define SSP_SW_RESET_TIME 3000 34 + /* Sensor polling in ms */ 35 + #define SSP_DEFAULT_POLLING_DELAY 200 36 + #define SSP_DEFAULT_RETRIES 3 37 + #define SSP_DATA_PACKET_SIZE 960 38 + #define SSP_HEADER_BUFFER_SIZE 4 39 + 40 + enum { 41 + SSP_KERNEL_BINARY = 0, 42 + SSP_KERNEL_CRASHED_BINARY, 43 + }; 44 + 45 + enum { 46 + SSP_INITIALIZATION_STATE = 0, 47 + SSP_NO_SENSOR_STATE, 48 + SSP_ADD_SENSOR_STATE, 49 + SSP_RUNNING_SENSOR_STATE, 50 + }; 51 + 52 + /* Firmware download STATE */ 53 + enum { 54 + SSP_FW_DL_STATE_FAIL = -1, 55 + SSP_FW_DL_STATE_NONE = 0, 56 + SSP_FW_DL_STATE_NEED_TO_SCHEDULE, 57 + SSP_FW_DL_STATE_SCHEDULED, 58 + SSP_FW_DL_STATE_DOWNLOADING, 59 + SSP_FW_DL_STATE_SYNC, 60 + SSP_FW_DL_STATE_DONE, 61 + }; 62 + 63 + #define SSP_INVALID_REVISION 99999 64 + #define SSP_INVALID_REVISION2 0xffffff 65 + 66 + /* AP -> SSP Instruction */ 67 + #define SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD 0xa1 68 + #define SSP_MSG2SSP_INST_BYPASS_SENSOR_RM 0xa2 69 + #define SSP_MSG2SSP_INST_REMOVE_ALL 0xa3 70 + #define SSP_MSG2SSP_INST_CHANGE_DELAY 0xa4 71 + #define SSP_MSG2SSP_INST_LIBRARY_ADD 0xb1 72 + #define SSP_MSG2SSP_INST_LIBRARY_REMOVE 0xb2 73 + #define SSP_MSG2SSP_INST_LIB_NOTI 0xb4 74 + #define SSP_MSG2SSP_INST_LIB_DATA 0xc1 75 + 76 + #define SSP_MSG2SSP_AP_MCU_SET_GYRO_CAL 0xcd 77 + #define SSP_MSG2SSP_AP_MCU_SET_ACCEL_CAL 0xce 78 + #define SSP_MSG2SSP_AP_STATUS_SHUTDOWN 0xd0 79 + #define SSP_MSG2SSP_AP_STATUS_WAKEUP 0xd1 80 + #define SSP_MSG2SSP_AP_STATUS_SLEEP 0xd2 81 + #define SSP_MSG2SSP_AP_STATUS_RESUME 0xd3 82 + #define SSP_MSG2SSP_AP_STATUS_SUSPEND 0xd4 83 + #define SSP_MSG2SSP_AP_STATUS_RESET 0xd5 84 + #define SSP_MSG2SSP_AP_STATUS_POW_CONNECTED 0xd6 85 + #define SSP_MSG2SSP_AP_STATUS_POW_DISCONNECTED 0xd7 86 + #define SSP_MSG2SSP_AP_TEMPHUMIDITY_CAL_DONE 0xda 87 + #define SSP_MSG2SSP_AP_MCU_SET_DUMPMODE 0xdb 88 + #define SSP_MSG2SSP_AP_MCU_DUMP_CHECK 0xdc 89 + #define SSP_MSG2SSP_AP_MCU_BATCH_FLUSH 0xdd 90 + #define SSP_MSG2SSP_AP_MCU_BATCH_COUNT 0xdf 91 + 92 + #define SSP_MSG2SSP_AP_WHOAMI 0x0f 93 + #define SSP_MSG2SSP_AP_FIRMWARE_REV 0xf0 94 + #define SSP_MSG2SSP_AP_SENSOR_FORMATION 0xf1 95 + #define SSP_MSG2SSP_AP_SENSOR_PROXTHRESHOLD 0xf2 96 + #define SSP_MSG2SSP_AP_SENSOR_BARCODE_EMUL 0xf3 97 + #define SSP_MSG2SSP_AP_SENSOR_SCANNING 0xf4 98 + #define SSP_MSG2SSP_AP_SET_MAGNETIC_HWOFFSET 0xf5 99 + #define SSP_MSG2SSP_AP_GET_MAGNETIC_HWOFFSET 0xf6 100 + #define SSP_MSG2SSP_AP_SENSOR_GESTURE_CURRENT 0xf7 101 + #define SSP_MSG2SSP_AP_GET_THERM 0xf8 102 + #define SSP_MSG2SSP_AP_GET_BIG_DATA 0xf9 103 + #define SSP_MSG2SSP_AP_SET_BIG_DATA 0xfa 104 + #define SSP_MSG2SSP_AP_START_BIG_DATA 0xfb 105 + #define SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX 0xfd 106 + #define SSP_MSG2SSP_AP_SENSOR_TILT 0xea 107 + #define SSP_MSG2SSP_AP_MCU_SET_TIME 0xfe 108 + #define SSP_MSG2SSP_AP_MCU_GET_TIME 0xff 109 + 110 + #define SSP_MSG2SSP_AP_FUSEROM 0x01 111 + 112 + /* voice data */ 113 + #define SSP_TYPE_WAKE_UP_VOICE_SERVICE 0x01 114 + #define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_AM 0x01 115 + #define SSP_TYPE_WAKE_UP_VOICE_SOUND_SOURCE_GRAMMER 0x02 116 + 117 + /* Factory Test */ 118 + #define SSP_ACCELEROMETER_FACTORY 0x80 119 + #define SSP_GYROSCOPE_FACTORY 0x81 120 + #define SSP_GEOMAGNETIC_FACTORY 0x82 121 + #define SSP_PRESSURE_FACTORY 0x85 122 + #define SSP_GESTURE_FACTORY 0x86 123 + #define SSP_TEMPHUMIDITY_CRC_FACTORY 0x88 124 + #define SSP_GYROSCOPE_TEMP_FACTORY 0x8a 125 + #define SSP_GYROSCOPE_DPS_FACTORY 0x8b 126 + #define SSP_MCU_FACTORY 0x8c 127 + #define SSP_MCU_SLEEP_FACTORY 0x8d 128 + 129 + /* SSP -> AP ACK about write CMD */ 130 + #define SSP_MSG_ACK 0x80 /* ACK from SSP to AP */ 131 + #define SSP_MSG_NAK 0x70 /* NAK from SSP to AP */ 132 + 133 + struct ssp_sensorhub_info { 134 + char *fw_name; 135 + char *fw_crashed_name; 136 + unsigned int fw_rev; 137 + const u8 * const mag_table; 138 + const unsigned int mag_length; 139 + }; 140 + 141 + /* ssp_msg options bit */ 142 + #define SSP_RW 0 143 + #define SSP_INDEX 3 144 + 145 + #define SSP_AP2HUB_READ 0 146 + #define SSP_AP2HUB_WRITE 1 147 + #define SSP_HUB2AP_WRITE 2 148 + #define SSP_AP2HUB_READY 3 149 + #define SSP_AP2HUB_RETURN 4 150 + 151 + /** 152 + * struct ssp_data - ssp platformdata structure 153 + * @spi: spi device 154 + * @sensorhub_info: info about sensorhub board specific features 155 + * @wdt_timer: watchdog timer 156 + * @work_wdt: watchdog work 157 + * @work_firmware: firmware upgrade work queue 158 + * @work_refresh: refresh work queue for reset request from MCU 159 + * @shut_down: shut down flag 160 + * @mcu_dump_mode: mcu dump mode for debug 161 + * @time_syncing: time syncing indication flag 162 + * @timestamp: previous time in ns calculated for time syncing 163 + * @check_status: status table for each sensor 164 + * @com_fail_cnt: communication fail count 165 + * @reset_cnt: reset count 166 + * @timeout_cnt: timeout count 167 + * @available_sensors: available sensors seen by sensorhub (bit array) 168 + * @cur_firm_rev: cached current firmware revision 169 + * @last_resume_state: last AP resume/suspend state used to handle the PM 170 + * state of ssp 171 + * @last_ap_state: (obsolete) sleep notification for MCU 172 + * @sensor_enable: sensor enable mask 173 + * @delay_buf: data acquisition intervals table 174 + * @batch_latency_buf: yet unknown but existing in communication protocol 175 + * @batch_opt_buf: yet unknown but existing in communication protocol 176 + * @accel_position: yet unknown but existing in communication protocol 177 + * @mag_position: yet unknown but existing in communication protocol 178 + * @fw_dl_state: firmware download state 179 + * @comm_lock: lock protecting the handshake 180 + * @pending_lock: lock protecting pending list and completion 181 + * @mcu_reset_gpio: mcu reset line 182 + * @ap_mcu_gpio: ap to mcu gpio line 183 + * @mcu_ap_gpio: mcu to ap gpio line 184 + * @pending_list: pending list for messages queued to be sent/read 185 + * @sensor_devs: registered IIO devices table 186 + * @enable_refcount: enable reference count for wdt (watchdog timer) 187 + * @header_buffer: cache aligned buffer for packet header 188 + */ 189 + struct ssp_data { 190 + struct spi_device *spi; 191 + struct ssp_sensorhub_info *sensorhub_info; 192 + struct timer_list wdt_timer; 193 + struct work_struct work_wdt; 194 + struct delayed_work work_refresh; 195 + 196 + bool shut_down; 197 + bool mcu_dump_mode; 198 + bool time_syncing; 199 + int64_t timestamp; 200 + 201 + int check_status[SSP_SENSOR_MAX]; 202 + 203 + unsigned int com_fail_cnt; 204 + unsigned int reset_cnt; 205 + unsigned int timeout_cnt; 206 + 207 + unsigned int available_sensors; 208 + unsigned int cur_firm_rev; 209 + 210 + char last_resume_state; 211 + char last_ap_state; 212 + 213 + unsigned int sensor_enable; 214 + u32 delay_buf[SSP_SENSOR_MAX]; 215 + s32 batch_latency_buf[SSP_SENSOR_MAX]; 216 + s8 batch_opt_buf[SSP_SENSOR_MAX]; 217 + 218 + int accel_position; 219 + int mag_position; 220 + int fw_dl_state; 221 + 222 + struct mutex comm_lock; 223 + struct mutex pending_lock; 224 + 225 + int mcu_reset_gpio; 226 + int ap_mcu_gpio; 227 + int mcu_ap_gpio; 228 + 229 + struct list_head pending_list; 230 + 231 + struct iio_dev *sensor_devs[SSP_SENSOR_MAX]; 232 + atomic_t enable_refcount; 233 + 234 + __le16 header_buffer[SSP_HEADER_BUFFER_SIZE / sizeof(__le16)] 235 + ____cacheline_aligned; 236 + }; 237 + 238 + void ssp_clean_pending_list(struct ssp_data *data); 239 + 240 + int ssp_command(struct ssp_data *data, char command, int arg); 241 + 242 + int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type, 243 + u8 *send_buf, u8 length); 244 + 245 + int ssp_irq_msg(struct ssp_data *data); 246 + 247 + int ssp_get_chipid(struct ssp_data *data); 248 + 249 + int ssp_set_magnetic_matrix(struct ssp_data *data); 250 + 251 + unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data); 252 + 253 + unsigned int ssp_get_firmware_rev(struct ssp_data *data); 254 + 255 + int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay); 256 + 257 + #endif /* __SSP_SENSORHUB_H__ */
+712
drivers/iio/common/ssp_sensors/ssp_dev.c
··· 1 + /* 2 + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + */ 15 + 16 + #include <linux/iio/iio.h> 17 + #include <linux/interrupt.h> 18 + #include <linux/io.h> 19 + #include <linux/mfd/core.h> 20 + #include <linux/module.h> 21 + #include <linux/of.h> 22 + #include <linux/of_gpio.h> 23 + #include <linux/of_platform.h> 24 + #include "ssp.h" 25 + 26 + #define SSP_WDT_TIME 10000 27 + #define SSP_LIMIT_RESET_CNT 20 28 + #define SSP_LIMIT_TIMEOUT_CNT 3 29 + 30 + /* It is possible that it is max clk rate for version 1.0 of bootcode */ 31 + #define SSP_BOOT_SPI_HZ 400000 32 + 33 + /* 34 + * These fields can look enigmatic but this structure is used mainly to flat 35 + * some values and depends on command type. 36 + */ 37 + struct ssp_instruction { 38 + __le32 a; 39 + __le32 b; 40 + u8 c; 41 + } __attribute__((__packed__)); 42 + 43 + static const u8 ssp_magnitude_table[] = {110, 85, 171, 71, 203, 195, 0, 67, 44 + 208, 56, 175, 244, 206, 213, 0, 92, 250, 0, 55, 48, 189, 252, 171, 45 + 243, 13, 45, 250}; 46 + 47 + static const struct ssp_sensorhub_info ssp_rinato_info = { 48 + .fw_name = "ssp_B2.fw", 49 + .fw_crashed_name = "ssp_crashed.fw", 50 + .fw_rev = 14052300, 51 + .mag_table = ssp_magnitude_table, 52 + .mag_length = ARRAY_SIZE(ssp_magnitude_table), 53 + }; 54 + 55 + static const struct ssp_sensorhub_info ssp_thermostat_info = { 56 + .fw_name = "thermostat_B2.fw", 57 + .fw_crashed_name = "ssp_crashed.fw", 58 + .fw_rev = 14080600, 59 + .mag_table = ssp_magnitude_table, 60 + .mag_length = ARRAY_SIZE(ssp_magnitude_table), 61 + }; 62 + 63 + static const struct mfd_cell sensorhub_sensor_devs[] = { 64 + { 65 + .name = "ssp-accelerometer", 66 + }, 67 + { 68 + .name = "ssp-gyroscope", 69 + }, 70 + }; 71 + 72 + static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data) 73 + { 74 + gpio_set_value(data->mcu_reset_gpio, 0); 75 + usleep_range(1000, 1200); 76 + gpio_set_value(data->mcu_reset_gpio, 1); 77 + msleep(50); 78 + } 79 + 80 + static void ssp_sync_available_sensors(struct ssp_data *data) 81 + { 82 + int i, ret; 83 + 84 + for (i = 0; i < SSP_SENSOR_MAX; ++i) { 85 + if (data->available_sensors & BIT(i)) { 86 + ret = ssp_enable_sensor(data, i, data->delay_buf[i]); 87 + if (ret < 0) { 88 + dev_err(&data->spi->dev, 89 + "Sync sensor nr: %d fail\n", i); 90 + continue; 91 + } 92 + } 93 + } 94 + 95 + ret = ssp_command(data, SSP_MSG2SSP_AP_MCU_SET_DUMPMODE, 96 + data->mcu_dump_mode); 97 + if (ret < 0) 98 + dev_err(&data->spi->dev, 99 + "SSP_MSG2SSP_AP_MCU_SET_DUMPMODE failed\n"); 100 + } 101 + 102 + static void ssp_enable_mcu(struct ssp_data *data, bool enable) 103 + { 104 + dev_info(&data->spi->dev, "current shutdown = %d, old = %d\n", enable, 105 + data->shut_down); 106 + 107 + if (enable && data->shut_down) { 108 + data->shut_down = false; 109 + enable_irq(data->spi->irq); 110 + enable_irq_wake(data->spi->irq); 111 + } else if (!enable && !data->shut_down) { 112 + data->shut_down = true; 113 + disable_irq(data->spi->irq); 114 + disable_irq_wake(data->spi->irq); 115 + } else { 116 + dev_warn(&data->spi->dev, "current shutdown = %d, old = %d\n", 117 + enable, data->shut_down); 118 + } 119 + } 120 + 121 + /* 122 + * This function is the first one which communicates with the mcu so it is 123 + * possible that the first attempt will fail 124 + */ 125 + static int ssp_check_fwbl(struct ssp_data *data) 126 + { 127 + int retries = 0; 128 + 129 + while (retries++ < 5) { 130 + data->cur_firm_rev = ssp_get_firmware_rev(data); 131 + if (data->cur_firm_rev == SSP_INVALID_REVISION || 132 + data->cur_firm_rev == SSP_INVALID_REVISION2) { 133 + dev_warn(&data->spi->dev, 134 + "Invalid revision, trying %d time\n", retries); 135 + } else { 136 + break; 137 + } 138 + } 139 + 140 + if (data->cur_firm_rev == SSP_INVALID_REVISION || 141 + data->cur_firm_rev == SSP_INVALID_REVISION2) { 142 + dev_err(&data->spi->dev, "SSP_INVALID_REVISION\n"); 143 + return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; 144 + } 145 + 146 + dev_info(&data->spi->dev, 147 + "MCU Firm Rev : Old = %8u, New = %8u\n", 148 + data->cur_firm_rev, 149 + data->sensorhub_info->fw_rev); 150 + 151 + if (data->cur_firm_rev != data->sensorhub_info->fw_rev) 152 + return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; 153 + 154 + return SSP_FW_DL_STATE_NONE; 155 + } 156 + 157 + static void ssp_reset_mcu(struct ssp_data *data) 158 + { 159 + ssp_enable_mcu(data, false); 160 + ssp_clean_pending_list(data); 161 + ssp_toggle_mcu_reset_gpio(data); 162 + ssp_enable_mcu(data, true); 163 + } 164 + 165 + static void ssp_wdt_work_func(struct work_struct *work) 166 + { 167 + struct ssp_data *data = container_of(work, struct ssp_data, work_wdt); 168 + 169 + dev_err(&data->spi->dev, "%s - Sensor state: 0x%x, RC: %u, CC: %u\n", 170 + __func__, data->available_sensors, data->reset_cnt, 171 + data->com_fail_cnt); 172 + 173 + ssp_reset_mcu(data); 174 + data->com_fail_cnt = 0; 175 + data->timeout_cnt = 0; 176 + } 177 + 178 + static void ssp_wdt_timer_func(unsigned long ptr) 179 + { 180 + struct ssp_data *data = (struct ssp_data *)ptr; 181 + 182 + switch (data->fw_dl_state) { 183 + case SSP_FW_DL_STATE_FAIL: 184 + case SSP_FW_DL_STATE_DOWNLOADING: 185 + case SSP_FW_DL_STATE_SYNC: 186 + goto _mod; 187 + } 188 + 189 + if (data->timeout_cnt > SSP_LIMIT_TIMEOUT_CNT || 190 + data->com_fail_cnt > SSP_LIMIT_RESET_CNT) 191 + queue_work(system_power_efficient_wq, &data->work_wdt); 192 + _mod: 193 + mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); 194 + } 195 + 196 + static void ssp_enable_wdt_timer(struct ssp_data *data) 197 + { 198 + mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); 199 + } 200 + 201 + static void ssp_disable_wdt_timer(struct ssp_data *data) 202 + { 203 + del_timer_sync(&data->wdt_timer); 204 + cancel_work_sync(&data->work_wdt); 205 + } 206 + 207 + /** 208 + * ssp_get_sensor_delay() - gets sensor data acquisition period 209 + * @data: sensorhub structure 210 + * @type: SSP sensor type 211 + * 212 + * Returns acquisition period in ms 213 + */ 214 + u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type type) 215 + { 216 + return data->delay_buf[type]; 217 + } 218 + EXPORT_SYMBOL(ssp_get_sensor_delay); 219 + 220 + /** 221 + * ssp_enable_sensor() - enables data acquisition for sensor 222 + * @data: sensorhub structure 223 + * @type: SSP sensor type 224 + * @delay: delay in ms 225 + * 226 + * Returns 0 or negative value in case of error 227 + */ 228 + int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type, 229 + u32 delay) 230 + { 231 + int ret; 232 + struct ssp_instruction to_send; 233 + 234 + to_send.a = cpu_to_le32(delay); 235 + to_send.b = cpu_to_le32(data->batch_latency_buf[type]); 236 + to_send.c = data->batch_opt_buf[type]; 237 + 238 + switch (data->check_status[type]) { 239 + case SSP_INITIALIZATION_STATE: 240 + /* do calibration step, now just enable */ 241 + case SSP_ADD_SENSOR_STATE: 242 + ret = ssp_send_instruction(data, 243 + SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD, 244 + type, 245 + (u8 *)&to_send, sizeof(to_send)); 246 + if (ret < 0) { 247 + dev_err(&data->spi->dev, "Enabling sensor failed\n"); 248 + data->check_status[type] = SSP_NO_SENSOR_STATE; 249 + goto derror; 250 + } 251 + 252 + data->sensor_enable |= BIT(type); 253 + data->check_status[type] = SSP_RUNNING_SENSOR_STATE; 254 + break; 255 + case SSP_RUNNING_SENSOR_STATE: 256 + ret = ssp_send_instruction(data, 257 + SSP_MSG2SSP_INST_CHANGE_DELAY, type, 258 + (u8 *)&to_send, sizeof(to_send)); 259 + if (ret < 0) { 260 + dev_err(&data->spi->dev, 261 + "Changing sensor delay failed\n"); 262 + goto derror; 263 + } 264 + break; 265 + default: 266 + data->check_status[type] = SSP_ADD_SENSOR_STATE; 267 + break; 268 + } 269 + 270 + data->delay_buf[type] = delay; 271 + 272 + if (atomic_inc_return(&data->enable_refcount) == 1) 273 + ssp_enable_wdt_timer(data); 274 + 275 + return 0; 276 + 277 + derror: 278 + return ret; 279 + } 280 + EXPORT_SYMBOL(ssp_enable_sensor); 281 + 282 + /** 283 + * ssp_change_delay() - changes data acquisition for sensor 284 + * @data: sensorhub structure 285 + * @type: SSP sensor type 286 + * @delay: delay in ms 287 + * 288 + * Returns 0 or negative value in case of error 289 + */ 290 + int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type, 291 + u32 delay) 292 + { 293 + int ret; 294 + struct ssp_instruction to_send; 295 + 296 + to_send.a = cpu_to_le32(delay); 297 + to_send.b = cpu_to_le32(data->batch_latency_buf[type]); 298 + to_send.c = data->batch_opt_buf[type]; 299 + 300 + ret = ssp_send_instruction(data, SSP_MSG2SSP_INST_CHANGE_DELAY, type, 301 + (u8 *)&to_send, sizeof(to_send)); 302 + if (ret < 0) { 303 + dev_err(&data->spi->dev, "Changing sensor delay failed\n"); 304 + return ret; 305 + } 306 + 307 + data->delay_buf[type] = delay; 308 + 309 + return 0; 310 + } 311 + EXPORT_SYMBOL(ssp_change_delay); 312 + 313 + /** 314 + * ssp_disable_sensor() - disables sensor 315 + * 316 + * @data: sensorhub structure 317 + * @type: SSP sensor type 318 + * 319 + * Returns 0 or negative value in case of error 320 + */ 321 + int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type) 322 + { 323 + int ret; 324 + __le32 command; 325 + 326 + if (data->sensor_enable & BIT(type)) { 327 + command = cpu_to_le32(data->delay_buf[type]); 328 + 329 + ret = ssp_send_instruction(data, 330 + SSP_MSG2SSP_INST_BYPASS_SENSOR_RM, 331 + type, (u8 *)&command, 332 + sizeof(command)); 333 + if (ret < 0) { 334 + dev_err(&data->spi->dev, "Remove sensor fail\n"); 335 + return ret; 336 + } 337 + 338 + data->sensor_enable &= ~BIT(type); 339 + } 340 + 341 + data->check_status[type] = SSP_ADD_SENSOR_STATE; 342 + 343 + if (atomic_dec_and_test(&data->enable_refcount)) 344 + ssp_disable_wdt_timer(data); 345 + 346 + return 0; 347 + } 348 + EXPORT_SYMBOL(ssp_disable_sensor); 349 + 350 + static irqreturn_t ssp_irq_thread_fn(int irq, void *dev_id) 351 + { 352 + struct ssp_data *data = dev_id; 353 + 354 + /* 355 + * This wrapper is done to preserve error path for ssp_irq_msg, also 356 + * it is defined in different file. 357 + */ 358 + ssp_irq_msg(data); 359 + 360 + return IRQ_HANDLED; 361 + } 362 + 363 + static int ssp_initialize_mcu(struct ssp_data *data) 364 + { 365 + int ret; 366 + 367 + ssp_clean_pending_list(data); 368 + 369 + ret = ssp_get_chipid(data); 370 + if (ret != SSP_DEVICE_ID) { 371 + dev_err(&data->spi->dev, "%s - MCU %s ret = %d\n", __func__, 372 + ret < 0 ? "is not working" : "identification failed", 373 + ret); 374 + return ret < 0 ? ret : -ENODEV; 375 + } 376 + 377 + dev_info(&data->spi->dev, "MCU device ID = %d\n", ret); 378 + 379 + /* 380 + * needs clarification, for now do not want to export all transfer 381 + * methods to sensors' drivers 382 + */ 383 + ret = ssp_set_magnetic_matrix(data); 384 + if (ret < 0) { 385 + dev_err(&data->spi->dev, 386 + "%s - ssp_set_magnetic_matrix failed\n", __func__); 387 + return ret; 388 + } 389 + 390 + data->available_sensors = ssp_get_sensor_scanning_info(data); 391 + if (data->available_sensors == 0) { 392 + dev_err(&data->spi->dev, 393 + "%s - ssp_get_sensor_scanning_info failed\n", __func__); 394 + return -EIO; 395 + } 396 + 397 + data->cur_firm_rev = ssp_get_firmware_rev(data); 398 + dev_info(&data->spi->dev, "MCU Firm Rev : New = %8u\n", 399 + data->cur_firm_rev); 400 + 401 + return ssp_command(data, SSP_MSG2SSP_AP_MCU_DUMP_CHECK, 0); 402 + } 403 + 404 + /* 405 + * sensorhub can request its reinitialization as some brutal and rare error 406 + * handling. It can be requested from the MCU. 407 + */ 408 + static void ssp_refresh_task(struct work_struct *work) 409 + { 410 + struct ssp_data *data = container_of((struct delayed_work *)work, 411 + struct ssp_data, work_refresh); 412 + 413 + dev_info(&data->spi->dev, "refreshing\n"); 414 + 415 + data->reset_cnt++; 416 + 417 + if (ssp_initialize_mcu(data) >= 0) { 418 + ssp_sync_available_sensors(data); 419 + if (data->last_ap_state != 0) 420 + ssp_command(data, data->last_ap_state, 0); 421 + 422 + if (data->last_resume_state != 0) 423 + ssp_command(data, data->last_resume_state, 0); 424 + 425 + data->timeout_cnt = 0; 426 + data->com_fail_cnt = 0; 427 + } 428 + } 429 + 430 + int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay) 431 + { 432 + cancel_delayed_work_sync(&data->work_refresh); 433 + 434 + return queue_delayed_work(system_power_efficient_wq, 435 + &data->work_refresh, 436 + msecs_to_jiffies(delay)); 437 + } 438 + 439 + #ifdef CONFIG_OF 440 + static struct of_device_id ssp_of_match[] = { 441 + { 442 + .compatible = "samsung,sensorhub-rinato", 443 + .data = &ssp_rinato_info, 444 + }, { 445 + .compatible = "samsung,sensorhub-thermostat", 446 + .data = &ssp_thermostat_info, 447 + }, 448 + {}, 449 + }; 450 + MODULE_DEVICE_TABLE(of, ssp_of_match); 451 + 452 + static struct ssp_data *ssp_parse_dt(struct device *dev) 453 + { 454 + int ret; 455 + struct ssp_data *data; 456 + struct device_node *node = dev->of_node; 457 + const struct of_device_id *match; 458 + 459 + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 460 + if (!data) 461 + return NULL; 462 + 463 + data->mcu_ap_gpio = of_get_named_gpio(node, "mcu-ap-gpios", 0); 464 + if (data->mcu_ap_gpio < 0) 465 + goto err_free_pd; 466 + 467 + data->ap_mcu_gpio = of_get_named_gpio(node, "ap-mcu-gpios", 0); 468 + if (data->ap_mcu_gpio < 0) 469 + goto err_free_pd; 470 + 471 + data->mcu_reset_gpio = of_get_named_gpio(node, "mcu-reset-gpios", 0); 472 + if (data->mcu_reset_gpio < 0) 473 + goto err_free_pd; 474 + 475 + ret = devm_gpio_request_one(dev, data->ap_mcu_gpio, GPIOF_OUT_INIT_HIGH, 476 + "ap-mcu-gpios"); 477 + if (ret) 478 + goto err_free_pd; 479 + 480 + ret = devm_gpio_request_one(dev, data->mcu_reset_gpio, 481 + GPIOF_OUT_INIT_HIGH, "mcu-reset-gpios"); 482 + if (ret) 483 + goto err_ap_mcu; 484 + 485 + match = of_match_node(ssp_of_match, node); 486 + if (!match) 487 + goto err_mcu_reset_gpio; 488 + 489 + data->sensorhub_info = (struct ssp_sensorhub_info *)match->data; 490 + 491 + dev_set_drvdata(dev, data); 492 + 493 + return data; 494 + 495 + err_mcu_reset_gpio: 496 + devm_gpio_free(dev, data->mcu_reset_gpio); 497 + err_ap_mcu: 498 + devm_gpio_free(dev, data->ap_mcu_gpio); 499 + err_free_pd: 500 + devm_kfree(dev, data); 501 + return NULL; 502 + } 503 + #else 504 + static struct ssp_data *ssp_parse_dt(struct device *pdev) 505 + { 506 + return NULL; 507 + } 508 + #endif 509 + 510 + /** 511 + * ssp_register_consumer() - registers iio consumer in ssp framework 512 + * 513 + * @indio_dev: consumer iio device 514 + * @type: ssp sensor type 515 + */ 516 + void ssp_register_consumer(struct iio_dev *indio_dev, enum ssp_sensor_type type) 517 + { 518 + struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); 519 + 520 + data->sensor_devs[type] = indio_dev; 521 + } 522 + EXPORT_SYMBOL(ssp_register_consumer); 523 + 524 + static int ssp_probe(struct spi_device *spi) 525 + { 526 + int ret, i; 527 + struct ssp_data *data; 528 + 529 + data = ssp_parse_dt(&spi->dev); 530 + if (!data) { 531 + dev_err(&spi->dev, "Failed to find platform data\n"); 532 + return -ENODEV; 533 + } 534 + 535 + ret = mfd_add_devices(&spi->dev, -1, sensorhub_sensor_devs, 536 + ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL); 537 + if (ret < 0) { 538 + dev_err(&spi->dev, "mfd add devices fail\n"); 539 + return ret; 540 + } 541 + 542 + spi->mode = SPI_MODE_1; 543 + ret = spi_setup(spi); 544 + if (ret < 0) { 545 + dev_err(&spi->dev, "Failed to setup spi\n"); 546 + return ret; 547 + } 548 + 549 + data->fw_dl_state = SSP_FW_DL_STATE_NONE; 550 + data->spi = spi; 551 + spi_set_drvdata(spi, data); 552 + 553 + mutex_init(&data->comm_lock); 554 + 555 + for (i = 0; i < SSP_SENSOR_MAX; ++i) { 556 + data->delay_buf[i] = SSP_DEFAULT_POLLING_DELAY; 557 + data->batch_latency_buf[i] = 0; 558 + data->batch_opt_buf[i] = 0; 559 + data->check_status[i] = SSP_INITIALIZATION_STATE; 560 + } 561 + 562 + data->delay_buf[SSP_BIO_HRM_LIB] = 100; 563 + 564 + data->time_syncing = true; 565 + 566 + mutex_init(&data->pending_lock); 567 + INIT_LIST_HEAD(&data->pending_list); 568 + 569 + atomic_set(&data->enable_refcount, 0); 570 + 571 + INIT_WORK(&data->work_wdt, ssp_wdt_work_func); 572 + INIT_DELAYED_WORK(&data->work_refresh, ssp_refresh_task); 573 + 574 + setup_timer(&data->wdt_timer, ssp_wdt_timer_func, (unsigned long)data); 575 + 576 + ret = request_threaded_irq(data->spi->irq, NULL, 577 + ssp_irq_thread_fn, 578 + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 579 + "SSP_Int", data); 580 + if (ret < 0) { 581 + dev_err(&spi->dev, "Irq request fail\n"); 582 + goto err_setup_irq; 583 + } 584 + 585 + /* Let's start with enabled one so irq balance could be ok */ 586 + data->shut_down = false; 587 + 588 + /* just to avoid unbalanced irq set wake up */ 589 + enable_irq_wake(data->spi->irq); 590 + 591 + data->fw_dl_state = ssp_check_fwbl(data); 592 + if (data->fw_dl_state == SSP_FW_DL_STATE_NONE) { 593 + ret = ssp_initialize_mcu(data); 594 + if (ret < 0) { 595 + dev_err(&spi->dev, "Initialize_mcu failed\n"); 596 + goto err_read_reg; 597 + } 598 + } else { 599 + dev_err(&spi->dev, "Firmware version not supported\n"); 600 + ret = -EPERM; 601 + goto err_read_reg; 602 + } 603 + 604 + return 0; 605 + 606 + err_read_reg: 607 + free_irq(data->spi->irq, data); 608 + err_setup_irq: 609 + mutex_destroy(&data->pending_lock); 610 + mutex_destroy(&data->comm_lock); 611 + 612 + dev_err(&spi->dev, "Probe failed!\n"); 613 + 614 + return ret; 615 + } 616 + 617 + static int ssp_remove(struct spi_device *spi) 618 + { 619 + struct ssp_data *data = spi_get_drvdata(spi); 620 + 621 + if (ssp_command(data, SSP_MSG2SSP_AP_STATUS_SHUTDOWN, 0) < 0) 622 + dev_err(&data->spi->dev, 623 + "SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n"); 624 + 625 + ssp_enable_mcu(data, false); 626 + ssp_disable_wdt_timer(data); 627 + 628 + ssp_clean_pending_list(data); 629 + 630 + free_irq(data->spi->irq, data); 631 + 632 + del_timer_sync(&data->wdt_timer); 633 + cancel_work_sync(&data->work_wdt); 634 + 635 + mutex_destroy(&data->comm_lock); 636 + mutex_destroy(&data->pending_lock); 637 + 638 + mfd_remove_devices(&spi->dev); 639 + 640 + return 0; 641 + } 642 + 643 + static int ssp_suspend(struct device *dev) 644 + { 645 + int ret; 646 + struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); 647 + 648 + data->last_resume_state = SSP_MSG2SSP_AP_STATUS_SUSPEND; 649 + 650 + if (atomic_read(&data->enable_refcount) > 0) 651 + ssp_disable_wdt_timer(data); 652 + 653 + ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_SUSPEND, 0); 654 + if (ret < 0) { 655 + dev_err(&data->spi->dev, 656 + "%s SSP_MSG2SSP_AP_STATUS_SUSPEND failed\n", __func__); 657 + 658 + ssp_enable_wdt_timer(data); 659 + return ret; 660 + } 661 + 662 + data->time_syncing = false; 663 + disable_irq(data->spi->irq); 664 + 665 + return 0; 666 + } 667 + 668 + static int ssp_resume(struct device *dev) 669 + { 670 + int ret; 671 + struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); 672 + 673 + enable_irq(data->spi->irq); 674 + 675 + if (atomic_read(&data->enable_refcount) > 0) 676 + ssp_enable_wdt_timer(data); 677 + 678 + ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_RESUME, 0); 679 + if (ret < 0) { 680 + dev_err(&data->spi->dev, 681 + "%s SSP_MSG2SSP_AP_STATUS_RESUME failed\n", __func__); 682 + ssp_disable_wdt_timer(data); 683 + return ret; 684 + } 685 + 686 + /* timesyncing is set by MCU */ 687 + data->last_resume_state = SSP_MSG2SSP_AP_STATUS_RESUME; 688 + 689 + return 0; 690 + } 691 + 692 + static const struct dev_pm_ops ssp_pm_ops = { 693 + SET_SYSTEM_SLEEP_PM_OPS(ssp_suspend, ssp_resume) 694 + }; 695 + 696 + static struct spi_driver ssp_driver = { 697 + .probe = ssp_probe, 698 + .remove = ssp_remove, 699 + .driver = { 700 + .pm = &ssp_pm_ops, 701 + .bus = &spi_bus_type, 702 + .owner = THIS_MODULE, 703 + .of_match_table = of_match_ptr(ssp_of_match), 704 + .name = "sensorhub" 705 + }, 706 + }; 707 + 708 + module_spi_driver(ssp_driver); 709 + 710 + MODULE_DESCRIPTION("ssp sensorhub driver"); 711 + MODULE_AUTHOR("Samsung Electronics"); 712 + MODULE_LICENSE("GPL");
+608
drivers/iio/common/ssp_sensors/ssp_spi.c
··· 1 + /* 2 + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + */ 15 + 16 + #include "ssp.h" 17 + 18 + #define SSP_DEV (&data->spi->dev) 19 + #define SSP_GET_MESSAGE_TYPE(data) (data & (3 << SSP_RW)) 20 + 21 + /* 22 + * SSP -> AP Instruction 23 + * They tell what packet type can be expected. In the future there will 24 + * be less of them. BYPASS means common sensor packets with accel, gyro, 25 + * hrm etc. data. LIBRARY and META are mock-up's for now. 26 + */ 27 + #define SSP_MSG2AP_INST_BYPASS_DATA 0x37 28 + #define SSP_MSG2AP_INST_LIBRARY_DATA 0x01 29 + #define SSP_MSG2AP_INST_DEBUG_DATA 0x03 30 + #define SSP_MSG2AP_INST_BIG_DATA 0x04 31 + #define SSP_MSG2AP_INST_META_DATA 0x05 32 + #define SSP_MSG2AP_INST_TIME_SYNC 0x06 33 + #define SSP_MSG2AP_INST_RESET 0x07 34 + 35 + #define SSP_UNIMPLEMENTED -1 36 + 37 + struct ssp_msg_header { 38 + u8 cmd; 39 + __le16 length; 40 + __le16 options; 41 + __le32 data; 42 + } __attribute__((__packed__)); 43 + 44 + struct ssp_msg { 45 + u16 length; 46 + u16 options; 47 + struct list_head list; 48 + struct completion *done; 49 + struct ssp_msg_header *h; 50 + char *buffer; 51 + }; 52 + 53 + static const int ssp_offset_map[SSP_SENSOR_MAX] = { 54 + [SSP_ACCELEROMETER_SENSOR] = SSP_ACCELEROMETER_SIZE + 55 + SSP_TIME_SIZE, 56 + [SSP_GYROSCOPE_SENSOR] = SSP_GYROSCOPE_SIZE + 57 + SSP_TIME_SIZE, 58 + [SSP_GEOMAGNETIC_UNCALIB_SENSOR] = SSP_UNIMPLEMENTED, 59 + [SSP_GEOMAGNETIC_RAW] = SSP_UNIMPLEMENTED, 60 + [SSP_GEOMAGNETIC_SENSOR] = SSP_UNIMPLEMENTED, 61 + [SSP_PRESSURE_SENSOR] = SSP_UNIMPLEMENTED, 62 + [SSP_GESTURE_SENSOR] = SSP_UNIMPLEMENTED, 63 + [SSP_PROXIMITY_SENSOR] = SSP_UNIMPLEMENTED, 64 + [SSP_TEMPERATURE_HUMIDITY_SENSOR] = SSP_UNIMPLEMENTED, 65 + [SSP_LIGHT_SENSOR] = SSP_UNIMPLEMENTED, 66 + [SSP_PROXIMITY_RAW] = SSP_UNIMPLEMENTED, 67 + [SSP_ORIENTATION_SENSOR] = SSP_UNIMPLEMENTED, 68 + [SSP_STEP_DETECTOR] = SSP_UNIMPLEMENTED, 69 + [SSP_SIG_MOTION_SENSOR] = SSP_UNIMPLEMENTED, 70 + [SSP_GYRO_UNCALIB_SENSOR] = SSP_UNIMPLEMENTED, 71 + [SSP_GAME_ROTATION_VECTOR] = SSP_UNIMPLEMENTED, 72 + [SSP_ROTATION_VECTOR] = SSP_UNIMPLEMENTED, 73 + [SSP_STEP_COUNTER] = SSP_UNIMPLEMENTED, 74 + [SSP_BIO_HRM_RAW] = SSP_BIO_HRM_RAW_SIZE + 75 + SSP_TIME_SIZE, 76 + [SSP_BIO_HRM_RAW_FAC] = SSP_BIO_HRM_RAW_FAC_SIZE + 77 + SSP_TIME_SIZE, 78 + [SSP_BIO_HRM_LIB] = SSP_BIO_HRM_LIB_SIZE + 79 + SSP_TIME_SIZE, 80 + }; 81 + 82 + #define SSP_HEADER_SIZE (sizeof(struct ssp_msg_header)) 83 + #define SSP_HEADER_SIZE_ALIGNED (ALIGN(SSP_HEADER_SIZE, 4)) 84 + 85 + static struct ssp_msg *ssp_create_msg(u8 cmd, u16 len, u16 opt, u32 data) 86 + { 87 + struct ssp_msg_header h; 88 + struct ssp_msg *msg; 89 + 90 + msg = kzalloc(sizeof(*msg), GFP_KERNEL); 91 + if (!msg) 92 + return NULL; 93 + 94 + h.cmd = cmd; 95 + h.length = cpu_to_le16(len); 96 + h.options = cpu_to_le16(opt); 97 + h.data = cpu_to_le32(data); 98 + 99 + msg->buffer = kzalloc(SSP_HEADER_SIZE_ALIGNED + len, 100 + GFP_KERNEL | GFP_DMA); 101 + if (!msg->buffer) { 102 + kfree(msg); 103 + return NULL; 104 + } 105 + 106 + msg->length = len; 107 + msg->options = opt; 108 + 109 + memcpy(msg->buffer, &h, SSP_HEADER_SIZE); 110 + 111 + return msg; 112 + } 113 + 114 + /* 115 + * It is a bit heavy to do it this way but often the function is used to compose 116 + * the message from smaller chunks which are placed on the stack. Often the 117 + * chunks are small so memcpy should be optimalized. 118 + */ 119 + static inline void ssp_fill_buffer(struct ssp_msg *m, unsigned int offset, 120 + const void *src, unsigned int len) 121 + { 122 + memcpy(&m->buffer[SSP_HEADER_SIZE_ALIGNED + offset], src, len); 123 + } 124 + 125 + static inline void ssp_get_buffer(struct ssp_msg *m, unsigned int offset, 126 + void *dest, unsigned int len) 127 + { 128 + memcpy(dest, &m->buffer[SSP_HEADER_SIZE_ALIGNED + offset], len); 129 + } 130 + 131 + #define SSP_GET_BUFFER_AT_INDEX(m, index) \ 132 + (m->buffer[SSP_HEADER_SIZE_ALIGNED + index]) 133 + #define SSP_SET_BUFFER_AT_INDEX(m, index, val) \ 134 + (m->buffer[SSP_HEADER_SIZE_ALIGNED + index] = val) 135 + 136 + static void ssp_clean_msg(struct ssp_msg *m) 137 + { 138 + kfree(m->buffer); 139 + kfree(m); 140 + } 141 + 142 + static int ssp_print_mcu_debug(char *data_frame, int *data_index, 143 + int received_len) 144 + { 145 + int length = data_frame[(*data_index)++]; 146 + 147 + if (length > received_len - *data_index || length <= 0) { 148 + ssp_dbg("[SSP]: MSG From MCU-invalid debug length(%d/%d)\n", 149 + length, received_len); 150 + return length ? length : -EPROTO; 151 + } 152 + 153 + ssp_dbg("[SSP]: MSG From MCU - %s\n", &data_frame[*data_index]); 154 + 155 + *data_index += length; 156 + 157 + return 0; 158 + } 159 + 160 + /* 161 + * It was designed that way - additional lines to some kind of handshake, 162 + * please do not ask why - only the firmware guy can know it. 163 + */ 164 + static int ssp_check_lines(struct ssp_data *data, bool state) 165 + { 166 + int delay_cnt = 0; 167 + 168 + gpio_set_value_cansleep(data->ap_mcu_gpio, state); 169 + 170 + while (gpio_get_value_cansleep(data->mcu_ap_gpio) != state) { 171 + usleep_range(3000, 3500); 172 + 173 + if (data->shut_down || delay_cnt++ > 500) { 174 + dev_err(SSP_DEV, "%s:timeout, hw ack wait fail %d\n", 175 + __func__, state); 176 + 177 + if (!state) 178 + gpio_set_value_cansleep(data->ap_mcu_gpio, 1); 179 + 180 + return -ETIMEDOUT; 181 + } 182 + } 183 + 184 + return 0; 185 + } 186 + 187 + static int ssp_do_transfer(struct ssp_data *data, struct ssp_msg *msg, 188 + struct completion *done, int timeout) 189 + { 190 + int status; 191 + /* 192 + * check if this is a short one way message or the whole transfer has 193 + * second part after an interrupt 194 + */ 195 + const bool use_no_irq = msg->length == 0; 196 + 197 + if (data->shut_down) 198 + return -EPERM; 199 + 200 + msg->done = done; 201 + 202 + mutex_lock(&data->comm_lock); 203 + 204 + status = ssp_check_lines(data, false); 205 + if (status < 0) 206 + goto _error_locked; 207 + 208 + status = spi_write(data->spi, msg->buffer, SSP_HEADER_SIZE); 209 + if (status < 0) { 210 + gpio_set_value_cansleep(data->ap_mcu_gpio, 1); 211 + dev_err(SSP_DEV, "%s spi_write fail\n", __func__); 212 + goto _error_locked; 213 + } 214 + 215 + if (!use_no_irq) { 216 + mutex_lock(&data->pending_lock); 217 + list_add_tail(&msg->list, &data->pending_list); 218 + mutex_unlock(&data->pending_lock); 219 + } 220 + 221 + status = ssp_check_lines(data, true); 222 + if (status < 0) { 223 + if (!use_no_irq) { 224 + mutex_lock(&data->pending_lock); 225 + list_del(&msg->list); 226 + mutex_unlock(&data->pending_lock); 227 + } 228 + goto _error_locked; 229 + } 230 + 231 + mutex_unlock(&data->comm_lock); 232 + 233 + if (!use_no_irq && done) 234 + if (wait_for_completion_timeout(done, 235 + msecs_to_jiffies(timeout)) == 236 + 0) { 237 + mutex_lock(&data->pending_lock); 238 + list_del(&msg->list); 239 + mutex_unlock(&data->pending_lock); 240 + 241 + data->timeout_cnt++; 242 + return -ETIMEDOUT; 243 + } 244 + 245 + return 0; 246 + 247 + _error_locked: 248 + mutex_unlock(&data->comm_lock); 249 + data->timeout_cnt++; 250 + return status; 251 + } 252 + 253 + static inline int ssp_spi_sync_command(struct ssp_data *data, 254 + struct ssp_msg *msg) 255 + { 256 + return ssp_do_transfer(data, msg, NULL, 0); 257 + } 258 + 259 + static int ssp_spi_sync(struct ssp_data *data, struct ssp_msg *msg, 260 + int timeout) 261 + { 262 + DECLARE_COMPLETION_ONSTACK(done); 263 + 264 + if (WARN_ON(!msg->length)) 265 + return -EPERM; 266 + 267 + return ssp_do_transfer(data, msg, &done, timeout); 268 + } 269 + 270 + static int ssp_handle_big_data(struct ssp_data *data, char *dataframe, int *idx) 271 + { 272 + /* mock-up, it will be changed with adding another sensor types */ 273 + *idx += 8; 274 + return 0; 275 + } 276 + 277 + static int ssp_parse_dataframe(struct ssp_data *data, char *dataframe, int len) 278 + { 279 + int idx, sd; 280 + struct timespec ts; 281 + struct ssp_sensor_data *spd; 282 + struct iio_dev **indio_devs = data->sensor_devs; 283 + 284 + getnstimeofday(&ts); 285 + 286 + for (idx = 0; idx < len;) { 287 + switch (dataframe[idx++]) { 288 + case SSP_MSG2AP_INST_BYPASS_DATA: 289 + sd = dataframe[idx++]; 290 + if (sd < 0 || sd >= SSP_SENSOR_MAX) { 291 + dev_err(SSP_DEV, 292 + "Mcu data frame1 error %d\n", sd); 293 + return -EPROTO; 294 + } 295 + 296 + if (indio_devs[sd]) { 297 + spd = iio_priv(indio_devs[sd]); 298 + if (spd->process_data) 299 + spd->process_data(indio_devs[sd], 300 + &dataframe[idx], 301 + data->timestamp); 302 + } else { 303 + dev_err(SSP_DEV, "no client for frame\n"); 304 + } 305 + 306 + idx += ssp_offset_map[sd]; 307 + break; 308 + case SSP_MSG2AP_INST_DEBUG_DATA: 309 + sd = ssp_print_mcu_debug(dataframe, &idx, len); 310 + if (sd) { 311 + dev_err(SSP_DEV, 312 + "Mcu data frame3 error %d\n", sd); 313 + return sd; 314 + } 315 + break; 316 + case SSP_MSG2AP_INST_LIBRARY_DATA: 317 + idx += len; 318 + break; 319 + case SSP_MSG2AP_INST_BIG_DATA: 320 + ssp_handle_big_data(data, dataframe, &idx); 321 + break; 322 + case SSP_MSG2AP_INST_TIME_SYNC: 323 + data->time_syncing = true; 324 + break; 325 + case SSP_MSG2AP_INST_RESET: 326 + ssp_queue_ssp_refresh_task(data, 0); 327 + break; 328 + } 329 + } 330 + 331 + if (data->time_syncing) 332 + data->timestamp = ts.tv_sec * 1000000000ULL + ts.tv_nsec; 333 + 334 + return 0; 335 + } 336 + 337 + /* threaded irq */ 338 + int ssp_irq_msg(struct ssp_data *data) 339 + { 340 + bool found = false; 341 + char *buffer; 342 + u8 msg_type; 343 + int ret; 344 + u16 length, msg_options; 345 + struct ssp_msg *msg, *n; 346 + 347 + ret = spi_read(data->spi, data->header_buffer, SSP_HEADER_BUFFER_SIZE); 348 + if (ret < 0) { 349 + dev_err(SSP_DEV, "header read fail\n"); 350 + return ret; 351 + } 352 + 353 + length = le16_to_cpu(data->header_buffer[1]); 354 + msg_options = le16_to_cpu(data->header_buffer[0]); 355 + 356 + if (length == 0) { 357 + dev_err(SSP_DEV, "length received from mcu is 0\n"); 358 + return -EINVAL; 359 + } 360 + 361 + msg_type = SSP_GET_MESSAGE_TYPE(msg_options); 362 + 363 + switch (msg_type) { 364 + case SSP_AP2HUB_READ: 365 + case SSP_AP2HUB_WRITE: 366 + /* 367 + * this is a small list, a few elements - the packets can be 368 + * received with no order 369 + */ 370 + mutex_lock(&data->pending_lock); 371 + list_for_each_entry_safe(msg, n, &data->pending_list, list) { 372 + if (msg->options == msg_options) { 373 + list_del(&msg->list); 374 + found = true; 375 + break; 376 + } 377 + } 378 + 379 + if (!found) { 380 + /* 381 + * here can be implemented dead messages handling 382 + * but the slave should not send such ones - it is to 383 + * check but let's handle this 384 + */ 385 + buffer = kmalloc(length, GFP_KERNEL | GFP_DMA); 386 + if (!buffer) { 387 + ret = -ENOMEM; 388 + goto _unlock; 389 + } 390 + 391 + /* got dead packet so it is always an error */ 392 + ret = spi_read(data->spi, buffer, length); 393 + if (ret >= 0) 394 + ret = -EPROTO; 395 + 396 + kfree(buffer); 397 + 398 + dev_err(SSP_DEV, "No match error %x\n", 399 + msg_options); 400 + 401 + goto _unlock; 402 + } 403 + 404 + if (msg_type == SSP_AP2HUB_READ) 405 + ret = spi_read(data->spi, 406 + &msg->buffer[SSP_HEADER_SIZE_ALIGNED], 407 + msg->length); 408 + 409 + if (msg_type == SSP_AP2HUB_WRITE) { 410 + ret = spi_write(data->spi, 411 + &msg->buffer[SSP_HEADER_SIZE_ALIGNED], 412 + msg->length); 413 + if (msg_options & SSP_AP2HUB_RETURN) { 414 + msg->options = 415 + SSP_AP2HUB_READ | SSP_AP2HUB_RETURN; 416 + msg->length = 1; 417 + 418 + list_add_tail(&msg->list, &data->pending_list); 419 + goto _unlock; 420 + } 421 + } 422 + 423 + if (msg->done) 424 + if (!completion_done(msg->done)) 425 + complete(msg->done); 426 + _unlock: 427 + mutex_unlock(&data->pending_lock); 428 + break; 429 + case SSP_HUB2AP_WRITE: 430 + buffer = kzalloc(length, GFP_KERNEL | GFP_DMA); 431 + if (!buffer) 432 + return -ENOMEM; 433 + 434 + ret = spi_read(data->spi, buffer, length); 435 + if (ret < 0) { 436 + dev_err(SSP_DEV, "spi read fail\n"); 437 + kfree(buffer); 438 + break; 439 + } 440 + 441 + ret = ssp_parse_dataframe(data, buffer, length); 442 + 443 + kfree(buffer); 444 + break; 445 + 446 + default: 447 + dev_err(SSP_DEV, "unknown msg type\n"); 448 + return -EPROTO; 449 + } 450 + 451 + return ret; 452 + } 453 + 454 + void ssp_clean_pending_list(struct ssp_data *data) 455 + { 456 + struct ssp_msg *msg, *n; 457 + 458 + mutex_lock(&data->pending_lock); 459 + list_for_each_entry_safe(msg, n, &data->pending_list, list) { 460 + list_del(&msg->list); 461 + 462 + if (msg->done) 463 + if (!completion_done(msg->done)) 464 + complete(msg->done); 465 + } 466 + mutex_unlock(&data->pending_lock); 467 + } 468 + 469 + int ssp_command(struct ssp_data *data, char command, int arg) 470 + { 471 + int ret; 472 + struct ssp_msg *msg; 473 + 474 + msg = ssp_create_msg(command, 0, SSP_AP2HUB_WRITE, arg); 475 + if (!msg) 476 + return -ENOMEM; 477 + 478 + ssp_dbg("%s - command 0x%x %d\n", __func__, command, arg); 479 + 480 + ret = ssp_spi_sync_command(data, msg); 481 + ssp_clean_msg(msg); 482 + 483 + return ret; 484 + } 485 + 486 + int ssp_send_instruction(struct ssp_data *data, u8 inst, u8 sensor_type, 487 + u8 *send_buf, u8 length) 488 + { 489 + int ret; 490 + struct ssp_msg *msg; 491 + 492 + if (data->fw_dl_state == SSP_FW_DL_STATE_DOWNLOADING) { 493 + dev_err(SSP_DEV, "%s - Skip Inst! DL state = %d\n", 494 + __func__, data->fw_dl_state); 495 + return -EBUSY; 496 + } else if (!(data->available_sensors & BIT(sensor_type)) && 497 + (inst <= SSP_MSG2SSP_INST_CHANGE_DELAY)) { 498 + dev_err(SSP_DEV, "%s - Bypass Inst Skip! - %u\n", 499 + __func__, sensor_type); 500 + return -EIO; /* just fail */ 501 + } 502 + 503 + msg = ssp_create_msg(inst, length + 2, SSP_AP2HUB_WRITE, 0); 504 + if (!msg) 505 + return -ENOMEM; 506 + 507 + ssp_fill_buffer(msg, 0, &sensor_type, 1); 508 + ssp_fill_buffer(msg, 1, send_buf, length); 509 + 510 + ssp_dbg("%s - Inst = 0x%x, Sensor Type = 0x%x, data = %u\n", 511 + __func__, inst, sensor_type, send_buf[1]); 512 + 513 + ret = ssp_spi_sync(data, msg, 1000); 514 + ssp_clean_msg(msg); 515 + 516 + return ret; 517 + } 518 + 519 + int ssp_get_chipid(struct ssp_data *data) 520 + { 521 + int ret; 522 + char buffer; 523 + struct ssp_msg *msg; 524 + 525 + msg = ssp_create_msg(SSP_MSG2SSP_AP_WHOAMI, 1, SSP_AP2HUB_READ, 0); 526 + if (!msg) 527 + return -ENOMEM; 528 + 529 + ret = ssp_spi_sync(data, msg, 1000); 530 + 531 + buffer = SSP_GET_BUFFER_AT_INDEX(msg, 0); 532 + 533 + ssp_clean_msg(msg); 534 + 535 + return ret < 0 ? ret : buffer; 536 + } 537 + 538 + int ssp_set_magnetic_matrix(struct ssp_data *data) 539 + { 540 + int ret; 541 + struct ssp_msg *msg; 542 + 543 + msg = ssp_create_msg(SSP_MSG2SSP_AP_SET_MAGNETIC_STATIC_MATRIX, 544 + data->sensorhub_info->mag_length, SSP_AP2HUB_WRITE, 545 + 0); 546 + if (!msg) 547 + return -ENOMEM; 548 + 549 + ssp_fill_buffer(msg, 0, data->sensorhub_info->mag_table, 550 + data->sensorhub_info->mag_length); 551 + 552 + ret = ssp_spi_sync(data, msg, 1000); 553 + ssp_clean_msg(msg); 554 + 555 + return ret; 556 + } 557 + 558 + unsigned int ssp_get_sensor_scanning_info(struct ssp_data *data) 559 + { 560 + int ret; 561 + __le32 result; 562 + u32 cpu_result = 0; 563 + 564 + struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_SENSOR_SCANNING, 4, 565 + SSP_AP2HUB_READ, 0); 566 + if (!msg) 567 + return 0; 568 + 569 + ret = ssp_spi_sync(data, msg, 1000); 570 + if (ret < 0) { 571 + dev_err(SSP_DEV, "%s - spi read fail %d\n", __func__, ret); 572 + goto _exit; 573 + } 574 + 575 + ssp_get_buffer(msg, 0, &result, 4); 576 + cpu_result = le32_to_cpu(result); 577 + 578 + dev_info(SSP_DEV, "%s state: 0x%08x\n", __func__, cpu_result); 579 + 580 + _exit: 581 + ssp_clean_msg(msg); 582 + return cpu_result; 583 + } 584 + 585 + unsigned int ssp_get_firmware_rev(struct ssp_data *data) 586 + { 587 + int ret; 588 + __le32 result; 589 + 590 + struct ssp_msg *msg = ssp_create_msg(SSP_MSG2SSP_AP_FIRMWARE_REV, 4, 591 + SSP_AP2HUB_READ, 0); 592 + if (!msg) 593 + return SSP_INVALID_REVISION; 594 + 595 + ret = ssp_spi_sync(data, msg, 1000); 596 + if (ret < 0) { 597 + dev_err(SSP_DEV, "%s - transfer fail %d\n", __func__, ret); 598 + ret = SSP_INVALID_REVISION; 599 + goto _exit; 600 + } 601 + 602 + ssp_get_buffer(msg, 0, &result, 4); 603 + ret = le32_to_cpu(result); 604 + 605 + _exit: 606 + ssp_clean_msg(msg); 607 + return ret; 608 + }
+82
include/linux/iio/common/ssp_sensors.h
··· 1 + /* 2 + * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2 of the License, or 7 + * (at your option) any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + */ 15 + #ifndef _SSP_SENSORS_H_ 16 + #define _SSP_SENSORS_H_ 17 + 18 + #include <linux/iio/iio.h> 19 + 20 + #define SSP_TIME_SIZE 4 21 + #define SSP_ACCELEROMETER_SIZE 6 22 + #define SSP_GYROSCOPE_SIZE 6 23 + #define SSP_BIO_HRM_RAW_SIZE 8 24 + #define SSP_BIO_HRM_RAW_FAC_SIZE 36 25 + #define SSP_BIO_HRM_LIB_SIZE 8 26 + 27 + /** 28 + * enum ssp_sensor_type - SSP sensor type 29 + */ 30 + enum ssp_sensor_type { 31 + SSP_ACCELEROMETER_SENSOR = 0, 32 + SSP_GYROSCOPE_SENSOR, 33 + SSP_GEOMAGNETIC_UNCALIB_SENSOR, 34 + SSP_GEOMAGNETIC_RAW, 35 + SSP_GEOMAGNETIC_SENSOR, 36 + SSP_PRESSURE_SENSOR, 37 + SSP_GESTURE_SENSOR, 38 + SSP_PROXIMITY_SENSOR, 39 + SSP_TEMPERATURE_HUMIDITY_SENSOR, 40 + SSP_LIGHT_SENSOR, 41 + SSP_PROXIMITY_RAW, 42 + SSP_ORIENTATION_SENSOR, 43 + SSP_STEP_DETECTOR, 44 + SSP_SIG_MOTION_SENSOR, 45 + SSP_GYRO_UNCALIB_SENSOR, 46 + SSP_GAME_ROTATION_VECTOR, 47 + SSP_ROTATION_VECTOR, 48 + SSP_STEP_COUNTER, 49 + SSP_BIO_HRM_RAW, 50 + SSP_BIO_HRM_RAW_FAC, 51 + SSP_BIO_HRM_LIB, 52 + SSP_SENSOR_MAX, 53 + }; 54 + 55 + struct ssp_data; 56 + 57 + /** 58 + * struct ssp_sensor_data - Sensor object 59 + * @process_data: Callback to feed sensor data. 60 + * @type: Used sensor type. 61 + * @buffer: Received data buffer. 62 + */ 63 + struct ssp_sensor_data { 64 + int (*process_data)(struct iio_dev *indio_dev, void *buf, 65 + int64_t timestamp); 66 + enum ssp_sensor_type type; 67 + u8 *buffer; 68 + }; 69 + 70 + void ssp_register_consumer(struct iio_dev *indio_dev, 71 + enum ssp_sensor_type type); 72 + 73 + int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type, 74 + u32 delay); 75 + 76 + int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type); 77 + 78 + u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type); 79 + 80 + int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type, 81 + u32 delay); 82 + #endif /* _SSP_SENSORS_H_ */