ssp_dev.c (16173B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright (C) 2014, Samsung Electronics Co. Ltd. All Rights Reserved. 4 */ 5 6#include <linux/iio/iio.h> 7#include <linux/interrupt.h> 8#include <linux/io.h> 9#include <linux/mfd/core.h> 10#include <linux/mod_devicetable.h> 11#include <linux/module.h> 12#include <linux/property.h> 13 14#include "ssp.h" 15 16#define SSP_WDT_TIME 10000 17#define SSP_LIMIT_RESET_CNT 20 18#define SSP_LIMIT_TIMEOUT_CNT 3 19 20/* It is possible that it is max clk rate for version 1.0 of bootcode */ 21#define SSP_BOOT_SPI_HZ 400000 22 23/* 24 * These fields can look enigmatic but this structure is used mainly to flat 25 * some values and depends on command type. 26 */ 27struct ssp_instruction { 28 __le32 a; 29 __le32 b; 30 u8 c; 31} __attribute__((__packed__)); 32 33static const u8 ssp_magnitude_table[] = {110, 85, 171, 71, 203, 195, 0, 67, 34 208, 56, 175, 244, 206, 213, 0, 92, 250, 0, 55, 48, 189, 252, 171, 35 243, 13, 45, 250}; 36 37static const struct ssp_sensorhub_info ssp_rinato_info = { 38 .fw_name = "ssp_B2.fw", 39 .fw_crashed_name = "ssp_crashed.fw", 40 .fw_rev = 14052300, 41 .mag_table = ssp_magnitude_table, 42 .mag_length = ARRAY_SIZE(ssp_magnitude_table), 43}; 44 45static const struct ssp_sensorhub_info ssp_thermostat_info = { 46 .fw_name = "thermostat_B2.fw", 47 .fw_crashed_name = "ssp_crashed.fw", 48 .fw_rev = 14080600, 49 .mag_table = ssp_magnitude_table, 50 .mag_length = ARRAY_SIZE(ssp_magnitude_table), 51}; 52 53static const struct mfd_cell sensorhub_sensor_devs[] = { 54 { 55 .name = "ssp-accelerometer", 56 }, 57 { 58 .name = "ssp-gyroscope", 59 }, 60}; 61 62static void ssp_toggle_mcu_reset_gpio(struct ssp_data *data) 63{ 64 gpiod_set_value(data->mcu_reset_gpiod, 0); 65 usleep_range(1000, 1200); 66 gpiod_set_value(data->mcu_reset_gpiod, 1); 67 msleep(50); 68} 69 70static void ssp_sync_available_sensors(struct ssp_data *data) 71{ 72 int i, ret; 73 74 for (i = 0; i < SSP_SENSOR_MAX; ++i) { 75 if (data->available_sensors & BIT(i)) { 76 ret = ssp_enable_sensor(data, i, data->delay_buf[i]); 77 if (ret < 0) { 78 dev_err(&data->spi->dev, 79 "Sync sensor nr: %d fail\n", i); 80 continue; 81 } 82 } 83 } 84 85 ret = ssp_command(data, SSP_MSG2SSP_AP_MCU_SET_DUMPMODE, 86 data->mcu_dump_mode); 87 if (ret < 0) 88 dev_err(&data->spi->dev, 89 "SSP_MSG2SSP_AP_MCU_SET_DUMPMODE failed\n"); 90} 91 92static void ssp_enable_mcu(struct ssp_data *data, bool enable) 93{ 94 dev_info(&data->spi->dev, "current shutdown = %d, old = %d\n", enable, 95 data->shut_down); 96 97 if (enable && data->shut_down) { 98 data->shut_down = false; 99 enable_irq(data->spi->irq); 100 enable_irq_wake(data->spi->irq); 101 } else if (!enable && !data->shut_down) { 102 data->shut_down = true; 103 disable_irq(data->spi->irq); 104 disable_irq_wake(data->spi->irq); 105 } else { 106 dev_warn(&data->spi->dev, "current shutdown = %d, old = %d\n", 107 enable, data->shut_down); 108 } 109} 110 111/* 112 * This function is the first one which communicates with the mcu so it is 113 * possible that the first attempt will fail 114 */ 115static int ssp_check_fwbl(struct ssp_data *data) 116{ 117 int retries = 0; 118 119 while (retries++ < 5) { 120 data->cur_firm_rev = ssp_get_firmware_rev(data); 121 if (data->cur_firm_rev == SSP_INVALID_REVISION || 122 data->cur_firm_rev == SSP_INVALID_REVISION2) { 123 dev_warn(&data->spi->dev, 124 "Invalid revision, trying %d time\n", retries); 125 } else { 126 break; 127 } 128 } 129 130 if (data->cur_firm_rev == SSP_INVALID_REVISION || 131 data->cur_firm_rev == SSP_INVALID_REVISION2) { 132 dev_err(&data->spi->dev, "SSP_INVALID_REVISION\n"); 133 return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; 134 } 135 136 dev_info(&data->spi->dev, 137 "MCU Firm Rev : Old = %8u, New = %8u\n", 138 data->cur_firm_rev, 139 data->sensorhub_info->fw_rev); 140 141 if (data->cur_firm_rev != data->sensorhub_info->fw_rev) 142 return SSP_FW_DL_STATE_NEED_TO_SCHEDULE; 143 144 return SSP_FW_DL_STATE_NONE; 145} 146 147static void ssp_reset_mcu(struct ssp_data *data) 148{ 149 ssp_enable_mcu(data, false); 150 ssp_clean_pending_list(data); 151 ssp_toggle_mcu_reset_gpio(data); 152 ssp_enable_mcu(data, true); 153} 154 155static void ssp_wdt_work_func(struct work_struct *work) 156{ 157 struct ssp_data *data = container_of(work, struct ssp_data, work_wdt); 158 159 dev_err(&data->spi->dev, "%s - Sensor state: 0x%x, RC: %u, CC: %u\n", 160 __func__, data->available_sensors, data->reset_cnt, 161 data->com_fail_cnt); 162 163 ssp_reset_mcu(data); 164 data->com_fail_cnt = 0; 165 data->timeout_cnt = 0; 166} 167 168static void ssp_wdt_timer_func(struct timer_list *t) 169{ 170 struct ssp_data *data = from_timer(data, t, wdt_timer); 171 172 switch (data->fw_dl_state) { 173 case SSP_FW_DL_STATE_FAIL: 174 case SSP_FW_DL_STATE_DOWNLOADING: 175 case SSP_FW_DL_STATE_SYNC: 176 goto _mod; 177 } 178 179 if (data->timeout_cnt > SSP_LIMIT_TIMEOUT_CNT || 180 data->com_fail_cnt > SSP_LIMIT_RESET_CNT) 181 queue_work(system_power_efficient_wq, &data->work_wdt); 182_mod: 183 mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); 184} 185 186static void ssp_enable_wdt_timer(struct ssp_data *data) 187{ 188 mod_timer(&data->wdt_timer, jiffies + msecs_to_jiffies(SSP_WDT_TIME)); 189} 190 191static void ssp_disable_wdt_timer(struct ssp_data *data) 192{ 193 del_timer_sync(&data->wdt_timer); 194 cancel_work_sync(&data->work_wdt); 195} 196 197/** 198 * ssp_get_sensor_delay() - gets sensor data acquisition period 199 * @data: sensorhub structure 200 * @type: SSP sensor type 201 * 202 * Returns acquisition period in ms 203 */ 204u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type type) 205{ 206 return data->delay_buf[type]; 207} 208EXPORT_SYMBOL_NS(ssp_get_sensor_delay, IIO_SSP_SENSORS); 209 210/** 211 * ssp_enable_sensor() - enables data acquisition for sensor 212 * @data: sensorhub structure 213 * @type: SSP sensor type 214 * @delay: delay in ms 215 * 216 * Returns 0 or negative value in case of error 217 */ 218int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type, 219 u32 delay) 220{ 221 int ret; 222 struct ssp_instruction to_send; 223 224 to_send.a = cpu_to_le32(delay); 225 to_send.b = cpu_to_le32(data->batch_latency_buf[type]); 226 to_send.c = data->batch_opt_buf[type]; 227 228 switch (data->check_status[type]) { 229 case SSP_INITIALIZATION_STATE: 230 /* do calibration step, now just enable */ 231 case SSP_ADD_SENSOR_STATE: 232 ret = ssp_send_instruction(data, 233 SSP_MSG2SSP_INST_BYPASS_SENSOR_ADD, 234 type, 235 (u8 *)&to_send, sizeof(to_send)); 236 if (ret < 0) { 237 dev_err(&data->spi->dev, "Enabling sensor failed\n"); 238 data->check_status[type] = SSP_NO_SENSOR_STATE; 239 goto derror; 240 } 241 242 data->sensor_enable |= BIT(type); 243 data->check_status[type] = SSP_RUNNING_SENSOR_STATE; 244 break; 245 case SSP_RUNNING_SENSOR_STATE: 246 ret = ssp_send_instruction(data, 247 SSP_MSG2SSP_INST_CHANGE_DELAY, type, 248 (u8 *)&to_send, sizeof(to_send)); 249 if (ret < 0) { 250 dev_err(&data->spi->dev, 251 "Changing sensor delay failed\n"); 252 goto derror; 253 } 254 break; 255 default: 256 data->check_status[type] = SSP_ADD_SENSOR_STATE; 257 break; 258 } 259 260 data->delay_buf[type] = delay; 261 262 if (atomic_inc_return(&data->enable_refcount) == 1) 263 ssp_enable_wdt_timer(data); 264 265 return 0; 266 267derror: 268 return ret; 269} 270EXPORT_SYMBOL_NS(ssp_enable_sensor, IIO_SSP_SENSORS); 271 272/** 273 * ssp_change_delay() - changes data acquisition for sensor 274 * @data: sensorhub structure 275 * @type: SSP sensor type 276 * @delay: delay in ms 277 * 278 * Returns 0 or negative value in case of error 279 */ 280int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type, 281 u32 delay) 282{ 283 int ret; 284 struct ssp_instruction to_send; 285 286 to_send.a = cpu_to_le32(delay); 287 to_send.b = cpu_to_le32(data->batch_latency_buf[type]); 288 to_send.c = data->batch_opt_buf[type]; 289 290 ret = ssp_send_instruction(data, SSP_MSG2SSP_INST_CHANGE_DELAY, type, 291 (u8 *)&to_send, sizeof(to_send)); 292 if (ret < 0) { 293 dev_err(&data->spi->dev, "Changing sensor delay failed\n"); 294 return ret; 295 } 296 297 data->delay_buf[type] = delay; 298 299 return 0; 300} 301EXPORT_SYMBOL_NS(ssp_change_delay, IIO_SSP_SENSORS); 302 303/** 304 * ssp_disable_sensor() - disables sensor 305 * 306 * @data: sensorhub structure 307 * @type: SSP sensor type 308 * 309 * Returns 0 or negative value in case of error 310 */ 311int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type) 312{ 313 int ret; 314 __le32 command; 315 316 if (data->sensor_enable & BIT(type)) { 317 command = cpu_to_le32(data->delay_buf[type]); 318 319 ret = ssp_send_instruction(data, 320 SSP_MSG2SSP_INST_BYPASS_SENSOR_RM, 321 type, (u8 *)&command, 322 sizeof(command)); 323 if (ret < 0) { 324 dev_err(&data->spi->dev, "Remove sensor fail\n"); 325 return ret; 326 } 327 328 data->sensor_enable &= ~BIT(type); 329 } 330 331 data->check_status[type] = SSP_ADD_SENSOR_STATE; 332 333 if (atomic_dec_and_test(&data->enable_refcount)) 334 ssp_disable_wdt_timer(data); 335 336 return 0; 337} 338EXPORT_SYMBOL_NS(ssp_disable_sensor, IIO_SSP_SENSORS); 339 340static irqreturn_t ssp_irq_thread_fn(int irq, void *dev_id) 341{ 342 struct ssp_data *data = dev_id; 343 344 /* 345 * This wrapper is done to preserve error path for ssp_irq_msg, also 346 * it is defined in different file. 347 */ 348 ssp_irq_msg(data); 349 350 return IRQ_HANDLED; 351} 352 353static int ssp_initialize_mcu(struct ssp_data *data) 354{ 355 int ret; 356 357 ssp_clean_pending_list(data); 358 359 ret = ssp_get_chipid(data); 360 if (ret != SSP_DEVICE_ID) { 361 dev_err(&data->spi->dev, "%s - MCU %s ret = %d\n", __func__, 362 ret < 0 ? "is not working" : "identification failed", 363 ret); 364 return ret < 0 ? ret : -ENODEV; 365 } 366 367 dev_info(&data->spi->dev, "MCU device ID = %d\n", ret); 368 369 /* 370 * needs clarification, for now do not want to export all transfer 371 * methods to sensors' drivers 372 */ 373 ret = ssp_set_magnetic_matrix(data); 374 if (ret < 0) { 375 dev_err(&data->spi->dev, 376 "%s - ssp_set_magnetic_matrix failed\n", __func__); 377 return ret; 378 } 379 380 data->available_sensors = ssp_get_sensor_scanning_info(data); 381 if (data->available_sensors == 0) { 382 dev_err(&data->spi->dev, 383 "%s - ssp_get_sensor_scanning_info failed\n", __func__); 384 return -EIO; 385 } 386 387 data->cur_firm_rev = ssp_get_firmware_rev(data); 388 dev_info(&data->spi->dev, "MCU Firm Rev : New = %8u\n", 389 data->cur_firm_rev); 390 391 return ssp_command(data, SSP_MSG2SSP_AP_MCU_DUMP_CHECK, 0); 392} 393 394/* 395 * sensorhub can request its reinitialization as some brutal and rare error 396 * handling. It can be requested from the MCU. 397 */ 398static void ssp_refresh_task(struct work_struct *work) 399{ 400 struct ssp_data *data = container_of((struct delayed_work *)work, 401 struct ssp_data, work_refresh); 402 403 dev_info(&data->spi->dev, "refreshing\n"); 404 405 data->reset_cnt++; 406 407 if (ssp_initialize_mcu(data) >= 0) { 408 ssp_sync_available_sensors(data); 409 if (data->last_ap_state != 0) 410 ssp_command(data, data->last_ap_state, 0); 411 412 if (data->last_resume_state != 0) 413 ssp_command(data, data->last_resume_state, 0); 414 415 data->timeout_cnt = 0; 416 data->com_fail_cnt = 0; 417 } 418} 419 420int ssp_queue_ssp_refresh_task(struct ssp_data *data, unsigned int delay) 421{ 422 cancel_delayed_work_sync(&data->work_refresh); 423 424 return queue_delayed_work(system_power_efficient_wq, 425 &data->work_refresh, 426 msecs_to_jiffies(delay)); 427} 428 429static const struct of_device_id ssp_of_match[] = { 430 { 431 .compatible = "samsung,sensorhub-rinato", 432 .data = &ssp_rinato_info, 433 }, { 434 .compatible = "samsung,sensorhub-thermostat", 435 .data = &ssp_thermostat_info, 436 }, 437 {}, 438}; 439MODULE_DEVICE_TABLE(of, ssp_of_match); 440 441static struct ssp_data *ssp_parse_dt(struct device *dev) 442{ 443 struct ssp_data *data; 444 445 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 446 if (!data) 447 return NULL; 448 449 data->mcu_ap_gpiod = devm_gpiod_get(dev, "mcu-ap", GPIOD_IN); 450 if (IS_ERR(data->mcu_ap_gpiod)) 451 return NULL; 452 453 data->ap_mcu_gpiod = devm_gpiod_get(dev, "ap-mcu", GPIOD_OUT_HIGH); 454 if (IS_ERR(data->ap_mcu_gpiod)) 455 return NULL; 456 457 data->mcu_reset_gpiod = devm_gpiod_get(dev, "mcu-reset", 458 GPIOD_OUT_HIGH); 459 if (IS_ERR(data->mcu_reset_gpiod)) 460 return NULL; 461 462 data->sensorhub_info = device_get_match_data(dev); 463 464 dev_set_drvdata(dev, data); 465 466 return data; 467} 468 469/** 470 * ssp_register_consumer() - registers iio consumer in ssp framework 471 * 472 * @indio_dev: consumer iio device 473 * @type: ssp sensor type 474 */ 475void ssp_register_consumer(struct iio_dev *indio_dev, enum ssp_sensor_type type) 476{ 477 struct ssp_data *data = dev_get_drvdata(indio_dev->dev.parent->parent); 478 479 data->sensor_devs[type] = indio_dev; 480} 481EXPORT_SYMBOL_NS(ssp_register_consumer, IIO_SSP_SENSORS); 482 483static int ssp_probe(struct spi_device *spi) 484{ 485 int ret, i; 486 struct ssp_data *data; 487 488 data = ssp_parse_dt(&spi->dev); 489 if (!data) { 490 dev_err(&spi->dev, "Failed to find platform data\n"); 491 return -ENODEV; 492 } 493 494 ret = mfd_add_devices(&spi->dev, PLATFORM_DEVID_NONE, 495 sensorhub_sensor_devs, 496 ARRAY_SIZE(sensorhub_sensor_devs), NULL, 0, NULL); 497 if (ret < 0) { 498 dev_err(&spi->dev, "mfd add devices fail\n"); 499 return ret; 500 } 501 502 spi->mode = SPI_MODE_1; 503 ret = spi_setup(spi); 504 if (ret < 0) { 505 dev_err(&spi->dev, "Failed to setup spi\n"); 506 return ret; 507 } 508 509 data->fw_dl_state = SSP_FW_DL_STATE_NONE; 510 data->spi = spi; 511 spi_set_drvdata(spi, data); 512 513 mutex_init(&data->comm_lock); 514 515 for (i = 0; i < SSP_SENSOR_MAX; ++i) { 516 data->delay_buf[i] = SSP_DEFAULT_POLLING_DELAY; 517 data->batch_latency_buf[i] = 0; 518 data->batch_opt_buf[i] = 0; 519 data->check_status[i] = SSP_INITIALIZATION_STATE; 520 } 521 522 data->delay_buf[SSP_BIO_HRM_LIB] = 100; 523 524 data->time_syncing = true; 525 526 mutex_init(&data->pending_lock); 527 INIT_LIST_HEAD(&data->pending_list); 528 529 atomic_set(&data->enable_refcount, 0); 530 531 INIT_WORK(&data->work_wdt, ssp_wdt_work_func); 532 INIT_DELAYED_WORK(&data->work_refresh, ssp_refresh_task); 533 534 timer_setup(&data->wdt_timer, ssp_wdt_timer_func, 0); 535 536 ret = request_threaded_irq(data->spi->irq, NULL, 537 ssp_irq_thread_fn, 538 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 539 "SSP_Int", data); 540 if (ret < 0) { 541 dev_err(&spi->dev, "Irq request fail\n"); 542 goto err_setup_irq; 543 } 544 545 /* Let's start with enabled one so irq balance could be ok */ 546 data->shut_down = false; 547 548 /* just to avoid unbalanced irq set wake up */ 549 enable_irq_wake(data->spi->irq); 550 551 data->fw_dl_state = ssp_check_fwbl(data); 552 if (data->fw_dl_state == SSP_FW_DL_STATE_NONE) { 553 ret = ssp_initialize_mcu(data); 554 if (ret < 0) { 555 dev_err(&spi->dev, "Initialize_mcu failed\n"); 556 goto err_read_reg; 557 } 558 } else { 559 dev_err(&spi->dev, "Firmware version not supported\n"); 560 ret = -EPERM; 561 goto err_read_reg; 562 } 563 564 return 0; 565 566err_read_reg: 567 free_irq(data->spi->irq, data); 568err_setup_irq: 569 mutex_destroy(&data->pending_lock); 570 mutex_destroy(&data->comm_lock); 571 572 dev_err(&spi->dev, "Probe failed!\n"); 573 574 return ret; 575} 576 577static void ssp_remove(struct spi_device *spi) 578{ 579 struct ssp_data *data = spi_get_drvdata(spi); 580 581 if (ssp_command(data, SSP_MSG2SSP_AP_STATUS_SHUTDOWN, 0) < 0) 582 dev_err(&data->spi->dev, 583 "SSP_MSG2SSP_AP_STATUS_SHUTDOWN failed\n"); 584 585 ssp_enable_mcu(data, false); 586 ssp_disable_wdt_timer(data); 587 588 ssp_clean_pending_list(data); 589 590 free_irq(data->spi->irq, data); 591 592 del_timer_sync(&data->wdt_timer); 593 cancel_work_sync(&data->work_wdt); 594 595 mutex_destroy(&data->comm_lock); 596 mutex_destroy(&data->pending_lock); 597 598 mfd_remove_devices(&spi->dev); 599} 600 601static int ssp_suspend(struct device *dev) 602{ 603 int ret; 604 struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); 605 606 data->last_resume_state = SSP_MSG2SSP_AP_STATUS_SUSPEND; 607 608 if (atomic_read(&data->enable_refcount) > 0) 609 ssp_disable_wdt_timer(data); 610 611 ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_SUSPEND, 0); 612 if (ret < 0) { 613 dev_err(&data->spi->dev, 614 "%s SSP_MSG2SSP_AP_STATUS_SUSPEND failed\n", __func__); 615 616 ssp_enable_wdt_timer(data); 617 return ret; 618 } 619 620 data->time_syncing = false; 621 disable_irq(data->spi->irq); 622 623 return 0; 624} 625 626static int ssp_resume(struct device *dev) 627{ 628 int ret; 629 struct ssp_data *data = spi_get_drvdata(to_spi_device(dev)); 630 631 enable_irq(data->spi->irq); 632 633 if (atomic_read(&data->enable_refcount) > 0) 634 ssp_enable_wdt_timer(data); 635 636 ret = ssp_command(data, SSP_MSG2SSP_AP_STATUS_RESUME, 0); 637 if (ret < 0) { 638 dev_err(&data->spi->dev, 639 "%s SSP_MSG2SSP_AP_STATUS_RESUME failed\n", __func__); 640 ssp_disable_wdt_timer(data); 641 return ret; 642 } 643 644 /* timesyncing is set by MCU */ 645 data->last_resume_state = SSP_MSG2SSP_AP_STATUS_RESUME; 646 647 return 0; 648} 649 650static DEFINE_SIMPLE_DEV_PM_OPS(ssp_pm_ops, ssp_suspend, ssp_resume); 651 652static struct spi_driver ssp_driver = { 653 .probe = ssp_probe, 654 .remove = ssp_remove, 655 .driver = { 656 .pm = pm_sleep_ptr(&ssp_pm_ops), 657 .of_match_table = ssp_of_match, 658 .name = "sensorhub" 659 }, 660}; 661 662module_spi_driver(ssp_driver); 663 664MODULE_DESCRIPTION("ssp sensorhub driver"); 665MODULE_AUTHOR("Samsung Electronics"); 666MODULE_LICENSE("GPL");