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
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 "cfe.h"
49#include "cfe_smbus.h"
50#include "ui_command.h"
51
52
53/*  *********************************************************************
54    *                     Supported chips
55    *    chip      vendor id (at 0xFE)    rev ID (at 0xFF)
56    *
57    *  ADT7461           0x41                0x51
58    *  MAX1617           0x4D                0x01
59    *  MAX6654           0x4D                0x08
60    *
61    ********************************************************************* */
62
63/*  *********************************************************************
64    *  Configuration
65    ********************************************************************* */
66
67#define _MAX6654_	/* Support Maxim 6654 temperature chip w/parasitic mode */
68
69/*  *********************************************************************
70    *  prototypes
71    ********************************************************************* */
72
73int ui_init_tempsensorcmds(void);
74
75#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
76static int ui_cmd_showtemp(ui_cmdline_t *cmd,int argc,char *argv[]);
77static void temp_timer_proc(void *);
78#endif
79
80/*  *********************************************************************
81    *  Data
82    ********************************************************************* */
83
84#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
85static int64_t temp_timer = 0;
86static int temp_prev_local = 0;
87static int temp_prev_remote = 0;
88#endif
89
90/*  *********************************************************************
91    *  ui_init_swarmcmds()
92    *
93    *  Add SWARM-specific commands to the command table
94    *
95    *  Input parameters:
96    *  	   nothing
97    *
98    *  Return value:
99    *  	   0
100    ********************************************************************* */
101
102
103int ui_init_tempsensorcmds(void)
104{
105
106#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
107    cmd_addcmd("show temp",
108	       ui_cmd_showtemp,
109	       NULL,
110	       "Display CPU temperature",
111	       "show temp",
112	       "-continuous;Poll for temperature changes|"
113	       "-stop;Stop polling for temperature changes");
114
115    cfe_bg_add(temp_timer_proc,NULL);
116#endif
117
118    return 0;
119}
120
121
122
123#if (defined(TEMPSENSOR_SMBUS_DEV) && defined(TEMPSENSOR_SMBUS_CHAN))
124/*  *********************************************************************
125    *  temp_smbus_read(chan,slaveaddr,devaddr)
126    *
127    *  Read a byte from the temperature sensor chip
128    *
129    *  Input parameters:
130    *  	   chan - SMBus channel
131    *  	   slaveaddr -  SMBus slave address
132    *  	   devaddr - byte with in the sensor device to read
133    *
134    *  Return value:
135    *  	   0 if ok
136    *  	   else -1
137    ********************************************************************* */
138
139static int temp_smbus_read(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr)
140{
141    uint8_t buf[1];
142    int err;
143
144    /*
145     * Read the data byte
146     */
147
148    err = SMBUS_XACT(chan,slaveaddr,devaddr,buf,1);
149    if (err < 0) return err;
150
151    return buf[0];
152}
153
154#ifdef _MAX6654_
155/*  *********************************************************************
156    *  temp_smbus_write(chan,slaveaddr,devaddr,data)
157    *
158    *  write a byte to the temperature sensor chip
159    *
160    *  Input parameters:
161    *  	   chan - SMBus channel
162    *  	   slaveaddr -  SMBus slave address
163    *  	   devaddr - byte with in the sensor device to read
164    *
165    *  Return value:
166    *  	   0 if ok
167    *  	   else -1
168    ********************************************************************* */
169
170static int temp_smbus_write(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr,int data)
171{
172    uint8_t buf[2];
173    int err;
174
175    /*
176     * Write the data byte
177     */
178
179    buf[0] = devaddr;
180    buf[1] = data;
181
182    err = SMBUS_WRITE(chan,slaveaddr,buf,2);
183    return err;
184}
185#endif
186
187
188/*  *********************************************************************
189    *  temp_showtemp(noisy)
190    *
191    *  Display the temperature.  If 'noisy' is true, display it
192    *  regardless of whether it has changed, otherwise only display
193    *  when it has changed.
194    *
195    *  Input parameters:
196    *  	   noisy - display whether or not changed
197    *
198    *  Return value:
199    *  	   nothing
200    ********************************************************************* */
201
202static int temp_showtemp(int noisy)
203{
204    int local,remote,status;
205    char statstr[50];
206    cfe_smbus_channel_t *chan = SMBUS_CHANNEL(TEMPSENSOR_SMBUS_CHAN);
207
208    local  = temp_smbus_read(chan,TEMPSENSOR_SMBUS_DEV,0);
209    remote = temp_smbus_read(chan,TEMPSENSOR_SMBUS_DEV,1);
210    status = temp_smbus_read(chan,TEMPSENSOR_SMBUS_DEV,2);
211
212    if ((local < 0) || (remote < 0) || (status < 0)) {
213	if (noisy) printf("Temperature sensor device did not respond\n");
214	return -1;
215	}
216
217    if (noisy || (local != temp_prev_local) || (remote != temp_prev_remote)) {
218	statstr[0] = 0;
219	if (status & 0x80) strcat(statstr,"Busy ");
220	if (status & 0x40) strcat(statstr,"HiTempLcl ");
221	if (status & 0x20) strcat(statstr,"LoTempLcl ");
222	if (status & 0x10) strcat(statstr,"HiTempRem ");
223	if (status & 0x08) strcat(statstr,"LoTempRem ");
224	if (status & 0x04) strcat(statstr,"Fault ");
225
226	if (noisy || !(status & 0x80)) {
227	    /* don't display if busy, always display if noisy */
228	    console_log("Temperature:  CPU: %dC  Board: %dC  Status:%02X [ %s]",
229		    remote,local,status,statstr);
230	    }
231	}
232
233    temp_prev_local = local;
234    temp_prev_remote = remote;
235
236    return 0;
237}
238
239
240
241
242/*  *********************************************************************
243    *  ui_cmd_showtemp(cmd,argc,argv)
244    *
245    *  Show temperature
246    *
247    *  Input parameters:
248    *  	   cmd - command structure
249    *  	   argc,argv - parameters
250    *
251    *  Return value:
252    *  	   -1 if error occured.  Does not return otherwise
253    ********************************************************************* */
254
255static int ui_cmd_showtemp(ui_cmdline_t *cmd,int argc,char *argv[])
256{
257
258    do {
259	int dev,rev;
260	static int didinit = 0;
261	cfe_smbus_channel_t *chan = SMBUS_CHANNEL(TEMPSENSOR_SMBUS_CHAN);
262
263	if (!didinit) {
264	    didinit = 1;
265	    dev = temp_smbus_read(chan,TEMPSENSOR_SMBUS_DEV,0xFE);
266	    rev = temp_smbus_read(chan,TEMPSENSOR_SMBUS_DEV,0xFF);
267	    printf("Temperature Sensor Device ID %02X rev %02X\n",dev,rev);
268
269#ifdef _MAX6654_
270	    if (dev == 0x4D && rev == 0x08) {		/* MAX6654 */
271		printf("Switching MAX6654 to parasitic mode\n");
272		/* Switch to 1hz conversion rate (1 seconds per conversion) */
273		temp_smbus_write(chan,TEMPSENSOR_SMBUS_DEV,0x0A,0x04);
274		/* Switch to parasitic mode */
275		temp_smbus_write(chan,TEMPSENSOR_SMBUS_DEV,9,0x10);
276		}
277#endif
278	    }
279       } while (0);
280
281    if (temp_showtemp(1) < 0) {
282	TIMER_CLEAR(temp_timer);
283	return -1;
284	}
285
286    if (cmd_sw_isset(cmd,"-continuous")) {
287	TIMER_SET(temp_timer,2*CFE_HZ);
288	}
289    if (cmd_sw_isset(cmd,"-stop")) {
290	TIMER_CLEAR(temp_timer);
291	}
292
293    return 0;
294}
295
296/*  *********************************************************************
297    *  temp_timer_proc()
298    *
299    *  So we can be fancy and log temperature changes as they happen.
300    *
301    *  Input parameters:
302    *  	   nothing
303    *
304    *  Return value:
305    *  	   nothing
306    ********************************************************************* */
307
308void temp_timer_proc(void *arg)
309{
310    if (!TIMER_RUNNING(temp_timer)) return;
311
312    if (TIMER_EXPIRED(temp_timer)) {
313	temp_showtemp(0);
314	TIMER_SET(temp_timer,2*CFE_HZ);
315	}
316}
317#endif
318