diff --git a/sys/pic32/Config.generic b/sys/pic32/Config.generic index 4140a85..a04fb70 100644 --- a/sys/pic32/Config.generic +++ b/sys/pic32/Config.generic @@ -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, diff --git a/sys/pic32/fubarino/Config-mrams b/sys/pic32/fubarino/Config-mrams index 9f3066a..6ea1c56 100644 --- a/sys/pic32/fubarino/Config-mrams +++ b/sys/pic32/fubarino/Config-mrams @@ -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 diff --git a/sys/pic32/fubarino/Config-spirams b/sys/pic32/fubarino/Config-spirams new file mode 100644 index 0000000..f0e5d5b --- /dev/null +++ b/sys/pic32/fubarino/Config-spirams @@ -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 diff --git a/sys/pic32/fubarino/Config-uart-sramc b/sys/pic32/fubarino/Config-uart-sramc index 95b8d16..617c915 100644 --- a/sys/pic32/fubarino/Config-uart-sramc +++ b/sys/pic32/fubarino/Config-uart-sramc @@ -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 # diff --git a/sys/pic32/spirams.c b/sys/pic32/spirams.c index fa04623..90056b4 100644 --- a/sys/pic32/spirams.c +++ b/sys/pic32/spirams.c @@ -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 #include #include #include #include +#include #include -#include +#include +#include #include #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; idev_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, +}; diff --git a/sys/pic32/spirams.h b/sys/pic32/spirams.h index 8ab721d..9613cb3 100644 --- a/sys/pic32/spirams.h +++ b/sys/pic32/spirams.h @@ -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