diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2005-11-06 22:29:02 -0500 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2005-11-07 19:17:40 -0500 |
| commit | 183d020258dfd08178a05c6793dae10409db8abb (patch) | |
| tree | 5b20bc62709c94bd63e17d800544140213eaf0f5 /include | |
| parent | 4350147a816b9c5b40fa59e4fa23f17490630b79 (diff) | |
[PATCH] ppc64: SMU partition recovery
This patch adds the ability to the SMU driver to recover missing
calibration partitions from the SMU chip itself. It also adds some
dynamic mecanism to /proc/device-tree so that new properties are visible
to userland.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'include')
| -rw-r--r-- | include/asm-powerpc/prom.h | 2 | ||||
| -rw-r--r-- | include/asm-powerpc/smu.h | 153 | ||||
| -rw-r--r-- | include/asm-ppc/prom.h | 2 | ||||
| -rw-r--r-- | include/asm-ppc64/prom.h | 2 | ||||
| -rw-r--r-- | include/linux/proc_fs.h | 9 |
5 files changed, 149 insertions, 19 deletions
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 7587bf5f38c6..f999df1c5c90 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
| @@ -203,7 +203,7 @@ extern int prom_n_addr_cells(struct device_node* np); | |||
| 203 | extern int prom_n_size_cells(struct device_node* np); | 203 | extern int prom_n_size_cells(struct device_node* np); |
| 204 | extern int prom_n_intr_cells(struct device_node* np); | 204 | extern int prom_n_intr_cells(struct device_node* np); |
| 205 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); | 205 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); |
| 206 | extern void prom_add_property(struct device_node* np, struct property* prop); | 206 | extern int prom_add_property(struct device_node* np, struct property* prop); |
| 207 | 207 | ||
| 208 | #ifdef CONFIG_PPC32 | 208 | #ifdef CONFIG_PPC32 |
| 209 | /* | 209 | /* |
diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 959bad660233..76c29a9784dd 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h | |||
| @@ -20,16 +20,52 @@ | |||
| 20 | /* | 20 | /* |
| 21 | * Partition info commands | 21 | * Partition info commands |
| 22 | * | 22 | * |
| 23 | * I do not know what those are for at this point | 23 | * These commands are used to retreive the sdb-partition-XX datas from |
| 24 | * the SMU. The lenght is always 2. First byte is the subcommand code | ||
| 25 | * and second byte is the partition ID. | ||
| 26 | * | ||
| 27 | * The reply is 6 bytes: | ||
| 28 | * | ||
| 29 | * - 0..1 : partition address | ||
| 30 | * - 2 : a byte containing the partition ID | ||
| 31 | * - 3 : length (maybe other bits are rest of header ?) | ||
| 32 | * | ||
| 33 | * The data must then be obtained with calls to another command: | ||
| 34 | * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). | ||
| 24 | */ | 35 | */ |
| 25 | #define SMU_CMD_PARTITION_COMMAND 0x3e | 36 | #define SMU_CMD_PARTITION_COMMAND 0x3e |
| 37 | #define SMU_CMD_PARTITION_LATEST 0x01 | ||
| 38 | #define SMU_CMD_PARTITION_BASE 0x02 | ||
| 39 | #define SMU_CMD_PARTITION_UPDATE 0x03 | ||
| 26 | 40 | ||
| 27 | 41 | ||
| 28 | /* | 42 | /* |
| 29 | * Fan control | 43 | * Fan control |
| 30 | * | 44 | * |
| 31 | * This is a "mux" for fan control commands, first byte is the | 45 | * This is a "mux" for fan control commands. The command seem to |
| 32 | * "sub" command. | 46 | * act differently based on the number of arguments. With 1 byte |
| 47 | * of argument, this seem to be queries for fans status, setpoint, | ||
| 48 | * etc..., while with 0xe arguments, we will set the fans speeds. | ||
| 49 | * | ||
| 50 | * Queries (1 byte arg): | ||
| 51 | * --------------------- | ||
| 52 | * | ||
| 53 | * arg=0x01: read RPM fans status | ||
| 54 | * arg=0x02: read RPM fans setpoint | ||
| 55 | * arg=0x11: read PWM fans status | ||
| 56 | * arg=0x12: read PWM fans setpoint | ||
| 57 | * | ||
| 58 | * the "status" queries return the current speed while the "setpoint" ones | ||
| 59 | * return the programmed/target speed. It _seems_ that the result is a bit | ||
| 60 | * mask in the first byte of active/available fans, followed by 6 words (16 | ||
| 61 | * bits) containing the requested speed. | ||
| 62 | * | ||
| 63 | * Setpoint (14 bytes arg): | ||
| 64 | * ------------------------ | ||
| 65 | * | ||
| 66 | * first arg byte is 0 for RPM fans and 0x10 for PWM. Second arg byte is the | ||
| 67 | * mask of fans affected by the command. Followed by 6 words containing the | ||
| 68 | * setpoint value for selected fans in the mask (or 0 if mask value is 0) | ||
| 33 | */ | 69 | */ |
| 34 | #define SMU_CMD_FAN_COMMAND 0x4a | 70 | #define SMU_CMD_FAN_COMMAND 0x4a |
| 35 | 71 | ||
| @@ -156,6 +192,14 @@ | |||
| 156 | #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" | 192 | #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" |
| 157 | #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" | 193 | #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" |
| 158 | 194 | ||
| 195 | /* | ||
| 196 | * Read ADC sensors | ||
| 197 | * | ||
| 198 | * This command takes one byte of parameter: the sensor ID (or "reg" | ||
| 199 | * value in the device-tree) and returns a 16 bits value | ||
| 200 | */ | ||
| 201 | #define SMU_CMD_READ_ADC 0xd8 | ||
| 202 | |||
| 159 | /* Misc commands | 203 | /* Misc commands |
| 160 | * | 204 | * |
| 161 | * This command seem to be a grab bag of various things | 205 | * This command seem to be a grab bag of various things |
| @@ -176,6 +220,25 @@ | |||
| 176 | * Misc commands | 220 | * Misc commands |
| 177 | * | 221 | * |
| 178 | * This command seem to be a grab bag of various things | 222 | * This command seem to be a grab bag of various things |
| 223 | * | ||
| 224 | * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to | ||
| 225 | * transfer blocks of data from the SMU. So far, I've decrypted it's | ||
| 226 | * usage to retreive partition data. In order to do that, you have to | ||
| 227 | * break your transfer in "chunks" since that command cannot transfer | ||
| 228 | * more than a chunk at a time. The chunk size used by OF is 0xe bytes, | ||
| 229 | * but it seems that the darwin driver will let you do 0x1e bytes if | ||
| 230 | * your "PMU" version is >= 0x30. You can get the "PMU" version apparently | ||
| 231 | * either in the last 16 bits of property "smu-version-pmu" or as the 16 | ||
| 232 | * bytes at offset 1 of "smu-version-info" | ||
| 233 | * | ||
| 234 | * For each chunk, the command takes 7 bytes of arguments: | ||
| 235 | * byte 0: subcommand code (0x02) | ||
| 236 | * byte 1: 0x04 (always, I don't know what it means, maybe the address | ||
| 237 | * space to use or some other nicety. It's hard coded in OF) | ||
| 238 | * byte 2..5: SMU address of the chunk (big endian 32 bits) | ||
| 239 | * byte 6: size to transfer (up to max chunk size) | ||
| 240 | * | ||
| 241 | * The data is returned directly | ||
| 179 | */ | 242 | */ |
| 180 | #define SMU_CMD_MISC_ee_COMMAND 0xee | 243 | #define SMU_CMD_MISC_ee_COMMAND 0xee |
| 181 | #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 | 244 | #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 |
| @@ -353,21 +416,26 @@ struct smu_sdbp_header { | |||
| 353 | __u8 flags; | 416 | __u8 flags; |
| 354 | }; | 417 | }; |
| 355 | 418 | ||
| 356 | /* | 419 | |
| 357 | * 32 bits integers are usually encoded with 2x16 bits swapped, | 420 | /* |
| 358 | * this demangles them | 421 | * demangle 16 and 32 bits integer in some SMU partitions |
| 422 | * (currently, afaik, this concerns only the FVT partition | ||
| 423 | * (0x12) | ||
| 359 | */ | 424 | */ |
| 360 | #define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) | 425 | #define SMU_U16_MIX(x) le16_to_cpu(x); |
| 426 | #define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8)) | ||
| 427 | |||
| 361 | 428 | ||
| 362 | /* This is the definition of the SMU sdb-partition-0x12 table (called | 429 | /* This is the definition of the SMU sdb-partition-0x12 table (called |
| 363 | * CPU F/V/T operating points in Darwin). The definition for all those | 430 | * CPU F/V/T operating points in Darwin). The definition for all those |
| 364 | * SMU tables should be moved to some separate file | 431 | * SMU tables should be moved to some separate file |
| 365 | */ | 432 | */ |
| 366 | #define SMU_SDB_FVT_ID 0x12 | 433 | #define SMU_SDB_FVT_ID 0x12 |
| 367 | 434 | ||
| 368 | struct smu_sdbp_fvt { | 435 | struct smu_sdbp_fvt { |
| 369 | __u32 sysclk; /* Base SysClk frequency in Hz for | 436 | __u32 sysclk; /* Base SysClk frequency in Hz for |
| 370 | * this operating point | 437 | * this operating point. Value need to |
| 438 | * be unmixed with SMU_U32_MIX() | ||
| 371 | */ | 439 | */ |
| 372 | __u8 pad; | 440 | __u8 pad; |
| 373 | __u8 maxtemp; /* Max temp. supported by this | 441 | __u8 maxtemp; /* Max temp. supported by this |
| @@ -376,10 +444,73 @@ struct smu_sdbp_fvt { | |||
| 376 | 444 | ||
| 377 | __u16 volts[3]; /* CPU core voltage for the 3 | 445 | __u16 volts[3]; /* CPU core voltage for the 3 |
| 378 | * PowerTune modes, a mode with | 446 | * PowerTune modes, a mode with |
| 379 | * 0V = not supported. | 447 | * 0V = not supported. Value need |
| 448 | * to be unmixed with SMU_U16_MIX() | ||
| 380 | */ | 449 | */ |
| 381 | }; | 450 | }; |
| 382 | 451 | ||
| 452 | /* This partition contains voltage & current sensor calibration | ||
| 453 | * informations | ||
| 454 | */ | ||
| 455 | #define SMU_SDB_CPUVCP_ID 0x21 | ||
| 456 | |||
| 457 | struct smu_sdbp_cpuvcp { | ||
| 458 | __u16 volt_scale; /* u4.12 fixed point */ | ||
| 459 | __s16 volt_offset; /* s4.12 fixed point */ | ||
| 460 | __u16 curr_scale; /* u4.12 fixed point */ | ||
| 461 | __s16 curr_offset; /* s4.12 fixed point */ | ||
| 462 | __s32 power_quads[3]; /* s4.28 fixed point */ | ||
| 463 | }; | ||
| 464 | |||
| 465 | /* This partition contains CPU thermal diode calibration | ||
| 466 | */ | ||
| 467 | #define SMU_SDB_CPUDIODE_ID 0x18 | ||
| 468 | |||
| 469 | struct smu_sdbp_cpudiode { | ||
| 470 | __u16 m_value; /* u1.15 fixed point */ | ||
| 471 | __s16 b_value; /* s10.6 fixed point */ | ||
| 472 | |||
| 473 | }; | ||
| 474 | |||
| 475 | /* This partition contains Slots power calibration | ||
| 476 | */ | ||
| 477 | #define SMU_SDB_SLOTSPOW_ID 0x78 | ||
| 478 | |||
| 479 | struct smu_sdbp_slotspow { | ||
| 480 | __u16 pow_scale; /* u4.12 fixed point */ | ||
| 481 | __s16 pow_offset; /* s4.12 fixed point */ | ||
| 482 | }; | ||
| 483 | |||
| 484 | /* This partition contains machine specific version information about | ||
| 485 | * the sensor/control layout | ||
| 486 | */ | ||
| 487 | #define SMU_SDB_SENSORTREE_ID 0x25 | ||
| 488 | |||
| 489 | struct smu_sdbp_sensortree { | ||
| 490 | u8 model_id; | ||
| 491 | u8 unknown[3]; | ||
| 492 | }; | ||
| 493 | |||
| 494 | /* This partition contains CPU thermal control PID informations. So far | ||
| 495 | * only single CPU machines have been seen with an SMU, so we assume this | ||
| 496 | * carries only informations for those | ||
| 497 | */ | ||
| 498 | #define SMU_SDB_CPUPIDDATA_ID 0x17 | ||
| 499 | |||
| 500 | struct smu_sdbp_cpupiddata { | ||
| 501 | u8 unknown1; | ||
| 502 | u8 target_temp_delta; | ||
| 503 | u8 unknown2; | ||
| 504 | u8 history_len; | ||
| 505 | s16 power_adj; | ||
| 506 | u16 max_power; | ||
| 507 | s32 gp,gr,gd; | ||
| 508 | }; | ||
| 509 | |||
| 510 | |||
| 511 | /* Other partitions without known structures */ | ||
| 512 | #define SMU_SDB_DEBUG_SWITCHES_ID 0x05 | ||
| 513 | |||
| 383 | #ifdef __KERNEL__ | 514 | #ifdef __KERNEL__ |
| 384 | /* | 515 | /* |
| 385 | * This returns the pointer to an SMU "sdb" partition data or NULL | 516 | * This returns the pointer to an SMU "sdb" partition data or NULL |
| @@ -423,8 +554,10 @@ struct smu_user_cmd_hdr | |||
| 423 | __u32 cmdtype; | 554 | __u32 cmdtype; |
| 424 | #define SMU_CMDTYPE_SMU 0 /* SMU command */ | 555 | #define SMU_CMDTYPE_SMU 0 /* SMU command */ |
| 425 | #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ | 556 | #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ |
| 557 | #define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ | ||
| 426 | 558 | ||
| 427 | __u8 cmd; /* SMU command byte */ | 559 | __u8 cmd; /* SMU command byte */ |
| 560 | __u8 pad[3]; /* padding */ | ||
| 428 | __u32 data_len; /* Lenght of data following */ | 561 | __u32 data_len; /* Lenght of data following */ |
| 429 | }; | 562 | }; |
| 430 | 563 | ||
diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index 75c0637acdc8..3e39827ed566 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h | |||
| @@ -93,7 +93,7 @@ extern int device_is_compatible(struct device_node *device, const char *); | |||
| 93 | extern int machine_is_compatible(const char *compat); | 93 | extern int machine_is_compatible(const char *compat); |
| 94 | extern unsigned char *get_property(struct device_node *node, const char *name, | 94 | extern unsigned char *get_property(struct device_node *node, const char *name, |
| 95 | int *lenp); | 95 | int *lenp); |
| 96 | extern void prom_add_property(struct device_node* np, struct property* prop); | 96 | extern int prom_add_property(struct device_node* np, struct property* prop); |
| 97 | extern void prom_get_irq_senses(unsigned char *, int, int); | 97 | extern void prom_get_irq_senses(unsigned char *, int, int); |
| 98 | extern int prom_n_addr_cells(struct device_node* np); | 98 | extern int prom_n_addr_cells(struct device_node* np); |
| 99 | extern int prom_n_size_cells(struct device_node* np); | 99 | extern int prom_n_size_cells(struct device_node* np); |
diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index bdb47174ff0e..76bb0266d67c 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h | |||
| @@ -213,6 +213,6 @@ extern int prom_n_addr_cells(struct device_node* np); | |||
| 213 | extern int prom_n_size_cells(struct device_node* np); | 213 | extern int prom_n_size_cells(struct device_node* np); |
| 214 | extern int prom_n_intr_cells(struct device_node* np); | 214 | extern int prom_n_intr_cells(struct device_node* np); |
| 215 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); | 215 | extern void prom_get_irq_senses(unsigned char *senses, int off, int max); |
| 216 | extern void prom_add_property(struct device_node* np, struct property* prop); | 216 | extern int prom_add_property(struct device_node* np, struct property* prop); |
| 217 | 217 | ||
| 218 | #endif /* _PPC64_PROM_H */ | 218 | #endif /* _PPC64_PROM_H */ |
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0563581e3a02..65ceeaa30652 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h | |||
| @@ -139,15 +139,12 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver); | |||
| 139 | /* | 139 | /* |
| 140 | * proc_devtree.c | 140 | * proc_devtree.c |
| 141 | */ | 141 | */ |
| 142 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 142 | struct device_node; | 143 | struct device_node; |
| 144 | struct property; | ||
| 143 | extern void proc_device_tree_init(void); | 145 | extern void proc_device_tree_init(void); |
| 144 | #ifdef CONFIG_PROC_DEVICETREE | ||
| 145 | extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); | 146 | extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); |
| 146 | #else /* !CONFIG_PROC_DEVICETREE */ | 147 | extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); |
| 147 | static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) | ||
| 148 | { | ||
| 149 | return; | ||
| 150 | } | ||
| 151 | #endif /* CONFIG_PROC_DEVICETREE */ | 148 | #endif /* CONFIG_PROC_DEVICETREE */ |
| 152 | 149 | ||
| 153 | extern struct proc_dir_entry *proc_symlink(const char *, | 150 | extern struct proc_dir_entry *proc_symlink(const char *, |
