diff --git a/sys/pic32/Config.generic b/sys/pic32/Config.generic index 2c71967..4140a85 100644 --- a/sys/pic32/Config.generic +++ b/sys/pic32/Config.generic @@ -156,24 +156,14 @@ options "SRAMC_SWAP_KBYTES=2048" # size of partition B # mrams - SPI block device controller spi1 # RAM disk: mrams device mr0 at spi1 - pins RA4, RA2, RB14, RB12, # chip select signals - RB10, RB11 -options "MRAMS_CHIPS=6" # number of chips + pins RA4, RA2, RB14, RB12 # chip select signals +options "MRAMS_CHIPS=4" # number of chips options "MRAMS_CHIPSIZE=512" # chip size in kbytes options "MRAMS_MHZ=10" # speed 10 MHz -options "MRAMS_PORT=SPI1CON" # TODO: delete this option -signal "MRAMS_CS0" pin RA4 # TODO: delete -signal "MRAMS_CS1" pin RA2 # TODO: delete -signal "MRAMS_CS2" pin RB14 # TODO: delete -signal "MRAMS_CS3" pin RB12 # TODO: delete -signal "MRAMS_CS4" pin RB10 # TODO: delete -signal "MRAMS_CS5" pin RB11 # TODO: delete signal "MRAMS_LED0" pin RF0 # optional LED indicators signal "MRAMS_LED1" pin RF1 signal "MRAMS_LED2" pin RF2 signal "MRAMS_LED3" pin RF3 -signal "MRAMS_LED4" pin RF4 -signal "MRAMS_LED5" pin RF5 # spirams - SPI block device controller spi1 # RAM disk: spirams diff --git a/sys/pic32/fubarino/Config-mrams b/sys/pic32/fubarino/Config-mrams new file mode 100644 index 0000000..9f3066a --- /dev/null +++ b/sys/pic32/fubarino/Config-mrams @@ -0,0 +1,74 @@ +# +# Fubarino SD board +# ================= +# 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 +# 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 sd0b + +# 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 + +# mrams - SPI block device +device mr0 at spi3 + pins RD4, RD5, RD6, RD7 # chip select signals +options "MRAMS_CHIPS=4" # number of chips +options "MRAMS_CHIPSIZE=512" # chip size in kbytes diff --git a/sys/pic32/mrams.c b/sys/pic32/mrams.c index 6dd80cc..5c6e2a0 100644 --- a/sys/pic32/mrams.c +++ b/sys/pic32/mrams.c @@ -1,5 +1,5 @@ /* - * TODO: Modify this driver to be able to function without rdisk layer. + * Disk driver for serial MRAM chips connected via SPI port. */ #include #include @@ -8,7 +8,8 @@ #include #include #include -#include +#include +#include #include #define MRAM_WREN 0x06 @@ -26,10 +27,12 @@ struct spiio mrams_io[MRAMS_CHIPS]; -int mrams_size(int unit) -{ - return MRAMS_CHIPS * MRAMS_CHIPSIZE; -} +int mrams_dkindex; /* disk index for statistics */ + +/* + * Size of RAM disk. + */ +#define MRAMS_TOTAL_KBYTES (MRAMS_CHIPS * MRAMS_CHIPSIZE) #define MRBSIZE 1024 #define MRBLOG2 10 @@ -108,7 +111,7 @@ unsigned int mr_read_block(unsigned int chip, unsigned int address, unsigned int return cs; } -int mrams_read(int unit, unsigned int offset, char *data, unsigned int bcount) +int mrams_read(unsigned int offset, char *data, unsigned int bcount) { register unsigned int chip; register unsigned int toread; @@ -211,7 +214,7 @@ unsigned int mr_write_block(unsigned int chip, unsigned int address, unsigned in return cs; } -int mrams_write(int unit, unsigned int offset, char *data, unsigned bcount) +int mrams_write(unsigned int offset, char *data, unsigned bcount) { register unsigned int chip; register unsigned int address; @@ -240,27 +243,33 @@ int mrams_write(int unit, unsigned int offset, char *data, unsigned bcount) return 1; } -void mrams_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 mrams_init(int spi_port, int cs0, int cs1, int cs2, int cs3) { struct spiio *io = &mrams_io[0]; - struct buf *bp; - - if (unit >= 1) - return; - - /* Initialize hardware. */ - - if (spi_setup(io, MRAMS_PORT, (unsigned int *)&MRAMS_CS0_PORT, MRAMS_CS0_PIN) != 0) - return; + if (spi_setup(io, spi_port, gpio_base(cs0), cs0 & 15) != 0) { + printf("mr0: cannot open SPI%u port\n", spi_port); + return 0; + } spi_brg(io, MRAMS_MHZ * 1000); spi_set(io, PIC32_SPICON_CKE); spi_select(io); spi_transfer(io, MRAM_WREN); spi_deselect(io); -#ifdef MRAMS_CS1_PORT - spi_setup(io+1, MRAMS_PORT, (unsigned int *)&MRAMS_CS1_PORT, MRAMS_CS1_PIN); +#if MRAMS_CHIPS >= 1 + spi_setup(io+1, spi_port, gpio_base(cs1), cs1 & 15); spi_brg(io+1, MRAMS_MHZ * 1000); spi_set(io+1, PIC32_SPICON_CKE); @@ -268,8 +277,8 @@ void mrams_preinit(int unit) spi_transfer(io+1, MRAM_WREN); spi_deselect(io+1); #endif -#ifdef MRAMS_CS2_PORT - spi_setup(io+2, MRAMS_PORT, (unsigned int *)&MRAMS_CS2_PORT, MRAMS_CS2_PIN); +#if MRAMS_CHIPS >= 2 + spi_setup(io+2, spi_port, gpio_base(cs2), cs2 & 15); spi_brg(io+2, MRAMS_MHZ * 1000); spi_set(io+2, PIC32_SPICON_CKE); @@ -277,8 +286,8 @@ void mrams_preinit(int unit) spi_transfer(io+2, MRAM_WREN); spi_deselect(io+2); #endif -#ifdef MRAMS_CS3_PORT - spi_setup(io+3, MRAMS_PORT, (unsigned int *)&MRAMS_CS3_PORT, MRAMS_CS3_PIN); +#if MRAMS_CHIPS >= 3 + spi_setup(io+3, spi_port, gpio_base(cs3), cs3 & 15); spi_brg(io+3, MRAMS_MHZ * 1000); spi_set(io+3, PIC32_SPICON_CKE); @@ -287,12 +296,137 @@ void mrams_preinit(int unit) spi_deselect(io+3); #endif - printf("mrams0: port %s, size %dKB, speed %d Mbit/sec\n", - spi_name(MRAMS_PORT), MRAMS_CHIPS * MRAMS_CHIPSIZE, - spi_get_brg(io) / 1000); - bp = prepartition_device("mrams0"); - if (bp) { - mrams_write(0, 0, bp->b_addr, 512); - brelse(bp); - } + printf("mr0: size %dKB, speed %d Mbit/sec\n", + MRAMS_CHIPS * MRAMS_CHIPSIZE, spi_get_brg(io) / 1000); + return 1; } + +/* + * Open the disk. + */ +int mrams_open(dev_t dev, int flag, int mode) +{ + return 0; +} + +int mrams_close(dev_t dev, int flag, int mode) +{ + return 0; +} + +/* + * Return the size of the device in kbytes. + */ +daddr_t mrams_size(dev_t dev) +{ + return MRAMS_TOTAL_KBYTES; +} + +void mrams_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 > MRAMS_TOTAL_KBYTES) { + /* if exactly at end of partition, return an EOF */ + if (bp->b_blkno == MRAMS_TOTAL_KBYTES) { + bp->b_resid = bp->b_bcount; + biodone(bp); + return; + } + /* or truncate if part of it fits */ + nblk = MRAMS_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 (mrams_dkindex >= 0) { + dk_busy |= 1 << mrams_dkindex; + dk_xfer[mrams_dkindex]++; + dk_bytes[mrams_dkindex] += bp->b_bcount; + } +#endif + + if (bp->b_flags & B_READ) { + mrams_read(offset, bp->b_addr, bp->b_bcount); + } else { + mrams_write(offset, bp->b_addr, bp->b_bcount); + } + + biodone(bp); + led_control(LED_SWAP, 0); +#ifdef UCB_METER + if (mrams_dkindex >= 0) + dk_busy &= ~(1 << mrams_dkindex); +#endif + splx(s); +} + +int mrams_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 = MRAMS_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 +mrams_probe(config) + struct conf_device *config; +{ + int cs0 = config->dev_pins[0]; + int cs1 = config->dev_pins[1]; + int cs2 = config->dev_pins[2]; + int cs3 = config->dev_pins[3]; + + /* Only one device unit is supported. */ + if (config->dev_unit != 0) + return 0; + + printf("mr0: port SPI%d, pins cs0=R%c%d/cs1=R%c%d/cs2=R%c%d/cs3=R%c%d\n", + config->dev_ctlr, + gpio_portname(cs0), gpio_pinno(cs0), + gpio_portname(cs1), gpio_pinno(cs1), + gpio_portname(cs2), gpio_pinno(cs2), + gpio_portname(cs3), gpio_pinno(cs3)); + + if (mrams_init(config->dev_ctlr, cs0, cs1, cs2, cs3) != 0) + return 0; + +#ifdef UCB_METER + dk_alloc(&mrams_dkindex, 1, "mr0"); +#endif + return 1; +} + +struct driver mrdriver = { + "mr", mrams_probe, +}; diff --git a/sys/pic32/mrams.h b/sys/pic32/mrams.h index 4530f20..f56c433 100644 --- a/sys/pic32/mrams.h +++ b/sys/pic32/mrams.h @@ -1,9 +1,12 @@ #ifndef _MRAMS_H #define _MRAMS_H -extern int mrams_size(int unit); -extern int mrams_read(int unit, unsigned int offset, char *data, unsigned int bcount); -extern int mrams_write (int unit, unsigned offset, char *data, unsigned bcount); -extern void mrams_preinit (int unit); +#ifdef KERNEL +extern int mrams_open(dev_t dev, int flag, int mode); +extern int mrams_close(dev_t dev, int flag, int mode); +extern daddr_t mrams_size(dev_t dev); +extern void mrams_strategy(struct buf *bp); +extern int mrams_ioctl (dev_t dev, u_int cmd, caddr_t addr, int flag); +#endif #endif diff --git a/sys/pic32/sramc.c b/sys/pic32/sramc.c index 1c14f31..ef503a3 100644 --- a/sys/pic32/sramc.c +++ b/sys/pic32/sramc.c @@ -1,6 +1,5 @@ /* * Driver for external SRAM-CPLD based Swap and Filesystem devices - * TODO: Modify this driver to be able to function without rdisk layer. * * This version is for 8MB RAMDISK v.1.1 and compatible * Pito 7.4.2014 - PIC32MX PMP bus version