diff --git a/sys/include/spi.h b/sys/include/spi.h index 8930e70..87f6fb3 100644 --- a/sys/include/spi.h +++ b/sys/include/spi.h @@ -12,6 +12,9 @@ #include +/* + * User-level interface to the SPI port. + */ #define SPICTL_SETMODE _IO ('p', 0) /* set SPI mode */ #define SPICTL_SETRATE _IO ('p', 1) /* set clock rate, kHz */ #define SPICTL_SETSELPIN _IO ('p', 2) /* set select pin */ @@ -35,13 +38,54 @@ #ifdef KERNEL #include "conf.h" -extern const struct devspec spidevs[]; +/* + * Kernel-level interface to the SPI port. + */ +struct spiio { + struct spireg *bus; + unsigned int *cs_tris; + unsigned int cs_pin; + unsigned int baud; + unsigned int mode; +}; +extern int spi_setup(struct spiio *io, int channel, unsigned int *tris, unsigned int pin); +extern void spi_set_cspin(struct spiio *io, unsigned int *tris, unsigned int pin); +extern void spi_select(struct spiio *io); +extern void spi_deselect(struct spiio *io); +extern void spi_set(struct spiio *io, unsigned int set); +extern void spi_clr(struct spiio *io, unsigned int set); +extern unsigned int spi_status(struct spiio *io); +extern unsigned char spi_transfer(struct spiio *io, unsigned char data); +extern void spi_bulk_write_32_be(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_write_32(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_write_16(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_write(struct spiio *io, unsigned int len, unsigned char *data); +extern void spi_bulk_read_32_be(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_read_32(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_read_16(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_read(struct spiio *io, unsigned int len, unsigned char *data); +extern void spi_bulk_rw_32_be(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_rw_32(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_rw_16(struct spiio *io, unsigned int len, char *data); +extern void spi_bulk_rw(struct spiio *io, unsigned int len, unsigned char *data); +extern void spi_brg(struct spiio *io, unsigned int baud); +extern char *spi_name(struct spiio *io); +extern char spi_csname(struct spiio *io); +extern int spi_cspin(struct spiio *io); +extern unsigned int spi_get_brg(struct spiio *io); + +/* + * Routines of the SPI device driver. + */ int spidev_open (dev_t dev, int flag, int mode); int spidev_close (dev_t dev, int flag, int mode); int spidev_read (dev_t dev, struct uio *uio, int flag); int spidev_write (dev_t dev, struct uio *uio, int flag); int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag); + +extern const struct devspec spidevs[]; + #endif #endif diff --git a/sys/include/spi_bus.h b/sys/include/spi_bus.h deleted file mode 100644 index 04cb7e7..0000000 --- a/sys/include/spi_bus.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _SPI_BUS_H -#define _SPI_BUS_H - -#ifdef KERNEL - -struct spireg { - volatile unsigned con; /* Control */ - volatile unsigned conclr; - volatile unsigned conset; - volatile unsigned coninv; - volatile unsigned stat; /* Status */ - volatile unsigned statclr; - volatile unsigned statset; - volatile unsigned statinv; - volatile unsigned buf; /* Transmit and receive buffer */ - volatile unsigned unused1; - volatile unsigned unused2; - volatile unsigned unused3; - volatile unsigned brg; /* Baud rate generator */ - volatile unsigned brgclr; - volatile unsigned brgset; - volatile unsigned brginv; -}; - -struct spi_dev { - struct spireg *bus; - unsigned int *cs_tris; - unsigned int cs_pin; - unsigned int baud; - unsigned int mode; -}; - -extern int spi_open(unsigned int bus, unsigned int *tris, unsigned int pin); -extern void spi_close(int dno); -extern void spi_set_cspin(int dno, unsigned int *tris, unsigned int pin); -extern void spi_select(int dno); -extern void spi_deselect(int dno); -extern void spi_set(int dno, unsigned int set); -extern void spi_clr(int dno, unsigned int set); -extern unsigned int spi_status(int dno); -extern unsigned char spi_transfer(int dno, unsigned char data); -extern void spi_bulk_write_32_be(int dno, unsigned int len, char *data); -extern void spi_bulk_write_32(int dno, unsigned int len, char *data); -extern void spi_bulk_write_16(int dno, unsigned int len, char *data); -extern void spi_bulk_write(int dno, unsigned int len, unsigned char *data); -extern void spi_bulk_read_32_be(int dno, unsigned int len, char *data); -extern void spi_bulk_read_32(int dno, unsigned int len, char *data); -extern void spi_bulk_read_16(int dno, unsigned int len, char *data); -extern void spi_bulk_read(int dno, unsigned int len, unsigned char *data); -extern void spi_bulk_rw_32_be(int dno, unsigned int len, char *data); -extern void spi_bulk_rw_32(int dno, unsigned int len, char *data); -extern void spi_bulk_rw_16(int dno, unsigned int len, char *data); -extern void spi_bulk_rw(int dno, unsigned int len, unsigned char *data); -extern void spi_brg(int dno, unsigned int baud); -extern char *spi_name(int dno); -extern char spi_csname(int dno); -extern int spi_cspin(int dno); -extern unsigned int spi_get_brg(int dno); - -#endif - -#endif diff --git a/sys/pic32/pic32mx.h b/sys/pic32/pic32mx.h index 5014ae5..dfbed07 100644 --- a/sys/pic32/pic32mx.h +++ b/sys/pic32/pic32mx.h @@ -828,6 +828,27 @@ struct gpioreg { #define SPI2BRGSET PIC32_R (0x5A38) #define SPI2BRGINV PIC32_R (0x5A3C) +#ifndef __ASSEMBLER__ +struct spireg { + volatile unsigned con; /* Control */ + volatile unsigned conclr; + volatile unsigned conset; + volatile unsigned coninv; + volatile unsigned stat; /* Status */ + volatile unsigned statclr; + volatile unsigned statset; + volatile unsigned statinv; + volatile unsigned buf; /* Transmit and receive buffer */ + volatile unsigned unused1; + volatile unsigned unused2; + volatile unsigned unused3; + volatile unsigned brg; /* Baud rate generator */ + volatile unsigned brgclr; + volatile unsigned brgset; + volatile unsigned brginv; +}; +#endif + /* * SPI Control register. */ diff --git a/sys/pic32/picga.c b/sys/pic32/picga.c index 8aaf924..98f9101 100644 --- a/sys/pic32/picga.c +++ b/sys/pic32/picga.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include const struct devspec picgadevs[] = { @@ -105,10 +105,9 @@ int picga_close(dev_t dev, int flag, int mode) int channel; channel = minor(dev); - if(channel>0) + if (channel>0) return ENODEV; - spi_close(fd); return 0; } diff --git a/sys/pic32/rd_mrams.c b/sys/pic32/rd_mrams.c index 6446e7d..4ec15d8 100644 --- a/sys/pic32/rd_mrams.c +++ b/sys/pic32/rd_mrams.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #define MRAM_WREN 0x06 diff --git a/sys/pic32/rd_sd.c b/sys/pic32/rd_sd.c index a99a824..9161d7b 100644 --- a/sys/pic32/rd_sd.c +++ b/sys/pic32/rd_sd.c @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -67,6 +67,7 @@ #define TIMO_WAIT_WSTOP 5000 int sd_type[NSD]; /* Card type */ +struct spiio sd_io[NSD]; /* Data for SPI driver */ int sd_dkn = -1; /* Statistics slot number */ int sd_timo_cmd; /* Max timeouts, for sysctl */ @@ -104,13 +105,11 @@ int sd_timo_wait_widle; #define STOP_TRAN_TOKEN 0xFD /* stop token for write multiple */ #define WRITE_MULTIPLE_TOKEN 0xFC /* start data for write multiple */ -int sd_fd[NSD]; - // Add extra clocks after a deselect -void sd_deselect(unsigned int fd) +void sd_deselect(struct spiio *io) { - spi_deselect(fd); - spi_transfer(fd,0xFF); + spi_deselect(io); + spi_transfer(io, 0xFF); } /* @@ -120,11 +119,12 @@ void sd_deselect(unsigned int fd) static void spi_wait_ready (int unit, int limit, int *maxcount) { int i; + struct spiio *io = &sd_io[unit]; - spi_transfer(sd_fd[unit],0xFF); + spi_transfer(io, 0xFF); for (i=0; i> 24); - spi_transfer(sd_fd[unit],addr >> 16); - spi_transfer(sd_fd[unit],addr >> 8); - spi_transfer(sd_fd[unit],addr); + spi_transfer(io, cmd | 0x40); + spi_transfer(io, addr >> 24); + spi_transfer(io, addr >> 16); + spi_transfer(io, addr >> 8); + spi_transfer(io, addr); /* Send cmd checksum for CMD_GO_IDLE. * For all other commands, CRC is ignored. */ if (cmd == CMD_GO_IDLE) - spi_transfer(sd_fd[unit],0x95); + spi_transfer(io, 0x95); else if (cmd == CMD_SEND_IF_COND) - spi_transfer(sd_fd[unit],0x87); + spi_transfer(io, 0x87); else - spi_transfer(sd_fd[unit],0xFF); + spi_transfer(io, 0xFF); /* Wait for a response. */ for (i=0; i= TIMO_SEND_OP) @@ -277,19 +279,19 @@ int card_init(int unit) /* If SD2 read OCR register to check for SDHC card. */ if (sd_type[unit] == 2) { - spi_select(sd_fd[unit]); + spi_select(io); reply = card_cmd(unit, CMD_READ_OCR, 0); if (reply != 0) { - sd_deselect(sd_fd[unit]); + sd_deselect(io); printf ("sd%d: READ_OCR failed, reply=%02x\n", unit, reply); return 0; } - response[0] = spi_transfer(sd_fd[unit],0xFF); - response[1] = spi_transfer(sd_fd[unit],0xFF); - response[2] = spi_transfer(sd_fd[unit],0xFF); - response[3] = spi_transfer(sd_fd[unit],0xFF); - sd_deselect(sd_fd[unit]); + response[0] = spi_transfer(io, 0xFF); + response[1] = spi_transfer(io, 0xFF); + response[2] = spi_transfer(io, 0xFF); + response[3] = spi_transfer(io, 0xFF); + sd_deselect(io); if ((response[0] & 0xC0) == 0xC0) { sd_type[unit] = 3; @@ -297,7 +299,7 @@ int card_init(int unit) } /* Fast speed. */ - spi_brg(sd_fd[unit],SD0_MHZ * 1000); + spi_brg(io, SD0_MHZ * 1000); return 1; } @@ -311,25 +313,26 @@ int sdsize(int unit) unsigned csize, n; int reply, i; int nsectors; + struct spiio *io = &sd_io[unit]; - spi_select(sd_fd[unit]); + spi_select(io); reply = card_cmd(unit,CMD_SEND_CSD, 0); if (reply != 0) { /* Command rejected. */ - sd_deselect(sd_fd[unit]); + sd_deselect(io); return 0; } /* Wait for a response. */ for (i=0; ; i++) { - reply = spi_transfer(sd_fd[unit],0xFF); + reply = spi_transfer(io, 0xFF); if (reply == DATA_START_BLOCK) break; if (i >= TIMO_SEND_CSD) { /* Command timed out. */ - sd_deselect(sd_fd[unit]); + sd_deselect(io); printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n", unit, reply); return 0; @@ -341,14 +344,14 @@ int sdsize(int unit) /* Read data. */ for (i=0; i= SECTSIZE) { - spi_bulk_read_32_be(sd_fd[unit],SECTSIZE,data); + spi_bulk_read_32_be(io, SECTSIZE,data); data += SECTSIZE; } else { - spi_bulk_read(sd_fd[unit],bcount,(unsigned char *)data); + spi_bulk_read(io, bcount, (unsigned char *)data); data += bcount; for (i=bcount; i SECTSIZE) { @@ -435,7 +440,7 @@ again: /* Stop a read-multiple sequence. */ card_cmd(unit, CMD_STOP, 0); - sd_deselect(sd_fd[unit]); + sd_deselect(io); return 1; } @@ -447,15 +452,16 @@ int card_write (int unit, unsigned offset, char *data, unsigned bcount) { unsigned reply, i; + struct spiio *io = &sd_io[unit]; /* Send pre-erase count. */ - spi_select(sd_fd[unit]); + spi_select(io); card_cmd(unit, CMD_APP, 0); reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE); if (reply != 0) { /* Command rejected. */ - sd_deselect(sd_fd[unit]); + sd_deselect(io); printf("sd%d: card_write: bad SET_WBECNT reply = %02x, count = %u\n", unit, reply, (bcount + SECTSIZE - 1) / SECTSIZE); return 0; @@ -467,38 +473,38 @@ card_write (int unit, unsigned offset, char *data, unsigned bcount) if (reply != 0) { /* Command rejected. */ - sd_deselect(sd_fd[unit]); + sd_deselect(io); printf("sd%d: card_write: bad WRITE_MULTIPLE reply = %02x\n", unit, reply); return 0; } - sd_deselect(sd_fd[unit]); + sd_deselect(io); again: /* Select, wait while busy. */ - spi_select(sd_fd[unit]); + spi_select(io); spi_wait_ready(unit, TIMO_WAIT_WDATA, &sd_timo_wait_wdata); /* Send data. */ - spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN); + spi_transfer(io, WRITE_MULTIPLE_TOKEN); if (bcount >= SECTSIZE) { - spi_bulk_write_32_be(sd_fd[unit],SECTSIZE,data); + spi_bulk_write_32_be(io, SECTSIZE, data); data += SECTSIZE; } else { - spi_bulk_write(sd_fd[unit],bcount,(unsigned char *)data); + spi_bulk_write(io, bcount, (unsigned char *)data); data += bcount; for (i=bcount; i SECTSIZE) { @@ -517,11 +523,11 @@ again: } /* Stop a write-multiple sequence. */ - spi_select(sd_fd[unit]); + spi_select(io); spi_wait_ready(unit, TIMO_WAIT_WSTOP, &sd_timo_wait_wstop); - spi_transfer(sd_fd[unit],STOP_TRAN_TOKEN); + spi_transfer(io, STOP_TRAN_TOKEN); spi_wait_ready(unit, TIMO_WAIT_WIDLE, &sd_timo_wait_widle); - sd_deselect(sd_fd[unit]); + sd_deselect(io); return 1; } @@ -529,10 +535,13 @@ void sd_preinit (int unit) { } +/* + * Detect a card. + */ int sdinit (int unit, int flag) { + struct spiio *io = &sd_io[unit]; unsigned nsectors; - /* Detect a card. */ #ifdef SD0_ENA_PORT /* On Duinomite Mega board, pin B13 set low @@ -562,13 +571,13 @@ int sdinit (int unit, int flag) printf ("sd%d: cannot get card size\n", unit); return ENODEV; } - if(!(flag & S_SILENT)) + if (! (flag & S_SILENT)) { printf ("sd%d: type %s, size %u kbytes, speed %u Mbit/sec\n", unit, sd_type[unit]==3 ? "SDHC" : sd_type[unit]==2 ? "II" : "I", nsectors, - spi_get_brg(sd_fd[unit]) / 1000); + spi_get_brg(io) / 1000); } DEBUG("sd%d: init done\n",unit); return 0; @@ -612,6 +621,7 @@ sdprobe(config) { int unit = config->dev_unit; int cs = config->dev_pins[0]; + struct spiio *io = &sd_io[unit]; if (unit < 0 || unit >= NSD) return 0; @@ -622,12 +632,10 @@ sdprobe(config) int pin = cs & 15; struct gpioreg *base = port + (struct gpioreg*) &TRISA; - int fd = spi_open(config->dev_ctlr, (unsigned int*) base, pin); - if (fd < 0) { - printf("sd%d: Cannot open SPI port\n", unit); + if (spi_setup(io, config->dev_ctlr, (unsigned int*) base, pin) != 0) { + printf("sd%u: cannot open SPI%u port\n", unit, config->dev_ctlr); return 0; } - sd_fd[unit] = fd; #ifdef SD0_ENA_PORT if (unit == 0) { @@ -647,8 +655,8 @@ sdprobe(config) } #endif - spi_brg(fd, SD0_MHZ * 1000); - spi_set(fd, PIC32_SPICON_CKE); + spi_brg(io, SD0_MHZ * 1000); + spi_set(io, PIC32_SPICON_CKE); return 1; } diff --git a/sys/pic32/rd_spirams.c b/sys/pic32/rd_spirams.c index 0fd3277..8891c98 100644 --- a/sys/pic32/rd_spirams.c +++ b/sys/pic32/rd_spirams.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #define SPIRAM_WREN 0x06 diff --git a/sys/pic32/spi.c b/sys/pic32/spi.c index 7bf1f12..d56827b 100644 --- a/sys/pic32/spi.c +++ b/sys/pic32/spi.c @@ -29,7 +29,6 @@ #include #include #include -#include const struct devspec spidevs[] = { { 0, "spi1" }, @@ -49,7 +48,7 @@ const struct devspec spidevs[] = { # define PRINTDBG(...) /*empty*/ #endif -int spi_fd[NSPI]; +struct spiio spi_io[NSPI]; /* Data for SPI driver */ /* * Open /dev/spi# device. @@ -57,9 +56,10 @@ int spi_fd[NSPI]; * - rate 250 kHz; * - no sleect pin. */ -int spidev_open (dev_t dev, int flag, int mode) +int spidev_open(dev_t dev, int flag, int mode) { - int channel = minor (dev); + int channel = minor(dev); + struct spiio *io = &spi_io[channel]; if (channel >= NSPI) return ENXIO; @@ -67,15 +67,14 @@ int spidev_open (dev_t dev, int flag, int mode) if (u.u_uid != 0) return EPERM; - spi_fd[channel] = spi_open(channel+1,NULL,NULL); - if(spi_fd[channel]==-1) + if (! io->bus) return ENODEV; return 0; } -int spidev_close (dev_t dev, int flag, int mode) +int spidev_close(dev_t dev, int flag, int mode) { - int channel = minor (dev); + int channel = minor(dev); if (channel >= NSPI) return ENXIO; @@ -83,16 +82,15 @@ int spidev_close (dev_t dev, int flag, int mode) if (u.u_uid != 0) return EPERM; - spi_close(spi_fd[channel]); return 0; } -int spidev_read (dev_t dev, struct uio *uio, int flag) +int spidev_read(dev_t dev, struct uio *uio, int flag) { return 0; } -int spidev_write (dev_t dev, struct uio *uio, int flag) +int spidev_write(dev_t dev, struct uio *uio, int flag) { return 0; } @@ -115,9 +113,10 @@ int spidev_write (dev_t dev, struct uio *uio, int flag) * - SPICTL_IO32WB(n) - n*32 bit WB transaction * - SPICTL_IO32B(n) - n*32 bit B transaction */ -int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag) +int spidev_ioctl(dev_t dev, u_int cmd, caddr_t addr, int flag) { - int channel = minor (dev); + int channel = minor(dev); + struct spiio *io = &spi_io[channel]; unsigned char *cval = (unsigned char *)addr; int nelem; static unsigned volatile *const tris[8] = { @@ -125,7 +124,7 @@ int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag) }; int portnum; - //PRINTDBG ("spi%d: ioctl (cmd=%08x, addr=%08x)\n", channel+1, cmd, addr); + //PRINTDBG("spi%d: ioctl(cmd=%08x, addr=%08x)\n", channel+1, cmd, addr); if (channel >= NSPI) return ENXIO; @@ -141,124 +140,140 @@ int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag) * 2 1 0 * 3 1 1 */ - if((unsigned int) addr & 0x01) - spi_set(spi_fd[channel], PIC32_SPICON_CKE); - if((unsigned int) addr & 0x02) - spi_set(spi_fd[channel], PIC32_SPICON_CKP); + if ((unsigned) addr & 1) + spi_set(io, PIC32_SPICON_CKE); + if ((unsigned) addr & 2) + spi_set(io, PIC32_SPICON_CKP); return 0; case SPICTL_SETRATE: /* set clock rate, kHz */ - spi_brg(spi_fd[channel], (unsigned int) addr); + spi_brg(io, (unsigned int) addr); return 0; case SPICTL_SETSELPIN: /* set select pin */ portnum = ((unsigned int) addr >> 8) & 7; if (! portnum) return 0; - spi_set_cspin(spi_fd[channel], - (unsigned int *)tris[portnum], - (unsigned int) addr & 15); + spi_set_cspin(io, (unsigned*) tris[portnum], (unsigned) addr & 15); return 0; case SPICTL_IO8(0): /* transfer n*8 bits */ - spi_select(spi_fd[channel]); + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; - if (baduaddr (addr) || baduaddr (addr + nelem - 1)) + if (baduaddr(addr) || baduaddr(addr + nelem - 1)) return EFAULT; - spi_bulk_rw(spi_fd[channel], nelem, cval); - spi_deselect(spi_fd[channel]); + spi_bulk_rw(io, nelem, cval); + spi_deselect(io); break; case SPICTL_IO16(0): /* transfer n*16 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 1) || - baduaddr (addr) || baduaddr (addr + nelem*2 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*2 - 1)) return EFAULT; - spi_bulk_rw_16(spi_fd[channel], nelem<<1, (char *)addr); + spi_bulk_rw_16(io, nelem<<1, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_rw_32(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_rw_32(io, nelem<<2, (char *)addr); + spi_deselect(io); break; + // IM: added R and W and BE modes case SPICTL_IO8R(0): /* transfer n*8 bits */ - spi_select(spi_fd[channel]); + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; - if (baduaddr (addr) || baduaddr (addr + nelem - 1)) + if (baduaddr(addr) || baduaddr(addr + nelem - 1)) return EFAULT; - spi_bulk_read(spi_fd[channel], nelem, cval); - spi_deselect(spi_fd[channel]); + spi_bulk_read(io, nelem, cval); + spi_deselect(io); break; case SPICTL_IO16R(0): /* transfer n*16 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 1) || - baduaddr (addr) || baduaddr (addr + nelem*2 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*2 - 1)) return EFAULT; - spi_bulk_read_16(spi_fd[channel], nelem<<1, (char *)addr); + spi_bulk_read_16(io, nelem<<1, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32R(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_read_32(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_read_32(io, nelem<<2, (char *)addr); + spi_deselect(io); break; case SPICTL_IO8W(0): /* transfer n*8 bits */ - spi_select(spi_fd[channel]); + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; - if (baduaddr (addr) || baduaddr (addr + nelem - 1)) + if (baduaddr(addr) || baduaddr(addr + nelem - 1)) return EFAULT; - spi_bulk_write(spi_fd[channel], nelem, cval); - spi_deselect(spi_fd[channel]); + spi_bulk_write(io, nelem, cval); + spi_deselect(io); break; case SPICTL_IO16W(0): /* transfer n*16 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 1) || - baduaddr (addr) || baduaddr (addr + nelem*2 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*2 - 1)) return EFAULT; - spi_bulk_write_16(spi_fd[channel], nelem<<1, (char *)addr); + spi_bulk_write_16(io, nelem<<1, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32W(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_write_32(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_write_32(io, nelem<<2, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32RB(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_read_32_be(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_read_32_be(io, nelem<<2, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32WB(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_write_32_be(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_write_32_be(io, nelem<<2, (char *)addr); + spi_deselect(io); break; case SPICTL_IO32B(0): /* transfer n*32 bits */ + spi_select(io); nelem = (cmd >> 16) & IOCPARM_MASK; if (((unsigned) addr & 3) || - baduaddr (addr) || baduaddr (addr + nelem*4 - 1)) + baduaddr(addr) || baduaddr(addr + nelem*4 - 1)) return EFAULT; - spi_bulk_write_32_be(spi_fd[channel], nelem<<2, (char *)addr); + spi_bulk_write_32_be(io, nelem<<2, (char *)addr); + spi_deselect(io); break; -// } return 0; } @@ -273,6 +288,7 @@ spiprobe(config) struct conf_ctlr *config; { int channel = config->ctlr_unit - 1; + struct spiio *io = &spi_io[channel]; int sdi, sdo, sck; static const int sdi_tab[NSPI] = { GPIO_PIN('C',4), /* SDI1 */ @@ -304,15 +320,15 @@ spiprobe(config) sdo = GPIO_PIN('F',8); sck = GPIO_PIN('D',15); } - printf ("spi%u: pins sdi=R%c%d/sdo=R%c%d/sck=R%c%d\n", channel+1, + printf("spi%u: pins sdi=R%c%d/sdo=R%c%d/sck=R%c%d\n", channel+1, gpio_portname(sdi), gpio_pinno(sdi), gpio_portname(sdo), gpio_pinno(sdo), gpio_portname(sck), gpio_pinno(sck)); - //TODO - //struct spiio *io = &spitab[channel]; - //io->reg = spi_base[channel]; - //spi_setup(io, 0, 0); + if (spi_setup(io, channel+1, 0, 0) != 0) { + printf("spi%u: setup failed\n", channel+1); + return 0; + } return 1; } diff --git a/sys/pic32/spi_bus.c b/sys/pic32/spi_bus.c index 0431b6d..366a29d 100644 --- a/sys/pic32/spi_bus.c +++ b/sys/pic32/spi_bus.c @@ -4,13 +4,16 @@ #include #include #include -#include +#include #define NSPI 4 /* Ports SPI1...SPI4 */ -#define MAXSPIDEV 20 - -struct spi_dev spi_devices[MAXSPIDEV]; +static struct spireg *const spi_base[NSPI] = { + (struct spireg*) &SPI1CON, + (struct spireg*) &SPI2CON, + (struct spireg*) &SPI3CON, + (struct spireg*) &SPI4CON, +}; // // Default SPI bus speed @@ -25,69 +28,36 @@ struct spi_dev spi_devices[MAXSPIDEV]; // Returns an integer for the number of the device (ala fd). // Returns -1 if no devices are available. // -int spi_open(unsigned int bus, unsigned int *tris, unsigned int pin) +int spi_setup(struct spiio *io, int channel, unsigned int *tris, unsigned int pin) { - int dno; - struct spi_dev *dev; - - // Find a free device - for (dno=0; dno NSPI) + return ENXIO; // Set up the device - switch (bus) { - case 1: - dev->bus = (struct spireg *)&SPI1CON; - break; - case 2: - dev->bus = (struct spireg *)&SPI2CON; - break; - case 3: - dev->bus = (struct spireg *)&SPI3CON; - break; - case 4: - dev->bus = (struct spireg *)&SPI4CON; - break; - default: - return -1; - } - dev->cs_tris = tris; - dev->cs_pin = pin; - dev->baud = (BUS_KHZ / SPI_MHZ / 1000 + 1) / 2 - 1; - dev->mode = PIC32_SPICON_MSTEN | PIC32_SPICON_ON; + io->bus = spi_base[channel-1]; + io->cs_tris = tris; + io->cs_pin = pin; + io->baud = (BUS_KHZ / SPI_MHZ / 1000 + 1) / 2 - 1; + io->mode = PIC32_SPICON_MSTEN | PIC32_SPICON_ON; if (tris) { // Configure the CS pin LAT_SET(*tris) = 1<= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - // Revert the old CS pin to an input (release it) - if (dev->cs_tris) { + if (io->cs_tris) { // Configure the CS pin - TRIS_SET(*dev->cs_tris) = 1<cs_tris) = 1<cs_tris = tris; - dev->cs_pin = pin; + io->cs_tris = tris; + io->cs_pin = pin; if (tris) { // Configure the CS pin LAT_SET(*tris) = 1<= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - - if (dev->cs_tris != NULL) { - // Revert the CS pin to input. - TRIS_CLR(*dev->cs_tris) = 1 << dev->cs_pin; - } - dev->cs_tris = NULL; - - // Disable the device (remove the bus pointer) - dev->bus = NULL; -} - // // Assert the CS pin of a device. // Not only do we set the CS pin, but before we do so we also reconfigure // the SPI bus to the required settings for this device. // -void spi_select(int dno) +void spi_select(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) + if (io->cs_tris == NULL) return; - dev = &spi_devices[dno]; - if (! dev->bus) - return; + io->bus->brg = io->baud; + io->bus->con = io->mode; - if (dev->cs_tris == NULL) - return; - - dev->bus->brg = dev->baud; - dev->bus->con = dev->mode; - - LAT_CLR(*dev->cs_tris) = 1 << dev->cs_pin; + LAT_CLR(*io->cs_tris) = 1 << io->cs_pin; } // // Deassert the CS pin of a device. // -void spi_deselect(int dno) +void spi_deselect(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) + if (io->cs_tris == NULL) return; - dev = &spi_devices[dno]; - if (! dev->bus) - return; - - if (dev->cs_tris == NULL) - return; - - LAT_SET(*dev->cs_tris) = 1 << dev->cs_pin; + LAT_SET(*io->cs_tris) = 1 << io->cs_pin; } // // Set a mode setting or two - just updates the internal records, the // actual mode is changed next time the CS is asserted // -void spi_set(int dno, unsigned int set) +void spi_set(struct spiio *io, unsigned int set) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - - dev->mode |= set; + io->mode |= set; } // // Clear a mode setting or two - just updates the internal records, the // actual mode is changed next time the CS is asserted // -void spi_clr(int dno, unsigned int set) +void spi_clr(struct spiio *io, unsigned int set) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - - dev->mode &= ~set; + io->mode &= ~set; } // // Return the current status of the SPI bus for the device in question // Just returns the ->stat entry in the register set. // -unsigned int spi_status(int dno) +unsigned int spi_status(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return 0; - - dev = &spi_devices[dno]; - if (! dev->bus) - return 0; - - return dev->bus->stat; + return io->bus->stat; } // @@ -226,22 +126,16 @@ unsigned int spi_status(int dno) // This is blocking, and waits for the transfer to complete // before returning. Times out after a certain period. // -unsigned char spi_transfer(int dno, unsigned char data) +unsigned char spi_transfer(struct spiio *io, unsigned char data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; unsigned int to = 100000; - if (dno >= MAXSPIDEV) - return 0xF0; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return 0xF1; - reg->con = dev->mode; - reg->brg = dev->baud; + reg->con = io->mode; + reg->brg = io->baud; reg->buf = data; while ((--to > 0) && ! (reg->stat & PIC32_SPISTAT_SPIRBF)) @@ -259,20 +153,14 @@ unsigned char spi_transfer(int dno, unsigned char data) // the enhanced buffer mode. // Data should be a multiple of 32 bits. // -void spi_bulk_write_32_be(int dno, unsigned int len, char *data) +void spi_bulk_write_32_be(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; int *data32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -294,23 +182,17 @@ void spi_bulk_write_32_be(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_write_32(int dno, unsigned int len, char *data) +void spi_bulk_write_32(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; int *data32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -332,23 +214,17 @@ void spi_bulk_write_32(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_write_16(int dno, unsigned int len, char *data) +void spi_bulk_write_16(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; short *data16 = (short *)data; unsigned int words = len >> 1; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -370,26 +246,18 @@ void spi_bulk_write_16(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_write(int dno, unsigned int len, unsigned char *data) +void spi_bulk_write(struct spiio *io, unsigned int len, unsigned char *data) { - struct spi_dev *dev; unsigned char *data8 = data; unsigned int i; unsigned char out; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - for (i=0; ibus; int *data32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -435,23 +297,17 @@ void spi_bulk_read_32_be(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_read_32(int dno, unsigned int len, char *data) +void spi_bulk_read_32(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; int *data32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -473,23 +329,17 @@ void spi_bulk_read_32(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_read_16(int dno, unsigned int len, char *data) +void spi_bulk_read_16(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; short *data16 = (short *)data; unsigned int words = len >> 1; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -511,46 +361,32 @@ void spi_bulk_read_16(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_read(int dno, unsigned int len, unsigned char *data) +void spi_bulk_read(struct spiio *io, unsigned int len, unsigned char *data) { - struct spi_dev *dev; unsigned char *data8 = data; unsigned int i; unsigned char in,out; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - for (i=0; ibus; int *read32 = (int *)data; int *write32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -572,24 +408,18 @@ void spi_bulk_rw_32_be(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_rw_32(int dno, unsigned int len, char *data) +void spi_bulk_rw_32(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; int *read32 = (int *)data; int *write32 = (int *)data; unsigned int words = len >> 2; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -611,24 +441,18 @@ void spi_bulk_rw_32(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_rw_16(int dno, unsigned int len, char *data) +void spi_bulk_rw_16(struct spiio *io, unsigned int len, char *data) { - struct spi_dev *dev; - struct spireg *reg; + struct spireg *reg = io->bus; short *read16 = (short *)data; short *write16 = (short *)data; unsigned int words = len >> 1; unsigned int nread; unsigned int nwritten; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - reg = dev->bus; if (! reg) return; @@ -650,26 +474,18 @@ void spi_bulk_rw_16(int dno, unsigned int len, char *data) nread++; } } - reg->con = dev->mode; + reg->con = io->mode; } -void spi_bulk_rw(int dno, unsigned int len, unsigned char *data) +void spi_bulk_rw(struct spiio *io, unsigned int len, unsigned char *data) { - struct spi_dev *dev; unsigned char *data8 = data; unsigned int i; unsigned char in,out; - if (dno >= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - for (i=0; i= MAXSPIDEV) - return; - - dev = &spi_devices[dno]; - if (! dev->bus) - return; - - dev->baud = (BUS_KHZ / baud + 1) / 2 - 1; + io->baud = (BUS_KHZ / baud + 1) / 2 - 1; } // // Return the name of the SPI bus for a device // -char *spi_name(int dno) +char *spi_name(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return "SPI?"; - - dev = &spi_devices[dno]; - if (! dev->bus) - return "NO SPI BUS"; - - if (dev->bus == (struct spireg *)&SPI1CON) + if (io->bus == spi_base[0]) return "SPI1"; - if (dev->bus == (struct spireg *)&SPI2CON) + if (io->bus == spi_base[1]) return "SPI2"; - if (dev->bus == (struct spireg *)&SPI3CON) + if (io->bus == spi_base[2]) return "SPI3"; - if (dev->bus == (struct spireg *)&SPI4CON) + if (io->bus == spi_base[3]) return "SPI4"; return "SPI?"; @@ -724,18 +522,9 @@ char *spi_name(int dno) // // Return the port name of the CS pin for a device // -char spi_csname(int dno) +char spi_csname(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return '?'; - - dev = &spi_devices[dno]; - if (! dev->bus) - return '?'; - - switch ((unsigned)dev->cs_tris) { + switch ((unsigned)io->cs_tris) { case (unsigned)&TRISA: return 'A'; case (unsigned)&TRISB: return 'B'; case (unsigned)&TRISC: return 'C'; @@ -747,30 +536,12 @@ char spi_csname(int dno) return '?'; } -int spi_cspin(int dno) +int spi_cspin(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return '?'; - - dev = &spi_devices[dno]; - if (! dev->bus) - return '?'; - - return dev->cs_pin; + return io->cs_pin; } -unsigned int spi_get_brg(int dno) +unsigned int spi_get_brg(struct spiio *io) { - struct spi_dev *dev; - - if (dno >= MAXSPIDEV) - return 0; - - dev = &spi_devices[dno]; - if (! dev->bus) - return 0; - - return BUS_KHZ / (dev->baud + 1) / 2; + return BUS_KHZ / (io->baud + 1) / 2; }