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

hwmon: (it87) Reapply probe path chip registers settings after resume

After a suspend / resume cycle we possibly need to reapply chip registers
settings that we had set or fixed in a probe path, since they might have
been reset to default values or set incorrectly by a BIOS again.

Tested on a Gigabyte M720-US3 board, which requires routing internal VCCH5V
to in7 (and had it wrong again on resume from S3).

Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name>
[groeck: Return value from it87_resume_sio() is unused; make it void]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Maciej S. Szmigiero and committed by
Guenter Roeck
384548e5 557cbf49

+74 -2
+74 -2
drivers/hwmon/it87.c
··· 497 497 #define has_vin3_5v(data) ((data)->features & FEAT_VIN3_5V) 498 498 499 499 struct it87_sio_data { 500 + int sioaddr; 500 501 enum chips type; 501 502 /* Values read from Super-I/O config space */ 502 503 u8 revision; 503 504 u8 vid_value; 504 505 u8 beep_pin; 505 506 u8 internal; /* Internal sensors can be labeled */ 507 + bool need_in7_reroute; 506 508 /* Features skipped based on config or DMI */ 507 509 u16 skip_in; 508 510 u8 skip_vid; ··· 519 517 */ 520 518 struct it87_data { 521 519 const struct attribute_group *groups[7]; 520 + int sioaddr; 522 521 enum chips type; 523 522 u32 features; 524 523 u8 peci_mask; ··· 535 532 u16 in_internal; /* Bitfield, internal sensors (for labels) */ 536 533 u16 has_in; /* Bitfield, voltage sensors enabled */ 537 534 u8 in[NUM_VIN][3]; /* [nr][0]=in, [1]=min, [2]=max */ 535 + bool need_in7_reroute; 538 536 u8 has_fan; /* Bitfield, fans enabled */ 539 537 u16 fan[NUM_FAN][2]; /* Register values, [nr][0]=fan, [1]=min */ 540 538 u8 has_temp; /* Bitfield, temp sensors enabled */ ··· 2491 2487 } 2492 2488 2493 2489 err = 0; 2490 + sio_data->sioaddr = sioaddr; 2494 2491 sio_data->revision = superio_inb(sioaddr, DEVREV) & 0x0f; 2495 2492 pr_info("Found IT%04x%s chip at 0x%x, revision %d\n", chip_type, 2496 2493 it87_devices[sio_data->type].suffix, ··· 2580 2575 reg2c |= BIT(1); 2581 2576 superio_outb(sioaddr, IT87_SIO_PINX2_REG, 2582 2577 reg2c); 2578 + sio_data->need_in7_reroute = true; 2583 2579 pr_notice("Routing internal VCCH5V to in7.\n"); 2584 2580 } 2585 2581 pr_notice("in7 routed to internal voltage divider, with external pin disabled.\n"); ··· 2783 2777 if ((sio_data->type == it8720 || uart6) && !(reg & BIT(1))) { 2784 2778 reg |= BIT(1); 2785 2779 superio_outb(sioaddr, IT87_SIO_PINX2_REG, reg); 2780 + sio_data->need_in7_reroute = true; 2786 2781 pr_notice("Routing internal VCCH5V to in7\n"); 2787 2782 } 2788 2783 if (reg & BIT(0)) ··· 3031 3024 "PWM configuration is too broken to be fixed\n"); 3032 3025 } 3033 3026 3034 - dev_info(dev, 3035 - "Detected broken BIOS defaults, disabling PWM interface\n"); 3036 3027 return 0; 3037 3028 } else if (fix_pwm_polarity) { 3038 3029 dev_info(dev, ··· 3063 3058 return -ENOMEM; 3064 3059 3065 3060 data->addr = res->start; 3061 + data->sioaddr = sio_data->sioaddr; 3066 3062 data->type = sio_data->type; 3067 3063 data->features = it87_devices[sio_data->type].features; 3068 3064 data->peci_mask = it87_devices[sio_data->type].peci_mask; ··· 3102 3096 3103 3097 /* Check PWM configuration */ 3104 3098 enable_pwm_interface = it87_check_pwm(dev); 3099 + if (!enable_pwm_interface) 3100 + dev_info(dev, 3101 + "Detected broken BIOS defaults, disabling PWM interface\n"); 3105 3102 3106 3103 /* Starting with IT8721F, we handle scaling of internal voltages */ 3107 3104 if (has_12mv_adc(data)) { ··· 3132 3123 } 3133 3124 3134 3125 data->in_internal = sio_data->internal; 3126 + data->need_in7_reroute = sio_data->need_in7_reroute; 3135 3127 data->has_in = 0x3ff & ~sio_data->skip_in; 3136 3128 3137 3129 if (has_six_temp(data)) { ··· 3188 3178 return PTR_ERR_OR_ZERO(hwmon_dev); 3189 3179 } 3190 3180 3181 + static void __maybe_unused it87_resume_sio(struct platform_device *pdev) 3182 + { 3183 + struct it87_data *data = dev_get_drvdata(&pdev->dev); 3184 + int err; 3185 + int reg2c; 3186 + 3187 + if (!data->need_in7_reroute) 3188 + return; 3189 + 3190 + err = superio_enter(data->sioaddr); 3191 + if (err) { 3192 + dev_warn(&pdev->dev, 3193 + "Unable to enter Super I/O to reroute in7 (%d)", 3194 + err); 3195 + return; 3196 + } 3197 + 3198 + superio_select(data->sioaddr, GPIO); 3199 + 3200 + reg2c = superio_inb(data->sioaddr, IT87_SIO_PINX2_REG); 3201 + if (!(reg2c & BIT(1))) { 3202 + dev_dbg(&pdev->dev, 3203 + "Routing internal VCCH5V to in7 again"); 3204 + 3205 + reg2c |= BIT(1); 3206 + superio_outb(data->sioaddr, IT87_SIO_PINX2_REG, 3207 + reg2c); 3208 + } 3209 + 3210 + superio_exit(data->sioaddr); 3211 + } 3212 + 3213 + static int __maybe_unused it87_resume(struct device *dev) 3214 + { 3215 + struct platform_device *pdev = to_platform_device(dev); 3216 + struct it87_data *data = dev_get_drvdata(dev); 3217 + 3218 + it87_resume_sio(pdev); 3219 + 3220 + mutex_lock(&data->update_lock); 3221 + 3222 + it87_check_pwm(dev); 3223 + it87_check_limit_regs(data); 3224 + it87_check_voltage_monitors_reset(data); 3225 + it87_check_tachometers_reset(pdev); 3226 + it87_check_tachometers_16bit_mode(pdev); 3227 + 3228 + it87_start_monitoring(data); 3229 + 3230 + /* force update */ 3231 + data->valid = 0; 3232 + 3233 + mutex_unlock(&data->update_lock); 3234 + 3235 + it87_update_device(dev); 3236 + 3237 + return 0; 3238 + } 3239 + 3240 + static SIMPLE_DEV_PM_OPS(it87_dev_pm_ops, NULL, it87_resume); 3241 + 3191 3242 static struct platform_driver it87_driver = { 3192 3243 .driver = { 3193 3244 .name = DRVNAME, 3245 + .pm = &it87_dev_pm_ops, 3194 3246 }, 3195 3247 .probe = it87_probe, 3196 3248 };