1/* ********************************************************************* 2 * Broadcom Common Firmware Environment (CFE) 3 * 4 * Temperature sensor commands: File: ui_tempsensor.c 5 * 6 * Temperature sensor commands 7 * 8 * Author: Mitch Lichtenberg (mpl@broadcom.com) 9 * 10 ********************************************************************* 11 * 12 * Copyright 2000,2001,2002,2003 13 * Broadcom Corporation. All rights reserved. 14 * 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. 21 * 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. 25 * 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. 31 * 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 ********************************************************************* */ 46 47 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" 53 54#include "cfe_console.h" 55#include "cfe_timer.h" 56 57#include "cfe_error.h" 58 59#include "ui_command.h" 60#include "cfe.h" 61 62#include "bsp_config.h" 63 64#include "sbmips.h" 65#include "sb1250_regs.h" 66#include "sb1250_smbus.h" 67 68 69/* ********************************************************************* 70 * Configuration 71 ********************************************************************* */ 72 73#define _MAX6654_ /* Support Maxim 6654 temperature chip w/parasitic mode */ 74 75/* ********************************************************************* 76 * prototypes 77 ********************************************************************* */ 78 79int ui_init_tempsensorcmds(void); 80 81#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN)) 82static int ui_cmd_showtemp(ui_cmdline_t *cmd,int argc,char *argv[]); 83static void temp_timer_proc(void *); 84#endif 85 86/* ********************************************************************* 87 * Data 88 ********************************************************************* */ 89 90#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN)) 91static int64_t temp_timer = 0; 92static int temp_prev_local = 0; 93static int temp_prev_remote = 0; 94#endif 95 96/* ********************************************************************* 97 * ui_init_swarmcmds() 98 * 99 * Add SWARM-specific commands to the command table 100 * 101 * Input parameters: 102 * nothing 103 * 104 * Return value: 105 * 0 106 ********************************************************************* */ 107 108 109int ui_init_tempsensorcmds(void) 110{ 111 112#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN)) 113 cmd_addcmd("show temp", 114 ui_cmd_showtemp, 115 NULL, 116 "Display CPU temperature", 117 "show temp", 118 "-continuous;Poll for temperature changes|" 119 "-stop;Stop polling for temperature changes"); 120 121 cfe_bg_add(temp_timer_proc,NULL); 122#endif 123 124 return 0; 125} 126 127 128 129#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN)) 130/* ********************************************************************* 131 * temp_smbus_init(chan) 132 * 133 * Initialize the specified SMBus channel for the temp sensor 134 * 135 * Input parameters: 136 * chan - channel # (0 or 1) 137 * 138 * Return value: 139 * nothing 140 ********************************************************************* */ 141 142static void temp_smbus_init(int chan) 143{ 144 uintptr_t reg; 145 146 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_FREQ)); 147 148 SBWRITECSR(reg,K_SMB_FREQ_100KHZ); /* 400Khz clock */ 149 150 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CONTROL)); 151 152 SBWRITECSR(reg,0); /* not in direct mode, no interrupts, will poll */ 153 154} 155 156/* ********************************************************************* 157 * temp_smbus_waitready(chan) 158 * 159 * Wait until the SMBus channel is ready. We simply poll 160 * the busy bit until it clears. 161 * 162 * Input parameters: 163 * chan - channel (0 or 1) 164 * 165 * Return value: 166 * nothing 167 ********************************************************************* */ 168static int temp_smbus_waitready(int chan) 169{ 170 uintptr_t reg; 171 uint64_t status; 172 173 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_STATUS)); 174 175 for (;;) { 176 status = SBREADCSR(reg); 177 if (status & M_SMB_BUSY) continue; 178 break; 179 } 180 181 if (status & M_SMB_ERROR) { 182 SBWRITECSR(reg,(status & M_SMB_ERROR)); 183 return -1; 184 } 185 return 0; 186} 187 188/* ********************************************************************* 189 * temp_smbus_read(chan,slaveaddr,devaddr) 190 * 191 * Read a byte from the temperature sensor chip 192 * 193 * Input parameters: 194 * chan - SMBus channel 195 * slaveaddr - SMBus slave address 196 * devaddr - byte with in the sensor device to read 197 * 198 * Return value: 199 * 0 if ok 200 * else -1 201 ********************************************************************* */ 202 203static int temp_smbus_read(int chan,int slaveaddr,int devaddr) 204{ 205 uintptr_t reg; 206 int err; 207 208 /* 209 * Make sure the bus is idle (probably should 210 * ignore error here) 211 */ 212 213 if (temp_smbus_waitready(chan) < 0) return -1; 214 215 /* 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. 219 */ 220 221 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD)); 222 SBWRITECSR(reg,devaddr); 223 224 /* 225 * Read the data byte 226 */ 227 228 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START)); 229 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_CMD_RD1BYTE) | slaveaddr); 230 231 err = temp_smbus_waitready(chan); 232 if (err < 0) return err; 233 234 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA)); 235 err = SBREADCSR(reg); 236 237 return (err & 0xFF); 238} 239 240#ifdef _MAX6654_ 241/* ********************************************************************* 242 * temp_smbus_write(chan,slaveaddr,devaddr,data) 243 * 244 * write a byte to the temperature sensor chip 245 * 246 * Input parameters: 247 * chan - SMBus channel 248 * slaveaddr - SMBus slave address 249 * devaddr - byte with in the sensor device to read 250 * 251 * Return value: 252 * 0 if ok 253 * else -1 254 ********************************************************************* */ 255 256static int temp_smbus_write(int chan,int slaveaddr,int devaddr,int data) 257{ 258 uintptr_t reg; 259 int err; 260 261 /* 262 * Make sure the bus is idle (probably should 263 * ignore error here) 264 */ 265 266 if (temp_smbus_waitready(chan) < 0) return -1; 267 268 /* 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. 272 */ 273 274 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_CMD)); 275 SBWRITECSR(reg,devaddr); 276 277 /* 278 * Write the data byte 279 */ 280 281 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_DATA)); 282 SBWRITECSR(reg,data); 283 284 /* 285 * Do the write command. 286 */ 287 288 reg = PHYS_TO_K1(A_SMB_REGISTER(chan,R_SMB_START)); 289 SBWRITECSR(reg,V_SMB_TT(K_SMB_TT_WR2BYTE) | slaveaddr); 290 291 err = temp_smbus_waitready(chan); 292 293 return err; 294} 295#endif 296 297 298/* ********************************************************************* 299 * temp_showtemp(noisy) 300 * 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. 304 * 305 * Input parameters: 306 * noisy - display whether or not changed 307 * 308 * Return value: 309 * nothing 310 ********************************************************************* */ 311 312static int temp_showtemp(int noisy) 313{ 314 int local,remote,status; 315 char statstr[50]; 316 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); 320 321 if ((local < 0) || (remote < 0) || (status < 0)) { 322 if (noisy) printf("Temperature sensor device did not respond\n"); 323 return -1; 324 } 325 326 if (noisy || (local != temp_prev_local) || (remote != temp_prev_remote)) { 327 statstr[0] = 0; 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 "); 334 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); 339 } 340 } 341 342 temp_prev_local = local; 343 temp_prev_remote = remote; 344 345 return 0; 346} 347 348 349 350 351/* ********************************************************************* 352 * ui_cmd_showtemp(cmd,argc,argv) 353 * 354 * Show temperature 355 * 356 * Input parameters: 357 * cmd - command structure 358 * argc,argv - parameters 359 * 360 * Return value: 361 * -1 if error occured. Does not return otherwise 362 ********************************************************************* */ 363 364static int ui_cmd_showtemp(ui_cmdline_t *cmd,int argc,char *argv[]) 365{ 366 367 temp_smbus_init(TEMPSENSOR_SMBUS_CHAN); 368 369#ifdef _MAX6654_ 370 do { 371 int dev,rev; 372 static int didinit = 0; 373 374 if (!didinit) { 375 didinit = 1; 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); 379 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); 386 } 387 } 388 } while (0); 389#endif 390 391 if (temp_showtemp(1) < 0) { 392 TIMER_CLEAR(temp_timer); 393 return -1; 394 } 395 396 if (cmd_sw_isset(cmd,"-continuous")) { 397 TIMER_SET(temp_timer,2*CFE_HZ); 398 } 399 if (cmd_sw_isset(cmd,"-stop")) { 400 TIMER_CLEAR(temp_timer); 401 } 402 403 return 0; 404} 405 406/* ********************************************************************* 407 * temp_timer_proc() 408 * 409 * So we can be fancy and log temperature changes as they happen. 410 * 411 * Input parameters: 412 * nothing 413 * 414 * Return value: 415 * nothing 416 ********************************************************************* */ 417 418void temp_timer_proc(void *arg) 419{ 420 if (!TIMER_RUNNING(temp_timer)) return; 421 422 if (TIMER_EXPIRED(temp_timer)) { 423 temp_showtemp(0); 424 TIMER_SET(temp_timer,2*CFE_HZ); 425 } 426} 427#endif 428