File: [local] / funnyos / arch / sam7s64 / dev / saspi.c (download)
Revision 1.3, Thu Dec 20 15:25:44 2007 UTC (16 years, 6 months ago) by nbrk
Branch: MAIN
Changes since 1.2: +35 -16 lines
complete saspi; now i can see if card is present and/or has write-protect.
|
/*
* $Id: saspi.c,v 1.3 2007/12/20 15:25:44 nbrk Exp $
*/
#include <sys/types.h>
#include <sys/device.h>
#include <sys/bus.h>
#include <sys/bus_spi.h>
#include <libkern/printf.h>
#include <arch/sam7s64/dev/at91sam7.h>
/*
* SPI driver.
*/
struct saspi_dd {
struct spi_bus_handle sd_sbh;
struct bus_handle *sd_bhp;
};
int saspi_attach(struct device *, uint32_t, uint8_t);
void saspi_init(struct saspi_dd *ddp);
uint8_t saspi_transmit(void *selfdd, uint8_t data);
struct driver saspi_dr = {
sizeof(struct saspi_dd),
saspi_attach,
NULL,
NULL
};
int
saspi_attach(struct device *self, uint32_t loc, uint8_t flags)
{
struct saspi_dd *ddp = self->dv_devdata;
/* grab bus_handle */
ddp->sd_bhp = self->dv_parent->dv_aux;
printf("SAM7 SPI: ");
/*
* XXX Check if card present and fail if it is not.
*/
/* 'Card Present' on PA15 */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ODR, 1 << 15);
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PER, 1 << 15);
/* Write Protect' on PA16 */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ODR, 1 << 16);
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PER, 1 << 16);
if((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDSR) & 1 << 15) == 0)
printf("card present; ");
else {
printf("card is not presented\n");
return(-1);
}
printf("write %s\n", (bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDSR) & 1 << 16) ? "protect" : "allowed");
/*
* Initialize ourselfes and provide spi_bus_handle to children throught dv_aux.
*/
saspi_init(ddp);
ddp->sd_sbh.sb_transmitfunc = saspi_transmit;
ddp->sd_sbh.sb_dd = ddp;
self->dv_aux = &ddp->sd_sbh;
return(0);
}
void
saspi_init(struct saspi_dd *ddp)
{
/*
* Initialize on-chip SPI controller.
*/
/*
* Disassociate SPI chip select, clock and data lines from PIO.
*
* PA11 - NPCS0
* PA12 - MISO
* PA13 - MOSI
* PA14 - SPCK
*/
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_PDR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14);
/* assign pins to Peripheral A */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PIOA_ASR, 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14);
/* reset and enable SPI */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN | AT91C_SPI_SWRST);
/* XXX just to be sure */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_SPIEN);
/* set SPI mode to master; disable decoding of Chip Select; PCS 1110 (using fixed CS line) */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CR, AT91C_SPI_MSTR | AT91C_SPI_MODFDIS | 0x0e << 16); /* XXX 15|16 */
/*
* Configure Chip Select Register no. 0 (so no offset from SPI_CSR).
* CPOL (Clock Polarity) is 0 (SPCK inactive is logic 0);
* NCPHA (Clock Phase) is 1;
* 8 bits per transfer;
* XXX SCBR=4a;
*/
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_CSR, AT91C_SPI_NCPHA | 0x4a00);
/* enable PDC transfers to/from SPI */
// bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_PDC_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN);
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_PTCR, AT91C_PDC_TXTEN | AT91C_PDC_RXTEN);
}
uint8_t
saspi_transmit(void *selfdd, uint8_t data)
{
struct saspi_dd *ddp = (struct saspi_dd *)selfdd;
/*
* Shift byte on the SPI bus.
*/
/* wait for Transmit Data Register Empty flag */
while((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR) & AT91C_SPI_TDRE) == 0)
;
/* okay, send our byte */
bus_write_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_TDR, 0x0000ffff & data);
/* wait while Receive Register is full and read it */
while((bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_SR) & AT91C_SPI_RDRF) == 0)
;
return( bus_read_4(ddp->sd_bhp, (uint32_t)AT91C_SPI_RDR) & 0x0000ffff );
}