1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Microchip 24lc128 EEPROM driver File: dev_sb1250_24lc128eeprom.c
6 * This module contains a CFE driver for a Microchip 24LC128 EEPROM
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 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_printf.h"
54 #include "cfe_device.h"
55 #include "cfe_ioctl.h"
56 #include "cfe_timer.h"
58 #include "sb1250_defs.h"
59 #include "sb1250_regs.h"
60 #include "sb1250_smbus.h"
63 /* *********************************************************************
64 * Forward Declarations
65 ********************************************************************* */
67 static void sb1250_24lc128eeprom_probe(cfe_driver_t
*drv
,
68 unsigned long probe_a
, unsigned long probe_b
,
72 static int sb1250_24lc128eeprom_open(cfe_devctx_t
*ctx
);
73 static int sb1250_24lc128eeprom_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
74 static int sb1250_24lc128eeprom_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
75 static int sb1250_24lc128eeprom_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
76 static int sb1250_24lc128eeprom_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
77 static int sb1250_24lc128eeprom_close(cfe_devctx_t
*ctx
);
79 /* *********************************************************************
81 ********************************************************************* */
83 #define M24LC128_EEPROM_SIZE 16384
85 const static cfe_devdisp_t sb1250_24lc128eeprom_dispatch
= {
86 sb1250_24lc128eeprom_open
,
87 sb1250_24lc128eeprom_read
,
88 sb1250_24lc128eeprom_inpstat
,
89 sb1250_24lc128eeprom_write
,
90 sb1250_24lc128eeprom_ioctl
,
91 sb1250_24lc128eeprom_close
,
96 const cfe_driver_t sb1250_24lc128eeprom
= {
97 "Microchip 24LC128 EEPROM",
100 &sb1250_24lc128eeprom_dispatch
,
101 sb1250_24lc128eeprom_probe
104 typedef struct sb1250_24lc128eeprom_s
{
109 unsigned char data
[M24LC128_EEPROM_SIZE
];
110 } sb1250_24lc128eeprom_t
;
113 /* *********************************************************************
116 * Initialize the specified SMBus channel
119 * chan - channel # (0 or 1)
123 ********************************************************************* */
125 static void smbus_init(int chan
)
129 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_FREQ
));
131 SBWRITECSR(reg
,K_SMB_FREQ_100KHZ
);
133 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CONTROL
));
135 SBWRITECSR(reg
,0); /* not in direct mode, no interrupts, will poll */
139 /* *********************************************************************
140 * smbus_waitready(chan)
142 * Wait until the SMBus channel is ready. We simply poll
143 * the busy bit until it clears.
146 * chan - channel (0 or 1)
150 ********************************************************************* */
151 static int smbus_waitready(int chan
)
156 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_STATUS
));
159 status
= SBREADCSR(reg
);
160 if (status
& M_SMB_BUSY
) continue;
164 if (status
& M_SMB_ERROR
) {
166 SBWRITECSR(reg
,(status
& M_SMB_ERROR
));
172 /* *********************************************************************
173 * smbus_readbyte(chan,slaveaddr,devaddr)
175 * Read a byte from the chip. The 'slaveaddr' parameter determines
176 * whether we're reading from the RTC section or the EEPROM section.
179 * chan - SMBus channel
180 * slaveaddr - SMBus slave address
181 * devaddr - byte with in the device to read
186 ********************************************************************* */
188 static int smbus_readbyte(int chan
,int slaveaddr
,int devaddr
)
194 * Make sure the bus is idle (probably should
198 if (smbus_waitready(chan
) < 0) return -1;
201 * Write the device address to the controller. There are two
202 * parts, the high part goes in the "CMD" field, and the
203 * low part is the data field.
206 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
207 SBWRITECSR(reg
,((devaddr
>> 8) & 0x3F));
210 * Write the data to the controller
213 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
214 SBWRITECSR(reg
,((devaddr
& 0xFF) & 0xFF));
220 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
221 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR2BYTE
) | slaveaddr
);
227 err
= smbus_waitready(chan
);
228 if (err
< 0) return err
;
234 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_RD1BYTE
) | slaveaddr
);
236 err
= smbus_waitready(chan
);
237 if (err
< 0) return err
;
239 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
240 err
= SBREADCSR(reg
);
245 /* *********************************************************************
246 * smbus_writebyte(chan,slaveaddr,devaddr,b)
248 * write a byte from the chip. The 'slaveaddr' parameter determines
249 * whethe we're writing to the RTC section or the EEPROM section.
252 * chan - SMBus channel
253 * slaveaddr - SMBus slave address
254 * devaddr - byte with in the device to read
260 ********************************************************************* */
263 static int smbus_writebyte(int chan
,int slaveaddr
,int devaddr
,int b
)
270 * Make sure the bus is idle (probably should
274 if (smbus_waitready(chan
) < 0) return -1;
277 * Write the device address to the controller. There are two
278 * parts, the high part goes in the "CMD" field, and the
279 * low part is the data field.
282 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_CMD
));
283 SBWRITECSR(reg
,((devaddr
>> 8) & 0x3F));
286 * Write the data to the controller
289 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_DATA
));
290 SBWRITECSR(reg
,((devaddr
& 0xFF) | ((b
& 0xFF) << 8)));
293 * Start the command. Keep pounding on the device until it
294 * submits or the timer expires, whichever comes first. The
295 * datasheet says writes can take up to 10ms, so we'll give it 500.
298 reg
= PHYS_TO_K1(A_SMB_REGISTER(chan
,R_SMB_START
));
299 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_WR3BYTE
) | slaveaddr
);
302 * Wait till the SMBus interface is done
305 err
= smbus_waitready(chan
);
306 if (err
< 0) return err
;
309 * Pound on the device with a quick command (R/W=0)
310 * to poll for the write complete. See sect 7.0 of the
317 while (!TIMER_EXPIRED(timer
)) {
320 SBWRITECSR(reg
,V_SMB_TT(K_SMB_TT_QUICKCMD
) | slaveaddr
);
322 err
= smbus_waitready(chan
);
330 /* *********************************************************************
331 * sb1250_24lc128eeprom_probe(drv,a,b,ptr)
333 * Probe routine for this driver. This routine creates the
334 * local device context and attaches it to the driver list
338 * drv - driver handle
339 * a,b - probe hints (longs)
340 * ptr - probe hint (pointer)
344 ********************************************************************* */
346 static void sb1250_24lc128eeprom_probe(cfe_driver_t
*drv
,
347 unsigned long probe_a
, unsigned long probe_b
,
350 sb1250_24lc128eeprom_t
*softc
;
353 softc
= (sb1250_24lc128eeprom_t
*) KMALLOC(sizeof(sb1250_24lc128eeprom_t
),0);
356 * Probe_a is the SMBus channel number
357 * Probe_b is the SMBus device offset
358 * Probe_ptr is unused.
361 softc
->smbus_channel
= (int)probe_a
;
362 softc
->smbus_address
= (int)probe_b
;
363 softc
->env_offset
= 0;
364 softc
->env_size
= M24LC128_EEPROM_SIZE
;
366 xsprintf(descr
,"%s on SMBus channel %d dev 0x%02X",
367 drv
->drv_description
,(int)probe_a
,(int)probe_b
);
368 cfe_attach(drv
,softc
,NULL
,descr
);
373 /* *********************************************************************
374 * sb1250_24lc128eeprom_open(ctx)
376 * Open this device. For the X1240, we do a quick test
377 * read to be sure the device is out there.
380 * ctx - device context (can obtain our softc here)
385 ********************************************************************* */
387 static int sb1250_24lc128eeprom_open(cfe_devctx_t
*ctx
)
389 sb1250_24lc128eeprom_t
*softc
= ctx
->dev_softc
;
392 smbus_init(softc
->smbus_channel
);
394 b
= smbus_readbyte(softc
->smbus_channel
,
395 softc
->smbus_address
,
398 return (b
< 0) ? -1 : 0;
401 /* *********************************************************************
402 * sb1250_24lc128eeprom_read(ctx,buffer)
404 * Read bytes from the device.
407 * ctx - device context (can obtain our softc here)
408 * buffer - buffer descriptor (target buffer, length, offset)
411 * number of bytes read
412 * -1 if an error occured
413 ********************************************************************* */
415 static int sb1250_24lc128eeprom_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
417 sb1250_24lc128eeprom_t
*softc
= ctx
->dev_softc
;
423 bptr
= buffer
->buf_ptr
;
424 blen
= buffer
->buf_length
;
426 if ((buffer
->buf_offset
+ blen
) > M24LC128_EEPROM_SIZE
) return -1;
428 idx
= (int) buffer
->buf_offset
;
431 b
= smbus_readbyte(softc
->smbus_channel
,
432 softc
->smbus_address
,
435 *bptr
++ = (unsigned char) b
;
440 buffer
->buf_retlen
= bptr
- buffer
->buf_ptr
;
441 return (b
< 0) ? -1 : 0;
444 /* *********************************************************************
445 * sb1250_24lc128eeprom_inpstat(ctx,inpstat)
447 * Test input (read) status for the device
450 * ctx - device context (can obtain our softc here)
451 * inpstat - input status descriptor to receive value
455 * -1 if an error occured
456 ********************************************************************* */
458 static int sb1250_24lc128eeprom_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
)
460 inpstat
->inp_status
= 1;
465 /* *********************************************************************
466 * sb1250_24lc128eeprom_write(ctx,buffer)
468 * Write bytes from the device.
471 * ctx - device context (can obtain our softc here)
472 * buffer - buffer descriptor (target buffer, length, offset)
475 * number of bytes read
476 * -1 if an error occured
477 ********************************************************************* */
479 static int sb1250_24lc128eeprom_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
481 sb1250_24lc128eeprom_t
*softc
= ctx
->dev_softc
;
487 bptr
= buffer
->buf_ptr
;
488 blen
= buffer
->buf_length
;
490 if ((buffer
->buf_offset
+ blen
) > M24LC128_EEPROM_SIZE
) return -1;
492 idx
= (int) buffer
->buf_offset
;
496 b
= smbus_writebyte(softc
->smbus_channel
,
497 softc
->smbus_address
,
505 buffer
->buf_retlen
= bptr
- buffer
->buf_ptr
;
506 return (b
< 0) ? -1 : 0;
509 /* *********************************************************************
510 * sb1250_24lc128eeprom_ioctl(ctx,buffer)
512 * Perform miscellaneous I/O control operations on the device.
515 * ctx - device context (can obtain our softc here)
516 * buffer - buffer descriptor (target buffer, length, offset)
519 * number of bytes read
520 * -1 if an error occured
521 ********************************************************************* */
523 static int sb1250_24lc128eeprom_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
525 sb1250_24lc128eeprom_t
*softc
= ctx
->dev_softc
;
528 switch ((int)buffer
->buf_ioctlcmd
) {
529 case IOCTL_NVRAM_GETINFO
:
530 info
= (nvram_info_t
*) buffer
->buf_ptr
;
531 if (buffer
->buf_length
!= sizeof(nvram_info_t
)) return -1;
532 info
->nvram_offset
= softc
->env_offset
;
533 info
->nvram_size
= softc
->env_size
;
534 info
->nvram_eraseflg
= FALSE
;
535 buffer
->buf_retlen
= sizeof(nvram_info_t
);
542 /* *********************************************************************
543 * sb1250_24lc128eeprom_close(ctx,buffer)
548 * ctx - device context (can obtain our softc here)
552 * -1 if an error occured
553 ********************************************************************* */
555 static int sb1250_24lc128eeprom_close(cfe_devctx_t
*ctx
)