Update spirams driver.

This commit is contained in:
Serge Vakulenko
2015-09-29 20:23:53 -07:00
parent 644b6c2112
commit d68b2f2dc1
6 changed files with 284 additions and 69 deletions

View File

@@ -167,7 +167,7 @@ signal "MRAMS_LED3" pin RF3
# spirams - SPI block device
controller spi1 # RAM disk: spirams
device sr0 at spi1 # chip select signals:
device sr0 at spi1
pins RF0, RF1, RF2, RF3, # chip select signals
RF4, RF5, RF6, RF7,
RF8, RF9, RF10, RF11,

View File

@@ -1,12 +1,12 @@
#
# Fubarino SD board
# =================
# Fubarino SD board with MRAM swap disk
# =====================================
# Console on USB.
# For details, see https://github.com/RetroBSD/retrobsd/wiki/Board-Fubarino-SD
#
# To build the kernel, use:
# cd sys/pic32/fubarino
# kconfig Config
# kconfig Config-mrams
# make clean
# make
#
@@ -28,7 +28,7 @@ signal "LED_KERNEL" pin RE5 # kernel activity indicator
# Root filesystem at /dev/sd0a, swap at /dev/sd0b
config unix root on sd0a
swap on sd0b
swap on mr0 # Swap on MRAM disk
# Console options
options "CONS_MAJOR=UARTUSB_MAJOR" # UARTUSB device

View File

@@ -0,0 +1,77 @@
#
# Fubarino SD board with RAM disk on SPI port
# ===========================================
# Console on USB.
# For details, see https://github.com/RetroBSD/retrobsd/wiki/Board-Fubarino-SD
#
# To build the kernel, use:
# cd sys/pic32/fubarino
# kconfig Config-spirams
# make clean
# make
#
# Format of this file is described on page:
# http://retrobsd.org/wiki/doku.php/doc/kconfig
#
architecture "pic32"
cpu "PIC32MX7" # Processor variant
board "FUBARINO" # Board type
ldscript "max32/bootloader.ld" # Linker script
# Standard system options
options "CPU_KHZ=80000" # Oscillator frequency of CPU core
options "BUS_KHZ=80000" # Frequency of peripheral bus
options "BUS_DIV=1" # Bus clock divisor 1/2/4/8
# LED
signal "LED_KERNEL" pin RE5 # kernel activity indicator
# Root filesystem at /dev/sd0a, swap at /dev/sd0b
config unix root on sd0a
swap on sr0 # Swap on SPI RAM disk
# Console options
options "CONS_MAJOR=UARTUSB_MAJOR" # UARTUSB device
# Virtual UART on USB
device uartusb
options "USB_MAX_EP_NUMBER=3"
options "USB_NUM_STRING_DESCRIPTORS=3"
# UART ports
device uart2 # Pins RF4, RF5
# SPI ports
controller spi2 # SD card
controller spi3 # Pins RD1, RD2, RD3
# microSD card
device sd0 at spi2 pin RG9 # select pin
# General purpose I/O ports
# Flags define a mask of available pins
# The following pins excluded:
# RG6, RG7, RG8, RG9 - spi2, SD card
# RD1, RD2, RD3 - spi3
# RF4, RF5 - uart2
device gpio1 flags 0xffff # port B
device gpio2 flags 0xf000 # port C
device gpio3 flags 0x0ff1 # port D
device gpio4 flags 0x00ff # port E
device gpio5 flags 0x000b # port F
device gpio6 flags 0x000c # port G
# ADC driver
device adc
# PWM driver
device pwm
# spirams - SPI block device
device sr0 at spi3
pins RD4, RD5, RD6, RD7, # chip select signals
RD8, RD9, RD10, RD11,
RE0, RE1, RE2, RE3,
RE4, RE5, RE6, RE7
options "SPIRAMS_CHIPS=16" # number of chips
options "SPIRAMS_CHIPSIZE=128" # chip size in kbytes

View File

@@ -1,13 +1,13 @@
#
# Fubarino SD board SRAMC swap disk
# =================================
# Fubarino SD board with SRAMC swap disk
# ======================================
# Console on UART2.
# Overclocked to 120MHz.
# Clock rate increased to 1000Hz.
#
# To build the kernel, use:
# cd sys/pic32/fubarino-uart-sramc
# kconfig Config
# cd sys/pic32/fubarino
# kconfig Config-uart-sramc
# make clean
# make
#

View File

@@ -1,13 +1,15 @@
/*
* TODO: Modify this driver to be able to function without rdisk layer.
* Disk driver for serial RAM chips connected via SPI port.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/errno.h>
#include <sys/dk.h>
#include <sys/disk.h>
#include <sys/spi.h>
#include <sys/debug.h>
#include <sys/kconfig.h>
#include <machine/debug.h>
#include <machine/spirams.h>
#define SPIRAM_WREN 0x06
@@ -25,10 +27,12 @@
struct spiio spirams_io[SPIRAMS_CHIPS];
int spirams_size(int unit)
{
return SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE;
}
int spirams_dkindex; /* disk index for statistics */
/*
* Size of RAM disk.
*/
#define SPIRAMS_TOTAL_KBYTES (SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE)
#define MRBSIZE 1024
#define MRBLOG2 10
@@ -179,7 +183,7 @@ unsigned int spir_read_block(unsigned int chip, unsigned int address, unsigned i
return cs;
}
int spirams_read(int unit, unsigned int offset, char *data, unsigned int bcount)
int spirams_read(unsigned int offset, char *data, unsigned int bcount)
{
register unsigned int chip;
register unsigned int toread;
@@ -282,7 +286,7 @@ unsigned int spir_write_block(unsigned int chip, unsigned int address, unsigned
return cs;
}
int spirams_write (int unit, unsigned int offset, char *data, unsigned bcount)
int spirams_write (unsigned int offset, char *data, unsigned bcount)
{
register unsigned int chip;
register unsigned int address;
@@ -311,119 +315,250 @@ int spirams_write (int unit, unsigned int offset, char *data, unsigned bcount)
return 1;
}
void spirams_preinit (int unit)
static unsigned *gpio_base(int cs)
{
int port = (cs >> 4) - 1;
struct gpioreg *base = port + (struct gpioreg*) &TRISA;
return (unsigned int*) base;
}
/*
* Initialize hardware.
*/
static int spirams_init(int spi_port, char cs[])
{
struct spiio *io = &spirams_io[0];
struct buf *bp;
if (unit >= 1)
return;
/* Initialize hardware. */
if (spi_setup(io, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS0_PORT,SPIRAMS_CS0_PIN) != 0)
return;
if (spi_setup(io, spi_port, gpio_base(cs[0]), cs[0] & 15) != 0) {
printf("sr0: cannot open SPI%u port\n", spi_port);
return 0;
}
spi_brg(io, SPIRAMS_MHZ * 1000);
spi_set(io, PIC32_SPICON_CKE);
#ifdef SPIRAMS_CS1_PORT
spi_setup(io+1, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS1_PORT,SPIRAMS_CS1_PIN);
#if SPIRAMS_CHIPS >= 1
spi_setup(io+1, spi_port, gpio_base(cs[1]), cs[1] & 15);
spi_brg(io+1, SPIRAMS_MHZ * 1000);
spi_set(io+1, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS2_PORT
spi_setup(io+2, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS2_PORT,SPIRAMS_CS2_PIN);
#if SPIRAMS_CHIPS >= 2
spi_setup(io+2, spi_port, gpio_base(cs[2]), cs[2] & 15);
spi_brg(io+2, SPIRAMS_MHZ * 1000);
spi_set(io+2, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS3_PORT
spi_setup(io+3, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS3_PORT,SPIRAMS_CS3_PIN);
#if SPIRAMS_CHIPS >= 3
spi_setup(io+3, spi_port, gpio_base(cs[3]), cs[3] & 15);
spi_brg(io+3, SPIRAMS_MHZ * 1000);
spi_set(io+3, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS4_PORT
spi_setup(io+4, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS4_PORT,SPIRAMS_CS4_PIN);
#if SPIRAMS_CHIPS >= 4
spi_setup(io+4, spi_port, gpio_base(cs[4]), cs[4] & 15);
spi_brg(io+4, SPIRAMS_MHZ * 1000);
spi_set(io+4, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS5_PORT
spi_setup(io+5, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS5_PORT,SPIRAMS_CS5_PIN);
#if SPIRAMS_CHIPS >= 5
spi_setup(io+5, spi_port, gpio_base(cs[5]), cs[5] & 15);
spi_brg(io+5, SPIRAMS_MHZ * 1000);
spi_set(io+5, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS6_PORT
spi_setup(io+6, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS6_PORT,SPIRAMS_CS6_PIN);
#if SPIRAMS_CHIPS >= 6
spi_setup(io+6, spi_port, gpio_base(cs[6]), cs[6] & 15);
spi_brg(io+6, SPIRAMS_MHZ * 1000);
spi_set(io+6, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS7_PORT
spi_setup(io+7, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS7_PORT,SPIRAMS_CS7_PIN);
#if SPIRAMS_CHIPS >= 7
spi_setup(io+7, spi_port, gpio_base(cs[7]), cs[7] & 15);
spi_brg(io+7, SPIRAMS_MHZ * 1000);
spi_set(io+7, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS8_PORT
spi_setup(io+8, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS8_PORT,SPIRAMS_CS8_PIN);
#if SPIRAMS_CHIPS >= 8
spi_setup(io+8, spi_port, gpio_base(cs[8]), cs[8] & 15);
spi_brg(io+8, SPIRAMS_MHZ * 1000);
spi_set(io+8, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS9_PORT
spi_setup(io+9, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS9_PORT,SPIRAMS_CS9_PIN);
#if SPIRAMS_CHIPS >= 9
spi_setup(io+9, spi_port, gpio_base(cs[9]), cs[9] & 15);
spi_brg(io+9, SPIRAMS_MHZ * 1000);
spi_set(io+9, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS10_PORT
spi_setup(io+10, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS10_PORT,SPIRAMS_CS10_PIN);
#if SPIRAMS_CHIPS >= 10
spi_setup(io+10, spi_port, gpio_base(cs[10]), cs[10] & 15);
spi_brg(io+10, SPIRAMS_MHZ * 1000);
spi_set(io+10, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS11_PORT
spi_setup(io+11, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS11_PORT,SPIRAMS_CS11_PIN);
#if SPIRAMS_CHIPS >= 11
spi_setup(io+11, spi_port, gpio_base(cs[11]), cs[11] & 15);
spi_brg(io+11, SPIRAMS_MHZ * 1000);
spi_set(io+11, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS12_PORT
spi_setup(io+12, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS12_PORT,SPIRAMS_CS12_PIN);
#if SPIRAMS_CHIPS >= 12
spi_setup(io+12, spi_port, gpio_base(cs[12]), cs[12] & 15);
spi_brg(io+12, SPIRAMS_MHZ * 1000);
spi_set(io+12, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS13_PORT
spi_setup(io+13, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS13_PORT,SPIRAMS_CS13_PIN);
#if SPIRAMS_CHIPS >= 13
spi_setup(io+13, spi_port, gpio_base(cs[13]), cs[13] & 15);
spi_brg(io+13, SPIRAMS_MHZ * 1000);
spi_set(io+13, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS14_PORT
spi_setup(io+14, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS14_PORT,SPIRAMS_CS14_PIN);
#if SPIRAMS_CHIPS >= 14
spi_setup(io+14, spi_port, gpio_base(cs[14]), cs[14] & 15);
spi_brg(io+14, SPIRAMS_MHZ * 1000);
spi_set(io+14, PIC32_SPICON_CKE);
#endif
#ifdef SPIRAMS_CS15_PORT
spi_setup(io+15, SPIRAMS_PORT,(unsigned int *)&SPIRAMS_CS15_PORT,SPIRAMS_CS15_PIN);
#if SPIRAMS_CHIPS >= 15
spi_setup(io+15, spi_port, gpio_base(cs[15]), cs[15] & 15);
spi_brg(io+15, SPIRAMS_MHZ * 1000);
spi_set(io+15, PIC32_SPICON_CKE);
#endif
printf("spirams0: port %d %s, size %dKB, speed %d Mbit/sec\n",
SPIRAMS_PORT, spi_name(io), SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE,
spi_get_brg(io) / 1000);
bp = prepartition_device("spirams0");
if (bp) {
spirams_write (0, 0, bp->b_addr, 512);
brelse(bp);
}
printf("spirams0: size %dKB, speed %d Mbit/sec\n",
SPIRAMS_CHIPS * SPIRAMS_CHIPSIZE, spi_get_brg(io) / 1000);
return 1;
}
/*
* Open the disk.
*/
int spirams_open(dev_t dev, int flag, int mode)
{
return 0;
}
int spirams_close(dev_t dev, int flag, int mode)
{
return 0;
}
/*
* Return the size of the device in kbytes.
*/
daddr_t spirams_size(dev_t dev)
{
return SPIRAMS_TOTAL_KBYTES;
}
void spirams_strategy(struct buf *bp)
{
int offset = bp->b_blkno;
long nblk = btod(bp->b_bcount);
int s;
/*
* Determine the size of the transfer, and make sure it is
* within the boundaries of the partition.
*/
if (bp->b_blkno + nblk > SPIRAMS_TOTAL_KBYTES) {
/* if exactly at end of partition, return an EOF */
if (bp->b_blkno == SPIRAMS_TOTAL_KBYTES) {
bp->b_resid = bp->b_bcount;
biodone(bp);
return;
}
/* or truncate if part of it fits */
nblk = SPIRAMS_TOTAL_KBYTES - bp->b_blkno;
if (nblk <= 0) {
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
biodone(bp);
return;
}
bp->b_bcount = nblk << DEV_BSHIFT;
}
led_control(LED_SWAP, 1);
s = splbio();
#ifdef UCB_METER
if (spirams_dkindex >= 0) {
dk_busy |= 1 << spirams_dkindex;
dk_xfer[spirams_dkindex]++;
dk_bytes[spirams_dkindex] += bp->b_bcount;
}
#endif
if (bp->b_flags & B_READ) {
spirams_read(offset, bp->b_addr, bp->b_bcount);
} else {
spirams_write(offset, bp->b_addr, bp->b_bcount);
}
biodone(bp);
led_control(LED_SWAP, 0);
#ifdef UCB_METER
if (spirams_dkindex >= 0)
dk_busy &= ~(1 << spirams_dkindex);
#endif
splx(s);
}
int spirams_ioctl(dev_t dev, u_int cmd, caddr_t addr, int flag)
{
int error = 0;
switch (cmd) {
case DIOCGETMEDIASIZE:
/* Get disk size in kbytes. */
*(int*) addr = SPIRAMS_TOTAL_KBYTES;
break;
default:
error = EINVAL;
break;
}
return error;
}
/*
* Test to see if device is present.
* Return true if found and initialized ok.
*/
static int
spirams_probe(config)
struct conf_device *config;
{
int i;
/* Only one device unit is supported. */
if (config->dev_unit != 0)
return 0;
printf("sr0: port SPI%d, pins ", config->dev_ctlr);
for (i=0; i<SPIRAMS_CHIPS; i++) {
int cs = config->dev_pins[i];
if (i > 0)
printf("/");
if (i == 7)
printf("\n ");
printf("R%c%d", gpio_portname(cs), gpio_pinno(cs));
}
printf("\n");
if (spirams_init(config->dev_ctlr, config->dev_pins) != 0)
return 0;
#ifdef UCB_METER
dk_alloc(&spirams_dkindex, 1, "sr0");
#endif
return 1;
}
struct driver srdriver = {
"sr", spirams_probe,
};

View File

@@ -1,9 +1,12 @@
#ifndef _SPIRAMS_H
#define _SPIRAMS_H
extern int spirams_size(int unit);
extern int spirams_read(int unit, unsigned int offset, char *data, unsigned int bcount);
extern int spirams_write (int unit, unsigned offset, char *data, unsigned bcount);
extern void spirams_preinit (int unit);
#ifdef KERNEL
extern int spirams_open(dev_t dev, int flag, int mode);
extern int spirams_close(dev_t dev, int flag, int mode);
extern daddr_t spirams_size(dev_t dev);
extern void spirams_strategy(struct buf *bp);
extern int spirams_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag);
#endif
#endif