1/*  *********************************************************************
2    *  Broadcom Common Firmware Environment (CFE)
3    *
4    *  Xicor RTC/EEPROM driver		File: dev_smbus_x1227eeprom.c
5    *
6    *  This module contains a CFE driver for a Xicor X1227 SMBus
7    *  real-time-clock & EEPROM module.  The only functionality
8    *  we currently export is the EEPROM, for use as environment
9    *  storage.
10    *
11    *  Author:  Mitch Lichtenberg
12    *
13    *********************************************************************
14    *
15    *  Copyright 2000,2001,2002,2003
16    *  Broadcom Corporation. All rights reserved.
17    *
18    *  This software is furnished under license and may be used and
19    *  copied only in accordance with the following terms and
20    *  conditions.  Subject to these conditions, you may download,
21    *  copy, install, use, modify and distribute modified or unmodified
22    *  copies of this software in source and/or binary form.  No title
23    *  or ownership is transferred hereby.
24    *
25    *  1) Any source code used, modified or distributed must reproduce
26    *     and retain this copyright notice and list of conditions
27    *     as they appear in the source file.
28    *
29    *  2) No right is granted to use any trade name, trademark, or
30    *     logo of Broadcom Corporation.  The "Broadcom Corporation"
31    *     name may not be used to endorse or promote products derived
32    *     from this software without the prior written permission of
33    *     Broadcom Corporation.
34    *
35    *  3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
36    *     IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
37    *     WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
38    *     PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
39    *     SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
40    *     PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
41    *     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42    *     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
43    *     GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
44    *     BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45    *     OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
46    *     TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
47    *     THE POSSIBILITY OF SUCH DAMAGE.
48    ********************************************************************* */
49
50
51#include "cfe.h"
52#include "cfe_smbus.h"
53
54/*
55 * XXX: The X1227 is a superset of the X1240/X1241 except that its
56 * EEPROM is 512 bytes and thus the block-protect bits cover smaller
57 * ranges.  The drivers should be unified.
58 */
59
60/*  *********************************************************************
61    *  Xicor X1227 RTC constants
62    ********************************************************************* */
63/*
64 * Register bits
65 */
66
67#define X1227REG_SR_BAT	0x80		/* currently on battery power */
68#define X1227REG_SR_RWEL 0x04		/* r/w latch is enabled, can write RTC */
69#define X1227REG_SR_WEL 0x02		/* r/w latch is unlocked, can enable r/w now */
70#define X1227REG_SR_RTCF 0x01		/* clock failed */
71#define X1227REG_BL_BP2 0x80		/* block protect 2 */
72#define X1227REG_BL_BP1 0x40		/* block protect 1 */
73#define X1227REG_BL_BP0 0x20		/* block protect 0 */
74#define X1227REG_BL_WD1	0x10
75#define X1227REG_BL_WD0	0x08
76#define X1227REG_HR_MIL 0x80		/* military time format */
77
78/*
79 * Register numbers
80 */
81
82#define X1227REG_BL	0x10		/* block protect bits */
83#define X1227REG_INT	0x11		/*  */
84#define X1227REG_SC	0x30		/* Seconds */
85#define X1227REG_MN	0x31		/* Minutes */
86#define X1227REG_HR	0x32		/* Hours */
87#define X1227REG_DT	0x33		/* Day of month */
88#define X1227REG_MO	0x34		/* Month */
89#define X1227REG_YR	0x35		/* Year */
90#define X1227REG_DW	0x36		/* Day of Week */
91#define X1227REG_Y2K	0x37		/* Year 2K */
92#define X1227REG_SR	0x3F		/* Status register */
93
94#define X1227_CCR_ADDRESS	0x6F
95#define X1227_ARRAY_ADDRESS	0x57
96
97#define X1227_EEPROM_SIZE 512
98
99/*  *********************************************************************
100    *  Forward Declarations
101    ********************************************************************* */
102
103static void sb1250_x1227eeprom_probe(cfe_driver_t *drv,
104				     unsigned long probe_a, unsigned long probe_b,
105				     void *probe_ptr);
106
107
108static int sb1250_x1227eeprom_open(cfe_devctx_t *ctx);
109static int sb1250_x1227eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
110static int sb1250_x1227eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
111static int sb1250_x1227eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
112static int sb1250_x1227eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
113static int sb1250_x1227eeprom_close(cfe_devctx_t *ctx);
114
115/*  *********************************************************************
116    *  Dispatch tables
117    ********************************************************************* */
118
119const static cfe_devdisp_t sb1250_x1227eeprom_dispatch = {
120    sb1250_x1227eeprom_open,
121    sb1250_x1227eeprom_read,
122    sb1250_x1227eeprom_inpstat,
123    sb1250_x1227eeprom_write,
124    sb1250_x1227eeprom_ioctl,
125    sb1250_x1227eeprom_close,
126    NULL,
127    NULL
128};
129
130const cfe_driver_t smbus_x1227eeprom = {
131    "Xicor X1227 EEPROM",
132    "eeprom",
133    CFE_DEV_NVRAM,
134    &sb1250_x1227eeprom_dispatch,
135    sb1250_x1227eeprom_probe
136};
137
138typedef struct sb1250_x1227eeprom_s {
139    cfe_smbus_channel_t *smbus_channel;
140    int env_offset;
141    int env_size;
142} sb1250_x1227eeprom_t;
143
144
145
146
147/*  *********************************************************************
148    *  smbus_readrtc(chan,slaveaddr,devaddr)
149    *
150    *  Read a byte from the chip.  The 'slaveaddr' parameter determines
151    *  whether we're reading from the RTC section or the EEPROM section.
152    *
153    *  Input parameters:
154    *  	   chan - SMBus channel
155    *  	   slaveaddr -  SMBus slave address
156    *  	   devaddr - byte with in the X1227 device to read
157    *
158    *  Return value:
159    *  	   0 if ok
160    *  	   else -1
161    ********************************************************************* */
162
163static int smbus_readrtc(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr)
164{
165    uint8_t buf[2];
166    int err;
167
168    /*
169     * Write the device address to the controller. There are two
170     * parts, the high part goes in the "CMD" field, and the
171     * low part is the data field.
172     */
173
174    buf[0] = (devaddr >> 8) & 0x07;
175    buf[1] = (devaddr & 0xFF);
176
177    err = SMBUS_WRITE(chan,slaveaddr,buf,2);
178    if (err < 0) return err;
179
180    /*
181     * Read the data byte
182     */
183
184    err = SMBUS_READ(chan,slaveaddr,buf,1);
185    if (err < 0) return err;
186
187    return (buf[0]);
188}
189
190/*  *********************************************************************
191    *  smbus_writertc(chan,slaveaddr,devaddr,b)
192    *
193    *  write a byte from the chip.  The 'slaveaddr' parameter determines
194    *  whethe we're writing to the RTC section or the EEPROM section.
195    *
196    *  Input parameters:
197    *  	   chan - SMBus channel
198    *  	   slaveaddr -  SMBus slave address
199    *  	   devaddr - byte with in the X1227 device to read
200    *      b - byte to write
201    *
202    *  Return value:
203    *  	   0 if ok
204    *  	   else -1
205    ********************************************************************* */
206
207
208static int smbus_writertc(cfe_smbus_channel_t *chan,int slaveaddr,int devaddr,int b)
209{
210    uint8_t buf[3];
211    int err;
212    int64_t timer;
213
214
215    /*
216     * Write the data to the controller
217     */
218
219
220    buf[0] = (devaddr >> 8) & 0x07;
221    buf[1] = (devaddr & 0xFF);
222    buf[2] = b;
223
224    err = SMBUS_WRITE(chan,slaveaddr,buf,3);
225    if (err < 0) return err;
226
227    /*
228     * Pound on the device with a current address read
229     * to poll for the write complete
230     */
231
232    TIMER_SET(timer,50);
233    err = -1;
234
235    while (!TIMER_EXPIRED(timer)) {
236	POLL();
237
238	err = SMBUS_READ(chan,slaveaddr,buf,1);
239	if (err == 0) break;
240	}
241
242    return err;
243}
244
245
246/*  *********************************************************************
247    *  sb1250_x1227eeprom_probe(drv,a,b,ptr)
248    *
249    *  Probe routine for this driver.  This routine creates the
250    *  local device context and attaches it to the driver list
251    *  within CFE.
252    *
253    *  Input parameters:
254    *  	   drv - driver handle
255    *  	   a,b - probe hints (longs)
256    *  	   ptr - probe hint (pointer)
257    *
258    *  Return value:
259    *  	   nothing
260    ********************************************************************* */
261
262static void sb1250_x1227eeprom_probe(cfe_driver_t *drv,
263				     unsigned long probe_a, unsigned long probe_b,
264				     void *probe_ptr)
265{
266    sb1250_x1227eeprom_t *softc;
267    char descr[80];
268
269    softc = (sb1250_x1227eeprom_t *) KMALLOC(sizeof(sb1250_x1227eeprom_t),0);
270
271    /*
272     * Probe_a is the SMBus channel number
273     * Probe_b is the SMBus device offset
274     * Probe_ptr is unused.
275     */
276
277    softc->smbus_channel = SMBUS_CHANNEL((int)probe_a);
278    softc->env_offset  = 0;
279    softc->env_size = X1227_EEPROM_SIZE;
280
281    xsprintf(descr,"%s on SMBus channel %d dev 0x%02X",
282	     drv->drv_description,probe_a,X1227_ARRAY_ADDRESS);
283    cfe_attach(drv,softc,NULL,descr);
284}
285
286
287
288/*  *********************************************************************
289    *  sb1250_x1227eeprom_open(ctx)
290    *
291    *  Open this device.  For the X1227, we do a quick test
292    *  read to be sure the device is out there.
293    *
294    *  Input parameters:
295    *  	   ctx - device context (can obtain our softc here)
296    *
297    *  Return value:
298    *  	   0 if ok
299    *  	   else error code
300    ********************************************************************* */
301
302static int sb1250_x1227eeprom_open(cfe_devctx_t *ctx)
303{
304    sb1250_x1227eeprom_t *softc = ctx->dev_softc;
305    int b;
306    int64_t timer;
307
308    /*
309     * Try to read byte 0 from the device.  If it does not
310     * respond, fail the open.  We may need to do this for
311     * up to 300ms in case the X1227 is busy wiggling its
312     * RESET line.
313     */
314
315    TIMER_SET(timer,300);
316    while (!TIMER_EXPIRED(timer)) {
317	POLL();
318	b = smbus_readrtc(softc->smbus_channel,
319			  X1227_ARRAY_ADDRESS,
320			  0);
321	if (b >= 0) break;		/* read is ok */
322	}
323
324    /*
325     * See if the watchdog is enabled.  If it is, turn it off.
326     */
327
328    b = smbus_readrtc(softc->smbus_channel,
329		      X1227_CCR_ADDRESS,
330		      X1227REG_BL);
331
332    if (b != (X1227REG_BL_WD1 | X1227REG_BL_WD0)) {
333
334	smbus_writertc(softc->smbus_channel,
335		       X1227_CCR_ADDRESS,
336		       X1227REG_SR,
337		       X1227REG_SR_WEL);
338
339	smbus_writertc(softc->smbus_channel,
340		       X1227_CCR_ADDRESS,
341		       X1227REG_SR,
342		       X1227REG_SR_WEL | X1227REG_SR_RWEL);
343
344	smbus_writertc(softc->smbus_channel,
345		       X1227_CCR_ADDRESS,
346		       X1227REG_BL,
347		       (X1227REG_BL_WD1 | X1227REG_BL_WD0));
348
349	smbus_writertc(softc->smbus_channel,
350		       X1227_CCR_ADDRESS,
351		       X1227REG_SR,
352		       0);
353	}
354
355
356
357    return (b < 0) ? -1 : 0;
358}
359
360/*  *********************************************************************
361    *  sb1250_x1227eeprom_read(ctx,buffer)
362    *
363    *  Read bytes from the device.
364    *
365    *  Input parameters:
366    *  	   ctx - device context (can obtain our softc here)
367    *  	   buffer - buffer descriptor (target buffer, length, offset)
368    *
369    *  Return value:
370    *  	   number of bytes read
371    *  	   -1 if an error occured
372    ********************************************************************* */
373
374static int sb1250_x1227eeprom_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
375{
376    sb1250_x1227eeprom_t *softc = ctx->dev_softc;
377    hsaddr_t bptr;
378    int blen;
379    int idx;
380    int b = 0;
381
382    bptr = buffer->buf_ptr;
383    blen = buffer->buf_length;
384
385    if ((buffer->buf_offset + blen) > X1227_EEPROM_SIZE) return -1;
386
387    idx = (int) buffer->buf_offset;
388
389    while (blen > 0) {
390	b = smbus_readrtc(softc->smbus_channel,
391			  X1227_ARRAY_ADDRESS,
392			  idx);
393	if (b < 0) break;
394	hs_write8(bptr,(unsigned char) b);
395	bptr++;
396	blen--;
397	idx++;
398	}
399
400    buffer->buf_retlen = bptr - buffer->buf_ptr;
401    return (b < 0) ? -1 : 0;
402}
403
404/*  *********************************************************************
405    *  sb1250_x1227eeprom_inpstat(ctx,inpstat)
406    *
407    *  Test input (read) status for the device
408    *
409    *  Input parameters:
410    *  	   ctx - device context (can obtain our softc here)
411    *  	   inpstat - input status descriptor to receive value
412    *
413    *  Return value:
414    *  	   0 if ok
415    *  	   -1 if an error occured
416    ********************************************************************* */
417
418static int sb1250_x1227eeprom_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
419{
420    inpstat->inp_status = 1;
421
422    return 0;
423}
424
425/*  *********************************************************************
426    *  sb1250_x1227eeprom_write(ctx,buffer)
427    *
428    *  Write bytes from the device.
429    *
430    *  Input parameters:
431    *  	   ctx - device context (can obtain our softc here)
432    *  	   buffer - buffer descriptor (target buffer, length, offset)
433    *
434    *  Return value:
435    *  	   number of bytes read
436    *  	   -1 if an error occured
437    ********************************************************************* */
438
439static int sb1250_x1227eeprom_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
440{
441    sb1250_x1227eeprom_t *softc = ctx->dev_softc;
442    hsaddr_t bptr;
443    int blen;
444    int idx;
445    int b = 0;
446
447    bptr = buffer->buf_ptr;
448    blen = buffer->buf_length;
449
450    if ((buffer->buf_offset + blen) > X1227_EEPROM_SIZE) return -1;
451
452    idx = (int) buffer->buf_offset;
453
454    smbus_writertc(softc->smbus_channel,
455		   X1227_CCR_ADDRESS,
456		   X1227REG_SR,
457		   X1227REG_SR_WEL);
458
459
460    while (blen > 0) {
461	b = hs_read8(bptr);
462	bptr++;
463	b = smbus_writertc(softc->smbus_channel,
464			   X1227_ARRAY_ADDRESS,
465			   idx,
466			   b);
467	if (b < 0) break;
468	blen--;
469	idx++;
470	}
471
472    smbus_writertc(softc->smbus_channel,
473		   X1227_CCR_ADDRESS,
474		   X1227REG_SR,
475		   0);
476
477    buffer->buf_retlen = bptr - buffer->buf_ptr;
478    return (b < 0) ? -1 : 0;
479}
480
481/*  *********************************************************************
482    *  sb1250_x1227eeprom_ioctl(ctx,buffer)
483    *
484    *  Perform miscellaneous I/O control operations on the device.
485    *
486    *  Input parameters:
487    *  	   ctx - device context (can obtain our softc here)
488    *  	   buffer - buffer descriptor (target buffer, length, offset)
489    *
490    *  Return value:
491    *  	   number of bytes read
492    *  	   -1 if an error occured
493    ********************************************************************* */
494
495static int sb1250_x1227eeprom_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
496{
497    sb1250_x1227eeprom_t *softc = ctx->dev_softc;
498    nvram_info_t info;
499
500    switch ((int)buffer->buf_ioctlcmd) {
501	case IOCTL_NVRAM_GETINFO:
502	    if (buffer->buf_length != sizeof(nvram_info_t)) return -1;
503	    info.nvram_offset = softc->env_offset;
504	    info.nvram_size =   softc->env_size;
505	    info.nvram_eraseflg = FALSE;
506	    buffer->buf_retlen = sizeof(nvram_info_t);
507	    hs_memcpy_to_hs(buffer->buf_ptr,&info,sizeof(info));
508	    return 0;
509	default:
510	    return -1;
511	}
512}
513
514/*  *********************************************************************
515    *  sb1250_x1227eeprom_close(ctx,buffer)
516    *
517    *  Close the device.
518    *
519    *  Input parameters:
520    *  	   ctx - device context (can obtain our softc here)
521    *
522    *  Return value:
523    *  	   0 if ok
524    *  	   -1 if an error occured
525    ********************************************************************* */
526
527static int sb1250_x1227eeprom_close(cfe_devctx_t *ctx)
528{
529    return 0;
530}
531
532
533