Simplify the SPI driver.

This commit is contained in:
Serge Vakulenko
2015-09-20 22:01:19 -07:00
parent a36504720c
commit 80ab2d4721
9 changed files with 321 additions and 524 deletions

View File

@@ -12,6 +12,9 @@
#include <sys/ioctl.h>
/*
* 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

View File

@@ -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

View File

@@ -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.
*/

View File

@@ -28,7 +28,7 @@
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/picga.h>
#include <sys/spi_bus.h>
#include <sys/spi.h>
#include <sys/debug.h>
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;
}

View File

@@ -4,7 +4,7 @@
#include <sys/errno.h>
#include <sys/dk.h>
#include <sys/rdisk.h>
#include <sys/spi_bus.h>
#include <sys/spi.h>
#include <sys/debug.h>
#define MRAM_WREN 0x06

View File

@@ -35,7 +35,7 @@
#include <sys/errno.h>
#include <sys/dk.h>
#include <sys/rdisk.h>
#include <sys/spi_bus.h>
#include <sys/spi.h>
#include <sys/debug.h>
#include <sys/kconfig.h>
@@ -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<limit; i++)
{
if (spi_transfer(sd_fd[unit],0xFF) == 0xFF)
if (spi_transfer(io, 0xFF) == 0xFF)
{
if (*maxcount < i)
*maxcount = i;
@@ -154,31 +154,32 @@ static void spi_wait_ready (int unit, int limit, int *maxcount)
static int card_cmd(unsigned int unit, unsigned int cmd, unsigned int addr)
{
int i, reply;
struct spiio *io = &sd_io[unit];
/* Wait for not busy, up to 300 msec. */
if (cmd != CMD_GO_IDLE)
spi_wait_ready(unit, TIMO_WAIT_CMD, &sd_timo_wait_cmd);
/* Send a comand packet (6 bytes). */
spi_transfer(sd_fd[unit],cmd | 0x40);
spi_transfer(sd_fd[unit],addr >> 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_CMD; i++)
{
reply = spi_transfer(sd_fd[unit],0xFF);
reply = spi_transfer(io, 0xFF);
if (! (reply & 0x80))
{
if (sd_timo_cmd < i)
@@ -203,28 +204,29 @@ int card_init(int unit)
int i, reply;
unsigned char response[4];
int timeout = 4;
struct spiio *io = &sd_io[unit];
/* Slow speed: 250 kHz */
spi_brg(sd_fd[unit], 250);
spi_brg(io, 250);
sd_type[unit] = 0;
do {
/* Unselect the card. */
sd_deselect(sd_fd[unit]);
sd_deselect(io);
/* Send 80 clock cycles for start up. */
for (i=0; i<10; i++)
spi_transfer(sd_fd[unit], 0xFF);
spi_transfer(io, 0xFF);
/* Select the card and send a single GO_IDLE command. */
spi_select(sd_fd[unit]);
spi_select(io);
timeout--;
reply = card_cmd(unit, CMD_GO_IDLE, 0);
} while ((reply != 0x01) && (timeout != 0));
sd_deselect(sd_fd[unit]);
sd_deselect(io);
if (reply != 1)
{
/* It must return Idle. */
@@ -232,19 +234,19 @@ int card_init(int unit)
}
/* Check SD version. */
spi_select(sd_fd[unit]);
spi_select(io);
reply = card_cmd(unit, CMD_SEND_IF_COND, 0x1AA);
if (reply & 4)
{
/* Illegal command: card type 1. */
sd_deselect(sd_fd[unit]);
sd_deselect(io);
sd_type[unit] = 1;
} else {
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[3] != 0xAA)
{
printf ("sd%d: cannot detect card type, response=%02x-%02x-%02x-%02x\n",
@@ -257,11 +259,11 @@ int card_init(int unit)
/* Send repeatedly SEND_OP until Idle terminates. */
for (i=0; ; i++)
{
spi_select(sd_fd[unit]);
spi_select(io);
card_cmd(unit,CMD_APP, 0);
reply = card_cmd(unit,CMD_SEND_OP_SDC,
(sd_type[unit] == 2) ? 0x40000000 : 0);
spi_select(sd_fd[unit]);
spi_select(io);
if (reply == 0)
break;
if (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<sizeof(csd); i++)
{
csd [i] = spi_transfer(sd_fd[unit],0xFF);
csd [i] = spi_transfer(io, 0xFF);
}
/* Ignore CRC. */
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(io, 0xFF);
spi_transfer(io, 0xFF);
/* Disable the card. */
sd_deselect(sd_fd[unit]);
sd_deselect(io);
/* CSD register has different structure
* depending upon protocol version. */
@@ -376,17 +379,19 @@ int sdsize(int unit)
int card_read(int unit, unsigned int offset, char *data, unsigned int bcount)
{
int reply, i;
struct spiio *io = &sd_io[unit];
/* Send read-multiple command. */
spi_select(sd_fd[unit]);
if (sd_type[unit] != 3) offset <<= 9;
spi_select(io);
if (sd_type[unit] != 3)
offset <<= 9;
reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1);
if (reply != 0)
{
/* Command rejected. */
printf ("sd%d: card_read: bad READ_MULTIPLE reply = %d, offset = %08x\n",
unit, reply, offset<<1);
sd_deselect(sd_fd[unit]);
sd_deselect(io);
return 0;
}
@@ -395,7 +400,7 @@ again:
for (i=0; ; i++)
{
int x = spl0();
reply = spi_transfer(sd_fd[unit],0xFF);
reply = spi_transfer(io, 0xFF);
splx(x);
if (reply == DATA_START_BLOCK)
break;
@@ -404,7 +409,7 @@ again:
/* Command timed out. */
printf ("sd%d: card_read: READ_MULTIPLE timed out, reply = %d\n",
unit, reply);
sd_deselect(sd_fd[unit]);
sd_deselect(io);
return 0;
}
}
@@ -414,17 +419,17 @@ again:
/* Read data. */
if (bcount >= 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; i++)
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(io, 0xFF);
}
/* Ignore CRC. */
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(io, 0xFF);
spi_transfer(io, 0xFF);
if (bcount > 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; i++)
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(io, 0xFF);
}
/* Send dummy CRC. */
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(sd_fd[unit],0xFF);
spi_transfer(io, 0xFF);
spi_transfer(io, 0xFF);
/* Check if data accepted. */
reply = spi_transfer(sd_fd[unit],0xFF);
reply = spi_transfer(io, 0xFF);
if ((reply & 0x1f) != 0x05)
{
/* Data rejected. */
sd_deselect(sd_fd[unit]);
sd_deselect(io);
printf("sd%d: card_write: data rejected, reply = %02x\n", unit,reply);
return 0;
}
@@ -507,7 +513,7 @@ again:
int x = spl0();
spi_wait_ready(unit, TIMO_WAIT_WDONE, &sd_timo_wait_wdone);
splx(x);
sd_deselect(sd_fd[unit]);
sd_deselect(io);
if (bcount > 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;
}

View File

@@ -4,7 +4,7 @@
#include <sys/errno.h>
#include <sys/dk.h>
#include <sys/rdisk.h>
#include <sys/spi_bus.h>
#include <sys/spi.h>
#include <sys/debug.h>
#define SPIRAM_WREN 0x06

View File

@@ -29,7 +29,6 @@
#include <sys/uio.h>
#include <sys/kconfig.h>
#include <sys/spi.h>
#include <sys/spi_bus.h>
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;
}

View File

@@ -4,13 +4,16 @@
#include <sys/ioctl.h>
#include <sys/systm.h>
#include <sys/uio.h>
#include <sys/spi_bus.h>
#include <sys/spi.h>
#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<MAXSPIDEV && spi_devices[dno].bus != NULL; dno++);
// or return if not found
if (dno == MAXSPIDEV)
return -1;
dev = &spi_devices[dno];
if (channel <= 0 || channel > 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<<pin;
TRIS_CLR(*tris) = 1<<pin;
}
// return the ID of the device.
return dno;
return 0;
}
void spi_set_cspin(int dno, unsigned int *tris, unsigned int pin)
void spi_set_cspin(struct spiio *io, unsigned int *tris, unsigned int pin)
{
struct spi_dev *dev;
if (dno >= 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<<pin;
TRIS_SET(*io->cs_tris) = 1<<pin;
}
dev->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<<pin;
@@ -95,128 +65,58 @@ void spi_set_cspin(int dno, unsigned int *tris, unsigned int pin)
}
}
//
// Close an SPI device
// Free up the device entry, and turn off the CS pin (set it to input)
//
void spi_close(int dno)
{
struct spi_dev *dev;
if (dno >= 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; i<len; i++) {
out = *data8;
spi_transfer(dno, out);
spi_transfer(io, out);
data8++;
}
}
@@ -400,20 +268,14 @@ void spi_bulk_write(int dno, unsigned int len, unsigned char *data)
// the enhanced buffer mode.
// Data should be a multiple of 32 bits.
//
void spi_bulk_read_32_be(int dno, unsigned int len, char *data)
void spi_bulk_read_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;
@@ -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; i<len; i++) {
out = 0xFF;
in = spi_transfer(dno, out);
in = spi_transfer(io, out);
*data8 = in;
data8++;
}
}
void spi_bulk_rw_32_be(int dno, unsigned int len, char *data)
void spi_bulk_rw_32_be(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;
@@ -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<len; i++) {
out = *data8;
in = spi_transfer(dno, out);
in = spi_transfer(io, out);
*data8 = in;
data8++;
}
@@ -678,44 +494,26 @@ void spi_bulk_rw(int dno, unsigned int len, unsigned char *data)
//
// Set the SPI baud rate for a device (in KHz)
//
void spi_brg(int dno, unsigned int baud)
void spi_brg(struct spiio *io, unsigned int baud)
{
struct spi_dev *dev;
if (dno >= 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;
}