diff options
author | wdenk <wdenk> | 2002-11-03 00:38:21 (GMT) |
---|---|---|
committer | wdenk <wdenk> | 2002-11-03 00:38:21 (GMT) |
commit | fe8c2806cdba70479e351299881a395dc2be7785 (patch) | |
tree | a1e8b98a1838cba6e6f5c765d9d85339257c45f5 /board/evb64260 | |
parent | f9087a3213cc245cf9b90436475b5af822bd7579 (diff) | |
download | u-boot-fsl-qoriq-fe8c2806cdba70479e351299881a395dc2be7785.tar.xz |
Initial revision
Diffstat (limited to 'board/evb64260')
-rw-r--r-- | board/evb64260/ecctest.c | 91 | ||||
-rw-r--r-- | board/evb64260/eth.h | 75 | ||||
-rw-r--r-- | board/evb64260/mpsc.c | 864 | ||||
-rw-r--r-- | board/evb64260/zuma_pbb.c | 200 | ||||
-rw-r--r-- | board/evb64260/zuma_pbb_mbox.c | 187 |
5 files changed, 1417 insertions, 0 deletions
diff --git a/board/evb64260/ecctest.c b/board/evb64260/ecctest.c new file mode 100644 index 0000000..e7c58b3 --- /dev/null +++ b/board/evb64260/ecctest.c @@ -0,0 +1,91 @@ +#ifdef ECC_TEST +static inline void ecc_off(void) +{ + *(volatile int *)(INTERNAL_REG_BASE_ADDR+0x4b4) &= ~0x00200000; +} + +static inline void ecc_on(void) +{ + *(volatile int *)(INTERNAL_REG_BASE_ADDR+0x4b4) |= 0x00200000; +} + +static int putshex(const char *buf, int len) +{ + int i; + for (i=0;i<len;i++) { + printf("%02x", buf[i]); + } + return 0; +} + +static int char_memcpy(void *d, const void *s, int len) +{ + int i; + char *cd=d; + const char *cs=s; + for(i=0;i<len;i++) { + *(cd++)=*(cs++); + } + return 0; +} + +static int memory_test(char *buf) +{ + const char src[][16]={ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01}, + {0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02}, + {0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04}, + {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08}, + {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10}, + {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}, + {0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40}, + {0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80}, + {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55}, + {0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa}, + {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff} + }; + const int foo[] = {0}; + int i,j,a; + + printf("\ntest @ %d %p\n", foo[0], buf); + for(i=0;i<12;i++) { + for(a=0;a<8;a++) { + const char *s=src[i]+a; + int align=(unsigned)(s)&0x7; + /* ecc_off(); */ + memcpy(buf,s,8); + /* ecc_on(); */ + putshex(s,8); + if(memcmp(buf,s,8)) { + putc('\n'); + putshex(buf,8); + printf(" [FAIL] (%p) align=%d\n", s, align); + for(j=0;j<8;j++) { + s[j]==buf[j]?puts(" "):printf("%02x", (s[j])^(buf[j])); + } + putc('\n'); + } else { + printf(" [PASS] (%p) align=%d\n", s, align); + } + /* ecc_off(); */ + char_memcpy(buf,s,8); + /* ecc_on(); */ + putshex(s,8); + if(memcmp(buf,s,8)) { + putc('\n'); + putshex(buf,8); + printf(" [FAIL] (%p) align=%d\n", s, align); + for(j=0;j<8;j++) { + s[j]==buf[j]?puts(" "):printf("%02x", (s[j])^(buf[j])); + } + putc('\n'); + } else { + printf(" [PASS] (%p) align=%d\n", s, align); + } + } + } + + return 0; +} +#endif diff --git a/board/evb64260/eth.h b/board/evb64260/eth.h new file mode 100644 index 0000000..ecc3762 --- /dev/null +++ b/board/evb64260/eth.h @@ -0,0 +1,75 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * eth.h - header file for the polled mode GT ethernet driver + */ + +#ifndef __GT6426x_ETH_H__ +#define __GT6426x_ETH_H__ + +#include <asm/types.h> +#include <asm/io.h> +#include <asm/byteorder.h> +#include <common.h> + +typedef struct eth0_tx_desc_struct { + volatile __u32 bytecount_reserved; + volatile __u32 command_status; + volatile struct eth0_tx_desc_struct * next_desc; + /* Note - the following will not work for 64 bit addressing */ + volatile unsigned char * buff_pointer; +} eth0_tx_desc_single __attribute__ ((packed)); + +typedef struct eth0_rx_desc_struct { + volatile __u32 buff_size_byte_count; + volatile __u32 command_status; + volatile struct eth0_rx_desc_struct * next_desc; + volatile unsigned char * buff_pointer; +} eth0_rx_desc_single __attribute__ ((packed)); + +#define NT 20 /* Number of Transmit buffers */ +#define NR 20 /* Number of Receive buffers */ +#define MAX_BUFF_SIZE (1536+2*CACHE_LINE_SIZE) /* 1600 */ +#define ETHERNET_PORTS_DIFFERENCE_OFFSETS 0x400 + +unsigned long TDN_ETH0 , RDN_ETH0; /* Rx/Tx current Descriptor Number*/ +unsigned int EVB64260_ETH0_irq; + +#define CLOSED 0 +#define OPENED 1 + +#define PORT_ETH0 0 + +extern eth0_tx_desc_single *eth0_tx_desc; +extern eth0_rx_desc_single *eth0_rx_desc; +extern char *eth0_tx_buffer; +extern char *eth0_rx_buffer[NR]; +extern char *eth_data; + +extern int gt6426x_eth_poll(void *v); +extern int gt6426x_eth_transmit(void *v, volatile char *p, unsigned int s); +extern void gt6426x_eth_disable(void *v); +extern int gt6426x_eth_probe(void *v, bd_t *bis); + +#endif /* __GT64260x_ETH_H__ */ diff --git a/board/evb64260/mpsc.c b/board/evb64260/mpsc.c new file mode 100644 index 0000000..31a6a0d --- /dev/null +++ b/board/evb64260/mpsc.c @@ -0,0 +1,864 @@ +/* + * (C) Copyright 2001 + * John Clemens <clemens@mclx.com>, Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * mpsc.c - driver for console over the MPSC. + */ + +#include <common.h> +#include <config.h> +#include <asm/cache.h> + +#include <malloc.h> +#include "mpsc.h" + +int (*mpsc_putchar)(char ch) = mpsc_putchar_early; + +static volatile unsigned int *rx_desc_base=NULL; +static unsigned int rx_desc_index=0; +static volatile unsigned int *tx_desc_base=NULL; +static unsigned int tx_desc_index=0; + +/* local function declarations */ +static int galmpsc_connect(int channel, int connect); +static int galmpsc_route_serial(int channel, int connect); +static int galmpsc_route_rx_clock(int channel, int brg); +static int galmpsc_route_tx_clock(int channel, int brg); +static int galmpsc_write_config_regs(int mpsc, int mode); +static int galmpsc_config_channel_regs(int mpsc); +static int galmpsc_set_char_length(int mpsc, int value); +static int galmpsc_set_stop_bit_length(int mpsc, int value); +static int galmpsc_set_parity(int mpsc, int value); +static int galmpsc_enter_hunt(int mpsc); +static int galmpsc_set_brkcnt(int mpsc, int value); +static int galmpsc_set_tcschar(int mpsc, int value); +static int galmpsc_set_snoop(int mpsc, int value); +static int galmpsc_shutdown(int mpsc); + +static int galsdma_set_RFT(int channel); +static int galsdma_set_SFM(int channel); +static int galsdma_set_rxle(int channel); +static int galsdma_set_txle(int channel); +static int galsdma_set_burstsize(int channel, unsigned int value); +static int galsdma_set_RC(int channel, unsigned int value); + +static int galbrg_set_CDV(int channel, int value); +static int galbrg_enable(int channel); +static int galbrg_disable(int channel); +static int galbrg_set_clksrc(int channel, int value); +static int galbrg_set_CUV(int channel, int value); + +static void galsdma_enable_rx(void); + +/* static int galbrg_reset(int channel); */ + +#define SOFTWARE_CACHE_MANAGEMENT + +#ifdef SOFTWARE_CACHE_MANAGEMENT +#define FLUSH_DCACHE(a,b) if(dcache_status()){clean_dcache_range((u32)(a),(u32)(b));} +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) if(dcache_status()){flush_dcache_range((u32)(a),(u32)(b));} +#define INVALIDATE_DCACHE(a,b) if(dcache_status()){invalidate_dcache_range((u32)(a),(u32)(b));} +#else +#define FLUSH_DCACHE(a,b) +#define FLUSH_AND_INVALIDATE_DCACHE(a,b) +#define INVALIDATE_DCACHE(a,b) +#endif + + +/* GT64240A errata: cant read MPSC/BRG registers... so make mirrors in ram for read/modify write */ +#define MIRROR_HACK ((struct _tag_mirror_hack *)&(gd->mirror_hack)) + +#define GT_REG_WRITE_MIRROR_G(a,d) {MIRROR_HACK->a ## _M = d; GT_REG_WRITE(a,d);} +#define GTREGREAD_MIRROR_G(a) (MIRROR_HACK->a ## _M) + +#define GT_REG_WRITE_MIRROR(a,i,g,d) {MIRROR_HACK->a ## _M[i] = d; GT_REG_WRITE(a + (i*g),d);} +#define GTREGREAD_MIRROR(a,i,g) (MIRROR_HACK->a ## _M[i]) + +/* make sure this isn't bigger than 16 long words (u-boot.h) */ +struct _tag_mirror_hack { + unsigned GALMPSC_PROTOCONF_REG_M[2]; /* 8008 */ + unsigned GALMPSC_CHANNELREG_1_M[2]; /* 800c */ + unsigned GALMPSC_CHANNELREG_2_M[2]; /* 8010 */ + unsigned GALBRG_0_CONFREG_M[2]; /* b200 */ + + unsigned GALMPSC_ROUTING_REGISTER_M; /* b400 */ + unsigned GALMPSC_RxC_ROUTE_M; /* b404 */ + unsigned GALMPSC_TxC_ROUTE_M; /* b408 */ + + unsigned int baudrate; /* current baudrate, for tsc delay calc */ +}; + +/* static struct _tag_mirror_hack *mh = NULL; */ + +/* special function for running out of flash. doesn't modify any + * global variables [josh] */ +int +mpsc_putchar_early(char ch) +{ + DECLARE_GLOBAL_DATA_PTR; + int mpsc=CHANNEL; + int temp=GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + galmpsc_set_tcschar(mpsc,ch); + GT_REG_WRITE(GALMPSC_CHANNELREG_2+(mpsc*GALMPSC_REG_GAP), temp|0x200); + +#define MAGIC_FACTOR (10*1000000) + + udelay(MAGIC_FACTOR / MIRROR_HACK->baudrate); + return 0; +} + +/* This is used after relocation, see serial.c and mpsc_init2 */ +static int +mpsc_putchar_sdma(char ch) +{ + volatile unsigned int *p; + unsigned int temp; + + + /* align the descriptor */ + p = tx_desc_base; + memset((void *)p, 0, 8 * sizeof(unsigned int)); + + /* fill one 64 bit buffer */ + /* word swap, pad with 0 */ + p[4] = 0; /* x */ + p[5] = (unsigned int)ch; /* x */ + + /* CHANGED completely according to GT64260A dox - NTL */ + p[0] = 0x00010001; /* 0 */ + p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* 4 */ + p[2] = 0; /* 8 */ + p[3] = (unsigned int)&p[4]; /* c */ + +#if 0 + p[9] = DESC_FIRST | DESC_LAST; + p[10] = (unsigned int)&p[0]; + p[11] = (unsigned int)&p[12]; +#endif + + FLUSH_DCACHE(&p[0], &p[8]); + + GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&p[0]); + GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&p[0]); + + temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF)); + temp |= (TX_DEMAND | TX_STOP); + GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp); + + INVALIDATE_DCACHE(&p[1], &p[2]); + + while(p[1] & DESC_OWNER) { + udelay(100); + INVALIDATE_DCACHE(&p[1], &p[2]); + } + + return 0; +} + +char +mpsc_getchar(void) +{ + DECLARE_GLOBAL_DATA_PTR; + static unsigned int done = 0; + volatile char ch; + unsigned int len=0, idx=0, temp; + + volatile unsigned int *p; + + + do { + p=&rx_desc_base[rx_desc_index*8]; + + INVALIDATE_DCACHE(&p[0], &p[1]); + /* Wait for character */ + while (p[1] & DESC_OWNER){ + udelay(100); + INVALIDATE_DCACHE(&p[0], &p[1]); + } + + /* Handle error case */ + if (p[1] & (1<<15)) { + printf("oops, error: %08x\n", p[1]); + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,CHANNEL,GALMPSC_REG_GAP); + temp |= (1 << 23); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2, CHANNEL,GALMPSC_REG_GAP, temp); + + /* Can't poll on abort bit, so we just wait. */ + udelay(100); + + galsdma_enable_rx(); + } + + /* Number of bytes left in this descriptor */ + len = p[0] & 0xffff; + + if (len) { + /* Where to look */ + idx = 5; + if (done > 3) idx = 4; + if (done > 7) idx = 7; + if (done > 11) idx = 6; + + INVALIDATE_DCACHE(&p[idx], &p[idx+1]); + ch = p[idx] & 0xff; + done++; + } + + if (done < len) { + /* this descriptor has more bytes still + * shift down the char we just read, and leave the + * buffer in place for the next time around + */ + p[idx] = p[idx] >> 8; + FLUSH_DCACHE(&p[idx], &p[idx+1]); + } + + if (done == len) { + /* nothing left in this descriptor. + * go to next one + */ + p[1] = DESC_OWNER | DESC_FIRST | DESC_LAST; + p[0] = 0x00100000; + FLUSH_DCACHE(&p[0], &p[1]); + /* Next descriptor */ + rx_desc_index = (rx_desc_index + 1) % RX_DESC; + done = 0; + } + } while (len==0); /* galileo bug.. len might be zero */ + + return ch; +} + +int +mpsc_test_char(void) +{ + volatile unsigned int *p=&rx_desc_base[rx_desc_index*8]; + + INVALIDATE_DCACHE(&p[1], &p[2]); + + if (p[1] & DESC_OWNER) return 0; + else return 1; +} + +int +mpsc_init(int baud) +{ + DECLARE_GLOBAL_DATA_PTR; + + memset(MIRROR_HACK, 0, sizeof(struct _tag_mirror_hack)); + MIRROR_HACK->GALMPSC_ROUTING_REGISTER_M=0x3fffffff; + + /* BRG CONFIG */ + galbrg_set_baudrate(CHANNEL, baud); +#ifdef CONFIG_ZUMA_V2 + galbrg_set_clksrc(CHANNEL,0x8); /* connect TCLK -> BRG */ +#else + galbrg_set_clksrc(CHANNEL,0); +#endif + galbrg_set_CUV(CHANNEL, 0); + galbrg_enable(CHANNEL); + + /* Set up clock routing */ + galmpsc_connect(CHANNEL, GALMPSC_CONNECT); + galmpsc_route_serial(CHANNEL, GALMPSC_CONNECT); + galmpsc_route_rx_clock(CHANNEL, CHANNEL); + galmpsc_route_tx_clock(CHANNEL, CHANNEL); + + /* reset MPSC state */ + galmpsc_shutdown(CHANNEL); + + /* SDMA CONFIG */ + galsdma_set_burstsize(CHANNEL, L1_CACHE_BYTES/8); /* in 64 bit words (8 bytes) */ + galsdma_set_txle(CHANNEL); + galsdma_set_rxle(CHANNEL); + galsdma_set_RC(CHANNEL, 0xf); + galsdma_set_SFM(CHANNEL); + galsdma_set_RFT(CHANNEL); + + /* MPSC CONFIG */ + galmpsc_write_config_regs(CHANNEL, GALMPSC_UART); + galmpsc_config_channel_regs(CHANNEL); + galmpsc_set_char_length(CHANNEL, GALMPSC_CHAR_LENGTH_8); /* 8 */ + galmpsc_set_parity(CHANNEL, GALMPSC_PARITY_NONE); /* N */ + galmpsc_set_stop_bit_length(CHANNEL, GALMPSC_STOP_BITS_1); /* 1 */ + + /* COMM_MPSC CONFIG */ +#ifdef SOFTWARE_CACHE_MANAGEMENT + galmpsc_set_snoop(CHANNEL, 0); /* disable snoop */ +#else + galmpsc_set_snoop(CHANNEL, 1); /* enable snoop */ +#endif + + return 0; +} + +void +mpsc_init2(void) +{ + int i; + + mpsc_putchar = mpsc_putchar_sdma; + + /* RX descriptors */ + rx_desc_base = (unsigned int *)malloc(((RX_DESC+1)*8) * + sizeof(unsigned int)); + + /* align descriptors */ + rx_desc_base = (unsigned int *) + (((unsigned int)rx_desc_base+32) & 0xFFFFFFF0); + + rx_desc_index = 0; + + memset((void *)rx_desc_base, 0, (RX_DESC*8)*sizeof(unsigned int)); + + for (i = 0; i < RX_DESC; i++) { + rx_desc_base[i*8 + 3] = (unsigned int)&rx_desc_base[i*8 + 4]; /* Buffer */ + rx_desc_base[i*8 + 2] = (unsigned int)&rx_desc_base[(i+1)*8]; /* Next descriptor */ + rx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST; /* Command & control */ + rx_desc_base[i*8] = 0x00100000; + } + rx_desc_base[(i-1)*8 + 2] = (unsigned int)&rx_desc_base[0]; + + FLUSH_DCACHE(&rx_desc_base[0], &rx_desc_base[RX_DESC*8]); + GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR+(CHANNEL*GALSDMA_REG_DIFF), + (unsigned int)&rx_desc_base[0]); + + /* TX descriptors */ + tx_desc_base = (unsigned int *)malloc(((TX_DESC+1)*8) * + sizeof(unsigned int)); + + /* align descriptors */ + tx_desc_base = (unsigned int *) + (((unsigned int)tx_desc_base+32) & 0xFFFFFFF0); + + tx_desc_index = -1; + + memset((void *)tx_desc_base, 0, (TX_DESC*8)*sizeof(unsigned int)); + + for (i = 0; i < TX_DESC; i++) { + tx_desc_base[i*8 + 5] = (unsigned int)0x23232323; + tx_desc_base[i*8 + 4] = (unsigned int)0x23232323; + tx_desc_base[i*8 + 3] = (unsigned int)&tx_desc_base[i*8 + 4]; + tx_desc_base[i*8 + 2] = (unsigned int)&tx_desc_base[(i+1)*8]; + tx_desc_base[i*8 + 1] = DESC_OWNER | DESC_FIRST | DESC_LAST; + + /* set sbytecnt and shadow byte cnt to 1 */ + tx_desc_base[i*8] = 0x00010001; + } + tx_desc_base[(i-1)*8 + 2] = (unsigned int)&tx_desc_base[0]; + + FLUSH_DCACHE(&tx_desc_base[0], &tx_desc_base[TX_DESC*8]); + + udelay(100); + + galsdma_enable_rx(); + + return; +} + +int +galbrg_set_baudrate(int channel, int rate) +{ + DECLARE_GLOBAL_DATA_PTR; + int clock; + + galbrg_disable(channel); + +#ifdef CONFIG_ZUMA_V2 + /* from tclk */ + clock = (CFG_BUS_HZ/(16*rate)) - 1; +#else + clock = (3686400/(16*rate)) - 1; +#endif + + galbrg_set_CDV(channel, clock); + + galbrg_enable(channel); + + MIRROR_HACK->baudrate = rate; + + return 0; +} + +/* ------------------------------------------------------------------ */ + +/* Below are all the private functions that no one else needs */ + +static int +galbrg_set_CDV(int channel, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp &= 0xFFFF0000; + temp |= (value & 0x0000FFFF); + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel,GALBRG_REG_GAP, temp); + + return 0; +} + +static int +galbrg_enable(int channel) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp |= 0x00010000; + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_disable(int channel) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP); + temp &= 0xFFFEFFFF; + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG, channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_set_clksrc(int channel, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP); + temp &= 0xFF83FFFF; + temp |= (value << 18); + GT_REG_WRITE_MIRROR(GALBRG_0_CONFREG,channel, GALBRG_REG_GAP,temp); + + return 0; +} + +static int +galbrg_set_CUV(int channel, int value) +{ + GT_REG_WRITE(GALBRG_0_BTREG + (channel * GALBRG_REG_GAP), value); + + return 0; +} + +#if 0 +static int +galbrg_reset(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP)); + temp |= 0x20000; + GT_REG_WRITE(GALBRG_0_CONFREG + (channel * GALBRG_REG_GAP), temp); + + return 0; +} +#endif + +static int +galsdma_set_RFT(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000001; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_SFM(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000002; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_rxle(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000040; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_txle(int channel) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp |= 0x00000080; + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_RC(int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp &= ~0x0000003c; + temp |= (value << 2); + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), temp); + + return 0; +} + +static int +galsdma_set_burstsize(int channel, unsigned int value) +{ + unsigned int temp; + + temp = GTREGREAD(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF)); + temp &= 0xFFFFCFFF; + switch (value) { + case 8: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x3 << 12))); + break; + + case 4: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x2 << 12))); + break; + + case 2: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x1 << 12))); + break; + + case 1: + GT_REG_WRITE(GALSDMA_0_CONF_REG+(channel*GALSDMA_REG_DIFF), + (temp | (0x0 << 12))); + break; + + default: + return -1; + break; + } + + return 0; +} + +static int +galmpsc_connect(int channel, int connect) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_ROUTING_REGISTER); + + if ((channel == 0) && connect) + temp &= ~0x00000007; + else if ((channel == 1) && connect) + temp &= ~(0x00000007 << 6); + else if ((channel == 0) && !connect) + temp |= 0x00000007; + else + temp |= (0x00000007 << 6); + + /* Just in case... */ + temp &= 0x3fffffff; + + GT_REG_WRITE_MIRROR_G(GALMPSC_ROUTING_REGISTER, temp); + + return 0; +} + +static int +galmpsc_route_serial(int channel, int connect) +{ + unsigned int temp; + + temp = GTREGREAD(GALMPSC_SERIAL_MULTIPLEX); + + if ((channel == 0) && connect) + temp |= 0x00000100; + else if ((channel == 1) && connect) + temp |= 0x00001000; + else if ((channel == 0) && !connect) + temp &= ~0x00000100; + else + temp &= ~0x00001000; + + GT_REG_WRITE(GALMPSC_SERIAL_MULTIPLEX,temp); + + return 0; +} + +static int +galmpsc_route_rx_clock(int channel, int brg) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_RxC_ROUTE); + + if (channel == 0) + temp |= brg; + else + temp |= (brg << 8); + + GT_REG_WRITE_MIRROR_G(GALMPSC_RxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_route_tx_clock(int channel, int brg) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR_G(GALMPSC_TxC_ROUTE); + + if (channel == 0) + temp |= brg; + else + temp |= (brg << 8); + + GT_REG_WRITE_MIRROR_G(GALMPSC_TxC_ROUTE,temp); + + return 0; +} + +static int +galmpsc_write_config_regs(int mpsc, int mode) +{ + if (mode == GALMPSC_UART) { + /* Main config reg Low (Null modem, Enable Tx/Rx, UART mode) */ + GT_REG_WRITE(GALMPSC_MCONF_LOW + (mpsc*GALMPSC_REG_GAP), + 0x000004c4); + + /* Main config reg High (32x Rx/Tx clock mode, width=8bits */ + GT_REG_WRITE(GALMPSC_MCONF_HIGH +(mpsc*GALMPSC_REG_GAP), + 0x024003f8); + /* 22 2222 1111 */ + /* 54 3210 9876 */ + /* 0000 0010 0000 0000 */ + /* 1 */ + /* 098 7654 3210 */ + /* 0000 0011 1111 1000 */ + } else + return -1; + + return 0; +} + +static int +galmpsc_config_channel_regs(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, 0); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_3+(mpsc*GALMPSC_REG_GAP), 1); + GT_REG_WRITE(GALMPSC_CHANNELREG_4+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_5+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_6+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_7+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_8+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_9+(mpsc*GALMPSC_REG_GAP), 0); + GT_REG_WRITE(GALMPSC_CHANNELREG_10+(mpsc*GALMPSC_REG_GAP), 0); + + galmpsc_set_brkcnt(mpsc, 0x3); + galmpsc_set_tcschar(mpsc, 0xab); + + return 0; +} + +static int +galmpsc_set_brkcnt(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP); + temp &= 0x0000FFFF; + temp |= (value << 16); + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_tcschar(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP); + temp &= 0xFFFF0000; + temp |= value; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_1,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_char_length(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP); + temp &= 0xFFFFCFFF; + temp |= (value << 12); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_set_stop_bit_length(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP); + temp |= (value << 14); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG,mpsc,GALMPSC_REG_GAP,temp); + + return 0; +} + +static int +galmpsc_set_parity(int mpsc, int value) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + if (value != -1) { + temp &= 0xFFF3FFF3; + temp |= ((value << 18) | (value << 2)); + temp |= ((value << 17) | (value << 1)); + } else { + temp &= 0xFFF1FFF1; + } + + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp); + + return 0; +} + +static int +galmpsc_enter_hunt(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + int temp; + + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + temp |= 0x80000000; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP, temp); + + /* Should Poll on Enter Hunt bit, but the register is write-only */ + /* errata suggests pausing 100 system cycles */ + udelay(100); + + return 0; +} + + +static int +galmpsc_shutdown(int mpsc) +{ + DECLARE_GLOBAL_DATA_PTR; + unsigned int temp; + + /* cause RX abort (clears RX) */ + temp = GTREGREAD_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP); + temp |= MPSC_RX_ABORT | MPSC_TX_ABORT; + temp &= ~MPSC_ENTER_HUNT; + GT_REG_WRITE_MIRROR(GALMPSC_CHANNELREG_2,mpsc,GALMPSC_REG_GAP,temp); + + GT_REG_WRITE(GALSDMA_0_COM_REG, 0); + GT_REG_WRITE(GALSDMA_0_COM_REG, SDMA_TX_ABORT | SDMA_RX_ABORT); + + /* shut down the MPSC */ + GT_REG_WRITE(GALMPSC_MCONF_LOW, 0); + GT_REG_WRITE(GALMPSC_MCONF_HIGH, 0); + GT_REG_WRITE_MIRROR(GALMPSC_PROTOCONF_REG, mpsc, GALMPSC_REG_GAP,0); + + udelay(100); + + /* shut down the sdma engines. */ + /* reset config to default */ + GT_REG_WRITE(GALSDMA_0_CONF_REG, 0x000000fc); + + udelay(100); + + /* clear the SDMA current and first TX and RX pointers */ + GT_REG_WRITE(GALSDMA_0_CUR_RX_PTR, 0); + GT_REG_WRITE(GALSDMA_0_CUR_TX_PTR, 0); + GT_REG_WRITE(GALSDMA_0_FIR_TX_PTR, 0); + + udelay(100); + + return 0; +} + +static void +galsdma_enable_rx(void) +{ + int temp; + + /* Enable RX processing */ + temp = GTREGREAD(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF)); + temp |= RX_ENABLE; + GT_REG_WRITE(GALSDMA_0_COM_REG+(CHANNEL*GALSDMA_REG_DIFF), temp); + + galmpsc_enter_hunt(CHANNEL); +} + +static int +galmpsc_set_snoop(int mpsc, int value) +{ + int reg = mpsc ? MPSC_1_ADDRESS_CONTROL_LOW : MPSC_0_ADDRESS_CONTROL_LOW; + int temp=GTREGREAD(reg); + if(value) + temp |= (1<< 6) | (1<<14) | (1<<22) | (1<<30); + else + temp &= ~((1<< 6) | (1<<14) | (1<<22) | (1<<30)); + GT_REG_WRITE(reg, temp); + return 0; +} diff --git a/board/evb64260/zuma_pbb.c b/board/evb64260/zuma_pbb.c new file mode 100644 index 0000000..10c4845 --- /dev/null +++ b/board/evb64260/zuma_pbb.c @@ -0,0 +1,200 @@ +#include <common.h> +#include <malloc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) +#include <command.h> +#include <cmd_bsp.h> +#endif + +#include <pci.h> +#include <galileo/pci.h> +#include "zuma_pbb.h" + +#undef DEBUG + +#define PAT_LO 0x00010203 +#define PAT_HI 0x04050607 + +static PBB_DMA_REG_MAP *zuma_pbb_reg = NULL; + +static char test_buf1[2048]; +static char test_buf2[2048]; + +int zuma_test_dma (int cmd, int size) +{ + static const char *const test_legend[] = { + "write", "verify", + "copy", "compare", + "write inc", "verify inc" + }; + register int i, j; + unsigned int p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff); + unsigned int p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff); + volatile unsigned int *ps = (unsigned int *) p1; + volatile unsigned int *pd = (unsigned int *) p2; + unsigned int funct, pat_lo = PAT_LO, pat_hi = PAT_HI; + DMA_INT_STATUS stat; + int ret = 0; + + if (!zuma_pbb_reg) { + printf ("not initted\n"); + return -1; + } + + if (cmd < 0 || cmd > 5) { + printf ("inv cmd %d\n", cmd); + return -1; + } + + if (cmd == 2 || cmd == 3) { + /* not implemented */ + return 0; + } + + if (size <= 0 || size > 1024) + size = 1024; + + size &= (~7); /* throw away bottom 3 bits */ + + p1 = ((unsigned int) test_buf1 + 0xff) & (~0xff); + p2 = ((unsigned int) test_buf2 + 0xff) & (~0xff); + + memset ((void *) p1, 0, size); + memset ((void *) p2, 0, size); + + for (i = 0; i < size / 4; i += 2) { + ps[i] = pat_lo; + ps[i + 1] = pat_hi; + if (cmd == 4 || cmd == 5) { + unsigned char *pl = (unsigned char *) &pat_lo; + unsigned char *ph = (unsigned char *) &pat_hi; + + for (j = 0; j < 4; j++) { + pl[j] += 8; + ph[j] += 8; + } + } + } + + funct = (1 << 31) | (cmd << 24) | (size); + + zuma_pbb_reg->int_mask.pci_bits.chan0 = + EOF_RX_FLAG | EOF_TX_FLAG | EOB_TX_FLAG; + + zuma_pbb_reg->debug_57 = PAT_LO; /* patl */ + zuma_pbb_reg->debug_58 = PAT_HI; /* path */ + + zuma_pbb_reg->debug_54 = cpu_to_le32 (p1); /* src 0x01b0 */ + zuma_pbb_reg->debug_55 = cpu_to_le32 (p2); /* dst 0x01b8 */ + zuma_pbb_reg->debug_56 = cpu_to_le32 (funct); /* func, 0x01c0 */ + + /* give DMA time to chew on things.. dont use DRAM or PCI */ + /* if you can avoid it. */ + do { + for (i = 0; i < 1000 * 10; i++); + } while (le32_to_cpu (zuma_pbb_reg->debug_56) & (1 << 31)); + + stat.word = zuma_pbb_reg->status.word; + zuma_pbb_reg->int_mask.word = 0; + + printf ("stat: %08x (%x)\n", stat.word, stat.pci_bits.chan0); + + printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56)); + printf ("src @%08x: %08x %08x %08x %08x\n", p1, ps[0], ps[1], ps[2], + ps[3]); + printf ("dst @%08x: %08x %08x %08x %08x\n", p2, pd[0], pd[1], pd[2], + pd[3]); + printf ("func: %08x\n", le32_to_cpu (zuma_pbb_reg->debug_56)); + + + if (cmd == 0 || cmd == 4) { + /* this is a write */ + if (!(stat.pci_bits.chan0 & EOF_RX_FLAG) || /* not done */ + (memcmp ((void *) ps, (void *) pd, size) != 0)) { /* cmp error */ + for (i = 0; i < size / 4; i += 2) { + if ((ps[i] != pd[i]) || (ps[i + 1] != pd[i + 1])) { + printf ("s @%p:%08x %08x\n", &ps[i], ps[i], ps[i + 1]); + printf ("d @%p:%08x %08x\n", &pd[i], pd[i], pd[i + 1]); + } + } + ret = -1; + } + } else { + /* this is a verify */ + if (!(stat.pci_bits.chan0 & EOF_TX_FLAG) || /* not done */ + (stat.pci_bits.chan0 & EOB_TX_FLAG)) { /* cmp error */ + printf ("%08x: %08x %08x\n", + le32_to_cpu (zuma_pbb_reg->debug_63), + zuma_pbb_reg->debug_61, zuma_pbb_reg->debug_62); + ret = -1; + } + } + + printf ("%s cmd %d, %d bytes: %s!\n", test_legend[cmd], cmd, size, + (ret == 0) ? "PASSED" : "FAILED"); + return 0; +} + +void zuma_init_pbb (void) +{ + unsigned int iobase; + pci_dev_t dev = + pci_find_device (VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0); + + if (dev == -1) { + printf ("no zuma pbb\n"); + return; + } + + pci_read_config_dword (dev, PCI_BASE_ADDRESS_0, &iobase); + + zuma_pbb_reg = + (PBB_DMA_REG_MAP *) (iobase & PCI_BASE_ADDRESS_MEM_MASK); + + if (!zuma_pbb_reg) { + printf ("zuma pbb bar none! (hah hah, get it?)\n"); + return; + } + + zuma_pbb_reg->int_mask.word = 0; + + printf ("pbb @ %p v%d.%d, timestamp %08x\n", zuma_pbb_reg, + zuma_pbb_reg->version.pci_bits.rev_major, + zuma_pbb_reg->version.pci_bits.rev_minor, + zuma_pbb_reg->timestamp); + +} + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +static int last_cmd = 4; /* write increment */ +static int last_size = 64; + +int +do_zuma_init_pbb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + zuma_init_pbb (); + return 0; +} + +int +do_zuma_test_dma (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc > 1) { + last_cmd = simple_strtoul (argv[1], NULL, 10); + } + if (argc > 2) { + last_size = simple_strtoul (argv[2], NULL, 10); + } + zuma_test_dma (last_cmd, last_size); + return 0; +} + +int +do_zuma_init_mbox (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + zuma_mbox_init (); + return 0; +} + +#endif /* CFG_CMD_BSP */ diff --git a/board/evb64260/zuma_pbb_mbox.c b/board/evb64260/zuma_pbb_mbox.c new file mode 100644 index 0000000..5131339 --- /dev/null +++ b/board/evb64260/zuma_pbb_mbox.c @@ -0,0 +1,187 @@ +#include <common.h> +#include <galileo/pci.h> +#include <net.h> +#include <pci.h> + +#include "zuma_pbb.h" +#include "zuma_pbb_mbox.h" + + +struct _zuma_mbox_dev zuma_mbox_dev; + + +static int zuma_mbox_write(struct _zuma_mbox_dev *dev, unsigned int data) +{ + unsigned int status, count = 0, i; + + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + + while((status & OUT_PENDING) && count < 1000) { + count++; + for(i=0;i<1000;i++); + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + } + if(count < 1000) { + /* if SET it means msg pending */ + /* printf("mbox real write %08x\n",data); */ + dev->sip->mbox_out = cpu_to_le32(data); + return 4; + } + + printf("mbox tx timeout\n"); + return 0; +} + +static int zuma_mbox_read(struct _zuma_mbox_dev *dev, unsigned int *data) +{ + unsigned int status, count = 0, i; + + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + + while(!(status & IN_VALID) && count < 1000) { + count++; + for(i=0;i<1000;i++); + status = (volatile int)le32_to_cpu(dev->sip->mbox_status); + } + if(count < 1000) { + /* if SET it means msg pending */ + *data=le32_to_cpu(dev->sip->mbox_in); + /*printf("mbox real read %08x\n", *data); */ + return 4; + } + printf("mbox rx timeout\n"); + return 0; +} + +static int zuma_mbox_do_one_mailbox(unsigned int out, unsigned int *in) +{ + int ret; + ret=zuma_mbox_write(&zuma_mbox_dev,out); + /*printf("write 0x%08x (%d bytes)\n", out, ret); */ + if(ret!=4) return -1; + ret=zuma_mbox_read(&zuma_mbox_dev,in); + /*printf("read 0x%08x (%d bytes)\n", *in, ret); */ + if(ret!=4) return -1; + return 0; +} + + +#define RET_IF_FAILED(x) if ((x) == -1) return -1 + +static int zuma_mbox_do_all_mailbox(void) +{ + unsigned int data_in; + unsigned short sdata_in; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_START, &data_in)); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACL, &data_in)); + memcpy(zuma_acc_mac+2,&data_in,4); + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_MACH, &data_in)); + sdata_in=data_in&0xffff; + memcpy(zuma_acc_mac,&sdata_in,2); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_IP, &data_in)); + zuma_ip=data_in; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_SLOT, &data_in)); + zuma_slot_bac=data_in>>3; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_BAUD, &data_in)); + zuma_console_baud = data_in & 0xffff; + zuma_debug_baud = data_in >> 16; + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_ENG_PRV_MACL, &data_in)); + memcpy(zuma_prv_mac+2,&data_in,4); + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_ENG_PRV_MACH, &data_in)); + sdata_in=data_in&0xffff; + memcpy(zuma_prv_mac,&sdata_in,2); + + RET_IF_FAILED(zuma_mbox_do_one_mailbox(ZUMA_MBOXMSG_DONE, &data_in)); + + return 0; +} + + +static void +zuma_mbox_dump(void) +{ + printf("ACC MAC=%04x%08x\n",*(unsigned short *)(&zuma_acc_mac),*(unsigned int *)((char *)&zuma_acc_mac+2)); + printf("PRV MAC=%04x%08x\n",*(unsigned short *)(&zuma_prv_mac),*(unsigned int *)((char *)&zuma_prv_mac+2)); + printf("slot:bac=%d:%d\n",(zuma_slot_bac>>2)&0xf, zuma_slot_bac & 0x3); + printf("BAUD1=%d BAUD2=%d\n",zuma_console_baud,zuma_debug_baud); +} + + +static void +zuma_mbox_setenv(void) +{ + unsigned char *data, buf[32]; + unsigned char save = 0; + + data = getenv("baudrate"); + + if(!data || (zuma_console_baud != simple_strtoul(data, NULL, 10))) { + sprintf(buf, "%6d", zuma_console_baud); + setenv("baudrate", buf); + save=1; + printf("baudrate doesn't match from mbox\n"); + } + + ip_to_string(zuma_ip, buf); + setenv("ipaddr", buf); + + sprintf(buf,"%02x:%02x:%02x:%02x:%02x:%02x", + zuma_prv_mac[0], + zuma_prv_mac[1], + zuma_prv_mac[2], + zuma_prv_mac[3], + zuma_prv_mac[4], + zuma_prv_mac[5]); + setenv("ethaddr", buf); + + sprintf(buf,"%02x",zuma_slot_bac); + setenv("bacslot", buf); + + if(save) + saveenv(); +} + +/** + * zuma_mbox_init: + */ + +int zuma_mbox_init(void) +{ + unsigned int iobase; + memset(&zuma_mbox_dev, 0, sizeof(struct _zuma_mbox_dev)); + + zuma_mbox_dev.dev = pci_find_device(VENDOR_ID_ZUMA, DEVICE_ID_ZUMA_PBB, 0); + + if(zuma_mbox_dev.dev == -1) { + printf("no zuma pbb\n"); + return -1; + } + + pci_read_config_dword(zuma_mbox_dev.dev, PCI_BASE_ADDRESS_0, &iobase); + + zuma_mbox_dev.sip = (PBB_DMA_REG_MAP *) (iobase & PCI_BASE_ADDRESS_MEM_MASK); + + zuma_mbox_dev.sip->int_mask.word=0; + + printf("pbb @ %p v%d.%d, timestamp %08x\n", zuma_mbox_dev.sip, + zuma_mbox_dev.sip->version.pci_bits.rev_major, + zuma_mbox_dev.sip->version.pci_bits.rev_minor, + zuma_mbox_dev.sip->timestamp); + + if (zuma_mbox_do_all_mailbox() == -1) { + printf("mailbox failed.. no ACC?\n"); + return -1; + } + + zuma_mbox_dump(); + + zuma_mbox_setenv(); + + return 0; +} |