implemented hook_interrupt() in PCI code

enabled PCI interrupts
ohci seems to damage something in PCI config -> PCI device enumeration 
does not top with latest device
networking in EmuTOS lost (probably a result of PCI interrupt
implementation)
This commit is contained in:
Markus Fröschle
2014-10-05 17:50:15 +00:00
parent 2ee1ddf58d
commit ab7371532f
21 changed files with 1842 additions and 1577 deletions

View File

@@ -28,6 +28,7 @@
#include "cache.h"
#include "usb.h"
#include "ehci.h"
#include "pci.h"
#define DBG_EHCI
#ifdef DBG_EHCI
@@ -124,6 +125,15 @@ struct pci_device_id ehci_usb_pci_table[] =
0,
0
}, /* NEC PCI OHCI module ids */
{
PCI_VENDOR_ID_NEC,
PCI_DEVICE_ID_NEC_USB_3,
PCI_ANY_ID,
PCI_ANY_ID,
PCI_CLASS_SERIAL_USB_EHCI,
0,
0
},
{
PCI_VENDOR_ID_PHILIPS,
PCI_DEVICE_ID_PHILIPS_ISP1561_2,

View File

@@ -43,17 +43,18 @@
*/
#include "wait.h" /* for wait routines */
#include "wait.h" /* for wait_ms routines */
#include "bas_printf.h"
#include "bas_string.h" /* for memset() */
#include "pci.h"
#include "interrupts.h"
#undef OHCI_USE_NPS /* force NoPowerSwitching mode */
#undef OHCI_VERBOSE_DEBUG /* not always helpful */
#undef OHCI_FILL_TRACE
//#define DEBUG_OHCI
#define DEBUG_OHCI
#ifdef DEBUG_OHCI
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else
@@ -126,6 +127,15 @@ struct pci_device_id ohci_usb_pci_table[] =
0,
0
}, /* NEC PCI OHCI module ids */
{
PCI_VENDOR_ID_NEC,
PCI_DEVICE_ID_NEC_USB_A,
PCI_ANY_ID,
PCI_ANY_ID,
PCI_CLASS_SERIAL_USB_OHCI,
0,
0
}, /* NEC PCI OHCI module ids */
{
PCI_VENDOR_ID_PHILIPS,
PCI_DEVICE_ID_PHILIPS_ISP1561,
@@ -148,7 +158,7 @@ struct pci_device_id ohci_usb_pci_table[] =
};
/* global ohci_t */
static ohci_t gohci[2];
static ohci_t gohci[10];
int ohci_inited;
static inline uint32_t roothub_a(ohci_t *ohci) { return readl(&ohci->regs->roothub.a); }
@@ -157,7 +167,6 @@ static inline uint32_t roothub_status(ohci_t *ohci) { return readl(&ohci->regs->
static inline uint32_t roothub_portstatus(ohci_t *ohci, int i) { return readl(&ohci->regs->roothub.portstatus[i]); }
/* forward declaration */
static void flush_data_cache(ohci_t *ohci);
static int hc_interrupt(ohci_t *ohci);
static void td_submit_job(ohci_t *ohci, struct usb_device *dev, uint32_t pipe,
void *buffer, int transfer_len, struct devrequest *setup,
@@ -550,10 +559,13 @@ static int sohci_submit_job(ohci_t *ohci, urb_priv_t *urb, struct devrequest *se
/* link the ed into a chain if is not already */
if (ed->state != ED_OPER)
{
ep_link(ohci, ed);
}
/* fill the TDs and link it to the ed */
td_submit_job(ohci, dev, pipe, buffer, transfer_len, setup, purb_priv, interval);
return 0;
}
@@ -571,7 +583,7 @@ static inline int sohci_return_job(ohci_t *ohci, urb_priv_t *urb)
readl(&regs->intrenable); /* PCI posting flush */
/* call interrupt device routine */
// dbg("irq_handle device %d", urb->dev->devnum);
dbg("irq_handle device %d", urb->dev->devnum);
urb->dev->irq_handle(urb->dev);
writel(OHCI_INTR_WDH, &regs->intrdisable);
@@ -1374,7 +1386,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
#else
if (ohci->irq)
{
wait(10);
wait_ms(10);
}
#endif
@@ -1462,7 +1474,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
OK(0);
case (RH_PORT_POWER):
WR_RH_PORTSTAT(RH_PS_PPS);
wait(100);
wait_ms(100);
OK(0);
case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/
if (RD_RH_PORTSTAT & RH_PS_CCS)
@@ -1562,7 +1574,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
#else
if (ohci->irq)
{
wait(10);
wait_ms(10);
}
#endif
@@ -1582,7 +1594,7 @@ static int ohci_submit_rh_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pip
if (ohci->irq)
{
wait(10);
wait_ms(10);
}
#endif
@@ -1629,7 +1641,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
#else
if (ohci->irq)
{
wait(10);
wait_ms(10);
}
#endif
@@ -1646,7 +1658,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
}
#if 0
wait(10);
wait_ms(10);
/* ohci_dump_status(ohci); */
#endif
@@ -1663,7 +1675,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
timeout = 1000;
}
/* wait for it to complete */
/* wait_ms for it to complete */
while (ohci->irq)
{
/* check whether the controller is done */
@@ -1702,13 +1714,13 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
if (--timeout)
{
wait(10);
wait_ms(10);
if (!urb->finished)
xprintf("*");
xprintf("*\r\n");
}
else
{
err("OHCI usb-%s-%c CTL:TIMEOUT", ohci->slot_name, (char)ohci->controller + '0');
err("OHCI usb-%s-%c CTL:TIMEOUT", ohci->slot_name, (char) ohci->controller + '0');
dbg("submit_common_msg: TO status %x\r\n", stat);
urb->finished = 1;
stat = USB_ST_CRC_ERR;
@@ -1722,7 +1734,7 @@ static int submit_common_msg(ohci_t *ohci, struct usb_device *dev, uint32_t pipe
pkt_print(ohci, urb, dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe));
#else
if (ohci->irq)
wait(10);
wait_ms(10);
#endif
/* free TDs in urb_priv */
if (!usb_pipeint(pipe))
@@ -1749,7 +1761,7 @@ int ohci_submit_control_msg(struct usb_device *dev, uint32_t pipe, void *buffer,
#else
if (ohci->irq)
{
wait(10);
wait_ms(10);
}
#endif
@@ -1796,7 +1808,7 @@ static int hc_reset(ohci_t *ohci)
* Some multi-function controllers (e.g. ISP1562) allow root hub
* resetting via EHCI registers only.
*/
short index = 0;
int index = 0;
long handle;
do
@@ -1831,7 +1843,7 @@ static int hc_reset(ohci_t *ohci)
err("USB RootHub reset timed out!\r\n");
break;
}
wait(1);
wait_ms(1);
}
}
}
@@ -1845,6 +1857,7 @@ static int hc_reset(ohci_t *ohci)
}
while (handle >= 0);
}
if ((ohci->controller == 0) && (ohci->ent->vendor == PCI_VENDOR_ID_NEC)
&& (ohci->ent->device == PCI_DEVICE_ID_NEC_USB))
{
@@ -1853,26 +1866,28 @@ static int hc_reset(ohci_t *ohci)
{
dbg("USB OHCI set 48MHz clock\r\n");
pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci
wait(10);
wait_us(1);
}
//else
#else
{
pci_write_config_longword(ohci->handle, 0xE4, pci_read_config_longword(ohci->handle, 0xE4) | 0x01); // disable ehci
wait(10);
wait_us(1);
}
#endif
}
dbg("control: %x\r\n", readl(&ohci->regs->control));
if (readl(&ohci->regs->control) & OHCI_CTRL_IR)
{
/* SMM owns the HC */
writel(OHCI_OCR, &ohci->regs->cmdstatus);/* request ownership */
writel(OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */
err("USB HC TakeOver from SMM");
while (readl(&ohci->regs->control) & OHCI_CTRL_IR)
{
wait(10);
wait_us(10);
if (--smm_timeout == 0)
{
err("USB HC TakeOver failed!");
@@ -1884,17 +1899,12 @@ static int hc_reset(ohci_t *ohci)
/* Disable HC interrupts */
writel(OHCI_INTR_MIE, &ohci->regs->intrdisable);
#ifdef DEBUG_OHCI
ohci_dump_status(ohci);
#endif /* DEBUG_OHCI */
dbg("USB OHCI HC reset_hc usb-%s-%c: ctrl = 0x%X\r\n", ohci->slot_name,
(char) ohci->controller + '0', readl(&ohci->regs->control));
/* Reset USB (needed by some controllers) */
ohci->hc_control = 0;
writel(ohci->hc_control, &ohci->regs->control);
wait(50);
/* HC Reset requires max 10 us delay */
writel(OHCI_HCR, &ohci->regs->cmdstatus);
@@ -1908,12 +1918,11 @@ static int hc_reset(ohci_t *ohci)
#endif /* DEBUG_OHCI */
return -1;
}
wait(10);
wait_us(1);
}
return 0;
}
/*-------------------------------------------------------------------------*/
/*
* Start an OHCI controller, set the BUS operational
@@ -1935,7 +1944,7 @@ static int hc_start(ohci_t *ohci)
writel(0, &ohci->regs->ed_controlhead);
writel(0, &ohci->regs->ed_bulkhead);
writel((uint32_t) ohci->hcca - ohci->dma_offset, &ohci->regs->hcca); /* a reset clears this */
writel((uint32_t) ohci->hcca, &ohci->regs->hcca); /* a reset clears this */
fminterval = 0x2edf;
writel((fminterval * 9) / 10, &ohci->regs->periodicstart);
@@ -1951,7 +1960,8 @@ static int hc_start(ohci_t *ohci)
/* disable all interrupts */
mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD |
OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | OHCI_INTR_OC | OHCI_INTR_MIE);
OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC |
OHCI_INTR_OC | OHCI_INTR_MIE);
writel(mask, &ohci->regs->intrdisable);
/* clear all interrupts */
@@ -1970,9 +1980,12 @@ static int hc_start(ohci_t *ohci)
#endif /* OHCI_USE_NPS */
/* POTPGT delay is bits 24-31, in 2 ms units. */
#define mdelay(n) ({unsigned long msec = (n); while (msec--) wait(1); })
#define mdelay(n) ({unsigned long msec = (n); while (msec--) wait_ms(1); })
dbg("wait_ms(0x%x)\r\n", (ohci->ndp >> 23) & 0x1fe);
mdelay((ohci->ndp >> 23) & 0x1fe);
ohci->ndp &= RH_A_NDP;
// ohci->ndp &= RH_A_NDP;
/* connect the virtual root hub */
ohci->rh.devnum = 0;
@@ -1981,33 +1994,7 @@ static int hc_start(ohci_t *ohci)
}
#ifdef CONFIG_USB_INTERRUPT_POLLING
/* Poll USB interrupt. */
void ohci_usb_event_poll(int interrupt)
{
if (ohci_inited)
{
int i;
for (i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
{
ohci_t *ohci = &gohci[i];
if (!ohci->handle || ohci->disabled)
continue;
else
{
flush_data_cache(ohci);
if (interrupt)
ohci->irq = 0;
hc_interrupt(ohci);
if (interrupt)
ohci->irq = -1;
}
}
}
}
#endif /* CONFIG_USB_INTERRUPT_POLLING */
/*
* an interrupt happens
@@ -2018,6 +2005,7 @@ static int hc_interrupt(ohci_t *ohci)
int ints;
int stat = -1;
dbg("\r\n");
if ((ohci->hcca->done_head != 0) && !(swpl(ohci->hcca->done_head) & 0x01))
{
ints = OHCI_INTR_WDH;
@@ -2050,18 +2038,6 @@ static int hc_interrupt(ohci_t *ohci)
if (ints & OHCI_INTR_RHSC) /* root hub status change */
{
#ifdef USB_POLL_HUB
if ((queue_poll_hub != NULL) && (rh_check_port_status(ohci) >= 0))
{
if (ohci->irq)
xQueueAltSend(queue_poll_hub, (void *)&ohci->usbnum, 0);
else
{
portBASE_TYPE xNeedSwitch = pdFALSE;
xNeedSwitch = xQueueSendFromISR(queue_poll_hub, &ohci->usbnum, xNeedSwitch);
} /* to fix xNeedSwitch usage */
}
#endif /* USB_POLL_HUB */
stat = 0xff;
}
@@ -2085,7 +2061,7 @@ static int hc_interrupt(ohci_t *ohci)
#else
if (ohci->irq)
{
wait(1);
wait_ms(1);
}
#endif
/* HC Reset */
@@ -2099,7 +2075,7 @@ static int hc_interrupt(ohci_t *ohci)
{
if (ohci->irq)
{
wait(1);
wait_ms(1);
}
writel(OHCI_INTR_WDH, &regs->intrdisable);
@@ -2122,29 +2098,26 @@ static int hc_interrupt(ohci_t *ohci)
{
unsigned int frame = swpw(ohci->hcca->frame_no) & 1;
if (ohci->irq)
wait(1);
wait_ms(1);
writel(OHCI_INTR_SF, &regs->intrdisable);
if (ohci->ed_rm_list[frame] != NULL)
{
writel(OHCI_INTR_SF, &regs->intrenable);
}
stat = 0xff;
}
writel(ints, &regs->intrstatus);
return stat;
}
#ifndef CONFIG_USB_INTERRUPT_POLLING
static int handle_usb_interrupt(ohci_t *ohci)
{
if (!ohci->irq_enabled)
if(!ohci->irq_enabled)
{
dbg("no interrupts enabled\r\n");
return 0;
}
// flush_data_cache(ohci); no need for that
ohci->irq = 0;
ohci->stat_irq = hc_interrupt(ohci);
ohci->irq = -1;
@@ -2157,11 +2130,14 @@ void ohci_usb_enable_interrupt(int enable)
int i;
dbg("usb_enable_interrupt(%d)", enable);
for (i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
for(i = 0; i < (sizeof(gohci) / sizeof(ohci_t)); i++)
{
ohci_t *ohci = &gohci[i];
if (!ohci->handle)
if(!ohci->handle)
{
continue;
}
ohci->irq_enabled = enable;
if (enable)
writel(OHCI_INTR_MIE, &ohci->regs->intrenable);
@@ -2170,15 +2146,15 @@ void ohci_usb_enable_interrupt(int enable)
}
}
#endif /* !CONFIG_USB_INTERRUPT_POLLING */
/* De-allocate all resources.. */
static void hc_release_ohci(ohci_t *ohci)
{
dbg("USB HC release OHCI usb-%s-%c", ohci->slot_name, (char)ohci->controller + '0');
dbg("USB HC release OHCI usb-%s-%c", ohci->slot_name, (char) ohci->controller + '0');
if (!ohci->disabled)
{
hc_reset(ohci);
}
}
static void hc_free_buffers(ohci_t *ohci)
@@ -2206,7 +2182,7 @@ static void hc_free_buffers(ohci_t *ohci)
int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void **priv)
{
uint32_t usb_base_addr = 0xFFFFFFFF;
ohci_t *ohci = &gohci[PCI_FUNCTION_FROM_HANDLE(handle) & 1];
ohci_t *ohci = &gohci[pci_handle2index(handle)];
struct pci_rd *pci_rsc_desc = pci_get_resource(handle); /* USB OHCI */
if (handle && (ent != NULL))
@@ -2372,9 +2348,11 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
#ifdef DEBUG_OHCI
ohci_dump(ohci, 1);
#endif
pci_hook_interrupt(handle, handle_usb_interrupt, ohci);
pci_hook_interrupt(handle, (pci_interrupt_handler) handle_usb_interrupt, ohci);
if (priv != NULL)
{
*priv = (void *) ohci;
}
ohci_inited = 1;

256
pci/pci.c
View File

@@ -33,12 +33,13 @@
#include "interrupts.h"
#include "wait.h"
#define DEBUG_PCI
//#define DEBUG_PCI
#ifdef DEBUG_PCI
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
#else
#define dbg(format, arg...) do { ; } while (0)
#endif /* DEBUG_PCI */
#define err(format, arg...) do { xprintf("ERROR: %s(): " format, __FUNCTION__, ##arg); } while (0)
#define pci_config_wait() do { __asm__ __volatile("tpf" ::: "memory"); } while (0)
@@ -122,36 +123,41 @@ static inline __attribute__((aligned(16))) void chip_errata_135(void)
*/
__asm__ __volatile(
" .extern __MBAR\n\t"
" clr.l d0\n\t"
" move.l d0,__MBAR+0xF0C\n\t" /* Must use direct addressing. write to EPORT module */
" .extern __MBAR \n\t"
" clr.l d0 \n\t"
" move.l d0,__MBAR+0xF0C \n\t" /* Must use direct addressing. write to EPORT module */
/* xlbus -> slavebus -> eport, writing '0' to register */
/* has no effect */
" rts\n\t"
" tpf.l #0x0\n\t"
" tpf.l #0x0\n\t"
" tpf.l #0x0\n\t"
" tpf.l #0x0\n\t"
" tpf.l #0x0\n\t"
" rts \n\t"
" tpf.l #0x0 \n\t"
" tpf.l #0x0 \n\t"
" tpf.l #0x0 \n\t"
" tpf.l #0x0 \n\t"
" tpf.l #0x0 \n\t"
::: "memory");
}
__attribute__((interrupt)) void pci_arb_interrupt(void)
static inline void chip_errata_055(int32_t handle)
{
dbg("XLBARB slave error interrupt\r\n");
MCF_XLB_XARB_SR |= ~MCF_XLB_XARB_SR_SEA;
}
uint32_t dummy;
__attribute__((interrupt)) void xlb_pci_interrupt(void)
{
dbg("XLBPCI interrupt\r\n");
}
return; /* test */
__attribute__((interrupt)) void pci_interrupt(void)
{
dbg("PCI interrupt\r\n");
/* initiate PCI configuration access to device */
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */
MCF_PCI_PCICAR_BUSNUM(3) | /* note: invalid bus number */
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(0);
/* issue a dummy read to an unsupported bus number (will fail) */
dummy = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */
/* silently clear the PCI errors we produced just now */
MCF_PCI_PCIISR = 0xffffffff; /* clear all errors */
MCF_PCI_PCIGSCR = MCF_PCI_PCIGSCR_PE | MCF_PCI_PCIGSCR_SE;
(void) dummy;
}
/*
@@ -162,14 +168,14 @@ __attribute__((interrupt)) void pci_interrupt(void)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
static int32_t pci_get_interrupt_cause(int32_t *handles)
int32_t pci_get_interrupt_cause(void)
{
int32_t handle;
int32_t *hdl = &handles[0];
/*
* loop through all PCI devices...
*/
while ((handle = *handles++) != -1)
while ((handle = *hdl++) != -1)
{
uint16_t command_register = swpw(pci_read_config_word(handle, PCICR));
uint16_t status_register = swpw(pci_read_config_word(handle, PCISR));
@@ -188,7 +194,7 @@ static int32_t pci_get_interrupt_cause(int32_t *handles)
return -1;
}
static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
{
int i;
@@ -205,58 +211,12 @@ static int32_t pci_call_interrupt_chain(int32_t handle, int32_t data)
}
#pragma GCC diagnostic pop
/*
* This gets called from irq5 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
void irq5_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
xprintf("IRQ5!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
}
}
}
#ifdef MACHINE_M5484LITE
/*
* This gets called from irq7 in exceptions.S
* Once we arrive here, the SR has been set to disable interrupts and the gcc scratch registers have been saved
*/
void irq7_handler(void)
{
int32_t handle;
int32_t value = 0;
int32_t newvalue;
MCF_EPORT_EPFR |= (1 << 7);
dbg("IRQ7!\r\n");
if ((handle = pci_get_interrupt_cause(handles)) > 0)
{
newvalue = pci_call_interrupt_chain(handle, value);
if (newvalue == value)
{
dbg("interrupt not handled!\r\n");
}
}
}
#endif /* MACHINE_M548X */
/*
* retrieve handle for i'th device
*/
static int handle2index(int32_t handle)
int pci_handle2index(int32_t handle)
{
int i;
@@ -287,6 +247,67 @@ static char *device_class(int classcode)
return "not found";
}
/*
* do error checking after a PCI transaction
*/
static int pci_check_status(void)
{
uint32_t pcisr;
uint32_t pcigscr;
int ret = 0;
pcisr = MCF_PCI_PCIISR; /* retrieve initiator status register */
if (pcisr & MCF_PCI_PCIISR_RE)
{
dbg("PCI initiator retry error. Cleared.\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_RE;
ret = 1;
}
if (pcisr & MCF_PCI_PCIISR_IA)
{
dbg("PCI initiator abort. Error cleared\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_IA;
ret = 1;
}
if (pcisr & MCF_PCI_PCIISR_TA)
{
dbg("PCI initiator target abort error. Error cleared\r\n");
MCF_PCI_PCIISR |= MCF_PCI_PCIISR_TA;
ret = 1;
}
pcigscr = MCF_PCI_PCIGSCR;
if (pcigscr & MCF_PCI_PCIGSCR_PE)
{
dbg("PCI parity error. Error cleared\r\n");
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_PE;
ret = 1;
}
if (pcigscr & MCF_PCI_PCIGSCR_SE)
{
dbg("PCI system error. Error cleared\r\n");
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SE;
ret = 1;
}
if (!ret)
{
dbg("no error\r\n");
}
return ret;
}
/*
* read an uint32_t from configuration space of card with handle and offset
*
@@ -297,22 +318,23 @@ uint32_t pci_read_config_longword(int32_t handle, int offset)
uint32_t value;
/* initiate PCI configuration access to device */
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */
MCF_PCI_PCICAR = MCF_PCI_PCICAR_E | /* enable configuration access special cycle */
MCF_PCI_PCICAR_BUSNUM(PCI_BUS_FROM_HANDLE(handle)) |
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile__("nop" ::: "memory"); /* this is what the Linux BSP does */
NOP();
pci_config_wait();
value = * (volatile uint32_t *) PCI_IO_OFFSET; /* access device */
__asm__ __volatile__("tpf" ::: "memory"); /* this is what the Linux BSP does */
NOP();
/* finish PCI configuration access special cycle (allow regular PCI accesses) */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value;
}
@@ -329,15 +351,17 @@ uint16_t pci_read_config_word(int32_t handle, int offset)
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) |
MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile("nop" ::: "memory"); /* this is what Linux BSP does */
NOP();
value = * (volatile uint16_t *) PCI_IO_OFFSET + (offset & 2);
__asm__ __volatile("tpf" ::: "memory");
NOP();
/* finish PCI configuration access special cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value;
}
@@ -352,14 +376,16 @@ uint8_t pci_read_config_byte(int32_t handle, int offset)
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4);
__asm__ __volatile__("nop" ::: "memory");
NOP();
value = * (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3));
__asm__ __volatile__("tpf" ::: "memory");
NOP();
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
pci_check_status();
return value;
}
@@ -376,18 +402,18 @@ int32_t pci_write_config_longword(int32_t handle, int offset, uint32_t value)
MCF_PCI_PCICAR_DEVNUM(PCI_DEVICE_FROM_HANDLE(handle)) | /* device number, devices 0 - 9 are reserved */
MCF_PCI_PCICAR_FUNCNUM(PCI_FUNCTION_FROM_HANDLE(handle)) | /* function number */
MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135();
__asm__ __volatile__("nop" ::: "memory");
NOP();
* (volatile uint32_t *) PCI_IO_OFFSET = value; /* access device */
chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory");
NOP();
/* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135();
pci_check_status();
return PCI_SUCCESSFUL;
}
@@ -405,16 +431,15 @@ int32_t pci_write_config_word(int32_t handle, int offset, uint16_t value)
MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory");
NOP();
* (volatile uint16_t *) (PCI_IO_OFFSET + (offset & 2)) = value;
chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory");
/* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135();
pci_check_status();
return PCI_SUCCESSFUL;
}
@@ -431,7 +456,7 @@ int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value)
MCF_PCI_PCICAR_DWORD(offset / 4);
chip_errata_135();
__asm__ __volatile__("tpf" ::: "memory");
NOP();
* (volatile uint8_t *) (PCI_IO_OFFSET + (offset & 3)) = value;
chip_errata_135();
@@ -441,7 +466,7 @@ int32_t pci_write_config_byte(int32_t handle, int offset, uint8_t value)
/* finish configuration space access cycle */
MCF_PCI_PCICAR &= ~MCF_PCI_PCICAR_E;
chip_errata_135();
pci_check_status();
return PCI_SUCCESSFUL;
}
@@ -455,11 +480,15 @@ struct pci_rd *pci_get_resource(int32_t handle)
int index = -1;
struct pci_rd *ret;
index = handle2index(handle);
index = pci_handle2index(handle);
if (index == -1)
{
ret = NULL;
}
else
{
ret = &resource_descriptors[index][0];
}
dbg("pci_get_resource: resource struct for handle %lx (index %d) is at %p\r\n", handle, index, ret);
@@ -840,7 +869,7 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
handle = PCI_HANDLE(bus, device, function);
/* find index into resource descriptor table for handle */
index = handle2index(handle);
index = pci_handle2index(handle);
if (index == -1)
{
@@ -992,9 +1021,11 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
il = pci_read_config_byte(handle, PCIIPR);
dbg("device requests interrupts on interrupt pin %d\r\n", il);
/* if so, register interrupts */
/* enable interrupt on PCI device */
/* TODO: register interrupts here */
il = pci_read_config_byte(handle, PCICR);
il &= ~PCICSR_INT_DISABLE;
pci_write_config_byte(handle, PCICR, il);
/*
* enable device memory or I/O access
@@ -1133,18 +1164,13 @@ void init_pci(void)
xprintf("initializing PCI bridge:\r\n");
(void) res; /* for now */
res = register_interrupt_handler(0, INT_SOURCE_PCIARB, 5, 5, pci_arb_interrupt);
dbg("registered interrupt handler for PCI arbiter: %s\r\n",
(res < 0 ? "failed" : "succeeded"));
register_interrupt_handler(0, INT_SOURCE_XLBPCI, 5, 5, xlb_pci_interrupt);
dbg("registered interrupt handler for XLB PCI: %s\r\n",
(res < 0 ? "failed" : "succeeded"));
init_eport();
init_xlbus_arbiter();
MCF_PCI_PCIGSCR = 1; /* reset PCI */
#ifdef _NOT_USED_
/*
* setup the PCI arbiter
*/
@@ -1152,6 +1178,7 @@ void init_pci(void)
| MCF_PCIARB_PACR_EXTMPRI(0xf) /* external master priority: high */
| MCF_PCIARB_PACR_INTMINTEN /* enable "internal master broken" interrupt */
| MCF_PCIARB_PACR_EXTMINTEN(0x0f); /* enable "external master broken" interrupt */
#endif
#ifdef _NOT_USED_ /* since this is already done in sysinit.c */
#if MACHINE_FIREBEE
@@ -1173,18 +1200,18 @@ void init_pci(void)
/* Setup burst parameters */
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(8) |
MCF_PCI_PCICR1_LATTIMER(0xff); /* TODO: test increased latency timer */
#ifdef _NOT_USED_
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(1) |
MCF_PCI_PCICR2_MAXLAT(32);
#endif /* _NOT_USED_ */
MCF_PCI_PCICR2 = 0; /* this is what Linux does */
// MCF_PCI_PCICR2 = 0; /* this is what Linux does */
/* error signaling */
#ifdef NOT_USED
MCF_PCI_PCIICR = MCF_PCI_PCIICR_TAE | /* target abort enable */
MCF_PCI_PCIICR_IAE; /* initiator abort enable */
#endif /* NOT_USED */
MCF_PCI_PCIICR = 0; /* this is what Linux does */
// MCF_PCI_PCIICR = 0; /* this is what Linux does */
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE; /* system error interrupt enable */
@@ -1194,20 +1221,21 @@ void init_pci(void)
MCF_PCI_PCIIW0BTAR = (PCI_MEMORY_OFFSET | (((PCI_MEMORY_SIZE - 1) >> 8) & 0xffff0000))
| ((PCI_MEMORY_OFFSET >> 16) & 0xff00);
NOP();
dbg("PCIIW0BTAR=0x%08x\r\n", MCF_PCI_PCIIW0BTAR);
/* initiator window 1 base / translation adress register */
MCF_PCI_PCIIW1BTAR = (PCI_IO_OFFSET | ((PCI_IO_SIZE - 1) >> 8)) & 0xffff0000;
NOP();
/* initiator window 2 base / translation address register */
MCF_PCI_PCIIW2BTAR = 0L; /* not used */
NOP();
/* initiator window configuration register */
MCF_PCI_PCIIWCR = MCF_PCI_PCIIWCR_WINCTRL0_MEMRDLINE |
MCF_PCI_PCIIWCR_WINCTRL1_IO |
MCF_PCI_PCIIWCR_WINCTRL0_E |
MCF_PCI_PCIIWCR_WINCTRL1_E;
NOP();
/*
* Initialize target control register.
* Used when an external bus master accesses the Coldfire PCI as target
@@ -1219,7 +1247,7 @@ void init_pci(void)
/* reset PCI devices */
MCF_PCI_PCIGSCR &= ~MCF_PCI_PCIGSCR_PR;
do {;} while (MCF_PCI_PCIGSCR & MCF_PCI_PCIGSCR_PR); /* wait until reset finished */
do { NOP(); } while (MCF_PCI_PCIGSCR & MCF_PCI_PCIGSCR_PR); /* wait until reset finished */
xprintf("finished\r\n");
/* initialize/clear resource descriptor table */
@@ -1235,7 +1263,7 @@ void init_pci(void)
* give devices a chance to come up befor attempting to configure them,
* necessary to properly detect the FireBee USB chip
*/
wait(600000);
wait_ms(400);
/*
* do normal initialization