still hangs, unfortunately

This commit is contained in:
Markus Fröschle
2013-11-09 19:57:16 +00:00
parent bc1cd70d8e
commit a8502bc856
3 changed files with 109 additions and 46 deletions

View File

@@ -72,11 +72,33 @@
#define CONFIG_SYS_OHCI_SWAP_REG_ACCESS
#ifdef CONFIG_SYS_OHCI_SWAP_REG_ACCESS
/*
#define readl(a) swpl(*((volatile uint32_t *)(a)))
#define writel(a, b) (*((volatile uint32_t *)(b)) = swpl((volatile uint32_t)(a)))
*/
inline uint32_t readl(volatile uint32_t *addr)
{
uint32_t res;
xprintf("reading from 0x%08x in %s, %d", addr, __FILE__, __LINE__);
res = swpl(*addr);
chip_errata_135();
xprintf(" result=0x%08x\r\n", res);
}
/*
#define writel(a, b) {xprintf("writing %08x to %08x\r\n", (a), (b)); *((volatile uint32_t *)(b)) = swpl((volatile uint32_t)(a)); }
*/
inline void writel(uint32_t value, uint32_t *address)
{
xprintf("writing %08x to %08x in %s, %d\r\n", value, address, __FILE__, __LINE__);
* (volatile uint32_t *) address = swpl(value);
}
#else
/*
#define readl(a) (*((volatile uint32_t *)(a)))
#define writel(a, b) (*((volatile uint32_t *)(b)) = ((volatile uint32_t)a))
*/
#error CONFIG_SYS_OHCI_SWAP_REG_ACESS must be defined
#endif /* CONFIG_SYS_OHCI_SWAP_REG_ACCESS */
#define min_t(type, x, y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
@@ -618,7 +640,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
case PIPE_CONTROL:
ed->hwNextED = 0;
if (ohci->ed_controltail == NULL)
writel(ed - ohci->dma_offset, &ohci->regs->ed_controlhead);
writel((uint32_t) ed - ohci->dma_offset, &ohci->regs->ed_controlhead);
else
ohci->ed_controltail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset);
@@ -633,7 +655,7 @@ static int ep_link(ohci_t *ohci, ed_t *edi)
case PIPE_BULK:
ed->hwNextED = 0;
if (ohci->ed_bulktail == NULL)
writel(ed - ohci->dma_offset, &ohci->regs->ed_bulkhead);
writel((uint32_t) ed - ohci->dma_offset, &ohci->regs->ed_bulkhead);
else
ohci->ed_bulktail->hwNextED = swpl((uint32_t)ed - ohci->dma_offset);
ed->ed_prev = ohci->ed_bulktail;
@@ -1571,6 +1593,7 @@ static int hc_reset(ohci_t *ohci)
int timeout = 30;
int smm_timeout = 50; /* 0,5 sec */
dbg("%s\r\n", __FUNCTION__);
if ((ohci->ent->vendor == PCI_VENDOR_ID_PHILIPS)
&& (ohci->ent->device == PCI_DEVICE_ID_PHILIPS_ISP1561))
{
@@ -1603,8 +1626,7 @@ static int hc_reset(ohci_t *ohci)
if (usb_base_addr == 0xFFFFFFFF)
{
uint32_t base = pci_rsc_desc->offset + pci_rsc_desc->start;
usb_base_addr = pci_rsc_desc->start;
writel(readl(base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET, base + EHCI_USBCMD_OFF);
writel(readl((uint32_t) base + EHCI_USBCMD_OFF) | EHCI_USBCMD_HCRESET, base + EHCI_USBCMD_OFF);
while (readl(base + EHCI_USBCMD_OFF) & EHCI_USBCMD_HCRESET)
{
if (timeout-- <= 0)
@@ -1627,13 +1649,13 @@ 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))
&& (ohci->ent->device == PCI_DEVICE_ID_NEC_USB))
{
if (ohci->handle == 1) /* NEC on motherboard has FPGA clock */
{
dbg("USB OHCI set 48MHz clock\r\n");
pci_write_config_longword(ohci->handle, 0xE4, 0x21); // oscillator & disable ehci
wait(10 * 1000);
wait(10);
}
else
{
@@ -1987,7 +2009,7 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
ohci->disabled = 1;
ohci->sleeping = 0;
ohci->irq = -1;
xprintf("pci_rsc_desc: %p\r\n", pci_rsc_desc);
if (pci_rsc_desc != NULL)
{
unsigned short flags;
@@ -2000,7 +2022,6 @@ int ohci_usb_lowlevel_init(int32_t handle, const struct pci_device_id *ent, void
if (usb_base_addr == 0xFFFFFFFF)
{
usb_base_addr = pci_rsc_desc->start;
xprintf("usb_base_addr = %p\r\n", usb_base_addr);
ohci->offset = pci_rsc_desc->offset;
ohci->regs = (void *)(pci_rsc_desc->offset + pci_rsc_desc->start);
ohci->dma_offset = pci_rsc_desc->dmaoffset;

View File

@@ -72,6 +72,51 @@ static int32_t handles[NUM_CARDS];
/* holds the card's resource descriptors; filled in pci_device_config() */
static struct pci_rd resource_descriptors[NUM_CARDS][NUM_RESOURCES];
void chip_errata_135(void)
{
/*
* Errata type: Silicon
* Affected component: PCI
* Description: When core PCI transactions that involve writes to configuration or I/O space
* are followed by a core line access to line addresses 0x4 and 0xC, core access
* to the XL bus can hang.
* Workaround: Prevent PCI configuration and I/O writes from being followed by the described
* line access by the core by generating a known good XL bus transaction after
* the PCI transaction.
* Create a dummy function which is called immediately after each of the affected
* transactions. There are three requirements for this dummy function.
* 1. The function must be aligned to a 16-byte boundary.
* 2. The function must contain a dummy write to a location on the XL bus,
* preferably one with no side effects.
* 3. The function must be longer than 32 bytes. If it is not, the function should
* be padded with 16- or 48-bit TPF instructions placed after the end of
* the function (after the RTS instruction) such that the length is longer
* than 32 bytes.
*/
__asm__ __volatile(
" bra .start\n\t"
" .align 16\n\t" /* force function start to 16-byte boundary */
".start:\n\t"
" clr.l d0\n\t"
" move.l d0, addr\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"
" .data\n\t"
"addr: ds.l 1\n\t"
" .text\n\t"
:::);
}
/*
* retrieve handle for i'th device
*/
@@ -134,6 +179,7 @@ uint32_t pci_read_config_longword(int32_t handle, int offset)
pci_config_wait();
chip_errata_135();
return value;
}
@@ -301,8 +347,8 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
struct pci_rd *descriptors;
int i;
uint32_t value;
static uint32_t mem_address = PCI_MEMORY_OFFSET;
static uint32_t io_address = PCI_IO_OFFSET;
static uint32_t mem_address = 0;
static uint32_t io_address = 0;
/* determine pci handle from bus, device + function number */
handle = PCI_HANDLE(bus, device, function);
@@ -349,10 +395,10 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
xprintf("device 0x%x: BAR[%d] requests %d kBytes of memory\r\n", handle, i, size / 1024);
/* calculate a valid map adress with alignment requirements */
mem_address = (mem_address + size - 1) & ~(size - 1);
address = (mem_address + size - 1) & ~(size - 1);
/* write it to the BAR */
pci_write_config_longword(handle, PCIBAR0 + i, swpl(mem_address));
pci_write_config_longword(handle, PCIBAR0 + i, swpl(address));
/* read it back, just to be sure */
value = swpl(pci_read_config_longword(handle, PCIBAR0 + i));
@@ -363,9 +409,9 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
/* fill resource descriptor */
rd->next = sizeof(struct pci_rd);
rd->flags = 0 | FLG_8BIT | FLG_16BIT | FLG_32BIT;
rd->start = mem_address;
rd->start = address;
rd->length = size;
rd->offset = 0; /* PCI_MEMORY_OFFSET; */
rd->offset = PCI_MEMORY_OFFSET;
rd->dmaoffset = 0;
/* adjust memory adress for next turn */
@@ -379,8 +425,8 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
int size = ~(address & 0xfffffffc) + 1;
xprintf("device 0x%x: BAR[%d] requests %d bytes of memory\r\n", handle, i, size);
io_address = (io_address + size - 1) & ~(size - 1);
pci_write_config_longword(handle, PCIBAR0 + i, swpl(io_address));
address = (io_address + size - 1) & ~(size - 1);
pci_write_config_longword(handle, PCIBAR0 + i, swpl(address));
value = swpl(pci_read_config_longword(handle, PCIBAR0 + i));
xprintf("set PCIBAR%d on device 0x%02x to 0x%08x\r\n",
@@ -388,8 +434,8 @@ static void pci_device_config(uint16_t bus, uint16_t device, uint16_t function)
rd->next = sizeof(struct pci_rd);
rd->flags = FLG_IO | FLG_8BIT | FLG_16BIT | FLG_32BIT | 1;
rd->start = io_address;
rd->offset = 0; /* PCI_IO_OFFSET; */
rd->start = address;
rd->offset = PCI_IO_OFFSET;
rd->length = size;
rd->dmaoffset = 0;
@@ -479,18 +525,19 @@ void init_xlbus_arbiter(void)
/* setup XL bus arbiter */
clock_ratio = (MCF_PCI_PCIGSCR >> 24) & 0x07;
if (clock_ratio == 4)
{
/* device errata 26: Flexbus hang up in 4:1 clock ratio */
MCF_PCI_PCIGSCR |= 0x80000000; /* disable pipeline */
}
MCF_XLB_XARB_CFG = MCF_XLB_XARB_CFG_BA |
MCF_XLB_XARB_CFG_DT |
MCF_XLB_XARB_CFG_AT |
MCF_XLB_XARB_CFG_PLDIS;
else
MCF_XLB_XARB_CFG = MCF_XLB_XARB_CFG_BA |
MCF_XLB_XARB_CFG_DT |
MCF_XLB_XARB_CFG_AT;
xprintf("PCIGSCR = %08x\r\n");
MCF_PCI_PCIGSCR |= 0x60000000; /* clear PERR and SERR in global status/command register */
xprintf("PCIGSCR = %08x\r\n");
/* FIXME: Firetos (boot2.S, l. 719) looks pretty strange at this place - is this a typo? */
MCF_XLB_XARB_ADRTO = 0x1fffff;
MCF_XLB_XARB_DATTO = 0x1fffff;
MCF_XLB_XARB_BUSTO = 0xffffff;
}
void init_pci(void)
@@ -503,18 +550,19 @@ void init_pci(void)
init_eport();
init_xlbus_arbiter();
/*
* setup the PCI arbiter
*/
MCF_PCIARB_PACR = MCF_PCIARB_PACR_INTMPRI
+ MCF_PCIARB_PACR_EXTMPRI(0x1F)
+ MCF_PCIARB_PACR_INTMINTEN
+ MCF_PCIARB_PACR_EXTMINTEN(0x1F);
/* Setup burst parameters */
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(4) + MCF_PCI_PCICR1_LATTIMER(16); /* TODO: test increased latency timer */
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(16) + MCF_PCI_PCICR2_MAXLAT(16);
/* Turn on error signaling, 32 write retries on failure */
MCF_PCI_PCIICR = MCF_PCI_PCIICR_REE + MCF_PCI_PCIICR_IAE + MCF_PCI_PCIICR_TAE + 32;
MCF_PCI_PCIGSCR |= MCF_PCI_PCIGSCR_SEE;
MCF_PCI_PCICR1 = MCF_PCI_PCICR1_CACHELINESIZE(32) |
MCF_PCI_PCICR1_LATTIMER(32); /* TODO: test increased latency timer */
MCF_PCI_PCICR2 = MCF_PCI_PCICR2_MINGNT(16) |
MCF_PCI_PCICR2_MAXLAT(16);
/* Configure Initiator Windows */
@@ -539,18 +587,12 @@ void init_pci(void)
/* initialize target control register */
MCF_PCI_PCITCR = 0;
value = MCF_PCI_PCISCR_M | /* memory access control enabled */
MCF_PCI_PCISCR = MCF_PCI_PCISCR_M | /* memory access control enabled */
MCF_PCI_PCISCR_B | /* bus master enabled */
MCF_PCI_PCISCR_MW | /* memory write and invalidate enabled */
MCF_PCI_PCISCR_PER | /* parity errors enabled, PERR# will be asserted */
MCF_PCI_PCISCR_S; /* SERR enabbled */
MCF_PCI_PCISCR = value;
new_value = MCF_PCI_PCISCR;
if (new_value != value)
xprintf("MCF_PCI_PCISCR wanted: %08x, got %08x\r\n", value, new_value);
/* reset PCI devices */
MCF_PCI_PCIGSCR &= ~MCF_PCI_PCIGSCR_PR;
@@ -568,4 +610,3 @@ void init_pci(void)
*/
pci_scan();
}

View File

@@ -351,7 +351,8 @@ void init_fbcs()
MCF_FBCS0_CSAR = BOOTFLASH_BASE_ADDRESS; /* flash base address */
MCF_FBCS0_CSCR = MCF_FBCS_CSCR_PS_16 | /* 16 bit word access */
MCF_FBCS_CSCR_WS(6)| /* 6 Waitstates */
MCF_FBCS_CSCR_AA; /* */
MCF_FBCS_CSCR_AA |
MCF_FBCS_CSCR_RDAH(1); /* chip errata SECF077 */
MCF_FBCS0_CSMR = BOOTFLASH_BAM |
MCF_FBCS_CSMR_V; /* enable */
@@ -394,14 +395,14 @@ void init_fbcs()
MCF_FBCS5_CSAR = 0x0;
MCF_FBCS5_CSCR = MCF_FBCS_CSCR_PS_8
| MCF_FBCS_CSCR_BSTR
| MCF_FBCS_CSCR_BSTW;
| MCF_FBCS_CSCR_BSTW
| MCF_FBCS_CSCR_RDAH(1); /* chip errata SECF077 */
MCF_FBCS5_CSMR = MCF_FBCS_CSMR_BAM_1G;
/* | MCF_FBCS_CSMR_V; */ /* not enabled */
xprintf("finished\r\n");
}
void wait_pll(void)
{
int32_t trgt = MCF_SLT0_SCNT - 100000;