Simplify the SPI driver.
This commit is contained in:
@@ -12,6 +12,9 @@
|
|||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* User-level interface to the SPI port.
|
||||||
|
*/
|
||||||
#define SPICTL_SETMODE _IO ('p', 0) /* set SPI mode */
|
#define SPICTL_SETMODE _IO ('p', 0) /* set SPI mode */
|
||||||
#define SPICTL_SETRATE _IO ('p', 1) /* set clock rate, kHz */
|
#define SPICTL_SETRATE _IO ('p', 1) /* set clock rate, kHz */
|
||||||
#define SPICTL_SETSELPIN _IO ('p', 2) /* set select pin */
|
#define SPICTL_SETSELPIN _IO ('p', 2) /* set select pin */
|
||||||
@@ -35,13 +38,54 @@
|
|||||||
#ifdef KERNEL
|
#ifdef KERNEL
|
||||||
#include "conf.h"
|
#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_open (dev_t dev, int flag, int mode);
|
||||||
int spidev_close (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_read (dev_t dev, struct uio *uio, int flag);
|
||||||
int spidev_write (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);
|
int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag);
|
||||||
|
|
||||||
|
extern const struct devspec spidevs[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -828,6 +828,27 @@ struct gpioreg {
|
|||||||
#define SPI2BRGSET PIC32_R (0x5A38)
|
#define SPI2BRGSET PIC32_R (0x5A38)
|
||||||
#define SPI2BRGINV PIC32_R (0x5A3C)
|
#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.
|
* SPI Control register.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/picga.h>
|
#include <sys/picga.h>
|
||||||
#include <sys/spi_bus.h>
|
#include <sys/spi.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
|
||||||
const struct devspec picgadevs[] = {
|
const struct devspec picgadevs[] = {
|
||||||
@@ -105,10 +105,9 @@ int picga_close(dev_t dev, int flag, int mode)
|
|||||||
int channel;
|
int channel;
|
||||||
|
|
||||||
channel = minor(dev);
|
channel = minor(dev);
|
||||||
if(channel>0)
|
if (channel>0)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
spi_close(fd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/dk.h>
|
#include <sys/dk.h>
|
||||||
#include <sys/rdisk.h>
|
#include <sys/rdisk.h>
|
||||||
#include <sys/spi_bus.h>
|
#include <sys/spi.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
|
||||||
#define MRAM_WREN 0x06
|
#define MRAM_WREN 0x06
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/dk.h>
|
#include <sys/dk.h>
|
||||||
#include <sys/rdisk.h>
|
#include <sys/rdisk.h>
|
||||||
#include <sys/spi_bus.h>
|
#include <sys/spi.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
#include <sys/kconfig.h>
|
#include <sys/kconfig.h>
|
||||||
|
|
||||||
@@ -67,6 +67,7 @@
|
|||||||
#define TIMO_WAIT_WSTOP 5000
|
#define TIMO_WAIT_WSTOP 5000
|
||||||
|
|
||||||
int sd_type[NSD]; /* Card type */
|
int sd_type[NSD]; /* Card type */
|
||||||
|
struct spiio sd_io[NSD]; /* Data for SPI driver */
|
||||||
int sd_dkn = -1; /* Statistics slot number */
|
int sd_dkn = -1; /* Statistics slot number */
|
||||||
|
|
||||||
int sd_timo_cmd; /* Max timeouts, for sysctl */
|
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 STOP_TRAN_TOKEN 0xFD /* stop token for write multiple */
|
||||||
#define WRITE_MULTIPLE_TOKEN 0xFC /* start data for write multiple */
|
#define WRITE_MULTIPLE_TOKEN 0xFC /* start data for write multiple */
|
||||||
|
|
||||||
int sd_fd[NSD];
|
|
||||||
|
|
||||||
// Add extra clocks after a deselect
|
// Add extra clocks after a deselect
|
||||||
void sd_deselect(unsigned int fd)
|
void sd_deselect(struct spiio *io)
|
||||||
{
|
{
|
||||||
spi_deselect(fd);
|
spi_deselect(io);
|
||||||
spi_transfer(fd,0xFF);
|
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)
|
static void spi_wait_ready (int unit, int limit, int *maxcount)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
for (i=0; i<limit; i++)
|
for (i=0; i<limit; i++)
|
||||||
{
|
{
|
||||||
if (spi_transfer(sd_fd[unit],0xFF) == 0xFF)
|
if (spi_transfer(io, 0xFF) == 0xFF)
|
||||||
{
|
{
|
||||||
if (*maxcount < i)
|
if (*maxcount < i)
|
||||||
*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)
|
static int card_cmd(unsigned int unit, unsigned int cmd, unsigned int addr)
|
||||||
{
|
{
|
||||||
int i, reply;
|
int i, reply;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
/* Wait for not busy, up to 300 msec. */
|
/* Wait for not busy, up to 300 msec. */
|
||||||
if (cmd != CMD_GO_IDLE)
|
if (cmd != CMD_GO_IDLE)
|
||||||
spi_wait_ready(unit, TIMO_WAIT_CMD, &sd_timo_wait_cmd);
|
spi_wait_ready(unit, TIMO_WAIT_CMD, &sd_timo_wait_cmd);
|
||||||
|
|
||||||
/* Send a comand packet (6 bytes). */
|
/* Send a comand packet (6 bytes). */
|
||||||
spi_transfer(sd_fd[unit],cmd | 0x40);
|
spi_transfer(io, cmd | 0x40);
|
||||||
spi_transfer(sd_fd[unit],addr >> 24);
|
spi_transfer(io, addr >> 24);
|
||||||
spi_transfer(sd_fd[unit],addr >> 16);
|
spi_transfer(io, addr >> 16);
|
||||||
spi_transfer(sd_fd[unit],addr >> 8);
|
spi_transfer(io, addr >> 8);
|
||||||
spi_transfer(sd_fd[unit],addr);
|
spi_transfer(io, addr);
|
||||||
|
|
||||||
/* Send cmd checksum for CMD_GO_IDLE.
|
/* Send cmd checksum for CMD_GO_IDLE.
|
||||||
* For all other commands, CRC is ignored. */
|
* For all other commands, CRC is ignored. */
|
||||||
if (cmd == CMD_GO_IDLE)
|
if (cmd == CMD_GO_IDLE)
|
||||||
spi_transfer(sd_fd[unit],0x95);
|
spi_transfer(io, 0x95);
|
||||||
else if (cmd == CMD_SEND_IF_COND)
|
else if (cmd == CMD_SEND_IF_COND)
|
||||||
spi_transfer(sd_fd[unit],0x87);
|
spi_transfer(io, 0x87);
|
||||||
else
|
else
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
|
|
||||||
/* Wait for a response. */
|
/* Wait for a response. */
|
||||||
for (i=0; i<TIMO_CMD; i++)
|
for (i=0; i<TIMO_CMD; i++)
|
||||||
{
|
{
|
||||||
reply = spi_transfer(sd_fd[unit],0xFF);
|
reply = spi_transfer(io, 0xFF);
|
||||||
if (! (reply & 0x80))
|
if (! (reply & 0x80))
|
||||||
{
|
{
|
||||||
if (sd_timo_cmd < i)
|
if (sd_timo_cmd < i)
|
||||||
@@ -203,28 +204,29 @@ int card_init(int unit)
|
|||||||
int i, reply;
|
int i, reply;
|
||||||
unsigned char response[4];
|
unsigned char response[4];
|
||||||
int timeout = 4;
|
int timeout = 4;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
/* Slow speed: 250 kHz */
|
/* Slow speed: 250 kHz */
|
||||||
spi_brg(sd_fd[unit], 250);
|
spi_brg(io, 250);
|
||||||
|
|
||||||
sd_type[unit] = 0;
|
sd_type[unit] = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Unselect the card. */
|
/* Unselect the card. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
|
|
||||||
/* Send 80 clock cycles for start up. */
|
/* Send 80 clock cycles for start up. */
|
||||||
for (i=0; i<10; i++)
|
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. */
|
/* Select the card and send a single GO_IDLE command. */
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
timeout--;
|
timeout--;
|
||||||
reply = card_cmd(unit, CMD_GO_IDLE, 0);
|
reply = card_cmd(unit, CMD_GO_IDLE, 0);
|
||||||
|
|
||||||
} while ((reply != 0x01) && (timeout != 0));
|
} while ((reply != 0x01) && (timeout != 0));
|
||||||
|
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
if (reply != 1)
|
if (reply != 1)
|
||||||
{
|
{
|
||||||
/* It must return Idle. */
|
/* It must return Idle. */
|
||||||
@@ -232,19 +234,19 @@ int card_init(int unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check SD version. */
|
/* Check SD version. */
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
reply = card_cmd(unit, CMD_SEND_IF_COND, 0x1AA);
|
reply = card_cmd(unit, CMD_SEND_IF_COND, 0x1AA);
|
||||||
if (reply & 4)
|
if (reply & 4)
|
||||||
{
|
{
|
||||||
/* Illegal command: card type 1. */
|
/* Illegal command: card type 1. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
sd_type[unit] = 1;
|
sd_type[unit] = 1;
|
||||||
} else {
|
} else {
|
||||||
response[0] = spi_transfer(sd_fd[unit], 0xFF);
|
response[0] = spi_transfer(io, 0xFF);
|
||||||
response[1] = spi_transfer(sd_fd[unit], 0xFF);
|
response[1] = spi_transfer(io, 0xFF);
|
||||||
response[2] = spi_transfer(sd_fd[unit], 0xFF);
|
response[2] = spi_transfer(io, 0xFF);
|
||||||
response[3] = spi_transfer(sd_fd[unit], 0xFF);
|
response[3] = spi_transfer(io, 0xFF);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
if (response[3] != 0xAA)
|
if (response[3] != 0xAA)
|
||||||
{
|
{
|
||||||
printf ("sd%d: cannot detect card type, response=%02x-%02x-%02x-%02x\n",
|
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. */
|
/* Send repeatedly SEND_OP until Idle terminates. */
|
||||||
for (i=0; ; i++)
|
for (i=0; ; i++)
|
||||||
{
|
{
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
card_cmd(unit,CMD_APP, 0);
|
card_cmd(unit,CMD_APP, 0);
|
||||||
reply = card_cmd(unit,CMD_SEND_OP_SDC,
|
reply = card_cmd(unit,CMD_SEND_OP_SDC,
|
||||||
(sd_type[unit] == 2) ? 0x40000000 : 0);
|
(sd_type[unit] == 2) ? 0x40000000 : 0);
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
if (reply == 0)
|
if (reply == 0)
|
||||||
break;
|
break;
|
||||||
if (i >= TIMO_SEND_OP)
|
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 SD2 read OCR register to check for SDHC card. */
|
||||||
if (sd_type[unit] == 2)
|
if (sd_type[unit] == 2)
|
||||||
{
|
{
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
reply = card_cmd(unit, CMD_READ_OCR, 0);
|
reply = card_cmd(unit, CMD_READ_OCR, 0);
|
||||||
if (reply != 0)
|
if (reply != 0)
|
||||||
{
|
{
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
printf ("sd%d: READ_OCR failed, reply=%02x\n", unit, reply);
|
printf ("sd%d: READ_OCR failed, reply=%02x\n", unit, reply);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
response[0] = spi_transfer(sd_fd[unit],0xFF);
|
response[0] = spi_transfer(io, 0xFF);
|
||||||
response[1] = spi_transfer(sd_fd[unit],0xFF);
|
response[1] = spi_transfer(io, 0xFF);
|
||||||
response[2] = spi_transfer(sd_fd[unit],0xFF);
|
response[2] = spi_transfer(io, 0xFF);
|
||||||
response[3] = spi_transfer(sd_fd[unit],0xFF);
|
response[3] = spi_transfer(io, 0xFF);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
if ((response[0] & 0xC0) == 0xC0)
|
if ((response[0] & 0xC0) == 0xC0)
|
||||||
{
|
{
|
||||||
sd_type[unit] = 3;
|
sd_type[unit] = 3;
|
||||||
@@ -297,7 +299,7 @@ int card_init(int unit)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fast speed. */
|
/* Fast speed. */
|
||||||
spi_brg(sd_fd[unit],SD0_MHZ * 1000);
|
spi_brg(io, SD0_MHZ * 1000);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,25 +313,26 @@ int sdsize(int unit)
|
|||||||
unsigned csize, n;
|
unsigned csize, n;
|
||||||
int reply, i;
|
int reply, i;
|
||||||
int nsectors;
|
int nsectors;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
reply = card_cmd(unit,CMD_SEND_CSD, 0);
|
reply = card_cmd(unit,CMD_SEND_CSD, 0);
|
||||||
if (reply != 0)
|
if (reply != 0)
|
||||||
{
|
{
|
||||||
/* Command rejected. */
|
/* Command rejected. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* Wait for a response. */
|
/* Wait for a response. */
|
||||||
for (i=0; ; i++)
|
for (i=0; ; i++)
|
||||||
{
|
{
|
||||||
reply = spi_transfer(sd_fd[unit],0xFF);
|
reply = spi_transfer(io, 0xFF);
|
||||||
if (reply == DATA_START_BLOCK)
|
if (reply == DATA_START_BLOCK)
|
||||||
break;
|
break;
|
||||||
if (i >= TIMO_SEND_CSD)
|
if (i >= TIMO_SEND_CSD)
|
||||||
{
|
{
|
||||||
/* Command timed out. */
|
/* Command timed out. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n",
|
printf ("sd%d: card_size: SEND_CSD timed out, reply = %d\n",
|
||||||
unit, reply);
|
unit, reply);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -341,14 +344,14 @@ int sdsize(int unit)
|
|||||||
/* Read data. */
|
/* Read data. */
|
||||||
for (i=0; i<sizeof(csd); i++)
|
for (i=0; i<sizeof(csd); i++)
|
||||||
{
|
{
|
||||||
csd [i] = spi_transfer(sd_fd[unit],0xFF);
|
csd [i] = spi_transfer(io, 0xFF);
|
||||||
}
|
}
|
||||||
/* Ignore CRC. */
|
/* Ignore CRC. */
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
|
|
||||||
/* Disable the card. */
|
/* Disable the card. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
|
|
||||||
/* CSD register has different structure
|
/* CSD register has different structure
|
||||||
* depending upon protocol version. */
|
* 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 card_read(int unit, unsigned int offset, char *data, unsigned int bcount)
|
||||||
{
|
{
|
||||||
int reply, i;
|
int reply, i;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
/* Send read-multiple command. */
|
/* Send read-multiple command. */
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
if (sd_type[unit] != 3) offset <<= 9;
|
if (sd_type[unit] != 3)
|
||||||
|
offset <<= 9;
|
||||||
reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1);
|
reply = card_cmd(unit, CMD_READ_MULTIPLE, offset<<1);
|
||||||
if (reply != 0)
|
if (reply != 0)
|
||||||
{
|
{
|
||||||
/* Command rejected. */
|
/* Command rejected. */
|
||||||
printf ("sd%d: card_read: bad READ_MULTIPLE reply = %d, offset = %08x\n",
|
printf ("sd%d: card_read: bad READ_MULTIPLE reply = %d, offset = %08x\n",
|
||||||
unit, reply, offset<<1);
|
unit, reply, offset<<1);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,7 +400,7 @@ again:
|
|||||||
for (i=0; ; i++)
|
for (i=0; ; i++)
|
||||||
{
|
{
|
||||||
int x = spl0();
|
int x = spl0();
|
||||||
reply = spi_transfer(sd_fd[unit],0xFF);
|
reply = spi_transfer(io, 0xFF);
|
||||||
splx(x);
|
splx(x);
|
||||||
if (reply == DATA_START_BLOCK)
|
if (reply == DATA_START_BLOCK)
|
||||||
break;
|
break;
|
||||||
@@ -404,7 +409,7 @@ again:
|
|||||||
/* Command timed out. */
|
/* Command timed out. */
|
||||||
printf ("sd%d: card_read: READ_MULTIPLE timed out, reply = %d\n",
|
printf ("sd%d: card_read: READ_MULTIPLE timed out, reply = %d\n",
|
||||||
unit, reply);
|
unit, reply);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,17 +419,17 @@ again:
|
|||||||
/* Read data. */
|
/* Read data. */
|
||||||
if (bcount >= SECTSIZE)
|
if (bcount >= SECTSIZE)
|
||||||
{
|
{
|
||||||
spi_bulk_read_32_be(sd_fd[unit],SECTSIZE,data);
|
spi_bulk_read_32_be(io, SECTSIZE,data);
|
||||||
data += SECTSIZE;
|
data += SECTSIZE;
|
||||||
} else {
|
} else {
|
||||||
spi_bulk_read(sd_fd[unit],bcount,(unsigned char *)data);
|
spi_bulk_read(io, bcount, (unsigned char *)data);
|
||||||
data += bcount;
|
data += bcount;
|
||||||
for (i=bcount; i<SECTSIZE; i++)
|
for (i=bcount; i<SECTSIZE; i++)
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
}
|
}
|
||||||
/* Ignore CRC. */
|
/* Ignore CRC. */
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
|
|
||||||
if (bcount > SECTSIZE)
|
if (bcount > SECTSIZE)
|
||||||
{
|
{
|
||||||
@@ -435,7 +440,7 @@ again:
|
|||||||
|
|
||||||
/* Stop a read-multiple sequence. */
|
/* Stop a read-multiple sequence. */
|
||||||
card_cmd(unit, CMD_STOP, 0);
|
card_cmd(unit, CMD_STOP, 0);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,15 +452,16 @@ int
|
|||||||
card_write (int unit, unsigned offset, char *data, unsigned bcount)
|
card_write (int unit, unsigned offset, char *data, unsigned bcount)
|
||||||
{
|
{
|
||||||
unsigned reply, i;
|
unsigned reply, i;
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
/* Send pre-erase count. */
|
/* Send pre-erase count. */
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
card_cmd(unit, CMD_APP, 0);
|
card_cmd(unit, CMD_APP, 0);
|
||||||
reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE);
|
reply = card_cmd(unit, CMD_SET_WBECNT, (bcount + SECTSIZE - 1) / SECTSIZE);
|
||||||
if (reply != 0)
|
if (reply != 0)
|
||||||
{
|
{
|
||||||
/* Command rejected. */
|
/* Command rejected. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
printf("sd%d: card_write: bad SET_WBECNT reply = %02x, count = %u\n",
|
printf("sd%d: card_write: bad SET_WBECNT reply = %02x, count = %u\n",
|
||||||
unit, reply, (bcount + SECTSIZE - 1) / SECTSIZE);
|
unit, reply, (bcount + SECTSIZE - 1) / SECTSIZE);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -467,38 +473,38 @@ card_write (int unit, unsigned offset, char *data, unsigned bcount)
|
|||||||
if (reply != 0)
|
if (reply != 0)
|
||||||
{
|
{
|
||||||
/* Command rejected. */
|
/* Command rejected. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
printf("sd%d: card_write: bad WRITE_MULTIPLE reply = %02x\n", unit, reply);
|
printf("sd%d: card_write: bad WRITE_MULTIPLE reply = %02x\n", unit, reply);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
again:
|
again:
|
||||||
/* Select, wait while busy. */
|
/* Select, wait while busy. */
|
||||||
spi_select(sd_fd[unit]);
|
spi_select(io);
|
||||||
spi_wait_ready(unit, TIMO_WAIT_WDATA, &sd_timo_wait_wdata);
|
spi_wait_ready(unit, TIMO_WAIT_WDATA, &sd_timo_wait_wdata);
|
||||||
|
|
||||||
/* Send data. */
|
/* Send data. */
|
||||||
spi_transfer(sd_fd[unit],WRITE_MULTIPLE_TOKEN);
|
spi_transfer(io, WRITE_MULTIPLE_TOKEN);
|
||||||
if (bcount >= SECTSIZE)
|
if (bcount >= SECTSIZE)
|
||||||
{
|
{
|
||||||
spi_bulk_write_32_be(sd_fd[unit],SECTSIZE,data);
|
spi_bulk_write_32_be(io, SECTSIZE, data);
|
||||||
data += SECTSIZE;
|
data += SECTSIZE;
|
||||||
} else {
|
} else {
|
||||||
spi_bulk_write(sd_fd[unit],bcount,(unsigned char *)data);
|
spi_bulk_write(io, bcount, (unsigned char *)data);
|
||||||
data += bcount;
|
data += bcount;
|
||||||
for (i=bcount; i<SECTSIZE; i++)
|
for (i=bcount; i<SECTSIZE; i++)
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
}
|
}
|
||||||
/* Send dummy CRC. */
|
/* Send dummy CRC. */
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
spi_transfer(sd_fd[unit],0xFF);
|
spi_transfer(io, 0xFF);
|
||||||
|
|
||||||
/* Check if data accepted. */
|
/* Check if data accepted. */
|
||||||
reply = spi_transfer(sd_fd[unit],0xFF);
|
reply = spi_transfer(io, 0xFF);
|
||||||
if ((reply & 0x1f) != 0x05)
|
if ((reply & 0x1f) != 0x05)
|
||||||
{
|
{
|
||||||
/* Data rejected. */
|
/* Data rejected. */
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
printf("sd%d: card_write: data rejected, reply = %02x\n", unit,reply);
|
printf("sd%d: card_write: data rejected, reply = %02x\n", unit,reply);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -507,7 +513,7 @@ again:
|
|||||||
int x = spl0();
|
int x = spl0();
|
||||||
spi_wait_ready(unit, TIMO_WAIT_WDONE, &sd_timo_wait_wdone);
|
spi_wait_ready(unit, TIMO_WAIT_WDONE, &sd_timo_wait_wdone);
|
||||||
splx(x);
|
splx(x);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
|
|
||||||
if (bcount > SECTSIZE)
|
if (bcount > SECTSIZE)
|
||||||
{
|
{
|
||||||
@@ -517,11 +523,11 @@ again:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Stop a write-multiple sequence. */
|
/* 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_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);
|
spi_wait_ready(unit, TIMO_WAIT_WIDLE, &sd_timo_wait_widle);
|
||||||
sd_deselect(sd_fd[unit]);
|
sd_deselect(io);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,10 +535,13 @@ void sd_preinit (int unit)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect a card.
|
||||||
|
*/
|
||||||
int sdinit (int unit, int flag)
|
int sdinit (int unit, int flag)
|
||||||
{
|
{
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
unsigned nsectors;
|
unsigned nsectors;
|
||||||
/* Detect a card. */
|
|
||||||
|
|
||||||
#ifdef SD0_ENA_PORT
|
#ifdef SD0_ENA_PORT
|
||||||
/* On Duinomite Mega board, pin B13 set low
|
/* 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);
|
printf ("sd%d: cannot get card size\n", unit);
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
}
|
}
|
||||||
if(!(flag & S_SILENT))
|
if (! (flag & S_SILENT))
|
||||||
{
|
{
|
||||||
printf ("sd%d: type %s, size %u kbytes, speed %u Mbit/sec\n", unit,
|
printf ("sd%d: type %s, size %u kbytes, speed %u Mbit/sec\n", unit,
|
||||||
sd_type[unit]==3 ? "SDHC" :
|
sd_type[unit]==3 ? "SDHC" :
|
||||||
sd_type[unit]==2 ? "II" : "I",
|
sd_type[unit]==2 ? "II" : "I",
|
||||||
nsectors,
|
nsectors,
|
||||||
spi_get_brg(sd_fd[unit]) / 1000);
|
spi_get_brg(io) / 1000);
|
||||||
}
|
}
|
||||||
DEBUG("sd%d: init done\n",unit);
|
DEBUG("sd%d: init done\n",unit);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -612,6 +621,7 @@ sdprobe(config)
|
|||||||
{
|
{
|
||||||
int unit = config->dev_unit;
|
int unit = config->dev_unit;
|
||||||
int cs = config->dev_pins[0];
|
int cs = config->dev_pins[0];
|
||||||
|
struct spiio *io = &sd_io[unit];
|
||||||
|
|
||||||
if (unit < 0 || unit >= NSD)
|
if (unit < 0 || unit >= NSD)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -622,12 +632,10 @@ sdprobe(config)
|
|||||||
int pin = cs & 15;
|
int pin = cs & 15;
|
||||||
struct gpioreg *base = port + (struct gpioreg*) &TRISA;
|
struct gpioreg *base = port + (struct gpioreg*) &TRISA;
|
||||||
|
|
||||||
int fd = spi_open(config->dev_ctlr, (unsigned int*) base, pin);
|
if (spi_setup(io, config->dev_ctlr, (unsigned int*) base, pin) != 0) {
|
||||||
if (fd < 0) {
|
printf("sd%u: cannot open SPI%u port\n", unit, config->dev_ctlr);
|
||||||
printf("sd%d: Cannot open SPI port\n", unit);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sd_fd[unit] = fd;
|
|
||||||
|
|
||||||
#ifdef SD0_ENA_PORT
|
#ifdef SD0_ENA_PORT
|
||||||
if (unit == 0) {
|
if (unit == 0) {
|
||||||
@@ -647,8 +655,8 @@ sdprobe(config)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
spi_brg(fd, SD0_MHZ * 1000);
|
spi_brg(io, SD0_MHZ * 1000);
|
||||||
spi_set(fd, PIC32_SPICON_CKE);
|
spi_set(io, PIC32_SPICON_CKE);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <sys/errno.h>
|
#include <sys/errno.h>
|
||||||
#include <sys/dk.h>
|
#include <sys/dk.h>
|
||||||
#include <sys/rdisk.h>
|
#include <sys/rdisk.h>
|
||||||
#include <sys/spi_bus.h>
|
#include <sys/spi.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
|
||||||
#define SPIRAM_WREN 0x06
|
#define SPIRAM_WREN 0x06
|
||||||
|
|||||||
132
sys/pic32/spi.c
132
sys/pic32/spi.c
@@ -29,7 +29,6 @@
|
|||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/kconfig.h>
|
#include <sys/kconfig.h>
|
||||||
#include <sys/spi.h>
|
#include <sys/spi.h>
|
||||||
#include <sys/spi_bus.h>
|
|
||||||
|
|
||||||
const struct devspec spidevs[] = {
|
const struct devspec spidevs[] = {
|
||||||
{ 0, "spi1" },
|
{ 0, "spi1" },
|
||||||
@@ -49,7 +48,7 @@ const struct devspec spidevs[] = {
|
|||||||
# define PRINTDBG(...) /*empty*/
|
# define PRINTDBG(...) /*empty*/
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int spi_fd[NSPI];
|
struct spiio spi_io[NSPI]; /* Data for SPI driver */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open /dev/spi# device.
|
* Open /dev/spi# device.
|
||||||
@@ -57,9 +56,10 @@ int spi_fd[NSPI];
|
|||||||
* - rate 250 kHz;
|
* - rate 250 kHz;
|
||||||
* - no sleect pin.
|
* - 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)
|
if (channel >= NSPI)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
@@ -67,15 +67,14 @@ int spidev_open (dev_t dev, int flag, int mode)
|
|||||||
if (u.u_uid != 0)
|
if (u.u_uid != 0)
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
spi_fd[channel] = spi_open(channel+1,NULL,NULL);
|
if (! io->bus)
|
||||||
if(spi_fd[channel]==-1)
|
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
return 0;
|
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)
|
if (channel >= NSPI)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
@@ -83,16 +82,15 @@ int spidev_close (dev_t dev, int flag, int mode)
|
|||||||
if (u.u_uid != 0)
|
if (u.u_uid != 0)
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
spi_close(spi_fd[channel]);
|
|
||||||
return 0;
|
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;
|
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;
|
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_IO32WB(n) - n*32 bit WB transaction
|
||||||
* - SPICTL_IO32B(n) - n*32 bit B 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;
|
unsigned char *cval = (unsigned char *)addr;
|
||||||
int nelem;
|
int nelem;
|
||||||
static unsigned volatile *const tris[8] = {
|
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;
|
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)
|
if (channel >= NSPI)
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
|
|
||||||
@@ -141,124 +140,140 @@ int spidev_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag)
|
|||||||
* 2 1 0
|
* 2 1 0
|
||||||
* 3 1 1
|
* 3 1 1
|
||||||
*/
|
*/
|
||||||
if((unsigned int) addr & 0x01)
|
if ((unsigned) addr & 1)
|
||||||
spi_set(spi_fd[channel], PIC32_SPICON_CKE);
|
spi_set(io, PIC32_SPICON_CKE);
|
||||||
if((unsigned int) addr & 0x02)
|
if ((unsigned) addr & 2)
|
||||||
spi_set(spi_fd[channel], PIC32_SPICON_CKP);
|
spi_set(io, PIC32_SPICON_CKP);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case SPICTL_SETRATE: /* set clock rate, kHz */
|
case SPICTL_SETRATE: /* set clock rate, kHz */
|
||||||
spi_brg(spi_fd[channel], (unsigned int) addr);
|
spi_brg(io, (unsigned int) addr);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case SPICTL_SETSELPIN: /* set select pin */
|
case SPICTL_SETSELPIN: /* set select pin */
|
||||||
portnum = ((unsigned int) addr >> 8) & 7;
|
portnum = ((unsigned int) addr >> 8) & 7;
|
||||||
if (! portnum)
|
if (! portnum)
|
||||||
return 0;
|
return 0;
|
||||||
spi_set_cspin(spi_fd[channel],
|
spi_set_cspin(io, (unsigned*) tris[portnum], (unsigned) addr & 15);
|
||||||
(unsigned int *)tris[portnum],
|
|
||||||
(unsigned int) addr & 15);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case SPICTL_IO8(0): /* transfer n*8 bits */
|
case SPICTL_IO8(0): /* transfer n*8 bits */
|
||||||
spi_select(spi_fd[channel]);
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (baduaddr (addr) || baduaddr (addr + nelem - 1))
|
if (baduaddr(addr) || baduaddr(addr + nelem - 1))
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
spi_bulk_rw(spi_fd[channel], nelem, cval);
|
spi_bulk_rw(io, nelem, cval);
|
||||||
spi_deselect(spi_fd[channel]);
|
spi_deselect(io);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO16(0): /* transfer n*16 bits */
|
case SPICTL_IO16(0): /* transfer n*16 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 1) ||
|
if (((unsigned) addr & 1) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*2 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*2 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32(0): /* transfer n*32 bits */
|
case SPICTL_IO32(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
// IM: added R and W and BE modes
|
// IM: added R and W and BE modes
|
||||||
case SPICTL_IO8R(0): /* transfer n*8 bits */
|
case SPICTL_IO8R(0): /* transfer n*8 bits */
|
||||||
spi_select(spi_fd[channel]);
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (baduaddr (addr) || baduaddr (addr + nelem - 1))
|
if (baduaddr(addr) || baduaddr(addr + nelem - 1))
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
spi_bulk_read(spi_fd[channel], nelem, cval);
|
spi_bulk_read(io, nelem, cval);
|
||||||
spi_deselect(spi_fd[channel]);
|
spi_deselect(io);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO16R(0): /* transfer n*16 bits */
|
case SPICTL_IO16R(0): /* transfer n*16 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 1) ||
|
if (((unsigned) addr & 1) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*2 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*2 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32R(0): /* transfer n*32 bits */
|
case SPICTL_IO32R(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO8W(0): /* transfer n*8 bits */
|
case SPICTL_IO8W(0): /* transfer n*8 bits */
|
||||||
spi_select(spi_fd[channel]);
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (baduaddr (addr) || baduaddr (addr + nelem - 1))
|
if (baduaddr(addr) || baduaddr(addr + nelem - 1))
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
spi_bulk_write(spi_fd[channel], nelem, cval);
|
spi_bulk_write(io, nelem, cval);
|
||||||
spi_deselect(spi_fd[channel]);
|
spi_deselect(io);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO16W(0): /* transfer n*16 bits */
|
case SPICTL_IO16W(0): /* transfer n*16 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 1) ||
|
if (((unsigned) addr & 1) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*2 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*2 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32W(0): /* transfer n*32 bits */
|
case SPICTL_IO32W(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32RB(0): /* transfer n*32 bits */
|
case SPICTL_IO32RB(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32WB(0): /* transfer n*32 bits */
|
case SPICTL_IO32WB(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
|
|
||||||
case SPICTL_IO32B(0): /* transfer n*32 bits */
|
case SPICTL_IO32B(0): /* transfer n*32 bits */
|
||||||
|
spi_select(io);
|
||||||
nelem = (cmd >> 16) & IOCPARM_MASK;
|
nelem = (cmd >> 16) & IOCPARM_MASK;
|
||||||
if (((unsigned) addr & 3) ||
|
if (((unsigned) addr & 3) ||
|
||||||
baduaddr (addr) || baduaddr (addr + nelem*4 - 1))
|
baduaddr(addr) || baduaddr(addr + nelem*4 - 1))
|
||||||
return EFAULT;
|
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;
|
break;
|
||||||
//
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -273,6 +288,7 @@ spiprobe(config)
|
|||||||
struct conf_ctlr *config;
|
struct conf_ctlr *config;
|
||||||
{
|
{
|
||||||
int channel = config->ctlr_unit - 1;
|
int channel = config->ctlr_unit - 1;
|
||||||
|
struct spiio *io = &spi_io[channel];
|
||||||
int sdi, sdo, sck;
|
int sdi, sdo, sck;
|
||||||
static const int sdi_tab[NSPI] = {
|
static const int sdi_tab[NSPI] = {
|
||||||
GPIO_PIN('C',4), /* SDI1 */
|
GPIO_PIN('C',4), /* SDI1 */
|
||||||
@@ -304,15 +320,15 @@ spiprobe(config)
|
|||||||
sdo = GPIO_PIN('F',8);
|
sdo = GPIO_PIN('F',8);
|
||||||
sck = GPIO_PIN('D',15);
|
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(sdi), gpio_pinno(sdi),
|
||||||
gpio_portname(sdo), gpio_pinno(sdo),
|
gpio_portname(sdo), gpio_pinno(sdo),
|
||||||
gpio_portname(sck), gpio_pinno(sck));
|
gpio_portname(sck), gpio_pinno(sck));
|
||||||
|
|
||||||
//TODO
|
if (spi_setup(io, channel+1, 0, 0) != 0) {
|
||||||
//struct spiio *io = &spitab[channel];
|
printf("spi%u: setup failed\n", channel+1);
|
||||||
//io->reg = spi_base[channel];
|
return 0;
|
||||||
//spi_setup(io, 0, 0);
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,13 +4,16 @@
|
|||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <sys/spi_bus.h>
|
#include <sys/spi.h>
|
||||||
|
|
||||||
#define NSPI 4 /* Ports SPI1...SPI4 */
|
#define NSPI 4 /* Ports SPI1...SPI4 */
|
||||||
|
|
||||||
#define MAXSPIDEV 20
|
static struct spireg *const spi_base[NSPI] = {
|
||||||
|
(struct spireg*) &SPI1CON,
|
||||||
struct spi_dev spi_devices[MAXSPIDEV];
|
(struct spireg*) &SPI2CON,
|
||||||
|
(struct spireg*) &SPI3CON,
|
||||||
|
(struct spireg*) &SPI4CON,
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// Default SPI bus speed
|
// 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 an integer for the number of the device (ala fd).
|
||||||
// Returns -1 if no devices are available.
|
// 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;
|
if (channel <= 0 || channel > NSPI)
|
||||||
struct spi_dev *dev;
|
return ENXIO;
|
||||||
|
|
||||||
// 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];
|
|
||||||
|
|
||||||
// Set up the device
|
// Set up the device
|
||||||
switch (bus) {
|
io->bus = spi_base[channel-1];
|
||||||
case 1:
|
io->cs_tris = tris;
|
||||||
dev->bus = (struct spireg *)&SPI1CON;
|
io->cs_pin = pin;
|
||||||
break;
|
io->baud = (BUS_KHZ / SPI_MHZ / 1000 + 1) / 2 - 1;
|
||||||
case 2:
|
io->mode = PIC32_SPICON_MSTEN | PIC32_SPICON_ON;
|
||||||
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;
|
|
||||||
|
|
||||||
if (tris) {
|
if (tris) {
|
||||||
// Configure the CS pin
|
// Configure the CS pin
|
||||||
LAT_SET(*tris) = 1<<pin;
|
LAT_SET(*tris) = 1<<pin;
|
||||||
TRIS_CLR(*tris) = 1<<pin;
|
TRIS_CLR(*tris) = 1<<pin;
|
||||||
}
|
}
|
||||||
// return the ID of the device.
|
return 0;
|
||||||
return dno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
// Revert the old CS pin to an input (release it)
|
||||||
if (dev->cs_tris) {
|
if (io->cs_tris) {
|
||||||
// Configure the CS pin
|
// Configure the CS pin
|
||||||
TRIS_SET(*dev->cs_tris) = 1<<pin;
|
TRIS_SET(*io->cs_tris) = 1<<pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev->cs_tris = tris;
|
io->cs_tris = tris;
|
||||||
dev->cs_pin = pin;
|
io->cs_pin = pin;
|
||||||
if (tris) {
|
if (tris) {
|
||||||
// Configure the CS pin
|
// Configure the CS pin
|
||||||
LAT_SET(*tris) = 1<<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.
|
// Assert the CS pin of a device.
|
||||||
// Not only do we set the CS pin, but before we do so we also reconfigure
|
// 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.
|
// 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 (io->cs_tris == NULL)
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
io->bus->brg = io->baud;
|
||||||
if (! dev->bus)
|
io->bus->con = io->mode;
|
||||||
return;
|
|
||||||
|
|
||||||
if (dev->cs_tris == NULL)
|
LAT_CLR(*io->cs_tris) = 1 << io->cs_pin;
|
||||||
return;
|
|
||||||
|
|
||||||
dev->bus->brg = dev->baud;
|
|
||||||
dev->bus->con = dev->mode;
|
|
||||||
|
|
||||||
LAT_CLR(*dev->cs_tris) = 1 << dev->cs_pin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Deassert the CS pin of a device.
|
// Deassert the CS pin of a device.
|
||||||
//
|
//
|
||||||
void spi_deselect(int dno)
|
void spi_deselect(struct spiio *io)
|
||||||
{
|
{
|
||||||
struct spi_dev *dev;
|
if (io->cs_tris == NULL)
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
LAT_SET(*io->cs_tris) = 1 << io->cs_pin;
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (dev->cs_tris == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LAT_SET(*dev->cs_tris) = 1 << dev->cs_pin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set a mode setting or two - just updates the internal records, the
|
// Set a mode setting or two - just updates the internal records, the
|
||||||
// actual mode is changed next time the CS is asserted
|
// 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;
|
io->mode |= set;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev->mode |= set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clear a mode setting or two - just updates the internal records, the
|
// Clear a mode setting or two - just updates the internal records, the
|
||||||
// actual mode is changed next time the CS is asserted
|
// 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;
|
io->mode &= ~set;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev->mode &= ~set;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the current status of the SPI bus for the device in question
|
// Return the current status of the SPI bus for the device in question
|
||||||
// Just returns the ->stat entry in the register set.
|
// 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;
|
return io->bus->stat;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return dev->bus->stat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -226,22 +126,16 @@ unsigned int spi_status(int dno)
|
|||||||
// This is blocking, and waits for the transfer to complete
|
// This is blocking, and waits for the transfer to complete
|
||||||
// before returning. Times out after a certain period.
|
// 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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
unsigned int to = 100000;
|
unsigned int to = 100000;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return 0xF0;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return 0xF1;
|
return 0xF1;
|
||||||
|
|
||||||
reg->con = dev->mode;
|
reg->con = io->mode;
|
||||||
reg->brg = dev->baud;
|
reg->brg = io->baud;
|
||||||
|
|
||||||
reg->buf = data;
|
reg->buf = data;
|
||||||
while ((--to > 0) && ! (reg->stat & PIC32_SPISTAT_SPIRBF))
|
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.
|
// the enhanced buffer mode.
|
||||||
// Data should be a multiple of 32 bits.
|
// 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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *data32 = (int *)data;
|
int *data32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -294,23 +182,17 @@ void spi_bulk_write_32_be(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *data32 = (int *)data;
|
int *data32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -332,23 +214,17 @@ void spi_bulk_write_32(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
short *data16 = (short *)data;
|
short *data16 = (short *)data;
|
||||||
unsigned int words = len >> 1;
|
unsigned int words = len >> 1;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -370,26 +246,18 @@ void spi_bulk_write_16(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 char *data8 = data;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned char out;
|
unsigned char out;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
out = *data8;
|
out = *data8;
|
||||||
spi_transfer(dno, out);
|
spi_transfer(io, out);
|
||||||
data8++;
|
data8++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,20 +268,14 @@ void spi_bulk_write(int dno, unsigned int len, unsigned char *data)
|
|||||||
// the enhanced buffer mode.
|
// the enhanced buffer mode.
|
||||||
// Data should be a multiple of 32 bits.
|
// 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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *data32 = (int *)data;
|
int *data32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -435,23 +297,17 @@ void spi_bulk_read_32_be(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *data32 = (int *)data;
|
int *data32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -473,23 +329,17 @@ void spi_bulk_read_32(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
short *data16 = (short *)data;
|
short *data16 = (short *)data;
|
||||||
unsigned int words = len >> 1;
|
unsigned int words = len >> 1;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -511,46 +361,32 @@ void spi_bulk_read_16(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 char *data8 = data;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned char in,out;
|
unsigned char in,out;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
out = 0xFF;
|
out = 0xFF;
|
||||||
in = spi_transfer(dno, out);
|
in = spi_transfer(io, out);
|
||||||
*data8 = in;
|
*data8 = in;
|
||||||
data8++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *read32 = (int *)data;
|
int *read32 = (int *)data;
|
||||||
int *write32 = (int *)data;
|
int *write32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -572,24 +408,18 @@ void spi_bulk_rw_32_be(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
int *read32 = (int *)data;
|
int *read32 = (int *)data;
|
||||||
int *write32 = (int *)data;
|
int *write32 = (int *)data;
|
||||||
unsigned int words = len >> 2;
|
unsigned int words = len >> 2;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -611,24 +441,18 @@ void spi_bulk_rw_32(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 = io->bus;
|
||||||
struct spireg *reg;
|
|
||||||
short *read16 = (short *)data;
|
short *read16 = (short *)data;
|
||||||
short *write16 = (short *)data;
|
short *write16 = (short *)data;
|
||||||
unsigned int words = len >> 1;
|
unsigned int words = len >> 1;
|
||||||
unsigned int nread;
|
unsigned int nread;
|
||||||
unsigned int nwritten;
|
unsigned int nwritten;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
reg = dev->bus;
|
|
||||||
if (! reg)
|
if (! reg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -650,26 +474,18 @@ void spi_bulk_rw_16(int dno, unsigned int len, char *data)
|
|||||||
nread++;
|
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 char *data8 = data;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned char in,out;
|
unsigned char in,out;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i=0; i<len; i++) {
|
for (i=0; i<len; i++) {
|
||||||
out = *data8;
|
out = *data8;
|
||||||
in = spi_transfer(dno, out);
|
in = spi_transfer(io, out);
|
||||||
*data8 = in;
|
*data8 = in;
|
||||||
data8++;
|
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)
|
// 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;
|
io->baud = (BUS_KHZ / baud + 1) / 2 - 1;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dev->baud = (BUS_KHZ / baud + 1) / 2 - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the name of the SPI bus for a device
|
// 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 (io->bus == spi_base[0])
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return "SPI?";
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return "NO SPI BUS";
|
|
||||||
|
|
||||||
if (dev->bus == (struct spireg *)&SPI1CON)
|
|
||||||
return "SPI1";
|
return "SPI1";
|
||||||
|
|
||||||
if (dev->bus == (struct spireg *)&SPI2CON)
|
if (io->bus == spi_base[1])
|
||||||
return "SPI2";
|
return "SPI2";
|
||||||
|
|
||||||
if (dev->bus == (struct spireg *)&SPI3CON)
|
if (io->bus == spi_base[2])
|
||||||
return "SPI3";
|
return "SPI3";
|
||||||
|
|
||||||
if (dev->bus == (struct spireg *)&SPI4CON)
|
if (io->bus == spi_base[3])
|
||||||
return "SPI4";
|
return "SPI4";
|
||||||
|
|
||||||
return "SPI?";
|
return "SPI?";
|
||||||
@@ -724,18 +522,9 @@ char *spi_name(int dno)
|
|||||||
//
|
//
|
||||||
// Return the port name of the CS pin for a device
|
// 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;
|
switch ((unsigned)io->cs_tris) {
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return '?';
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return '?';
|
|
||||||
|
|
||||||
switch ((unsigned)dev->cs_tris) {
|
|
||||||
case (unsigned)&TRISA: return 'A';
|
case (unsigned)&TRISA: return 'A';
|
||||||
case (unsigned)&TRISB: return 'B';
|
case (unsigned)&TRISB: return 'B';
|
||||||
case (unsigned)&TRISC: return 'C';
|
case (unsigned)&TRISC: return 'C';
|
||||||
@@ -747,30 +536,12 @@ char spi_csname(int dno)
|
|||||||
return '?';
|
return '?';
|
||||||
}
|
}
|
||||||
|
|
||||||
int spi_cspin(int dno)
|
int spi_cspin(struct spiio *io)
|
||||||
{
|
{
|
||||||
struct spi_dev *dev;
|
return io->cs_pin;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return '?';
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return '?';
|
|
||||||
|
|
||||||
return dev->cs_pin;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int spi_get_brg(int dno)
|
unsigned int spi_get_brg(struct spiio *io)
|
||||||
{
|
{
|
||||||
struct spi_dev *dev;
|
return BUS_KHZ / (io->baud + 1) / 2;
|
||||||
|
|
||||||
if (dno >= MAXSPIDEV)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
dev = &spi_devices[dno];
|
|
||||||
if (! dev->bus)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return BUS_KHZ / (dev->baud + 1) / 2;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user