| 303 | | /* <TODO> add conversion routines here */ |
| | 331 | /* PROCHOT-OVERRIDE; 0-15, 0 is 6.25%, 15 is 99.88% |
| | 332 | * REG: (same) */ |
| | 333 | static u8 LM93_PROCHOT_OVERRIDE_TO_REG(int force1, int force2, long prochot) |
| | 334 | { |
| | 335 | u8 result = 0; |
| | 336 | |
| | 337 | result |= force1 ? 0x80 : 0x00; |
| | 338 | result |= force2 ? 0x40 : 0x00; |
| | 339 | prochot = SENSORS_LIMIT(prochot, 0, 15); |
| | 340 | result |= prochot; |
| | 341 | return result; |
| | 342 | } |
| | 343 | |
| | 344 | /* PROCHOT-INTERVAL: 73 - 37200 (1/100 seconds) |
| | 345 | * REG: 0-9 as mapped below */ |
| | 346 | static int lm93_interval_map[10] = { |
| | 347 | 73, 146, 290, 580, 1170, 2330, 4660, 9320, 18600, 37200, |
| | 348 | }; |
| | 349 | |
| | 350 | static int LM93_INTERVAL_FROM_REG(u8 reg) |
| | 351 | { |
| | 352 | return lm93_interval_map[reg & 0x0f]; |
| | 353 | } |
| | 354 | |
| | 355 | /* round up to nearest match */ |
| | 356 | static u8 LM93_INTERVAL_TO_REG(long interval) |
| | 357 | { |
| | 358 | int i; |
| | 359 | for (i = 0; i < 9; i++) |
| | 360 | if (interval <= lm93_interval_map[i]) |
| | 361 | break; |
| | 362 | |
| | 363 | /* can fall through with i==9 */ |
| | 364 | return (u8)i; |
| | 365 | } |
| | 366 | |
| | 367 | /* PWM: 0-255 per sensors documentation |
| | 368 | REG: 0-13 as mapped below... *left* justified */ |
| | 369 | typedef enum { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ } pwm_freq_t; |
| | 370 | static int lm93_pwm_map[2][14] = { |
| | 371 | { |
| | 372 | 0x00, /* 0.00% */ 0x40, /* 25.00% */ |
| | 373 | 0x50, /* 31.25% */ 0x60, /* 37.50% */ |
| | 374 | 0x70, /* 43.75% */ 0x80, /* 50.00% */ |
| | 375 | 0x90, /* 56.25% */ 0xa0, /* 62.50% */ |
| | 376 | 0xb0, /* 68.75% */ 0xc0, /* 75.00% */ |
| | 377 | 0xd0, /* 81.25% */ 0xe0, /* 87.50% */ |
| | 378 | 0xf0, /* 93.75% */ 0xff, /* 100.00% */ |
| | 379 | }, |
| | 380 | { |
| | 381 | 0x00, /* 0.00% */ 0x40, /* 25.00% */ |
| | 382 | 0x49, /* 28.57% */ 0x52, /* 32.14% */ |
| | 383 | 0x5b, /* 35.71% */ 0x64, /* 39.29% */ |
| | 384 | 0x6d, /* 42.86% */ 0x76, /* 46.43% */ |
| | 385 | 0x80, /* 50.00% */ 0x89, /* 53.57% */ |
| | 386 | 0x92, /* 57.14% */ 0xb6, /* 71.43% */ |
| | 387 | 0xdb, /* 85.71% */ 0xff, /* 100.00% */ |
| | 388 | }, |
| | 389 | }; |
| | 390 | |
| | 391 | static int LM93_PWM_FROM_REG(u8 reg, pwm_freq_t freq) |
| | 392 | { |
| | 393 | return lm93_pwm_map[freq][reg >> 4 & 0x0f]; |
| | 394 | } |
| | 395 | |
| | 396 | /* round up to nearest match */ |
| | 397 | static u8 LM93_PWM_TO_REG(int pwm, pwm_freq_t freq) |
| | 398 | { |
| | 399 | int i; |
| | 400 | for (i = 0; i < 13; i++) |
| | 401 | if (pwm <= lm93_pwm_map[freq][i]) |
| | 402 | break; |
| | 403 | |
| | 404 | /* can fall through with i==13 */ |
| | 405 | return (u8)(i << 4); |
| | 406 | } |
| | 407 | |
| | 408 | /* PWM FREQ: HZ |
| | 409 | REG: 0-7 as mapped below */ |
| | 410 | static int lm93_pwm_freq_map[8] = { |
| | 411 | 22500, 96, 84, 72, 60, 48, 36, 12 |
| | 412 | }; |
| | 413 | |
| | 414 | static int LM93_PWM_FREQ_FROM_REG(u8 reg) |
| | 415 | { |
| | 416 | return lm93_pwm_freq_map[reg & 0x07]; |
| | 417 | } |
| | 418 | |
| | 419 | /* round up to nearest match */ |
| | 420 | static u8 LM93_PWM_FREQ_TO_REG(int freq) |
| | 421 | { |
| | 422 | int i; |
| | 423 | for (i = 7; i > 0; i--) |
| | 424 | if (freq <= lm93_pwm_freq_map[i]) |
| | 425 | break; |
| | 426 | |
| | 427 | /* can fall through with i==0 */ |
| | 428 | return (u8)i; |
| | 429 | } |
| | 430 | |
| | 431 | /* GPIO: 0-255, GPIO0 is LSB |
| | 432 | * REG: inverted */ |
| | 433 | static unsigned LM93_GPI_FROM_REG(u8 reg) |
| | 434 | { |
| | 435 | return ~reg & 0xff; |
| | 436 | } |
| | 437 | |
| | 438 | /* ALARMS: SYSCTL format described further below |
| | 439 | REG: 64 bits in 8 registers, as immediately below */ |
| | 440 | struct block1_t { |
| | 441 | u8 host_status_1; |
| | 442 | u8 host_status_2; |
| | 443 | u8 host_status_3; |
| | 444 | u8 host_status_4; |
| | 445 | u8 p1_prochot_status; |
| | 446 | u8 p2_prochot_status; |
| | 447 | u8 gpi_status; |
| | 448 | u8 fan_status; |
| | 449 | }; |
| | 450 | |
| | 451 | static unsigned LM93_ALARMS_FROM_REG(struct block1_t b1) |
| | 452 | { |
| | 453 | unsigned result; |
| | 454 | result = b1.host_status_2; |
| | 455 | result |= b1.host_status_3 << 8; |
| | 456 | result |= (b1.fan_status & 0x04) << 16; |
| | 457 | result |= (b1.p1_prochot_status & 0x80) << 13; |
| | 458 | result |= (b1.p2_prochot_status & 0x80) << 14; |
| | 459 | result |= (b1.host_status_4 & 0xfc) << 20; |
| | 460 | result |= (b1.host_status_1 & 0x07) << 28; |
| | 461 | return result; |
| | 462 | } |
| 415 | | int ctl_name, int *nrels_mag, long *results); |
| 416 | | #if 0 |
| | 578 | int ctl_name, int *nrels_mag, long *results); |
| | 579 | static void lm93_prochot_override(struct i2c_client *client, int operation, |
| | 580 | int ctl_name, int *nrels_mag, long *results); |
| | 581 | static void lm93_prochot_interval(struct i2c_client *client, int operation, |
| | 582 | int ctl_name, int *nrels_mag, long *results); |
| | 583 | static void lm93_vrdhot(struct i2c_client *client, int operation, |
| | 584 | int ctl_name, int *nrels_mag, long *results); |
| | 585 | static void lm93_gpio(struct i2c_client *client, int operation, |
| | 586 | int ctl_name, int *nrels_mag, long *results); |
| 494 | | #define LM93_ALARM_FAN1 0x0000000000000001ull |
| 495 | | #define LM93_ALARM_FAN2 0x0000000000000002ull |
| 496 | | #define LM93_ALARM_FAN3 0x0000000000000004ull |
| 497 | | #define LM93_ALARM_FAN4 0x0000000000000008ull |
| 498 | | #define LM93_ALARM_PH2_ERR 0x0000000000800000ull |
| 499 | | #define LM93_ALARM_PH1_ERR 0x0000000080000000ull |
| 500 | | #define LM93_ALARM_SCSI1_ERR 0x0000000400000000ull |
| 501 | | #define LM93_ALARM_SCSI2_ERR 0x0000000800000000ull |
| 502 | | #define LM93_ALARM_DVDDP1_ERR 0x0000001000000000ull |
| 503 | | #define LM93_ALARM_DVDDP2_ERR 0x0000002000000000ull |
| 504 | | #define LM93_ALARM_D1_ERR 0x0000004000000000ull |
| 505 | | #define LM93_ALARM_D2_ERR 0x0000008000000000ull |
| 506 | | #define LM93_ALARM_IN1 0x0000010000000000ull |
| 507 | | #define LM93_ALARM_IN2 0x0000020000000000ull |
| 508 | | #define LM93_ALARM_IN3 0x0000040000000000ull |
| 509 | | #define LM93_ALARM_IN4 0x0000080000000000ull |
| 510 | | #define LM93_ALARM_IN5 0x0000100000000000ull |
| 511 | | #define LM93_ALARM_IN6 0x0000200000000000ull |
| 512 | | #define LM93_ALARM_IN7 0x0000400000000000ull |
| 513 | | #define LM93_ALARM_IN8 0x0000800000000000ull |
| 514 | | #define LM93_ALARM_IN9 0x0001000000000000ull |
| 515 | | #define LM93_ALARM_IN10 0x0002000000000000ull |
| 516 | | #define LM93_ALARM_IN11 0x0004000000000000ull |
| 517 | | #define LM93_ALARM_IN12 0x0008000000000000ull |
| 518 | | #define LM93_ALARM_IN13 0x0010000000000000ull |
| 519 | | #define LM93_ALARM_IN14 0x0020000000000000ull |
| 520 | | #define LM93_ALARM_IN15 0x0040000000000000ull |
| 521 | | #define LM93_ALARM_IN16 0x0080000000000000ull |
| 522 | | #define LM93_ALARM_TEMP1 0x0100000000000000ull |
| 523 | | #define LM93_ALARM_TEMP2 0x0200000000000000ull |
| 524 | | #define LM93_ALARM_TEMP3 0x0400000000000000ull |
| 525 | | #define LM93_ALARM_VRD1_ERR 0x1000000000000000ull |
| 526 | | #define LM93_ALARM_VRD2_ERR 0x2000000000000000ull |
| 527 | | |
| | 682 | #define LM93_ALARM_IN1 0x00000001 |
| | 683 | #define LM93_ALARM_IN2 0x00000002 |
| | 684 | #define LM93_ALARM_IN3 0x00000004 |
| | 685 | #define LM93_ALARM_IN4 0x00000008 |
| | 686 | #define LM93_ALARM_IN5 0x00000010 |
| | 687 | #define LM93_ALARM_IN6 0x00000020 |
| | 688 | #define LM93_ALARM_IN7 0x00000040 |
| | 689 | #define LM93_ALARM_IN8 0x00000080 |
| | 690 | #define LM93_ALARM_IN9 0x00000100 |
| | 691 | #define LM93_ALARM_IN10 0x00000200 |
| | 692 | #define LM93_ALARM_IN11 0x00000400 |
| | 693 | #define LM93_ALARM_IN12 0x00000800 |
| | 694 | #define LM93_ALARM_IN13 0x00001000 |
| | 695 | #define LM93_ALARM_IN14 0x00002000 |
| | 696 | #define LM93_ALARM_IN15 0x00004000 |
| | 697 | #define LM93_ALARM_IN16 0x00008000 |
| | 698 | #define LM93_ALARM_FAN1 0x00010000 |
| | 699 | #define LM93_ALARM_FAN2 0x00020000 |
| | 700 | #define LM93_ALARM_FAN3 0x00040000 |
| | 701 | #define LM93_ALARM_FAN4 0x00080000 |
| | 702 | #define LM93_ALARM_PH1_ERR 0x00100000 |
| | 703 | #define LM93_ALARM_PH2_ERR 0x00200000 |
| | 704 | #define LM93_ALARM_SCSI1_ERR 0x00400000 |
| | 705 | #define LM93_ALARM_SCSI2_ERR 0x00800000 |
| | 706 | #define LM93_ALARM_DVDDP1_ERR 0x01000000 |
| | 707 | #define LM93_ALARM_DVDDP2_ERR 0x02000000 |
| | 708 | #define LM93_ALARM_D1_ERR 0x04000000 |
| | 709 | #define LM93_ALARM_D2_ERR 0x08000000 |
| | 710 | #define LM93_ALARM_TEMP1 0x10000000 |
| | 711 | #define LM93_ALARM_TEMP2 0x20000000 |
| | 712 | #define LM93_ALARM_TEMP3 0x40000000 |
| 597 | | #if 0 |
| | 788 | |
| | 789 | {LM93_SYSCTL_PROCHOT_OVERRIDE, "prochot_override", NULL, 0, 0644, NULL, |
| | 790 | &i2c_proc_real, &i2c_sysctl_real, NULL, &lm93_prochot_override}, |
| | 791 | |
| | 792 | {LM93_SYSCTL_PROCHOT_INTERVAL, "prochot_interval", NULL, 0, 0644, NULL, |
| | 793 | &i2c_proc_real, &i2c_sysctl_real, NULL, &lm93_prochot_interval}, |
| | 794 | |
| | 795 | LM93_SYSCTL_VRDHOT(1), |
| | 796 | LM93_SYSCTL_VRDHOT(2), |
| | 797 | |
| | 798 | {LM93_SYSCTL_GPIO, "gpio", NULL, 0, 0444, NULL, |
| | 799 | &i2c_proc_real, &i2c_sysctl_real, NULL, &lm93_gpio}, |
| | 800 | |
| | 1401 | |
| | 1402 | /* helper function - must grab data->update_lock before calling |
| | 1403 | fan is 0-3, indicating fan1-fan4 */ |
| | 1404 | static void lm93_write_fan_smart_tach(struct i2c_client *client, |
| | 1405 | struct lm93_data *data, int fan, long value) |
| | 1406 | { |
| | 1407 | /* insert the new mapping and write it out */ |
| | 1408 | data->sf_tach_to_pwm = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM); |
| | 1409 | data->sf_tach_to_pwm &= ~0x3 << fan * 2; |
| | 1410 | data->sf_tach_to_pwm |= value << fan * 2; |
| | 1411 | lm93_write_byte(client, LM93_REG_SF_TACH_TO_PWM, data->sf_tach_to_pwm); |
| | 1412 | |
| | 1413 | /* insert the enable bit and write it out */ |
| | 1414 | data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); |
| | 1415 | if (value) |
| | 1416 | data->sfc2 |= 1 << fan; |
| | 1417 | else |
| | 1418 | data->sfc2 &= ~1 << fan; |
| | 1419 | lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); |
| | 1420 | } |
| | 1421 | |
| | 1422 | /* helper function - must grab data->update_lock before calling |
| | 1423 | pwm is 0-1, indicating pwm1-pwm2 |
| | 1424 | this disables smart tach for all tach channels bound to the given pwm */ |
| | 1425 | static void lm93_disable_fan_smart_tach(struct i2c_client *client, |
| | 1426 | struct lm93_data *data, int pwm) |
| | 1427 | { |
| | 1428 | int mapping = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM); |
| | 1429 | int mask; |
| | 1430 | |
| | 1431 | /* collapse the mapping into a mask of enable bits */ |
| | 1432 | mapping = (mapping >> pwm) & 0x55; |
| | 1433 | mask = mapping & 0x01; |
| | 1434 | mask |= (mapping & 0x04) >> 1; |
| | 1435 | mask |= (mapping & 0x10) >> 2; |
| | 1436 | mask |= (mapping & 0x40) >> 3; |
| | 1437 | |
| | 1438 | /* disable smart tach according to the mask */ |
| | 1439 | data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); |
| | 1440 | data->sfc2 &= ~mask; |
| | 1441 | lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); |
| | 1442 | } |
| | 1443 | |
| 1213 | | /* insert the new mapping and write it out */ |
| 1214 | | data->sf_tach_to_pwm = lm93_read_byte(client, |
| 1215 | | LM93_REG_SF_TACH_TO_PWM); |
| 1216 | | data->sf_tach_to_pwm &= ~0x3 << nr * 2; |
| 1217 | | data->sf_tach_to_pwm |= results[0] << nr * 2; |
| 1218 | | lm93_write_byte(client, LM93_REG_SF_TACH_TO_PWM, |
| 1219 | | data->sf_tach_to_pwm); |
| 1220 | | |
| 1221 | | /* insert the enable bit and write it out */ |
| 1222 | | data->sfc2 = lm93_read_byte(client, |
| 1223 | | LM93_REG_SFC2); |
| 1224 | | if (results[0]) |
| 1225 | | data->sfc2 |= 1 << nr; |
| 1226 | | else |
| 1227 | | data->sfc2 &= ~1 << nr; |
| 1228 | | lm93_write_byte(client, LM93_REG_SFC2, |
| 1229 | | data->sfc2); |
| | 1476 | /* can't enable if pwm freq is 22.5KHz */ |
| | 1477 | if (results[0]) { |
| | 1478 | u8 ctl4 = lm93_read_byte(client, |
| | 1479 | LM93_REG_PWM_CTL(results[0]-1, |
| | 1480 | LM93_PWM_CTL4)); |
| | 1481 | if ((ctl4 & 0x07) == 0) |
| | 1482 | results[0] = 0; |
| | 1483 | } |
| | 1484 | |
| | 1485 | lm93_write_fan_smart_tach(client, data, nr, |
| | 1486 | results[0]); |
| 1300 | | lm78_update_client(client); |
| 1301 | | results[0] = ALARMS_FROM_REG(data->alarms); |
| | 1559 | lm93_update_client(client); |
| | 1560 | results[0] = (data->prochot_override & 0x80) ? 1 : 0; |
| | 1561 | results[1] = (data->prochot_override & 0x40) ? 1 : 0; |
| | 1562 | results[2] = data->prochot_override & 0x0f; |
| | 1563 | *nrels_mag = 3; |
| | 1564 | } else if (operation == SENSORS_PROC_REAL_WRITE) { |
| | 1565 | |
| | 1566 | /* grab old values */ |
| | 1567 | int force2 = (data->prochot_override & 0x40) ? 1 : 0; |
| | 1568 | int prochot = data->prochot_override & 0x0f; |
| | 1569 | |
| | 1570 | down(&data->update_lock); |
| | 1571 | if (*nrels_mag >= 3) { |
| | 1572 | data->prochot_override = LM93_PROCHOT_OVERRIDE_TO_REG( |
| | 1573 | results[0], results[1], results[2]); |
| | 1574 | } |
| | 1575 | if (*nrels_mag == 2) { |
| | 1576 | data->prochot_override = LM93_PROCHOT_OVERRIDE_TO_REG( |
| | 1577 | results[0], results[1], prochot); |
| | 1578 | } |
| | 1579 | if (*nrels_mag == 1) { |
| | 1580 | data->prochot_override = LM93_PROCHOT_OVERRIDE_TO_REG( |
| | 1581 | results[0], force2, prochot); |
| | 1582 | } |
| | 1583 | if (*nrels_mag >= 1) { |
| | 1584 | lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE, |
| | 1585 | data->prochot_override); |
| | 1586 | } |
| | 1587 | up(&data->update_lock); |
| | 1588 | } |
| | 1589 | } |
| | 1590 | |
| | 1591 | void lm93_prochot_interval(struct i2c_client *client, int operation, |
| | 1592 | int ctl_name, int *nrels_mag, long *results) |
| | 1593 | { |
| | 1594 | struct lm93_data *data = client->data; |
| | 1595 | |
| | 1596 | if (ctl_name != LM93_SYSCTL_PROCHOT_INTERVAL) |
| | 1597 | return; /* ERROR */ |
| | 1598 | |
| | 1599 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1600 | *nrels_mag = 2; |
| | 1601 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1602 | lm93_update_client(client); |
| | 1603 | results[0] = LM93_INTERVAL_FROM_REG( |
| | 1604 | data->prochot_interval & 0x0f); |
| | 1605 | results[1] = LM93_INTERVAL_FROM_REG( |
| | 1606 | (data->prochot_interval & 0xf0) >> 4); |
| | 1607 | *nrels_mag = 2; |
| | 1608 | } else if (operation == SENSORS_PROC_REAL_WRITE) { |
| | 1609 | down(&data->update_lock); |
| | 1610 | if (*nrels_mag >= 2) { |
| | 1611 | results[1] = SENSORS_LIMIT(results[1], 0, 9); |
| | 1612 | data->prochot_interval = |
| | 1613 | (LM93_INTERVAL_TO_REG(results[1] << 4)) | |
| | 1614 | (data->prochot_interval & 0x0f); |
| | 1615 | } |
| | 1616 | if (*nrels_mag >= 1) { |
| | 1617 | results[0] = SENSORS_LIMIT(results[0], 0, 9); |
| | 1618 | data->prochot_interval = |
| | 1619 | (data->prochot_interval & 0xf0) | |
| | 1620 | LM93_INTERVAL_TO_REG(results[0]); |
| | 1621 | lm93_write_byte(client, LM93_REG_PROCHOT_INTERVAL, |
| | 1622 | data->prochot_interval); |
| | 1623 | } |
| | 1624 | up(&data->update_lock); |
| | 1625 | } |
| | 1626 | } |
| | 1627 | |
| | 1628 | void lm93_vrdhot(struct i2c_client *client, int operation, int ctl_name, |
| | 1629 | int *nrels_mag, long *results) |
| | 1630 | { |
| | 1631 | struct lm93_data *data = client->data; |
| | 1632 | int nr = ctl_name - LM93_SYSCTL_VRDHOT1; |
| | 1633 | |
| | 1634 | if (0 > nr || nr > 1) |
| | 1635 | return; /* ERROR */ |
| | 1636 | |
| | 1637 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1638 | *nrels_mag = 0; |
| | 1639 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1640 | lm93_update_client(client); |
| | 1641 | results[0] = data->block1.host_status_1 & (1 << (nr+4)) ? 1 : 0; |
| 1306 | | #endif |
| | 1646 | void lm93_gpio(struct i2c_client *client, int operation, int ctl_name, |
| | 1647 | int *nrels_mag, long *results) |
| | 1648 | { |
| | 1649 | struct lm93_data *data = client->data; |
| | 1650 | |
| | 1651 | if (ctl_name != LM93_SYSCTL_GPIO) |
| | 1652 | return; /* ERROR */ |
| | 1653 | |
| | 1654 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1655 | *nrels_mag = 0; |
| | 1656 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1657 | lm93_update_client(client); |
| | 1658 | results[0] = LM93_GPI_FROM_REG(data->gpi); |
| | 1659 | *nrels_mag = 1; |
| | 1660 | } |
| | 1661 | } |
| | 1662 | |
| | 1663 | void lm93_pwm(struct i2c_client *client, int operation, int ctl_name, |
| | 1664 | int *nrels_mag, long *results) |
| | 1665 | { |
| | 1666 | struct lm93_data *data = client->data; |
| | 1667 | int nr = ctl_name - LM93_SYSCTL_PWM1; |
| | 1668 | u8 ctl2, ctl4; |
| | 1669 | |
| | 1670 | if (0 > nr || nr > 1) |
| | 1671 | return; /* ERROR */ |
| | 1672 | |
| | 1673 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1674 | *nrels_mag = 0; |
| | 1675 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1676 | lm93_update_client(client); |
| | 1677 | ctl2 = data->block9[nr][LM93_PWM_CTL2]; |
| | 1678 | ctl4 = data->block9[nr][LM93_PWM_CTL4]; |
| | 1679 | results[1] = (ctl2 & 0x01) ? 1 : 0; |
| | 1680 | if (results[1]) /* show user commanded value if enabled */ |
| | 1681 | results[0] = data->pwm_override[nr]; |
| | 1682 | else /* show present h/w value if manual pwm disabled */ |
| | 1683 | results[0] = LM93_PWM_FROM_REG(ctl2, (ctl4 & 0x07) ? |
| | 1684 | LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ); |
| | 1685 | *nrels_mag = 2; |
| | 1686 | } |
| | 1687 | else if (operation == SENSORS_PROC_REAL_WRITE) { |
| | 1688 | if (*nrels_mag >= 1) { |
| | 1689 | down(&data->update_lock); |
| | 1690 | ctl2 = lm93_read_byte( |
| | 1691 | client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2)); |
| | 1692 | ctl4 = lm93_read_byte( |
| | 1693 | client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4)); |
| | 1694 | ctl2 = (ctl2 & 0x0f) | |
| | 1695 | LM93_PWM_TO_REG(results[0], (ctl4 & 0x07) ? |
| | 1696 | LM93_PWM_MAP_LO_FREQ : |
| | 1697 | LM93_PWM_MAP_HI_FREQ); |
| | 1698 | if (*nrels_mag >= 2) { |
| | 1699 | if (results[1]) |
| | 1700 | ctl2 |= 0x01; |
| | 1701 | else |
| | 1702 | ctl2 &= ~0x01; |
| | 1703 | } |
| | 1704 | /* save user commanded value */ |
| | 1705 | data->pwm_override[nr] = |
| | 1706 | LM93_PWM_FROM_REG(ctl2, (ctl4 & 0x07) ? |
| | 1707 | LM93_PWM_MAP_LO_FREQ : |
| | 1708 | LM93_PWM_MAP_HI_FREQ); |
| | 1709 | lm93_write_byte(client, |
| | 1710 | LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2), ctl2); |
| | 1711 | up(&data->update_lock); |
| | 1712 | } |
| | 1713 | } |
| | 1714 | } |
| | 1715 | |
| | 1716 | void lm93_pwm_freq(struct i2c_client *client, int operation, int ctl_name, |
| | 1717 | int *nrels_mag, long *results) |
| | 1718 | { |
| | 1719 | struct lm93_data *data = client->data; |
| | 1720 | int nr = ctl_name - LM93_SYSCTL_PWM1_FREQ; |
| | 1721 | u8 ctl4; |
| | 1722 | |
| | 1723 | if (0 > nr || nr > 1) |
| | 1724 | return; /* ERROR */ |
| | 1725 | |
| | 1726 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1727 | *nrels_mag = 0; |
| | 1728 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1729 | lm93_update_client(client); |
| | 1730 | ctl4 = data->block9[nr][LM93_PWM_CTL4]; |
| | 1731 | results[0] = LM93_PWM_FREQ_FROM_REG(ctl4); |
| | 1732 | *nrels_mag = 1; |
| | 1733 | } |
| | 1734 | else if (operation == SENSORS_PROC_REAL_WRITE) { |
| | 1735 | if (*nrels_mag >= 1) { |
| | 1736 | down(&data->update_lock); |
| | 1737 | ctl4 = lm93_read_byte( client, |
| | 1738 | LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4)); |
| | 1739 | ctl4 = (ctl4 & 0xf8) | LM93_PWM_FREQ_TO_REG(results[0]); |
| | 1740 | data->block9[nr][LM93_PWM_CTL4] = ctl4; |
| | 1741 | |
| | 1742 | /* ctl4 == 0 -> 22.5KHz -> disable smart tach */ |
| | 1743 | if (!ctl4) |
| | 1744 | lm93_disable_fan_smart_tach(client, data, nr); |
| | 1745 | |
| | 1746 | lm93_write_byte(client, |
| | 1747 | LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4), ctl4); |
| | 1748 | up(&data->update_lock); |
| | 1749 | } |
| | 1750 | } |
| | 1751 | } |
| | 1752 | |
| | 1753 | void lm93_alarms(struct i2c_client *client, int operation, int ctl_name, |
| | 1754 | int *nrels_mag, long *results) |
| | 1755 | { |
| | 1756 | struct lm93_data *data = client->data; |
| | 1757 | if (operation == SENSORS_PROC_REAL_INFO) |
| | 1758 | *nrels_mag = 0; |
| | 1759 | else if (operation == SENSORS_PROC_REAL_READ) { |
| | 1760 | lm93_update_client(client); |
| | 1761 | results[0] = LM93_ALARMS_FROM_REG(data->block1); |
| | 1762 | *nrels_mag = 1; |
| | 1763 | } |
| | 1764 | } |