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:
2
.gdbinit
2
.gdbinit
@@ -3,7 +3,7 @@ define tr
|
||||
#!killall m68k-bdm-gdbserver
|
||||
target remote | m68k-bdm-gdbserver pipe /dev/bdmcf3
|
||||
#target remote localhost:1234
|
||||
#target remote | m68k-bdm-gdbserver pipe /dev/tblcf3
|
||||
#target remote | m68k-bdm-gdbserver pipe /dev/tblcf1
|
||||
#target dbug /dev/ttyS0
|
||||
#monitor bdm-reset
|
||||
end
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#error "unknown machine!"
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
//#define DBG_DMA
|
||||
#define DBG_DMA
|
||||
#ifdef DBG_DMA
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||
#else
|
||||
|
||||
@@ -63,4 +63,4 @@ erase 0xe0000000 37
|
||||
erase 0xe0000000 38
|
||||
erase 0xe0000000 39
|
||||
|
||||
load ../../emutos/emutos-m548x_bas.elf
|
||||
load ../../emutos/emutos-m548x-bas_gcc.elf
|
||||
|
||||
@@ -95,14 +95,41 @@
|
||||
#define FEC1TX_DMA_PRI 4
|
||||
#define FECTX_DMA_PRI(x) ((x == 0) ? FEC0TX_DMA_PRI : FEC1TX_DMA_PRI)
|
||||
|
||||
extern int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void));
|
||||
|
||||
#define ISR_DBUG_ISR 0x01
|
||||
#define ISR_USER_ISR 0x02
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
/* Firebee FPGA interrupt controller */
|
||||
#define FPGA_INTR_CONTROL ((volatile uint32_t *) 0xf0010000)
|
||||
#define FPGA_INTR_ENABLE ((volatile uint32_t *) 0xf0010004)
|
||||
#define FPGA_INTR_CLEAR ((volatile uint32_t *) 0xf0010008)
|
||||
#define FPGA_INTR_PENDING ((volatile uint32_t *) 0xff01000c)
|
||||
|
||||
/* register bits for Firebee FPGA-based interrupt controller */
|
||||
#define FPGA_INTR_PIC (1)
|
||||
#define FPGA_INTR_ETHERNET (1 << 1)
|
||||
#define FPGA_INTR_DVI (1 << 2)
|
||||
#define FPGA_INTR_PCI_INTA (1 << 3)
|
||||
#define FPGA_INTR_PCI_INTB (1 << 4)
|
||||
#define FPGA_INTR_PCI_INTC (1 << 5)
|
||||
#define FPGA_INTR_PCI_INTD (1 << 6)
|
||||
#define FPGA_INTR_INT_DSP (1 << 7)
|
||||
#define FPGA_INTR_INT_VSYNC (1 << 8)
|
||||
#define FPGA_INTR_INT_HSYNC (1 << 9)
|
||||
#define FPGA_INTR_INT_HSYNC_IRQ2 (1 << 26)
|
||||
#define FPGA_INTR_INT_CTR0_IRQ3 (1 << 27)
|
||||
#define FPGA_INTR_INT_VSYNC_IRQ4 (1 << 28)
|
||||
#define FPGA_INTR_INT_FPGA_IRQ5 (1 << 29)
|
||||
#define FPGA_INTR_INT_MFP_IRQ6 (1 << 30)
|
||||
#define FPGA_INTR_INT_IRQ7 (1 << 31)
|
||||
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
extern void isr_init(void);
|
||||
extern int isr_register_handler(int vector, int (*handler)(void *, void *), void *hdev, void *harg);
|
||||
extern void isr_remove_handler(int (*handler)(void *, void *));
|
||||
extern bool isr_execute_handler(int vector);
|
||||
extern int pic_interrupt_handler(void *arg1, void *arg2);
|
||||
extern int xlbpci_interrupt_handler(void *arg1, void *arg2);
|
||||
extern int pciarb_interrupt_handler(void *arg1, void *arg2);
|
||||
#endif /* _INTERRUPTS_H_ */
|
||||
|
||||
@@ -100,7 +100,7 @@ extern long video_sbt;
|
||||
struct page_descriptor;
|
||||
|
||||
extern void mmu_init(void);
|
||||
extern int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags);
|
||||
extern int mmu_map_page(int32_t virt, int32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags);
|
||||
|
||||
/*
|
||||
* API functions for the BaS driver interface
|
||||
|
||||
@@ -227,10 +227,14 @@ typedef struct /* structure of address conversion */
|
||||
extern void init_eport(void);
|
||||
extern void init_xlbus_arbiter(void);
|
||||
extern void init_pci(void);
|
||||
extern int pci_handle2index(int32_t handle);
|
||||
|
||||
extern int32_t pci_find_device(uint16_t device_id, uint16_t vendor_id, int index);
|
||||
extern int32_t pci_find_classcode(uint32_t classcode, int index);
|
||||
|
||||
extern int32_t pci_get_interrupt_cause(void);
|
||||
extern int32_t pci_call_interrupt_chain(int32_t handle, int32_t data);
|
||||
|
||||
/*
|
||||
* match bits for pci_find_classcode()
|
||||
*/
|
||||
|
||||
@@ -598,8 +598,10 @@
|
||||
#define PCI_DEVICE_ID_NEC_VL 0x0016 /* PCI-VL Bridge */
|
||||
#define PCI_DEVICE_ID_NEC_STARALPHA2 0x002c /* STAR ALPHA2 */
|
||||
#define PCI_DEVICE_ID_NEC_CBUS_2 0x002d /* PCI-Cbus Bridge */
|
||||
#define PCI_DEVICE_ID_NEC_USB_A 0x0031
|
||||
#define PCI_DEVICE_ID_NEC_USB 0x0035 /* PCI-USB Host */
|
||||
#define PCI_DEVICE_ID_NEC_USB_2 0x00e0 /* PCI-USB 2 Host */
|
||||
#define PCI_DEVICE_ID_NEC_USB_3 0x00f0
|
||||
#define PCI_DEVICE_ID_NEC_CBUS_3 0x003b
|
||||
#define PCI_DEVICE_ID_NEC_NAPCCARD 0x003e
|
||||
#define PCI_DEVICE_ID_NEC_PCX2 0x0046 /* PowerVR */
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
typedef bool (*checker_func)(void);
|
||||
|
||||
extern void wait(uint32_t);
|
||||
extern void wait_us(uint32_t); /* this is just an alias to the above */
|
||||
|
||||
inline static void udelay(long us)
|
||||
{
|
||||
wait((uint32_t) us);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#error Unknown machine!
|
||||
#endif
|
||||
|
||||
// #define DBG_FEC
|
||||
#define DBG_FEC
|
||||
#ifdef DBG_FEC
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG: %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||
#else
|
||||
|
||||
@@ -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,
|
||||
|
||||
156
pci/ohci-hcd.c
156
pci/ohci-hcd.c
@@ -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(®s->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, ®s->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, ®s->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, ®s->intrdisable);
|
||||
if (ohci->ed_rm_list[frame] != NULL)
|
||||
{
|
||||
writel(OHCI_INTR_SF, ®s->intrenable);
|
||||
}
|
||||
stat = 0xff;
|
||||
}
|
||||
writel(ints, ®s->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;
|
||||
|
||||
|
||||
252
pci/pci.c
252
pci/pci.c
@@ -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
|
||||
*
|
||||
@@ -303,16 +324,17 @@ uint32_t pci_read_config_longword(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"); /* 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
|
||||
|
||||
94
sys/BaS.c
94
sys/BaS.c
@@ -48,6 +48,8 @@
|
||||
#include "interrupts.h"
|
||||
#include "exceptions.h"
|
||||
#include "net_timer.h"
|
||||
#include "pci.h"
|
||||
#include "video.h"
|
||||
|
||||
//#define BAS_DEBUG
|
||||
#if defined(BAS_DEBUG)
|
||||
@@ -194,17 +196,13 @@ void acia_init()
|
||||
xprintf("finished\r\n");
|
||||
}
|
||||
|
||||
/* ACP interrupt controller */
|
||||
#define FPGA_INTR_CONTRL (volatile uint32_t *) 0xf0010000
|
||||
#define FPGA_INTR_ENABLE (volatile uint8_t *) 0xf0010004
|
||||
#define FPGA_INTR_PENDIN (volatile uint32_t *) 0xf0010008
|
||||
|
||||
void enable_coldfire_interrupts()
|
||||
{
|
||||
xprintf("enable interrupts: ");
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
*FPGA_INTR_CONTRL = 0L; /* disable all interrupts */
|
||||
*FPGA_INTR_CONTROL = 0L; /* disable all interrupts */
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
MCF_EPORT_EPPAR = 0xaaa8; /* all interrupts on falling edge */
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
@@ -218,11 +216,22 @@ void enable_coldfire_interrupts()
|
||||
/* route GPT0 interrupt on interrupt controller */
|
||||
MCF_INTC_ICR62 = 0x3f; /* interrupt level 7, interrupt priority 7 */
|
||||
|
||||
*FPGA_INTR_ENABLE = 0xfe; /* enable int 1-7 */
|
||||
|
||||
MCF_EPORT_EPIER = 0xfe; /* int 1-7 on */
|
||||
MCF_EPORT_EPFR = 0xff; /* clear all pending interrupts */
|
||||
MCF_INTC_IMRL = 0xffffff00; /* int 1-7 on */
|
||||
MCF_INTC_IMRH = 0xbffffffe; /* psc3 and timer 0 int on */
|
||||
*FPGA_INTR_ENABLE = FPGA_INTR_INT_IRQ7 |
|
||||
FPGA_INTR_INT_MFP_IRQ6 |
|
||||
FPGA_INTR_INT_FPGA_IRQ5 |
|
||||
FPGA_INTR_INT_VSYNC_IRQ4 |
|
||||
FPGA_INTR_INT_CTR0_IRQ3 |
|
||||
FPGA_INTR_INT_HSYNC_IRQ2 |
|
||||
FPGA_INTR_PCI_INTA |
|
||||
FPGA_INTR_PCI_INTB |
|
||||
FPGA_INTR_PCI_INTC |
|
||||
FPGA_INTR_PCI_INTD |
|
||||
FPGA_INTR_ETHERNET;
|
||||
#endif
|
||||
|
||||
xprintf("finished\r\n");
|
||||
@@ -283,6 +292,31 @@ void init_isr(void)
|
||||
dbg("Error: unable to register ISR for PSC3\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* register the XLB PCI interrupt handler
|
||||
*/
|
||||
if (!isr_register_handler(64 + INT_SOURCE_XLBPCI, xlbpci_interrupt_handler, NULL, NULL))
|
||||
{
|
||||
dbg("Error: unable to register isr for XLB PIC interrupts\r\n");
|
||||
return;
|
||||
}
|
||||
MCF_XLB_XARB_IMR = MCF_XLB_XARB_IMR_SEAE | /* slave error acknowledge interrupt */
|
||||
MCF_XLB_XARB_IMR_MME | /* multiple master at prio 0 interrupt */
|
||||
MCF_XLB_XARB_IMR_TTAE | /* TT address only interrupt */
|
||||
MCF_XLB_XARB_IMR_TTRE | /* TT reserved interrupt enable */
|
||||
MCF_XLB_XARB_IMR_ECWE | /* external control word interrupt */
|
||||
MCF_XLB_XARB_IMR_TTME | /* TBST/TSIZ mismatch interrupt */
|
||||
MCF_XLB_XARB_IMR_BAE; /* bus activity tenure timeout interrupt */
|
||||
|
||||
if (!isr_register_handler(64 + INT_SOURCE_PCIARB, pciarb_interrupt_handler, NULL, NULL))
|
||||
{
|
||||
dbg("Error: unable to register isr for PCIARB interrupts\r\n");
|
||||
|
||||
return;
|
||||
}
|
||||
MCF_PCIARB_PACR = MCF_PCIARB_PACR_EXTMINTEN(0x1f) | /* external master broken interrupt */
|
||||
MCF_PCIARB_PACR_INTMINTEN; /* internal master broken interrupt */
|
||||
}
|
||||
|
||||
void BaS(void)
|
||||
@@ -337,46 +371,10 @@ void BaS(void)
|
||||
* (volatile uint32_t *) (0xf0000410 + 8) = 0x0190015d; /* horizontal 320x240 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 12) = 0x020C020A; /* vertical 320x230 */
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
// 32MHz
|
||||
* (volatile uint32_t *) (0xf0000410 + 0) = 0x037002ba; /* horizontal 640x480 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 4) = 0x020d020a; /* vertical 640x480 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 8) = 0x02a001e0; /* horizontal 320x240 */
|
||||
* (volatile uint32_t *) (0xf0000410 + 12) = 0x05a00160; /* vertical 320x230 */
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
/* fifo on, refresh on, ddrcs and cke on, video dac on */
|
||||
* (volatile uint32_t *) (0xf0000410 - 0x20) = 0x01070002;
|
||||
|
||||
xprintf("finished\r\n");
|
||||
|
||||
enable_coldfire_interrupts();
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
screen_init();
|
||||
|
||||
/* experimental */
|
||||
{
|
||||
int i;
|
||||
uint32_t *scradr = 0xd00000;
|
||||
|
||||
for (i = 0; i < 100; i++)
|
||||
{
|
||||
uint32_t *p = scradr;
|
||||
|
||||
for (p = scradr; p < scradr + 1024 * 150L; p++)
|
||||
{
|
||||
*p = 0xffffffff;
|
||||
}
|
||||
|
||||
for (p = scradr; p < scradr + 1024 * 150L; p++)
|
||||
{
|
||||
*p = 0x0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
sd_card_init();
|
||||
@@ -420,8 +418,16 @@ void BaS(void)
|
||||
};
|
||||
|
||||
xprintf("BaS initialization finished, enable interrupts\r\n");
|
||||
enable_coldfire_interrupts();
|
||||
init_isr();
|
||||
enable_coldfire_interrupts();
|
||||
init_pci();
|
||||
video_init();
|
||||
set_ipl(0); /* enable interrupts */
|
||||
|
||||
/* initialize USB devices */
|
||||
init_usb();
|
||||
|
||||
//set_ipl(7); /* disable interrupts */
|
||||
|
||||
xprintf("call EmuTOS\r\n");
|
||||
struct rom_header *os_header = (struct rom_header *) TOS;
|
||||
|
||||
@@ -216,6 +216,9 @@ init_vec_loop:
|
||||
// install lowlevel_isr_handler for the PSC3 interrupt
|
||||
move.l a1,(INT_SOURCE_PSC3 + 64) * 4(a0)
|
||||
|
||||
// install lowlevel_isr_handler for the XLBPCI interrupt
|
||||
move.l a1,(INT_SOURCE_XLBPCI + 64) * 4(a0)
|
||||
|
||||
#ifndef MACHINE_FIREBEE
|
||||
// FEC1 not wired on the FireBee, but used on other machines
|
||||
move.l a1,(INT_SOURCE_FEC1 + 64) * 4(a0)
|
||||
@@ -429,10 +432,65 @@ irq7text:
|
||||
.text
|
||||
|
||||
#elif MACHINE_FIREBEE /* these handlers are only meaningful for the Firebee */
|
||||
irq5:
|
||||
irq 0x74,5,0x20
|
||||
|
||||
irq6: // MFP interrupt from FPGA
|
||||
irq5: move.w #0x2700,sr // disable interrupts
|
||||
subq.l #4,sp // extra space
|
||||
|
||||
link a6,#-4 * 4 // save gcc scratch registers
|
||||
movem.l d0-d1/a0-a1,(sp)
|
||||
|
||||
jsr _irq5_handler // call C handler routine
|
||||
|
||||
tst.l d0 // handled?
|
||||
bne irq5_forward
|
||||
|
||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||
unlk a6
|
||||
addq.l #4,sp
|
||||
|
||||
rte // return from exception
|
||||
|
||||
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
|
||||
add.l _rt_vbr,a0 // add runtime vbr
|
||||
move.l a0,4(a6) // put on stack
|
||||
|
||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||
unlk a6 //
|
||||
move.w #0x2500,sr // set interrupt level
|
||||
rts // jump through vector
|
||||
|
||||
|
||||
irq6: move.w #0x2700,sr // disable interrupt
|
||||
subq.l #4,sp // extra space
|
||||
link a6,#-4 * 4 // save gcc scratch registers
|
||||
movem.l d0-d1/a0-a1,(sp)
|
||||
|
||||
move.l 4(a6),-(sp) // format status word
|
||||
move.l 8(a6),-(sp) // pc at exception
|
||||
jsr _irq6_interrupt_handler // call C handler
|
||||
lea 8(sp),sp // fix stack
|
||||
|
||||
tst.l d0 // interrupt handled?
|
||||
bne irq6_forward // no, forward to TOS
|
||||
|
||||
movem.l (sp),d0-d1/a0-a1 // restore registers
|
||||
unlk a6
|
||||
addq.l #4,sp // extra word not needed in this case
|
||||
rte
|
||||
|
||||
irq6_forward:
|
||||
move.l 0xf0020000,a0 // fetch "autovector"
|
||||
add.l _rt_vbr,a0 // add runtime VBR
|
||||
move.l (a0),4(a6) // fetch handler address and put it on stack
|
||||
|
||||
movem.l (sp),d0-d1/a0-a1
|
||||
unlk a6
|
||||
move.w #0x2600,sr // set interrupt level
|
||||
|
||||
rts // jump through vector
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
// MFP interrupt from FPGA
|
||||
move.w #0x2700,sr // disable interrupt
|
||||
subq.l #8,sp
|
||||
movem.l d0/a5,(sp) // save registers
|
||||
@@ -555,6 +613,9 @@ acsi_dma_end:
|
||||
move.l (sp)+,d1
|
||||
move.l (sp)+,a1
|
||||
rts
|
||||
|
||||
#endif /* _NOT_USED_ */
|
||||
|
||||
/*
|
||||
* irq 7 = pseudo bus error
|
||||
*/
|
||||
|
||||
123
sys/interrupts.c
123
sys/interrupts.c
@@ -35,63 +35,19 @@
|
||||
#include "cache.h"
|
||||
#include "util.h"
|
||||
#include "dma.h"
|
||||
#include "pci.h"
|
||||
|
||||
extern void (*rt_vbr[])(void);
|
||||
#define VBR rt_vbr
|
||||
|
||||
//#define IRQ_DEBUG
|
||||
#define IRQ_DEBUG
|
||||
#if defined(IRQ_DEBUG)
|
||||
#define dbg(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||
#else
|
||||
#define dbg(format, arg...) do { ; } while (0)
|
||||
#endif
|
||||
#define err(format, arg...) do { xprintf("DEBUG %s(): " format, __FUNCTION__, ##arg); } while (0)
|
||||
|
||||
/*
|
||||
* register an interrupt handler at the Coldfire interrupt controller and add the handler to
|
||||
* the interrupt vector table
|
||||
*/
|
||||
int register_interrupt_handler(uint8_t source, uint8_t level, uint8_t priority, uint8_t intr, void (*handler)(void))
|
||||
{
|
||||
int ipl;
|
||||
int i;
|
||||
volatile uint8_t *ICR = &MCF_INTC_ICR01 - 1;
|
||||
uint8_t lp;
|
||||
|
||||
source &= 63;
|
||||
priority &= 7;
|
||||
|
||||
if (source < 1 || source > 63)
|
||||
{
|
||||
dbg("interrupt source %d not defined\r\n", source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lp = MCF_INTC_ICR_IL(level) | MCF_INTC_ICR_IP(priority);
|
||||
|
||||
/* check if this combination is already set somewhere */
|
||||
for (i = 1; i < 64; i++)
|
||||
{
|
||||
if (ICR[i] == lp)
|
||||
{
|
||||
dbg("level %d and priority %d already used for interrupt source %d!\r\n",
|
||||
level, priority, i);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* disable interrupts */
|
||||
ipl = set_ipl(7);
|
||||
|
||||
VBR[64 + source] = handler; /* first 64 vectors are system exceptions */
|
||||
|
||||
/* set level and priority in interrupt controller */
|
||||
ICR[source] = lp;
|
||||
|
||||
/* set interrupt mask to where it was before */
|
||||
set_ipl(ipl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef MAX_ISR_ENTRY
|
||||
#define MAX_ISR_ENTRY (20)
|
||||
@@ -236,12 +192,19 @@ int pic_interrupt_handler(void *arg1, void *arg2)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void video_addr_timeout(void)
|
||||
int xlbpci_interrupt_handler(void *arg1, void *arg2)
|
||||
{
|
||||
dbg("video address timeout\r\n");
|
||||
dbg("XLB PCI interrupt\r\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pciarb_interrupt_handler(void *arg1, void *arg2)
|
||||
{
|
||||
dbg("PCI ARB interrupt\r\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* blink the Firebee's LED to show we are still alive
|
||||
@@ -288,6 +251,7 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
//err("IRQ6!\r\n");
|
||||
MCF_EPORT_EPFR |= (1 << 6); /* clear int6 from edge port */
|
||||
|
||||
if (FALCON_MFP_IPRA || FALCON_MFP_IPRB)
|
||||
@@ -298,6 +262,65 @@ bool irq6_interrupt_handler(uint32_t sf1, uint32_t sf2)
|
||||
return handled;
|
||||
}
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
int irq5_handler(void)
|
||||
{
|
||||
int32_t handle;
|
||||
int32_t value = 0;
|
||||
int32_t newvalue;
|
||||
|
||||
err("FPGA_INTR_CONTROL = 0x%08x\r\n", * FPGA_INTR_CONTROL);
|
||||
err("FPGA_INTR_ENABLE = 0x%08x\r\n", * FPGA_INTR_ENABLE);
|
||||
err("FPGA_INTR_CLEAR = 0x%08x\r\n", * FPGA_INTR_CLEAR);
|
||||
err("FPGA_INTR_PENDING = 0x%08x\r\n", * FPGA_INTR_PENDING);
|
||||
|
||||
* FPGA_INTR_CLEAR &= ~0x20000000UL; /* clear interrupt from FPGA */
|
||||
err("\r\nFPGA_INTR_CLEAR = 0x%08x\r\n", * FPGA_INTR_CLEAR);
|
||||
//MCF_EPORT_EPFR |= (1 << 5); /* clear interrupt from edge port */
|
||||
|
||||
//xprintf("IRQ5!\r\n");
|
||||
|
||||
if ((handle = pci_get_interrupt_cause()) > 0)
|
||||
{
|
||||
newvalue = pci_call_interrupt_chain(handle, value);
|
||||
if (newvalue == value)
|
||||
{
|
||||
dbg("interrupt not handled!\r\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
|
||||
#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()) > 0)
|
||||
{
|
||||
newvalue = pci_call_interrupt_chain(handle, value);
|
||||
if (newvalue == value)
|
||||
{
|
||||
dbg("interrupt not handled!\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* MACHINE_M548X */
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
#define vbasehi (* (volatile uint8_t *) 0xffff8201)
|
||||
#define vbasemid (* (volatile uint8_t *) 0xffff8203)
|
||||
|
||||
159
sys/mmu.c
159
sys/mmu.c
@@ -213,6 +213,7 @@ struct virt_to_phys
|
||||
uint32_t physical_offset;
|
||||
};
|
||||
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
static struct virt_to_phys translation[] =
|
||||
{
|
||||
/* virtual , length , offset */
|
||||
@@ -221,9 +222,33 @@ static struct virt_to_phys translation[] =
|
||||
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
|
||||
{ 0x01000000, 0x1f000000, 0x00000000 }, /* map rest of ram virt = phys */
|
||||
};
|
||||
#elif defined(MACHINE_M5484LITE)
|
||||
static struct virt_to_phys translation[] =
|
||||
{
|
||||
/* virtual , length , offset */
|
||||
{ 0x00000000, 0x00e00000, 0x00000000 }, /* map first 14 MByte to first 14 Mb of SD ram */
|
||||
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
|
||||
{ 0x01000000, 0x04000000, 0x00000000 }, /* map rest of ram virt = phys */
|
||||
{ 0x60000000, 0x10000000, 0x00000000 }, /* map CPLD CF card I/O area */
|
||||
|
||||
};
|
||||
#elif defined(MACHINE_M54455)
|
||||
/* FIXME: this is not determined yet! */
|
||||
static struct virt_to_phys translation[] =
|
||||
{
|
||||
/* virtual , length , offset */
|
||||
{ 0x00000000, 0x00e00000, 0x60000000 }, /* map first 14 MByte to first 14 Mb of video ram */
|
||||
{ 0x00e00000, 0x00100000, 0x00000000 }, /* map TOS to SDRAM */
|
||||
{ 0x00f00000, 0x00100000, 0xff000000 }, /* map Falcon I/O area to FPGA */
|
||||
{ 0x01000000, 0x1f000000, 0x00000000 }, /* map rest of ram virt = phys */
|
||||
};
|
||||
#else
|
||||
#error unknown machine!
|
||||
#endif
|
||||
|
||||
static int num_translations = sizeof(translation) / sizeof(struct virt_to_phys);
|
||||
|
||||
static inline uint32_t lookup_phys(uint32_t virt)
|
||||
static inline int32_t lookup_phys(int32_t virt)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -235,6 +260,7 @@ static inline uint32_t lookup_phys(uint32_t virt)
|
||||
}
|
||||
}
|
||||
err("virtual address 0x%lx not found in translation table!\r\n", virt);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -253,19 +279,23 @@ struct page_descriptor
|
||||
* page descriptors. Size depending on DEFAULT_PAGE_SIZE, either 1M (resulting in 512
|
||||
* bytes size) or 8k pages (64k descriptor array size)
|
||||
*/
|
||||
static struct page_descriptor pages[512UL * 1024 * 1024 / DEFAULT_PAGE_SIZE];
|
||||
static struct page_descriptor pages[SDRAM_SIZE / DEFAULT_PAGE_SIZE];
|
||||
|
||||
|
||||
int mmu_map_instruction_page(uint32_t virt, uint8_t asid)
|
||||
int mmu_map_instruction_page(int32_t virt, uint8_t asid)
|
||||
{
|
||||
const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */
|
||||
int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */
|
||||
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
|
||||
int ipl;
|
||||
uint32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
|
||||
int32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
|
||||
|
||||
if (phys == -1)
|
||||
{
|
||||
/* no valid mapping found, caller will issue a bus error in return */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DBG_MMU
|
||||
register int sp asm("sp");
|
||||
@@ -307,17 +337,21 @@ int mmu_map_instruction_page(uint32_t virt, uint8_t asid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mmu_map_data_page(uint32_t virt, uint8_t asid)
|
||||
int mmu_map_data_page(int32_t virt, uint8_t asid)
|
||||
{
|
||||
uint16_t ipl;
|
||||
const uint32_t size_mask = ~ (DEFAULT_PAGE_SIZE - 1); /* pagesize */
|
||||
int page_index = (virt & size_mask) / DEFAULT_PAGE_SIZE; /* index into page_descriptor array */
|
||||
struct page_descriptor *page = &pages[page_index]; /* attributes of page to map */
|
||||
|
||||
uint32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
|
||||
int32_t phys = lookup_phys(virt); /* virtual to physical translation of page */
|
||||
|
||||
if (phys == -1)
|
||||
{
|
||||
/* no valid mapping found, caller will issue a bus error in return */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DBG_MMU
|
||||
register int sp asm("sp");
|
||||
@@ -365,7 +399,7 @@ int mmu_map_data_page(uint32_t virt, uint8_t asid)
|
||||
* per instruction as a minimum, more for performance. Thus locked pages (that can't be touched by the
|
||||
* LRU algorithm) should be used sparsingly.
|
||||
*/
|
||||
int mmu_map_page(uint32_t virt, uint32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags)
|
||||
int mmu_map_page(int32_t virt, int32_t phys, enum mmu_page_size sz, uint8_t page_id, const struct page_descriptor *flags)
|
||||
{
|
||||
int size_mask;
|
||||
int ipl;
|
||||
@@ -447,7 +481,8 @@ void mmu_init(void)
|
||||
{
|
||||
uint32_t addr = i * DEFAULT_PAGE_SIZE;
|
||||
|
||||
if (addr >= 0x00f00000 && addr < 0x00ffffff)
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
if (addr >= 0x00f00000UL && addr < 0x00ffffffUL) /* Falcon I/O area on the Firebee */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
|
||||
pages[i].execute = 0;
|
||||
@@ -457,7 +492,7 @@ void mmu_init(void)
|
||||
pages[i].global = 1;
|
||||
pages[i].supervisor_protect = 1;
|
||||
}
|
||||
else if (addr >= 0x0 && addr < 0x00e00000) /* ST-RAM, potential video memory */
|
||||
else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_WRITETHROUGH;
|
||||
pages[i].execute = 1;
|
||||
@@ -467,7 +502,7 @@ void mmu_init(void)
|
||||
pages[i].execute = 1;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
else if (addr >= 0x00e00000 && addr < 0x00f00000) /* EmuTOS */
|
||||
else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_COPYBACK;
|
||||
pages[i].execute = 1;
|
||||
@@ -488,16 +523,107 @@ void mmu_init(void)
|
||||
}
|
||||
pages[i].locked = 0; /* not locked */
|
||||
pages[0].supervisor_protect = 0; /* protect system vectors */
|
||||
|
||||
#elif defined(MACHINE_M5484LITE)
|
||||
if (addr >= 0x60000000UL && addr < 0x70000000UL) /* Compact Flash on the m5484lite */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
|
||||
pages[i].execute = 0;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].execute = 0;
|
||||
pages[i].global = 1;
|
||||
pages[i].supervisor_protect = 1;
|
||||
}
|
||||
else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_WRITETHROUGH;
|
||||
pages[i].execute = 1;
|
||||
pages[i].supervisor_protect = 0;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].execute = 1;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_COPYBACK;
|
||||
pages[i].execute = 1;
|
||||
pages[i].supervisor_protect = 1;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 0;
|
||||
pages[i].execute = 1;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pages[i].cache_mode = CACHE_COPYBACK; /* rest of RAM */
|
||||
pages[i].execute = 1;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].supervisor_protect = 0;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
pages[i].locked = 0; /* not locked */
|
||||
pages[0].supervisor_protect = 0; /* protect system vectors */
|
||||
|
||||
#elif defined(MACHINE_M54455)
|
||||
if (addr >= 0x60000000UL && addr < 0x70000000UL) /* Compact Flash on the m5484lite */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_NOCACHE_PRECISE;
|
||||
pages[i].execute = 0;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].execute = 0;
|
||||
pages[i].global = 1;
|
||||
pages[i].supervisor_protect = 1;
|
||||
}
|
||||
else if (addr >= 0x0UL && addr < 0x00e00000UL) /* ST-RAM, potential video memory */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_WRITETHROUGH;
|
||||
pages[i].execute = 1;
|
||||
pages[i].supervisor_protect = 0;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].execute = 1;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
else if (addr >= 0x00e00000UL && addr < 0x00f00000UL) /* EmuTOS */
|
||||
{
|
||||
pages[i].cache_mode = CACHE_COPYBACK;
|
||||
pages[i].execute = 1;
|
||||
pages[i].supervisor_protect = 1;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 0;
|
||||
pages[i].execute = 1;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pages[i].cache_mode = CACHE_COPYBACK; /* rest of RAM */
|
||||
pages[i].execute = 1;
|
||||
pages[i].read = 1;
|
||||
pages[i].write = 1;
|
||||
pages[i].supervisor_protect = 0;
|
||||
pages[i].global = 1;
|
||||
}
|
||||
pages[i].locked = 0; /* not locked */
|
||||
pages[0].supervisor_protect = 0; /* protect system vectors */
|
||||
#else
|
||||
#error Unknown machine!
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
}
|
||||
|
||||
set_asid(0); /* do not use address extension (ASID provides virtual 48 bit addresses */
|
||||
|
||||
/* set data access attributes in ACR0 and ACR1 */
|
||||
|
||||
/* map PCI address space */
|
||||
set_acr0(ACR_W(0) | /* read and write accesses permitted */
|
||||
ACR_SP(0) | /* supervisor and user mode access permitted */
|
||||
ACR_SP(1) | /* supervisor and user mode access permitted */
|
||||
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* cache inhibit, precise */
|
||||
ACR_AMM(0) | /* control region > 16 MB */
|
||||
ACR_S(ACR_S_ALL) | /* match addresses in user and supervisor mode */
|
||||
ACR_S(ACR_S_SUPERVISOR_MODE) | /* match addresses in supervisor mode only */
|
||||
ACR_E(1) | /* enable ACR */
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
ACR_ADMSK(0x7f) | /* cover 2GB area from 0x80000000 to 0xffffffff */
|
||||
@@ -520,11 +646,11 @@ void mmu_init(void)
|
||||
ACR_SP(0) |
|
||||
ACR_CM(0) |
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) | /* flash on the Firebee */
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) |
|
||||
#elif defined(MACHINE_M5484LITE)
|
||||
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* Compact Flash on the M548xLITE */
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) |
|
||||
#elif defined(MACHINE_M54455)
|
||||
ACR_CM(ACR_CM_CACHE_INH_PRECISE) | /* FIXME: not determined yet */
|
||||
ACR_CM(ACR_CM_CACHEABLE_WT) |
|
||||
#else
|
||||
#error unknown machine!
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
@@ -568,6 +694,7 @@ void mmu_init(void)
|
||||
/* 0x00000000 - 0x00100000 (first MB of physical memory) locked virt = phys */
|
||||
mmu_map_page(0x0, 0x0, MMU_PAGE_SIZE_1M, 0, &flags);
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
#if defined(MACHINE_FIREBEE)
|
||||
/*
|
||||
* 0x00d00000 - 0x00e00000 (last megabyte of ST RAM = Falcon video memory) locked ID = 6
|
||||
@@ -581,8 +708,8 @@ void mmu_init(void)
|
||||
flags.execute = 1;
|
||||
flags.locked = true;
|
||||
mmu_map_page(0x00d00000, 0x60d00000, MMU_PAGE_SIZE_1M, SCA_PAGE_ID, &flags);
|
||||
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make the TOS (in SDRAM) read-only
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include "startcf.h"
|
||||
#include "cache.h"
|
||||
#include "sysinit.h"
|
||||
#include "pci.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
#include "bas_types.h"
|
||||
@@ -52,7 +51,6 @@
|
||||
#include "pci_ids.h"
|
||||
#include "driver_mem.h"
|
||||
#include "usb.h"
|
||||
#include "video.h"
|
||||
|
||||
#define DEBUG_SYSINIT
|
||||
#ifdef DEBUG_SYSINIT
|
||||
@@ -708,9 +706,11 @@ void init_usb(void)
|
||||
uint32_t id = 0;
|
||||
uint32_t pci_class = 0;
|
||||
|
||||
dbg("PCI device handle = %x\r\n", handle);
|
||||
|
||||
id = pci_read_config_longword(handle, PCIIDR);
|
||||
pci_class = pci_read_config_longword(handle, PCIREV);
|
||||
dbg("compare class code 0x%x to 0x%x\r\n", PCI_CLASS_CODE(pci_class), PCI_CLASS_SERIAL_USB);
|
||||
|
||||
if (PCI_CLASS_CODE(pci_class) == PCI_CLASS_SERIAL_USB)
|
||||
{
|
||||
xprintf("serial USB found at bus=0x%x, dev=0x%x, fnc=0x%x (0x%x)\r\n",
|
||||
@@ -718,14 +718,12 @@ void init_usb(void)
|
||||
PCI_DEVICE_FROM_HANDLE(handle),
|
||||
PCI_FUNCTION_FROM_HANDLE(handle),
|
||||
handle);
|
||||
dbg("compare subclass code 0x%x against 0x%x\r\n", PCI_SUBCLASS(pci_class), PCI_CLASS_SERIAL_USB_EHCI);
|
||||
|
||||
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_EHCI)
|
||||
{
|
||||
board = ehci_usb_pci_table;
|
||||
while (board->vendor)
|
||||
{
|
||||
dbg("compare vendor id 0x%x against 0x%x\r\n", board->vendor, PCI_VENDOR_ID(id));
|
||||
dbg("compare device id 0x%x against 0x%x\r\n", board->device, PCI_DEVICE_ID(id));
|
||||
if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id))
|
||||
{
|
||||
dbg("match. trying to init board\r\n");
|
||||
@@ -738,15 +736,12 @@ void init_usb(void)
|
||||
}
|
||||
}
|
||||
|
||||
dbg("compare subclass code 0x%x against 0x%x\r\n", PCI_SUBCLASS(pci_class), PCI_CLASS_SERIAL_USB_OHCI);
|
||||
if (PCI_SUBCLASS(pci_class) == PCI_CLASS_SERIAL_USB_OHCI)
|
||||
{
|
||||
board = ohci_usb_pci_table;
|
||||
|
||||
while (board->vendor)
|
||||
{
|
||||
dbg("matched. compare vendor id 0x%x against 0x%x\r\n", board->vendor, PCI_VENDOR_ID(id));
|
||||
dbg("compare device id 0x%x against 0x%x\r\n", board->device, PCI_DEVICE_ID(id));
|
||||
if ((board->vendor == PCI_VENDOR_ID(id)) && board->device == PCI_DEVICE_ID(id))
|
||||
{
|
||||
if (usb_init(handle, board) >= 0)
|
||||
@@ -759,7 +754,6 @@ void init_usb(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
dbg("PCI device handle = %x\r\n", handle);
|
||||
} while (handle >= 0);
|
||||
|
||||
xprintf("finished (found %d USB host controller(s))\r\n", usb_found);
|
||||
@@ -1228,11 +1222,6 @@ void initialize_hardware(void)
|
||||
|
||||
#endif /* MACHINE_FIREBEE */
|
||||
driver_mem_init();
|
||||
init_pci();
|
||||
video_init();
|
||||
|
||||
/* initialize USB devices */
|
||||
init_usb();
|
||||
|
||||
#if MACHINE_FIREBEE
|
||||
init_ac97();
|
||||
|
||||
@@ -529,7 +529,7 @@ int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
|
||||
|
||||
if (head->bDescriptorType != USB_DT_CONFIG)
|
||||
{
|
||||
dbg(" ERROR: NOT USB_CONFIG_DESC %x\r\n", head->bDescriptorType);
|
||||
dbg(" ERROR: NOT USB_CONFIG_DESC (0x%x instead of 0x%x)\r\n", head->bDescriptorType, USB_DT_CONFIG);
|
||||
return -1;
|
||||
}
|
||||
memcpy(&dev->config, buffer, buffer[0]);
|
||||
@@ -1089,6 +1089,7 @@ int usb_new_device(struct usb_device *dev)
|
||||
unsigned char *tmpbuf;
|
||||
|
||||
dbg("\r\n");
|
||||
|
||||
#ifndef CONFIG_LEGACY_USB_INIT_SEQ
|
||||
struct usb_device_descriptor *desc;
|
||||
int port = -1;
|
||||
@@ -1113,6 +1114,7 @@ int usb_new_device(struct usb_device *dev)
|
||||
return 1;
|
||||
}
|
||||
|
||||
//#define CONFIG_LEGACY_USB_INIT_SEQ
|
||||
#ifdef CONFIG_LEGACY_USB_INIT_SEQ
|
||||
/*
|
||||
* this is the old and known way of initializing devices, it is
|
||||
@@ -1244,6 +1246,9 @@ int usb_new_device(struct usb_device *dev)
|
||||
dev->descriptor.idProduct = swpw(dev->descriptor.idProduct);
|
||||
dev->descriptor.bcdDevice = swpw(dev->descriptor.bcdDevice);
|
||||
|
||||
dbg("vendor: 0x%x, prod: 0x%x, dev: 0x%x\r\n",
|
||||
dev->descriptor.idVendor, dev->descriptor.idProduct, dev->descriptor.bcdDevice);
|
||||
|
||||
/* only support for one config for now */
|
||||
usb_get_configuration_no(dev, &tmpbuf[0], 0);
|
||||
usb_parse_config(dev, &tmpbuf[0], 0);
|
||||
|
||||
@@ -216,12 +216,14 @@ static int usb_mouse_probe(struct usb_device *dev, unsigned int ifnum)
|
||||
int pipe;
|
||||
int maxp;
|
||||
|
||||
#ifdef _NOT_USED_
|
||||
if (dev->descriptor.bNumConfigurations != 1)
|
||||
{
|
||||
dbg("dev->descriptor.bNumConfigurations != 1\r\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
iface = &dev->config.if_desc[ifnum];
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ void wait(uint32_t us)
|
||||
|
||||
while (MCF_SLT_SCNT(0) - target > 0);
|
||||
}
|
||||
void wait_us() __attribute__ ((weak, alias("wait")));
|
||||
|
||||
/*
|
||||
* same as above, but with milliseconds wait time
|
||||
|
||||
Reference in New Issue
Block a user