1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * BCM1250 (BCM1250 as PCI device) driver File: dev_bcm1250.c
6 *********************************************************************
8 * Copyright 2000,2001,2002,2003
9 * Broadcom Corporation. All rights reserved.
11 * This software is furnished under license and may be used and
12 * copied only in accordance with the following terms and
13 * conditions. Subject to these conditions, you may download,
14 * copy, install, use, modify and distribute modified or unmodified
15 * copies of this software in source and/or binary form. No title
16 * or ownership is transferred hereby.
18 * 1) Any source code used, modified or distributed must reproduce
19 * and retain this copyright notice and list of conditions
20 * as they appear in the source file.
22 * 2) No right is granted to use any trade name, trademark, or
23 * logo of Broadcom Corporation. The "Broadcom Corporation"
24 * name may not be used to endorse or promote products derived
25 * from this software without the prior written permission of
26 * Broadcom Corporation.
28 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
29 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
30 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
31 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
32 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
33 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
35 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
36 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
37 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
38 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
39 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
40 * THE POSSIBILITY OF SUCH DAMAGE.
41 ********************************************************************* */
47 #define _SB_MAKE64(x) ((uint64_t)(x))
50 #define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))
53 #include "lib_types.h"
54 #include "lib_physio.h"
55 #include "lib_malloc.h"
56 #include "lib_printf.h"
59 #include "cfe_error.h"
60 #include "cfe_device.h"
65 #include "bsp_config.h"
67 /* Note that PTR_TO_PHYS only works with 32-bit addresses */
68 #define PTR_TO_PHYS(x) (K0_TO_PHYS((uint32_t)(uintptr_t)(x)))
71 static void bcm1250_probe(cfe_driver_t
*drv
,
72 unsigned long probe_a
, unsigned long probe_b
,
75 static int bcm1250_open(cfe_devctx_t
*ctx
);
76 static int bcm1250_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
77 static int bcm1250_inpstat(cfe_devctx_t
*ctx
,iocb_inpstat_t
*inpstat
);
78 static int bcm1250_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
79 static int bcm1250_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
);
80 static int bcm1250_close(cfe_devctx_t
*ctx
);
82 const static cfe_devdisp_t bcm1250_dispatch
= {
93 const cfe_driver_t bcm1250drv
= {
102 typedef struct bcm1250_s
{
105 uint8_t irq
; /* interrupt mapping */
106 pcitag_t tag
; /* tag for configuration register */
108 int downloaded
; /* code has already been downloaded. */
114 * probe_a, probe_b and probe_ptr all unused
118 bcm1250_probe(cfe_driver_t
*drv
,
119 unsigned long probe_a
, unsigned long probe_b
,
128 if (pci_find_device(0x166d, 0x0001, index
, &tag
) != 0)
131 if (tag
!= 0x00000000) { /* don't configure ourselves */
136 softc
= (bcm1250_t
*) KMALLOC(sizeof(bcm1250_t
), 0);
138 xprintf("BCM1250: No memory to complete probe\n");
144 pci_map_mem(tag
, PCI_MAPREG(0), PCI_MATCH_BYTES
, &pa
);
145 xsprintf(descr
, "%s at 0x%X", drv
->drv_description
, (uint32_t)pa
);
146 softc
->mem_base
= pa
;
148 /* Map the CPU0 mailbox registers of the device 1250.
149 Note that our BAR2 space maps to its "alias" mailbox
150 registers. Set bit 3 for mbox_set; clear bit 3 for
151 reading. Address bits 15-4 are don't cares. */
152 pci_map_mem(tag
, PCI_MAPREG(2), PCI_MATCH_BYTES
, &pa
);
155 softc
->downloaded
= 0;
157 cfe_attach(drv
, softc
, NULL
, descr
);
167 elf_header (const uint8_t *hdr
)
169 return (hdr
[EI_MAG0
] == ELFMAG0
&&
170 hdr
[EI_MAG1
] == ELFMAG1
&&
171 hdr
[EI_MAG2
] == ELFMAG2
&&
172 hdr
[EI_MAG3
] == ELFMAG3
);
176 #include "cfe_timer.h"
179 uint32_t addr
; /* source address, in device's PCI space */
180 uint32_t len
; /* length of this chunk */
184 #define MBOX_SET_BIT 0x8
186 extern void download_start(void), download_end(void);
189 bcm1250_open(cfe_devctx_t
*ctx
)
191 bcm1250_t
*softc
= ctx
->dev_softc
;
192 physaddr_t cmd_p
= softc
->mailbox
+ 4;
194 if (softc
->downloaded
) {
195 xprintf("bcm1250_open: Warning: Device previously downloaded\n");
196 softc
->downloaded
= 0;
199 if (phys_read32(cmd_p
) != 0) {
200 xprintf("bcm1250_open: Device not in initial state\n");
208 bcm1250_read(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
214 bcm1250_inpstat(cfe_devctx_t
*ctx
, iocb_inpstat_t
*inpstat
)
220 bcm1250_write(cfe_devctx_t
*ctx
, iocb_buffer_t
*buffer
)
222 bcm1250_t
*softc
= ctx
->dev_softc
;
223 physaddr_t arg_p
= softc
->mailbox
+ 0;
224 physaddr_t cmd_p
= softc
->mailbox
+ 4;
230 /* Note: This code assumes that PTR_TO_PHYS gives a PCI memory space
231 address that is accessible via our BAR4 or BAR5 */
233 code
.addr
= PTR_TO_PHYS((uint8_t *)buffer
->buf_ptr
);
234 code
.len
= buffer
->buf_length
;
236 cmd
= 0x1; /* load */
237 if (!elf_header((uint8_t *)buffer
->buf_ptr
)) {
238 /* No recognizable elf seal, so assume compressed. */
242 phys_write32(arg_p
| MBOX_SET_BIT
, PTR_TO_PHYS(&code
));
243 phys_write32(cmd_p
| MBOX_SET_BIT
, cmd
); /* load */
245 /* Wait for handshake */
247 res
= CFE_ERR_TIMEOUT
;
248 TIMER_SET(timer
, 5*CFE_HZ
);
249 while (!TIMER_EXPIRED(timer
)) {
250 if ((phys_read32(cmd_p
) & 0x3) == 0) {
251 softc
->downloaded
= 1;
252 buffer
->buf_retlen
= 0;
253 /* Note that the result code need not be translated only
254 because we are assuming a CFE in the device that is
255 compatible with us. */
256 res
= (int)phys_read32(arg_p
);
266 bcm1250_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
272 bcm1250_close(cfe_devctx_t
*ctx
)