1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Temperature sensor commands: File: ui_tempsensor.c
6 * Temperature sensor commands
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
48 #include "lib_types.h"
49 #include "lib_string.h"
50 #include "lib_queue.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
54 #include "cfe_console.h"
55 #include "cfe_timer.h"
57 #include "cfe_error.h"
59 #include "ui_command.h"
62 #include "bsp_config.h"
65 #include "sb1250_regs.h"
66 #include "sb1250_smbus.h"
69 /* *********************************************************************
71 ********************************************************************* */
73 #define _MAX6654_ /* Support Maxim 6654 temperature chip w/parasitic mode */
75 /* *********************************************************************
77 ********************************************************************* */
79 int ui_init_tempsensorcmds(void);
81 #if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
82 static int ui_cmd_showtemp(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
83 static void temp_timer_proc(void *);
86 /* *********************************************************************
88 ********************************************************************* */
90 #if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
91 static int64_t temp_timer
= 0;
92 static int temp_prev_local
= 0;
93 static int temp_prev_remote
= 0;
96 /* *********************************************************************
99 * Add SWARM-specific commands to the command table
106 ********************************************************************* */
109 int ui_init_tempsensorcmds(void)
112 #if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
113 cmd_addcmd("show temp",
116 "Display CPU temperature",
118 "-continuous;Poll for temperature changes|"
119 "-stop;Stop polling for temperature changes");
121 cfe_bg_add(temp_timer_proc
,NULL
);
129 #if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
130 /* *********************************************************************
131 * temp_smbus_init(chan)
133 * Initialize the specified SMBus channel for the temp sensor
136 * chan - channel # (0 or 1)
140 ********************************************************************* */
142 static void temp_smbus_init(int chan
)
146 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_FREQ
));
148 SBWRITECSR(reg
,K_SMB_FREQ_100KHZ
); /* 400Khz clock */
150 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CONTROL
));
152 SBWRITECSR(reg
,0); /* not in direct mode, no interrupts, will poll */
156 /* *********************************************************************
157 * temp_smbus_waitready(chan)
159 * Wait until the SMBus channel is ready. We simply poll
160 * the busy bit until it clears.
163 * chan - channel (0 or 1)
167 ********************************************************************* */
168 static int temp_smbus_waitready(int chan
)
173 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_STATUS
));
176 status
= SBREADCSR(reg
);
177 if (status
& M_SMB_BUSY
) continue;
181 if (status
& M_SMB_ERROR
) {
182 SBWRITECSR(reg
,(status
& M_SMB_ERROR
));
188 /* *********************************************************************
189 * temp_smbus_read(chan,slaveaddr,devaddr)
191 * Read a byte from the temperature sensor chip
194 * chan - SMBus channel
195 * slaveaddr - SMBus slave address
196 * devaddr - byte with in the sensor device to read
201 ********************************************************************* */
203 static int temp_smbus_read(int chan
,int slaveaddr
,int devaddr
)
209 * Make sure the bus is idle (probably should
213 if (temp_smbus_waitready(chan
) < 0) return -1;
216 * Write the device address to the controller. There are two
217 * parts, the high part goes in the "CMD" field, and the
218 * low part is the data field.
221 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
222 SBWRITECSR(reg
,devaddr
);
228 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
229 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_CMD_RD1BYTE
) | slaveaddr
);
231 err
= temp_smbus_waitready(chan
);
232 if (err
< 0) return err
;
234 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
235 err
= SBREADCSR(reg
);
241 /* *********************************************************************
242 * temp_smbus_write(chan,slaveaddr,devaddr,data)
244 * write a byte to the temperature sensor chip
247 * chan - SMBus channel
248 * slaveaddr - SMBus slave address
249 * devaddr - byte with in the sensor device to read
254 ********************************************************************* */
256 static int temp_smbus_write(int chan
,int slaveaddr
,int devaddr
,int data
)
262 * Make sure the bus is idle (probably should
266 if (temp_smbus_waitready(chan
) < 0) return -1;
269 * Write the device address to the controller. There are two
270 * parts, the high part goes in the "CMD" field, and the
271 * low part is the data field.
274 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
275 SBWRITECSR(reg
,devaddr
);
278 * Write the data byte
281 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
282 SBWRITECSR(reg
,data
);
285 * Do the write command.
288 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
289 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR2BYTE
) | slaveaddr
);
291 err
= temp_smbus_waitready(chan
);
298 /* *********************************************************************
299 * temp_showtemp(noisy)
301 * Display the temperature. If 'noisy' is true, display it
302 * regardless of whether it has changed, otherwise only display
303 * when it has changed.
306 * noisy - display whether or not changed
310 ********************************************************************* */
312 static int temp_showtemp(int noisy
)
314 int local
,remote
,status
;
317 local
= temp_smbus_read(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,0);
318 remote
= temp_smbus_read(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,1);
319 status
= temp_smbus_read(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,2);
321 if ((local
< 0) || (remote
< 0) || (status
< 0)) {
322 if (noisy
) printf("Temperature sensor device did not respond\n");
326 if (noisy
|| (local
!= temp_prev_local
) || (remote
!= temp_prev_remote
)) {
328 if (status
& 0x80) strcat(statstr
,"Busy ");
329 if (status
& 0x40) strcat(statstr
,"HiTempLcl ");
330 if (status
& 0x20) strcat(statstr
,"LoTempLcl ");
331 if (status
& 0x10) strcat(statstr
,"HiTempRem ");
332 if (status
& 0x08) strcat(statstr
,"LoTempRem ");
333 if (status
& 0x04) strcat(statstr
,"Fault ");
335 if (noisy
|| !(status
& 0x80)) {
336 /* don't display if busy, always display if noisy */
337 console_log("Temperature: CPU: %dC Board: %dC Status:%02X [ %s]",
338 remote
,local
,status
,statstr
);
342 temp_prev_local
= local
;
343 temp_prev_remote
= remote
;
351 /* *********************************************************************
352 * ui_cmd_showtemp(cmd,argc,argv)
357 * cmd - command structure
358 * argc,argv - parameters
361 * -1 if error occured. Does not return otherwise
362 ********************************************************************* */
364 static int ui_cmd_showtemp(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
367 temp_smbus_init(TEMPSENSOR_SMBUS_CHAN
);
372 static int didinit
= 0;
376 dev
= temp_smbus_read(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,0xFE);
377 rev
= temp_smbus_read(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,0xFF);
378 printf("Temperature Sensor Device ID %02X rev %02X\n",dev
,rev
);
380 if (dev
== 0x4D) { /* MAX6654 */
381 printf("Switching MAX6654 to parasitic mode\n");
382 /* Switch to 1hz conversion rate (1 seconds per conversion) */
383 temp_smbus_write(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,0x0A,0x04);
384 /* Switch to parasitic mode */
385 temp_smbus_write(TEMPSENSOR_SMBUS_CHAN
,TEMPSENSOR_SMBUS_DEV
,9,0x10);
391 if (temp_showtemp(1) < 0) {
392 TIMER_CLEAR(temp_timer
);
396 if (cmd_sw_isset(cmd
,"-continuous")) {
397 TIMER_SET(temp_timer
,2*CFE_HZ
);
399 if (cmd_sw_isset(cmd
,"-stop")) {
400 TIMER_CLEAR(temp_timer
);
406 /* *********************************************************************
409 * So we can be fancy and log temperature changes as they happen.
416 ********************************************************************* */
418 void temp_timer_proc(void *arg
)
420 if (!TIMER_RUNNING(temp_timer
)) return;
422 if (TIMER_EXPIRED(temp_timer
)) {
424 TIMER_SET(temp_timer
,2*CFE_HZ
);