SPI on MBX/MPC860 ?
Tobias Otto-Adamczak
Tobias.Otto-Adamczak at e-technik.tu-chemnitz.de
Wed Aug 30 20:52:11 EST 2000
I'm a beginner. I'm trying to get SPI working on my MBX. I use Monta Vista
kernel sources without microcode patch. Has anyone ever done some work
with the SPI ? Dan, I read in a posting from you that you did ? I followed
the programming example in UM but didn't succeed. I tried ty send a few
bytes, but SPIE says 0 afterwards.
Here's what I did:
--------- snip ---------
/* initialize the 860 SPI and send a few bytes */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/types.h>
#include <asm/page.h>
#include <asm/8xx_immap.h>
#include <commproc.h>
#define DP_RAM_OFFSET 0x2000
#define SPI_BUFSIZE 16
#define say(fmt,args...) printk(fmt,##args)
int init_module (void)
{
uint i_isb = 0; // internal space base address
immap_t* im = 0; // memory map, see UM chapter 2
cpm8xx_t* cp = 0; // CP resources
cpic8xx_t* cpic = 0; // CP interrupt controller registers
spi_t* spi_pr = 0; // SPI's parameter RAM
cbd_t* spi_bd = 0; // SPI's BD's
uint spi_bd_dp = 0; // SPI's BD's (DP RAM relative address)
uint spi_buf = 0; // SPI's Rx/Tx buffer virtual start address
int i;
char buf[2*SPI_BUFSIZE] = {0}; // Test Buffer
say ("Module isdn_init inserted.\n");
asm ("mfspr %0,638":"=r"(i_isb):); // taken from arch/ppc/8xx_io/uart.c
i_isb &= 0xffff0000; // cut off lower 16 bit
// set some base addresses
im = (immap_t*)(i_isb);
cp = (cpm8xx_t*)(i_isb+0x09c0);
cpic = (cpic8xx_t*)(i_isb+0x0930);
spi_pr = (spi_t*)(i_isb+0x3d80); // SPI parameter RAM
// disable SPI
cp->cp_spmode &= 0xfeff;
// configure hardware interface
cp->cp_pbpar |= 0x0000000e; cp->cp_pbpar &= 0xfffffffe;
cp->cp_pbdir |= 0x0000000e;
cp->cp_pbodr &= 0xfff1;
// configure PB[23] to operate as low active 'SPI enable'
cp->cp_pbpar &= 0xfffffeff;
cp->cp_pbodr &= 0xfeff;
cp->cp_pbdir |= 0x00000100;
cp->cp_pbdat &= 0xfffffeff;
// configure DMA for SPI
im->im_siu_conf.sc_sdcr = 0x0001;
spi_pr->spi_rfcr = 0x10;
spi_pr->spi_tfcr = 0x10;
// allocate the BD's and buffers
spi_buf = (uint)buf;
strcpy((char*)(spi_buf+SPI_BUFSIZE), "Teststring123"); // Init TxBuffer
spi_bd_dp = m8xx_cpm_dpalloc (2*sizeof(cbd_t)); // one RxBD, TxBD
// set Rx/Tx table base address. We use one RxBD followed by one TxBD
spi_pr->spi_rbase = (ushort)spi_bd_dp;
spi_pr->spi_tbase = (ushort)(spi_bd_dp+sizeof(cbd_t));
spi_pr->spi_mrblr = (ushort)SPI_BUFSIZE; // maximum receive buffer length
// CPCR: send command to CP: init Rx/Tx params for SPI
while (cp->cp_cpcr & CPM_CR_FLG)
for (i=0; i<0xFF; i++); // wait
cp->cp_cpcr = 0x0051;
for (i=0; i<0x123456; i++); // wait
while (cp->cp_cpcr & CPM_CR_FLG)
for (i=0; i<0xFF; i++); // wait
// initialize RxBD, TxBD
spi_bd = (cbd_t*)(i_isb+DP_RAM_OFFSET+spi_bd_dp);
spi_bd[0].cbd_bufaddr = __pa(spi_buf); // va->pa for DMA
spi_bd[0].cbd_datlen = 0; // optional
spi_bd[0].cbd_sc = (ushort)(BD_SC_EMPTY | BD_SC_WRAP | BD_SC_INTRPT);
spi_bd[1].cbd_bufaddr = __pa(spi_buf+SPI_BUFSIZE); // va->pa for DMA
spi_bd[1].cbd_datlen = (ushort)SPI_BUFSIZE;
spi_bd[1].cbd_sc = (ushort)(BD_SC_READY | BD_SC_WRAP | BD_SC_INTRPT | BD_SC_LAST);
// configure interrupts
cp->cp_spie = 0xFF; // clear all events
cp->cp_spim = 0x37; // set up mask
cpic->cpic_cimr |= 0x00000020; // enable SPI interrupts at CPIC
cpic->cpic_cicr |= CICR_IEN; // interrupt master enable
// ... and go !
cp->cp_spmode = 0x4b70;
cp->cp_spcom = 0x80;
// test the loop transfer
for (i=0; i<0x1234567; i++); // wait
say ("SPI parameter RAM and register summary:\n");
say ("RBASE=%0#6x TBASE=%0#6x MRBLR=%0#6x RFCR=%0#4x TFCR=%0#4x\n",
spi_pr->spi_rbase, spi_pr->spi_tbase, spi_pr->spi_mrblr,
spi_pr->spi_rfcr, spi_pr->spi_tfcr);
say ("RBPTR=%0#6x TBPTR=%0#6x RBC=%0#6x TBC=%0#6x RDP=%0#10x TDP=%0#10x\n",
spi_pr->spi_rbptr, spi_pr->spi_tbptr,
spi_pr->spi_rbc, spi_pr->spi_tbc, spi_pr->spi_rdp, spi_pr->spi_tdp);
say ("SPIE=%0#4x SPIM=%0#4x SPCOM=%0#4x SPMODE=%0#6x CIMR=%0#10x CICR=%0#10x\n",
cp->cp_spie, cp->cp_spim, cp->cp_spcom, cp->cp_spmode,
cpic->cpic_cimr, cpic->cpic_cicr);
say ("RxBD: SC=%0#6x LEN=%0#6x ADDR=%0#10x\n",
spi_bd[0].cbd_sc, spi_bd[0].cbd_datlen, spi_bd[0].cbd_bufaddr);
say ("TxBD: SC=%0#6x LEN=%0#6x ADDR=%0#10x\n",
spi_bd[1].cbd_sc, spi_bd[1].cbd_datlen, spi_bd[1].cbd_bufaddr);
say ("DMA status: SDSR=%0#4x\t", im->im_sdma.sdma_sdsr);
say ("TxBUF:%s RxBUF:%s\n", (char*)(spi_buf+SPI_BUFSIZE), (char*)spi_buf);
return 0;
}
--------- snip ---------
Ciao - Tobias
** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/
More information about the Linuxppc-embedded
mailing list