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

regulator: max8973: add support for junction thermal warning

The driver MAX8973 supports the driver for Maxim PMIC MAX77621.
MAX77621 supports the junction temp warning at 120 degC and
140 degC which is configurable. It generates alert signal when
junction temperature crosses these threshold.

MAX77621 does not support the continuous temp monitoring of
junction temperature. It just report whether junction temperature
crossed the threshold or not.

Add support to
- Configure junction temp warning threshold via DT property
to generate alert when it crosses the threshold.
- Add support to interrupt the host from this device when alert
occurred.
- read the junction temp via thermal framework.

Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Laxman Dewangan and committed by
Mark Brown
d2d5437b 19dd159c

+103
+1
drivers/regulator/Kconfig
··· 409 409 config REGULATOR_MAX8973 410 410 tristate "Maxim MAX8973 voltage regulator " 411 411 depends on I2C 412 + depends on THERMAL && THERMAL_OF 412 413 select REGMAP_I2C 413 414 help 414 415 The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
+97
drivers/regulator/max8973-regulator.c
··· 38 38 #include <linux/i2c.h> 39 39 #include <linux/slab.h> 40 40 #include <linux/regmap.h> 41 + #include <linux/thermal.h> 42 + #include <linux/irq.h> 43 + #include <linux/interrupt.h> 41 44 42 45 /* Register definitions */ 43 46 #define MAX8973_VOUT 0x0 ··· 77 74 #define MAX8973_WDTMR_ENABLE BIT(6) 78 75 #define MAX8973_DISCH_ENBABLE BIT(5) 79 76 #define MAX8973_FT_ENABLE BIT(4) 77 + #define MAX77621_T_JUNCTION_120 BIT(7) 80 78 81 79 #define MAX8973_CKKADV_TRIP_MASK 0xC 82 80 #define MAX8973_CKKADV_TRIP_DISABLE 0xC ··· 96 92 #define MAX8973_MAX_VOLATGE 1400000 97 93 #define MAX8973_VOLATGE_STEP 6250 98 94 #define MAX8973_BUCK_N_VOLTAGE 0x80 95 + 96 + #define MAX77621_CHIPID_TJINT_S BIT(0) 97 + 98 + #define MAX77621_NORMAL_OPERATING_TEMP 100000 99 + #define MAX77621_TJINT_WARNING_TEMP_120 120000 100 + #define MAX77621_TJINT_WARNING_TEMP_140 140000 99 101 100 102 enum device_id { 101 103 MAX8973, ··· 122 112 int curr_gpio_val; 123 113 struct regulator_ops ops; 124 114 enum device_id id; 115 + int junction_temp_warning; 116 + int irq; 117 + struct thermal_zone_device *tz_device; 125 118 }; 126 119 127 120 /* ··· 404 391 if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE) 405 392 control1 |= MAX8973_FREQSHIFT_9PER; 406 393 394 + if ((pdata->junction_temp_warning == MAX77621_TJINT_WARNING_TEMP_120) && 395 + (max->id == MAX77621)) 396 + control2 |= MAX77621_T_JUNCTION_120; 397 + 407 398 if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE)) 408 399 control2 |= MAX8973_DISCH_ENBABLE; 409 400 ··· 474 457 return ret; 475 458 } 476 459 460 + static int max8973_thermal_read_temp(void *data, int *temp) 461 + { 462 + struct max8973_chip *mchip = data; 463 + unsigned int val; 464 + int ret; 465 + 466 + ret = regmap_read(mchip->regmap, MAX8973_CHIPID1, &val); 467 + if (ret < 0) { 468 + dev_err(mchip->dev, "Failed to read register CHIPID1, %d", ret); 469 + return ret; 470 + } 471 + 472 + /* +1 degC to trigger cool devive */ 473 + if (val & MAX77621_CHIPID_TJINT_S) 474 + *temp = mchip->junction_temp_warning + 1000; 475 + else 476 + *temp = MAX77621_NORMAL_OPERATING_TEMP; 477 + 478 + return 0; 479 + } 480 + 481 + static irqreturn_t max8973_thermal_irq(int irq, void *data) 482 + { 483 + struct max8973_chip *mchip = data; 484 + 485 + thermal_zone_device_update(mchip->tz_device); 486 + 487 + return IRQ_HANDLED; 488 + } 489 + 490 + static const struct thermal_zone_of_device_ops max77621_tz_ops = { 491 + .get_temp = max8973_thermal_read_temp, 492 + }; 493 + 494 + static int max8973_thermal_init(struct max8973_chip *mchip) 495 + { 496 + struct thermal_zone_device *tzd; 497 + struct irq_data *irq_data; 498 + unsigned long irq_flags = 0; 499 + int ret; 500 + 501 + if (mchip->id != MAX77621) 502 + return 0; 503 + 504 + tzd = devm_thermal_zone_of_sensor_register(mchip->dev, 0, mchip, 505 + &max77621_tz_ops); 506 + if (IS_ERR(tzd)) { 507 + ret = PTR_ERR(tzd); 508 + dev_err(mchip->dev, "Failed to register thermal sensor: %d\n", 509 + ret); 510 + return ret; 511 + } 512 + 513 + if (mchip->irq <= 0) 514 + return 0; 515 + 516 + irq_data = irq_get_irq_data(mchip->irq); 517 + if (irq_data) 518 + irq_flags = irqd_get_trigger_type(irq_data); 519 + 520 + ret = devm_request_threaded_irq(mchip->dev, mchip->irq, NULL, 521 + max8973_thermal_irq, 522 + IRQF_ONESHOT | IRQF_SHARED | irq_flags, 523 + dev_name(mchip->dev), mchip); 524 + if (ret < 0) { 525 + dev_err(mchip->dev, "Failed to request irq %d, %d\n", 526 + mchip->irq, ret); 527 + return ret; 528 + } 529 + 530 + return 0; 531 + } 532 + 477 533 static const struct regmap_config max8973_regmap_config = { 478 534 .reg_bits = 8, 479 535 .val_bits = 8, ··· 610 520 } else { 611 521 pdata->control_flags |= MAX8973_CONTROL_CLKADV_TRIP_DISABLED; 612 522 } 523 + 524 + pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_140; 525 + ret = of_property_read_u32(np, "junction-warn-millicelsius", &pval); 526 + if (!ret && (pval <= MAX77621_TJINT_WARNING_TEMP_120)) 527 + pdata->junction_temp_warning = MAX77621_TJINT_WARNING_TEMP_120; 613 528 614 529 return pdata; 615 530 } ··· 703 608 max->enable_external_control = pdata->enable_ext_control; 704 609 max->curr_gpio_val = pdata->dvs_def_state; 705 610 max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state; 611 + max->junction_temp_warning = pdata->junction_temp_warning; 706 612 707 613 if (gpio_is_valid(max->enable_gpio)) 708 614 max->enable_external_control = true; ··· 814 718 return ret; 815 719 } 816 720 721 + max8973_thermal_init(max); 817 722 return 0; 818 723 } 819 724
+5
include/linux/regulator/max8973-regulator.h
··· 54 54 * @reg_init_data: The regulator init data. 55 55 * @control_flags: Control flags which are ORed value of above flags to 56 56 * configure device. 57 + * @junction_temp_warning: Junction temp in millicelcius on which warning need 58 + * to be set. Thermal functionality is only supported on 59 + * MAX77621. The threshold warning supported by MAX77621 60 + * are 120C and 140C. 57 61 * @enable_ext_control: Enable the voltage enable/disable through external 58 62 * control signal from EN input pin. If it is false then 59 63 * voltage output will be enabled/disabled through EN bit of ··· 71 67 struct max8973_regulator_platform_data { 72 68 struct regulator_init_data *reg_init_data; 73 69 unsigned long control_flags; 70 + unsigned long junction_temp_warning; 74 71 bool enable_ext_control; 75 72 int enable_gpio; 76 73 int dvs_gpio;