/* * $Id: bcm1250.c,v 1.6 2002/11/01 10:54:52 telka Exp $ * * Copyright (C) 2002 ETC s.r.o. * * 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. * * Written by Marcel Telka , 2002. * */ #include #include #include "part.h" #include "bus.h" int bcm1250_ejtag_do(parts *, uint64_t, uint64_t, int, int, unsigned char *, int); static void setup_address( part *p, uint32_t a ) { int i; char buff[10]; for (i = 0; i < 24; i++) { sprintf( buff, "IO_AD%d", i ); part_set_signal( p, buff, 1, (a >> i) & 1 ); } } static void set_data_in( part *p ) { int i; char buff[10]; for (i = 0; i < 8; i++) { sprintf( buff, "IO_AD%d", i+24 ); part_set_signal( p, buff, 0, 0 ); } } static void setup_data( part *p, uint32_t d ) { int i; char buff[10]; for (i = 0; i < 8; i++) { sprintf( buff, "IO_AD%d", i+24 ); part_set_signal( p, buff, 1, (d >> i) & 1 ); } } #if 0 void bcm1250_bus_read_start( parts *ps, uint32_t adr ) { /* see Figure 10-12 in SA doc */ part *p = ps->parts[0]; part_set_signal( p, "IO_CS_L0", 1, 0 ); part_set_signal( p, "IO_CS_L1", 1, 1 ); part_set_signal( p, "IO_CS_L2", 1, 1 ); part_set_signal( p, "IO_CS_L3", 1, 1 ); part_set_signal( p, "IO_CS_L4", 1, 1 ); part_set_signal( p, "IO_CS_L5", 1, 1 ); part_set_signal( p, "IO_CS_L6", 1, 1 ); part_set_signal( p, "IO_CS_L7", 1, 1 ); part_set_signal( p, "IO_RW", 1, 1 ); part_set_signal( p, "IO_WR_L", 1, 1 ); part_set_signal( p, "IO_OE_L", 1, 0 ); setup_address( p, adr ); set_data_in( p ); parts_shift_data_registers( ps ); } uint32_t bcm1250_bus_read_next( parts *ps, uint32_t adr ) { /* see Figure 10-12 in SA doc */ part *p = ps->parts[0]; setup_address( p, adr ); parts_shift_data_registers( ps ); { int i; char buff[10]; uint32_t d = 0; for (i = 0; i < 8; i++) { sprintf( buff, "IO_AD%d", i+24 ); d |= (uint32_t) (part_get_signal( p, buff ) << i); } return d; } } uint32_t bcm1250_bus_read_end( parts *ps ) { /* see Figure 10-12 in SA doc */ part *p = ps->parts[0]; part_set_signal( p, "IO_CS_L0", 1, 1 ); part_set_signal( p, "IO_OE_L", 1, 1 ); parts_shift_data_registers( ps ); { int i; char buff[10]; uint32_t d = 0; for (i = 0; i < 8; i++) { sprintf( buff, "IO_AD%d", i+24 ); d |= (uint32_t) (part_get_signal( p, buff ) << i); } return d; } } uint32_t bcm1250_bus_read( parts *ps, uint32_t adr ) { bcm1250_bus_read_start( ps, adr ); return bcm1250_bus_read_end( ps ); } void bcm1250_bus_write( parts *ps, uint32_t adr, uint32_t data ) { /* see Figure 10-16 in SA doc */ part *p = ps->parts[0]; part_set_signal( p, "IO_CS_L0", 1, 0 ); part_set_signal( p, "IO_CS_L1", 1, 1 ); part_set_signal( p, "IO_CS_L2", 1, 1 ); part_set_signal( p, "IO_CS_L3", 1, 1 ); part_set_signal( p, "IO_CS_L4", 1, 1 ); part_set_signal( p, "IO_CS_L5", 1, 1 ); part_set_signal( p, "IO_CS_L6", 1, 1 ); part_set_signal( p, "IO_CS_L7", 1, 1 ); part_set_signal( p, "IO_RW", 1, 0 ); part_set_signal( p, "IO_WR_L", 1, 1 ); part_set_signal( p, "IO_OE_L", 1, 1 ); setup_address( p, adr ); setup_data( p, data ); parts_shift_data_registers( ps ); part_set_signal( p, "IO_WR_L", 1, 0 ); parts_shift_data_registers( ps ); part_set_signal( p, "IO_WR_L", 1, 1 ); parts_shift_data_registers( ps ); } #else int addr; uint64_t base = 0x1fc00000; uint32_t bcm1250_bus_read(parts *ps, uint32_t adr ) { unsigned char buf[32]; bcm1250_ejtag_do(ps, adr+base, 0, 1, 0, buf, 0); return buf[adr&0x1f]; } uint32_t bcm1250_bus_read_next(parts *ps, uint32_t adr ) { uint32_t t; t=bcm1250_bus_read(ps, addr); addr=adr; return t; } uint32_t bcm1250_bus_read_end(parts *ps) { return bcm1250_bus_read(ps, addr); } void bcm1250_bus_read_start(parts *ps, uint32_t adr ) { addr=adr; } void bcm1250_bus_write( parts *ps, uint32_t adr, uint32_t data ) { unsigned char buf[32]; bcm1250_ejtag_do(ps, adr+base, data, 0, 0, buf, 0); } #endif int bcm1250_bus_width( parts *ps ) { return 8; } bus_driver_t bcm1250_bus_driver = { bcm1250_bus_width, bcm1250_bus_read_start, bcm1250_bus_read_next, bcm1250_bus_read_end, bcm1250_bus_read, bcm1250_bus_write }; int bcm1250_ejtag_do(parts *ps, uint64_t ad, uint64_t da, int read, int type, unsigned char *buf, int verbose) { part *p = ps->parts[0]; char ctrl[15]="010000000000"; char addrr[80]="0000" "111" "000" "11111111111111111111111111111111" "00000000" "00011111" "11000000" "00000000" "000"; int j, k, n, m; uint64_t a; if(verbose)printf("BCM1250: ejtag_do(%08Lx, %08Lx, %i, %i)\n", ad, da, read, type); a=ad>>5; for(j=0;j<35;j++) { addrr[76-j]='0'+(a&1); a>>=1; } j=(1<0){ j--; p->active_instruction->data_register->in->data[j]=ctrl[k++]&1; } parts_shift_data_registers( ps ); if(read) { addrr[7]='0'; addrr[8]='0'; addrr[9]='0'; } else { addrr[7]='0'; addrr[8]='1'; addrr[9]='0'; } part_set_instruction( ps->parts[0], "ADDR" ); parts_shift_instructions(ps); j=strlen(addrr); k=0; while(j>0){ j--; ps->parts[0]->active_instruction->data_register->in->data[j]=addrr[k++]&1; } parts_shift_data_registers( ps ); if(!read) { part_set_instruction( ps->parts[0], "DATA"); parts_shift_instructions(ps); for(j=0;j<277;j++) p->active_instruction->data_register->in->data[j]=j&1; p->active_instruction->data_register->in->data[259]=1; p->active_instruction->data_register->in->data[258]=0; p->active_instruction->data_register->in->data[257]=0; p->active_instruction->data_register->in->data[256]=1; j=0; if(type<5) { k=256-(n+(1<active_instruction->data_register->in->data[k+j]=da&1; da>>=1; j++; } } else { int r; for(r=0; r<32; r++) { int s,t; t=buf[r]; for(s=0;s<8;s++) { p->active_instruction->data_register->in->data[248-r*8+s]=t&1; t>>=1; } } } parts_shift_data_registers( ps ); } ctrl[2]='1'; if(!read)ctrl[3]='1'; part_set_instruction( p, "CONTROLL" ); parts_shift_instructions(ps); j=strlen(ctrl); k=0; while(j>0){ j--; p->active_instruction->data_register->in->data[j]=ctrl[k++]&1; } parts_shift_data_registers( ps ); if(verbose || read) { volatile int q; int to; to=5; for(q=0;q<100;q++); part_set_instruction( p, "DATA"); parts_shift_instructions(ps); parts_shift_data_registers( ps ); while((p->active_instruction->data_register->out->data[276-17]==0) && to--) { parts_shift_data_registers( ps ); } for(j=n;jactive_instruction->data_register->out->data[255-(j*8)-m]&1; } if(verbose)printf("%02x ",buf[j]); } if(verbose) { printf("\n"); printf(" status:\n"); for(j=0;j<21;j++) { printf("%c", '0'+p->active_instruction->data_register->out->data[276-j]); if((j==5) || (j==11) || (j==12) || (j==16) || (j==17))printf(" "); } printf("\n"); } } return 0; }