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

hwmon: (pmbus) Introduce page_change_delay

We have some buggy pmbus devices that require a delay after performing a
page change operation before trying to issue more commands to the
device.

This allows for a configurable delay after page changes, but not
affecting other read or write operations.

This makes a slight behavioral tweak to the existing delay logic, where
it considers the longest of delays between operations, instead of always
chosing the write delay over the access delay.

Signed-off-by: William A. Kennington III <william@wkennington.com>
Link: https://lore.kernel.org/r/20250407201002.1198092-1-william@wkennington.com
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

William A. Kennington III and committed by
Guenter Roeck
73e5b6b5 2c183963

+36 -34
+1
drivers/hwmon/pmbus/pmbus.h
··· 482 482 */ 483 483 int access_delay; /* in microseconds */ 484 484 int write_delay; /* in microseconds */ 485 + int page_change_delay; /* in microseconds */ 485 486 }; 486 487 487 488 /* Regulator ops */
+35 -34
drivers/hwmon/pmbus/pmbus_core.c
··· 32 32 #define PMBUS_ATTR_ALLOC_SIZE 32 33 33 #define PMBUS_NAME_SIZE 24 34 34 35 + /* 36 + * The type of operation used for picking the delay between 37 + * successive pmbus operations. 38 + */ 39 + #define PMBUS_OP_WRITE BIT(0) 40 + #define PMBUS_OP_PAGE_CHANGE BIT(1) 41 + 35 42 static int wp = -1; 36 43 module_param(wp, int, 0444); 37 44 ··· 120 113 121 114 int vout_low[PMBUS_PAGES]; /* voltage low margin */ 122 115 int vout_high[PMBUS_PAGES]; /* voltage high margin */ 123 - ktime_t write_time; /* Last SMBUS write timestamp */ 124 - ktime_t access_time; /* Last SMBUS access timestamp */ 116 + 117 + ktime_t next_access_backoff; /* Wait until at least this time */ 125 118 }; 126 119 127 120 struct pmbus_debugfs_entry { ··· 176 169 static void pmbus_wait(struct i2c_client *client) 177 170 { 178 171 struct pmbus_data *data = i2c_get_clientdata(client); 179 - const struct pmbus_driver_info *info = data->info; 180 - s64 delta; 172 + s64 delay = ktime_us_delta(data->next_access_backoff, ktime_get()); 181 173 182 - if (info->access_delay) { 183 - delta = ktime_us_delta(ktime_get(), data->access_time); 184 - 185 - if (delta < info->access_delay) 186 - fsleep(info->access_delay - delta); 187 - } else if (info->write_delay) { 188 - delta = ktime_us_delta(ktime_get(), data->write_time); 189 - 190 - if (delta < info->write_delay) 191 - fsleep(info->write_delay - delta); 192 - } 174 + if (delay > 0) 175 + fsleep(delay); 193 176 } 194 177 195 - /* Sets the last accessed timestamp for pmbus_wait */ 196 - static void pmbus_update_ts(struct i2c_client *client, bool write_op) 178 + /* Sets the last operation timestamp for pmbus_wait */ 179 + static void pmbus_update_ts(struct i2c_client *client, int op) 197 180 { 198 181 struct pmbus_data *data = i2c_get_clientdata(client); 199 182 const struct pmbus_driver_info *info = data->info; 183 + int delay = info->access_delay; 200 184 201 - if (info->access_delay) 202 - data->access_time = ktime_get(); 203 - else if (info->write_delay && write_op) 204 - data->write_time = ktime_get(); 185 + if (op & PMBUS_OP_WRITE) 186 + delay = max(delay, info->write_delay); 187 + if (op & PMBUS_OP_PAGE_CHANGE) 188 + delay = max(delay, info->page_change_delay); 189 + 190 + if (delay > 0) 191 + data->next_access_backoff = ktime_add_us(ktime_get(), delay); 205 192 } 206 193 207 194 int pmbus_set_page(struct i2c_client *client, int page, int phase) ··· 210 209 data->info->pages > 1 && page != data->currpage) { 211 210 pmbus_wait(client); 212 211 rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 213 - pmbus_update_ts(client, true); 212 + pmbus_update_ts(client, PMBUS_OP_WRITE | PMBUS_OP_PAGE_CHANGE); 214 213 if (rv < 0) 215 214 return rv; 216 215 217 216 pmbus_wait(client); 218 217 rv = i2c_smbus_read_byte_data(client, PMBUS_PAGE); 219 - pmbus_update_ts(client, false); 218 + pmbus_update_ts(client, 0); 220 219 if (rv < 0) 221 220 return rv; 222 221 ··· 230 229 pmbus_wait(client); 231 230 rv = i2c_smbus_write_byte_data(client, PMBUS_PHASE, 232 231 phase); 233 - pmbus_update_ts(client, true); 232 + pmbus_update_ts(client, PMBUS_OP_WRITE); 234 233 if (rv) 235 234 return rv; 236 235 } ··· 250 249 251 250 pmbus_wait(client); 252 251 rv = i2c_smbus_write_byte(client, value); 253 - pmbus_update_ts(client, true); 252 + pmbus_update_ts(client, PMBUS_OP_WRITE); 254 253 255 254 return rv; 256 255 } ··· 285 284 286 285 pmbus_wait(client); 287 286 rv = i2c_smbus_write_word_data(client, reg, word); 288 - pmbus_update_ts(client, true); 287 + pmbus_update_ts(client, PMBUS_OP_WRITE); 289 288 290 289 return rv; 291 290 } ··· 406 405 407 406 pmbus_wait(client); 408 407 rv = i2c_smbus_read_word_data(client, reg); 409 - pmbus_update_ts(client, false); 408 + pmbus_update_ts(client, 0); 410 409 411 410 return rv; 412 411 } ··· 469 468 470 469 pmbus_wait(client); 471 470 rv = i2c_smbus_read_byte_data(client, reg); 472 - pmbus_update_ts(client, false); 471 + pmbus_update_ts(client, 0); 473 472 474 473 return rv; 475 474 } ··· 485 484 486 485 pmbus_wait(client); 487 486 rv = i2c_smbus_write_byte_data(client, reg, value); 488 - pmbus_update_ts(client, true); 487 + pmbus_update_ts(client, PMBUS_OP_WRITE); 489 488 490 489 return rv; 491 490 } ··· 521 520 522 521 pmbus_wait(client); 523 522 rv = i2c_smbus_read_block_data(client, reg, data_buf); 524 - pmbus_update_ts(client, false); 523 + pmbus_update_ts(client, 0); 525 524 526 525 return rv; 527 526 } ··· 2525 2524 rv = i2c_smbus_xfer(client->adapter, client->addr, client->flags, 2526 2525 I2C_SMBUS_WRITE, PMBUS_COEFFICIENTS, 2527 2526 I2C_SMBUS_BLOCK_PROC_CALL, &data); 2528 - pmbus_update_ts(client, true); 2527 + pmbus_update_ts(client, PMBUS_OP_WRITE); 2529 2528 2530 2529 if (rv < 0) 2531 2530 return rv; ··· 2729 2728 if (!(data->flags & PMBUS_NO_CAPABILITY)) { 2730 2729 pmbus_wait(client); 2731 2730 ret = i2c_smbus_read_byte_data(client, PMBUS_CAPABILITY); 2732 - pmbus_update_ts(client, false); 2731 + pmbus_update_ts(client, 0); 2733 2732 2734 2733 if (ret >= 0 && (ret & PB_CAPABILITY_ERROR_CHECK)) { 2735 2734 if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_PEC)) ··· 2745 2744 data->read_status = pmbus_read_status_word; 2746 2745 pmbus_wait(client); 2747 2746 ret = i2c_smbus_read_word_data(client, PMBUS_STATUS_WORD); 2748 - pmbus_update_ts(client, false); 2747 + pmbus_update_ts(client, 0); 2749 2748 2750 2749 if (ret < 0 || ret == 0xffff) { 2751 2750 data->read_status = pmbus_read_status_byte; 2752 2751 pmbus_wait(client); 2753 2752 ret = i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE); 2754 - pmbus_update_ts(client, false); 2753 + pmbus_update_ts(client, 0); 2755 2754 2756 2755 if (ret < 0 || ret == 0xff) { 2757 2756 dev_err(dev, "PMBus status register not found\n");