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 *, |