1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * SB1250 PCI host driver File: dev_sb1250_pcihost.c
6 * This is a simple driver to support device-mode downloading via
7 * PCI from the host system.
9 *********************************************************************
11 * Copyright 2000,2001,2002,2003
12 * Broadcom Corporation. All rights reserved.
14 * This software is furnished under license and may be used and
15 * copied only in accordance with the following terms and
16 * conditions. Subject to these conditions, you may download,
17 * copy, install, use, modify and distribute modified or unmodified
18 * copies of this software in source and/or binary form. No title
19 * or ownership is transferred hereby.
21 * 1) Any source code used, modified or distributed must reproduce
22 * and retain this copyright notice and list of conditions
23 * as they appear in the source file.
25 * 2) No right is granted to use any trade name, trademark, or
26 * logo of Broadcom Corporation. The "Broadcom Corporation"
27 * name may not be used to endorse or promote products derived
28 * from this software without the prior written permission of
29 * Broadcom Corporation.
31 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
33 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
34 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
35 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
36 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
37 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
39 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
40 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
41 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
42 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
43 * THE POSSIBILITY OF SUCH DAMAGE.
44 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_physio.h"
51 #include "lib_malloc.h"
52 #include "lib_printf.h"
54 #include "cfe_device.h"
55 #include "cfe_ioctl.h"
56 #include "cfe_timer.h"
57 #include "sb1250_defs.h"
58 #include "sb1250_regs.h"
60 #include "bsp_config.h"
62 static void sb1250_hostpci_probe(cfe_driver_t
*drv
,
63 unsigned long probe_a
, unsigned long probe_b
,
67 static int sb1250_host_open(cfe_devctx_t
*ctx
);
68 static int sb1250_host_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
);
69 static int sb1250_host_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
);
70 static int sb1250_host_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
);
71 static int sb1250_host_ioctl(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
);
72 static int sb1250_host_close(cfe_devctx_t
*ctx
);
74 const static cfe_devdisp_t sb1250_host_dispatch
= {
85 const cfe_driver_t sb1250_pcihost
= {
89 &sb1250_host_dispatch
,
93 typedef struct sb1250_host_s
{
100 sb1250_hostpci_probe(cfe_driver_t
*drv
,
101 unsigned long probe_a
, unsigned long probe_b
,
104 sb1250_host_t
*softc
;
107 /* probe_a, probe_b, and probe_ptr are unused. */
109 softc
= (sb1250_host_t
*) KMALLOC(sizeof(sb1250_host_t
), 0);
115 xsprintf(descr
,"%s", drv
->drv_description
);
116 cfe_attach(drv
,softc
,NULL
,descr
);
121 #define K1_PTR64(pa) ((uint64_t *)(PHYS_TO_K1(pa)))
122 #define PCI_TO_CPU(addr) \
123 ((physaddr_t)((uint64_t)(addr) | 0xf800000000))
126 sb1250_host_open(cfe_devctx_t
*ctx
)
128 sb1250_host_t
*softc
= ctx
->dev_softc
;
129 uint64_t *mbox_p
= K1_PTR64 (A_IMR_REGISTER(0, R_IMR_MAILBOX_CPU
));
130 uint32_t *cmd_p
= ((uint32_t *)mbox_p
) + 1;
131 uint32_t *arg_p
= ((uint32_t *)mbox_p
) + 0;
132 physaddr_t desc_addr
, data_addr
; /* in PCI full-access space */
135 /* The caller has probably done this already. */
136 while ((*cmd_p
& 0x3) == 0) {
137 POLL(); /* timeout might be good */
140 desc_addr
= PCI_TO_CPU(*arg_p
);
141 data_addr
= phys_read32(desc_addr
);
142 softc
->pci_base
= PCI_TO_CPU(data_addr
);
143 softc
->limit
= phys_read32(desc_addr
+ 4);
149 sb1250_host_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
151 sb1250_host_t
*softc
= ctx
->dev_softc
;
155 /* For random-access devices, there is an implicit seek with every
156 read. We maintain a current offset in case a sequential mode is
158 boffset
= (uint32_t)buffer
->buf_offset
;
160 if (boffset
>= softc
->limit
) {
162 softc
->offset
= softc
->limit
;
169 src
= softc
->pci_base
+ boffset
;
170 bptr
= buffer
->buf_ptr
;
171 blen
= buffer
->buf_length
;
172 if (blen
> softc
->limit
- boffset
)
173 blen
= softc
->limit
- boffset
;
175 /* copy the bytes (better to use the data mover?) */
176 for (i
= 0; i
< blen
; i
++) {
182 softc
->offset
= boffset
;
185 buffer
->buf_retlen
= blen
;
191 sb1250_host_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
193 sb1250_host_t
*softc
= ctx
->dev_softc
;
195 return softc
->pci_base
!= 0 && softc
->offset
< softc
->limit
;
199 sb1250_host_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
201 /* This is a readonly device */
206 sb1250_host_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
208 /* None needed (for now?) */
213 sb1250_host_close(cfe_devctx_t
*ctx
)
215 /* Put any needed cleanup here. */