2 * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved.
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.
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.
16 #include <linux/iio/iio.h>
17 #include <linux/interrupt.h>
19 #include <linux/mfd/core.h>
20 #include <linux/module.h>
22 #include <linux/of_gpio.h>
23 #include <linux/of_platform.h>
26 #define SSP_WDT_TIME 10000
27 #define SSP_LIMIT_RESET_CNT 20
28 #define SSP_LIMIT_TIMEOUT_CNT 3
30 /* It is possible that it is max clk rate for version 1.0 of bootcode */
31 #define SSP_BOOT_SPI_HZ 400000
34 * These fields can look enigmatic but this structure is used mainly to flat
35 * some values and depends on command type.
37 struct ssp_instruction
{
41 } __attribute__((__packed__
));
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,
47 static const struct ssp_sensorhub_info ssp_rinato_info
= {
48 .fw_name
= "ssp_B2.fw",
49 .fw_crashed_name
= "ssp_crashed.fw",
51 .mag_table
= ssp_magnitude_table
,
52 .mag_length
= ARRAY_SIZE(ssp_magnitude_table
),
55 static const struct ssp_sensorhub_info ssp_thermostat_info
= {
56 .fw_name
= "thermostat_B2.fw",
57 .fw_crashed_name
= "ssp_crashed.fw",
59 .mag_table
= ssp_magnitude_table
,
60 .mag_length
= ARRAY_SIZE(ssp_magnitude_table
),
63 static const struct mfd_cell sensorhub_sensor_devs
[] = {
65 .name
= "ssp-accelerometer",
68 .name
= "ssp-gyroscope",
72 static void ssp_toggle_mcu_reset_gpio(struct ssp_data
*data
)
74 gpio_set_value(data
->mcu_reset_gpio
, 0);
75 usleep_range(1000, 1200);
76 gpio_set_value(data
->mcu_reset_gpio
, 1);
80 static void ssp_sync_available_sensors(struct ssp_data
*data
)
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
]);
88 dev_err(&data
->spi
->dev
,
89 "Sync sensor nr: %d fail\n", i
);
95 ret
= ssp_command(data
, SSP_MSG2SSP_AP_MCU_SET_DUMPMODE
,
98 dev_err(&data
->spi
->dev
,
99 "SSP_MSG2SSP_AP_MCU_SET_DUMPMODE failed\n");
102 static void ssp_enable_mcu(struct ssp_data
*data
, bool enable
)
104 dev_info(&data
->spi
->dev
, "current shutdown = %d, old = %d\n", enable
,
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
);
116 dev_warn(&data
->spi
->dev
, "current shutdown = %d, old = %d\n",
117 enable
, data
->shut_down
);
122 * This function is the first one which communicates with the mcu so it is
123 * possible that the first attempt will fail
125 static int ssp_check_fwbl(struct ssp_data
*data
)
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
);
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
;
146 dev_info(&data
->spi
->dev
,
147 "MCU Firm Rev : Old = %8u, New = %8u\n",
149 data
->sensorhub_info
->fw_rev
);
151 if (data
->cur_firm_rev
!= data
->sensorhub_info
->fw_rev
)
152 return SSP_FW_DL_STATE_NEED_TO_SCHEDULE
;
154 return SSP_FW_DL_STATE_NONE
;
157 static void ssp_reset_mcu(struct ssp_data
*data
)
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);
165 static void ssp_wdt_work_func(struct work_struct
*work
)
167 struct ssp_data
*data
= container_of(work
, struct ssp_data
, work_wdt
);
169 dev_err(&data
->spi
->dev
, "%s - Sensor state: 0x%x, RC: %u, CC: %u\n",
170 __func__
, data
->available_sensors
, data
->reset_cnt
,
174 data
->com_fail_cnt
= 0;
175 data
->timeout_cnt
= 0;
178 static void ssp_wdt_timer_func(unsigned long ptr
)
180 struct ssp_data
*data
= (struct ssp_data
*)ptr
;
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
:
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
);
193 mod_timer(&data
->wdt_timer
, jiffies
+ msecs_to_jiffies(SSP_WDT_TIME
));
196 static void ssp_enable_wdt_timer(struct ssp_data
*data
)
198 mod_timer(&data
->wdt_timer
, jiffies
+ msecs_to_jiffies(SSP_WDT_TIME
));
201 static void ssp_disable_wdt_timer(struct ssp_data
*data
)
203 del_timer_sync(&data
->wdt_timer
);
204 cancel_work_sync(&data
->work_wdt
);
208 * ssp_get_sensor_delay() - gets sensor data acquisition period
209 * @data: sensorhub structure
210 * @type: SSP sensor type
212 * Returns acquisition period in ms
214 u32
ssp_get_sensor_delay(struct ssp_data
*data
, enum ssp_sensor_type type
)
216 return data
->delay_buf
[type
];
218 EXPORT_SYMBOL(ssp_get_sensor_delay
);
221 * ssp_enable_sensor() - enables data acquisition for sensor
222 * @data: sensorhub structure
223 * @type: SSP sensor type
224 * @delay: delay in ms
226 * Returns 0 or negative value in case of error
228 int ssp_enable_sensor(struct ssp_data
*data
, enum ssp_sensor_type type
,
232 struct ssp_instruction to_send
;
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
];
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
,
245 (u8
*)&to_send
, sizeof(to_send
));
247 dev_err(&data
->spi
->dev
, "Enabling sensor failed\n");
248 data
->check_status
[type
] = SSP_NO_SENSOR_STATE
;
252 data
->sensor_enable
|= BIT(type
);
253 data
->check_status
[type
] = SSP_RUNNING_SENSOR_STATE
;
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
));
260 dev_err(&data
->spi
->dev
,
261 "Changing sensor delay failed\n");
266 data
->check_status
[type
] = SSP_ADD_SENSOR_STATE
;
270 data
->delay_buf
[type
] = delay
;
272 if (atomic_inc_return(&data
->enable_refcount
) == 1)
273 ssp_enable_wdt_timer(data
);
280 EXPORT_SYMBOL(ssp_enable_sensor
);
283 * ssp_change_delay() - changes data acquisition for sensor
284 * @data: sensorhub structure
285 * @type: SSP sensor type
286 * @delay: delay in ms
288 * Returns 0 or negative value in case of error
290 int ssp_change_delay(struct ssp_data
*data
, enum ssp_sensor_type type
,
294 struct ssp_instruction to_send
;
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
];
300 ret
= ssp_send_instruction(data
, SSP_MSG2SSP_INST_CHANGE_DELAY
, type
,
301 (u8
*)&to_send
, sizeof(to_send
));
303 dev_err(&data
->spi
->dev
, "Changing sensor delay failed\n");
307 data
->delay_buf
[type
] = delay
;
311 EXPORT_SYMBOL(ssp_change_delay
);
314 * ssp_disable_sensor() - disables sensor
316 * @data: sensorhub structure
317 * @type: SSP sensor type
319 * Returns 0 or negative value in case of error
321 int ssp_disable_sensor(struct ssp_data
*data
, enum ssp_sensor_type type
)
326 if (data
->sensor_enable
& BIT(type
)) {
327 command
= cpu_to_le32(data
->delay_buf
[type
]);
329 ret
= ssp_send_instruction(data
,
330 SSP_MSG2SSP_INST_BYPASS_SENSOR_RM
,
331 type
, (u8
*)&command
,
334 dev_err(&data
->spi
->dev
, "Remove sensor fail\n");
338 data
->sensor_enable
&= ~BIT(type
);
341 data
->check_status
[type
] = SSP_ADD_SENSOR_STATE
;
343 if (atomic_dec_and_test(&data
->enable_refcount
))
344 ssp_disable_wdt_timer(data
);
348 EXPORT_SYMBOL(ssp_disable_sensor
);
350 static irqreturn_t
ssp_irq_thread_fn(int irq
, void *dev_id
)
352 struct ssp_data
*data
= dev_id
;
355 * This wrapper is done to preserve error path for ssp_irq_msg, also
356 * it is defined in different file.
363 static int ssp_initialize_mcu(struct ssp_data
*data
)
367 ssp_clean_pending_list(data
);
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",
374 return ret
< 0 ? ret
: -ENODEV
;
377 dev_info(&data
->spi
->dev
, "MCU device ID = %d\n", ret
);
380 * needs clarification, for now do not want to export all transfer
381 * methods to sensors' drivers
383 ret
= ssp_set_magnetic_matrix(data
);
385 dev_err(&data
->spi
->dev
,
386 "%s - ssp_set_magnetic_matrix failed\n", __func__
);
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__
);
397 data
->cur_firm_rev
= ssp_get_firmware_rev(data
);
398 dev_info(&data
->spi
->dev
, "MCU Firm Rev : New = %8u\n",
401 return ssp_command(data
, SSP_MSG2SSP_AP_MCU_DUMP_CHECK
, 0);
405 * sensorhub can request its reinitialization as some brutal and rare error
406 * handling. It can be requested from the MCU.
408 static void ssp_refresh_task(struct work_struct
*work
)
410 struct ssp_data
*data
= container_of((struct delayed_work
*)work
,
411 struct ssp_data
, work_refresh
);
413 dev_info(&data
->spi
->dev
, "refreshing\n");
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);
422 if (data
->last_resume_state
!= 0)
423 ssp_command(data
, data
->last_resume_state
, 0);
425 data
->timeout_cnt
= 0;
426 data
->com_fail_cnt
= 0;
430 int ssp_queue_ssp_refresh_task(struct ssp_data
*data
, unsigned int delay
)
432 cancel_delayed_work_sync(&data
->work_refresh
);
434 return queue_delayed_work(system_power_efficient_wq
,
436 msecs_to_jiffies(delay
));
440 static const struct of_device_id ssp_of_match
[] = {
442 .compatible
= "samsung,sensorhub-rinato",
443 .data
= &ssp_rinato_info
,
445 .compatible
= "samsung,sensorhub-thermostat",
446 .data
= &ssp_thermostat_info
,
450 MODULE_DEVICE_TABLE(of
, ssp_of_match
);
452 static struct ssp_data
*ssp_parse_dt(struct device
*dev
)
455 struct ssp_data
*data
;
456 struct device_node
*node
= dev
->of_node
;
457 const struct of_device_id
*match
;
459 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
463 data
->mcu_ap_gpio
= of_get_named_gpio(node
, "mcu-ap-gpios", 0);
464 if (data
->mcu_ap_gpio
< 0)
467 data
->ap_mcu_gpio
= of_get_named_gpio(node
, "ap-mcu-gpios", 0);
468 if (data
->ap_mcu_gpio
< 0)
471 data
->mcu_reset_gpio
= of_get_named_gpio(node
, "mcu-reset-gpios", 0);
472 if (data
->mcu_reset_gpio
< 0)
475 ret
= devm_gpio_request_one(dev
, data
->ap_mcu_gpio
, GPIOF_OUT_INIT_HIGH
,
480 ret
= devm_gpio_request_one(dev
, data
->mcu_reset_gpio
,
481 GPIOF_OUT_INIT_HIGH
, "mcu-reset-gpios");
485 match
= of_match_node(ssp_of_match
, node
);
487 goto err_mcu_reset_gpio
;
489 data
->sensorhub_info
= (struct ssp_sensorhub_info
*)match
->data
;
491 dev_set_drvdata(dev
, data
);
496 devm_gpio_free(dev
, data
->mcu_reset_gpio
);
498 devm_gpio_free(dev
, data
->ap_mcu_gpio
);
500 devm_kfree(dev
, data
);
504 static struct ssp_data
*ssp_parse_dt(struct device
*pdev
)
511 * ssp_register_consumer() - registers iio consumer in ssp framework
513 * @indio_dev: consumer iio device
514 * @type: ssp sensor type
516 void ssp_register_consumer(struct iio_dev
*indio_dev
, enum ssp_sensor_type type
)
518 struct ssp_data
*data
= dev_get_drvdata(indio_dev
->dev
.parent
->parent
);
520 data
->sensor_devs
[type
] = indio_dev
;
522 EXPORT_SYMBOL(ssp_register_consumer
);
524 static int ssp_probe(struct spi_device
*spi
)
527 struct ssp_data
*data
;
529 data
= ssp_parse_dt(&spi
->dev
);
531 dev_err(&spi
->dev
, "Failed to find platform data\n");
535 ret
= mfd_add_devices(&spi
->dev
, -1, sensorhub_sensor_devs
,
536 ARRAY_SIZE(sensorhub_sensor_devs
), NULL
, 0, NULL
);
538 dev_err(&spi
->dev
, "mfd add devices fail\n");
542 spi
->mode
= SPI_MODE_1
;
543 ret
= spi_setup(spi
);
545 dev_err(&spi
->dev
, "Failed to setup spi\n");
549 data
->fw_dl_state
= SSP_FW_DL_STATE_NONE
;
551 spi_set_drvdata(spi
, data
);
553 mutex_init(&data
->comm_lock
);
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
;
562 data
->delay_buf
[SSP_BIO_HRM_LIB
] = 100;
564 data
->time_syncing
= true;
566 mutex_init(&data
->pending_lock
);
567 INIT_LIST_HEAD(&data
->pending_list
);
569 atomic_set(&data
->enable_refcount
, 0);
571 INIT_WORK(&data
->work_wdt
, ssp_wdt_work_func
);
572 INIT_DELAYED_WORK(&data
->work_refresh
, ssp_refresh_task
);
574 setup_timer(&data
->wdt_timer
, ssp_wdt_timer_func
, (unsigned long)data
);
576 ret
= request_threaded_irq(data
->spi
->irq
, NULL
,
578 IRQF_TRIGGER_FALLING
| IRQF_ONESHOT
,
581 dev_err(&spi
->dev
, "Irq request fail\n");
585 /* Let's start with enabled one so irq balance could be ok */
586 data
->shut_down
= false;
588 /* just to avoid unbalanced irq set wake up */
589 enable_irq_wake(data
->spi
->irq
);
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
);
595 dev_err(&spi
->dev
, "Initialize_mcu failed\n");
599 dev_err(&spi
->dev
, "Firmware version not supported\n");
607 free_irq(data
->spi
->irq
, data
);
609 mutex_destroy(&data
->pending_lock
);
610 mutex_destroy(&data
->comm_lock
);
612 dev_err(&spi
->dev
, "Probe failed!\n");
617 static int ssp_remove(struct spi_device
*spi
)
619 struct ssp_data
*data
= spi_get_drvdata(spi
);
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");
625 ssp_enable_mcu(data
, false);
626 ssp_disable_wdt_timer(data
);
628 ssp_clean_pending_list(data
);
630 free_irq(data
->spi
->irq
, data
);
632 del_timer_sync(&data
->wdt_timer
);
633 cancel_work_sync(&data
->work_wdt
);
635 mutex_destroy(&data
->comm_lock
);
636 mutex_destroy(&data
->pending_lock
);
638 mfd_remove_devices(&spi
->dev
);
643 #ifdef CONFIG_PM_SLEEP
644 static int ssp_suspend(struct device
*dev
)
647 struct ssp_data
*data
= spi_get_drvdata(to_spi_device(dev
));
649 data
->last_resume_state
= SSP_MSG2SSP_AP_STATUS_SUSPEND
;
651 if (atomic_read(&data
->enable_refcount
) > 0)
652 ssp_disable_wdt_timer(data
);
654 ret
= ssp_command(data
, SSP_MSG2SSP_AP_STATUS_SUSPEND
, 0);
656 dev_err(&data
->spi
->dev
,
657 "%s SSP_MSG2SSP_AP_STATUS_SUSPEND failed\n", __func__
);
659 ssp_enable_wdt_timer(data
);
663 data
->time_syncing
= false;
664 disable_irq(data
->spi
->irq
);
669 static int ssp_resume(struct device
*dev
)
672 struct ssp_data
*data
= spi_get_drvdata(to_spi_device(dev
));
674 enable_irq(data
->spi
->irq
);
676 if (atomic_read(&data
->enable_refcount
) > 0)
677 ssp_enable_wdt_timer(data
);
679 ret
= ssp_command(data
, SSP_MSG2SSP_AP_STATUS_RESUME
, 0);
681 dev_err(&data
->spi
->dev
,
682 "%s SSP_MSG2SSP_AP_STATUS_RESUME failed\n", __func__
);
683 ssp_disable_wdt_timer(data
);
687 /* timesyncing is set by MCU */
688 data
->last_resume_state
= SSP_MSG2SSP_AP_STATUS_RESUME
;
692 #endif /* CONFIG_PM_SLEEP */
694 static const struct dev_pm_ops ssp_pm_ops
= {
695 SET_SYSTEM_SLEEP_PM_OPS(ssp_suspend
, ssp_resume
)
698 static struct spi_driver ssp_driver
= {
700 .remove
= ssp_remove
,
703 .of_match_table
= of_match_ptr(ssp_of_match
),
708 module_spi_driver(ssp_driver
);
710 MODULE_DESCRIPTION("ssp sensorhub driver");
711 MODULE_AUTHOR("Samsung Electronics");
712 MODULE_LICENSE("GPL");