Files
retrobsd/sys/pic32/rd_mrams.c
Serge Vakulenko 585773955b Fix include paths in the kernel sources.
Max32 kernel successfully compiled with kconfig utility.
2015-08-31 00:21:41 -07:00

295 lines
7.3 KiB
C

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/buf.h>
#include <sys/errno.h>
#include <sys/dk.h>
#include <sys/rdisk.h>
#include <sys/spi_bus.h>
#include <sys/debug.h>
#define MRAM_WREN 0x06
#define MRAM_WRDI 0x04
#define MRAM_RDSR 0x05
#define MRAM_WRSR 0x01
#define MRAM_READ 0x03
#define MRAM_WRITE 0x02
#define MRAM_SLEEP 0xB9
#define MRAM_WAKE 0xAB
#ifndef MRAMS_MHZ
#define MRAMS_MHZ 13
#endif
int fd[MRAMS_CHIPS];
int mrams_size(int unit)
{
return MRAMS_CHIPS * MRAMS_CHIPSIZE;
}
#define MRBSIZE 1024
#define MRBLOG2 10
unsigned int mr_read_block(unsigned int chip, unsigned int address, unsigned int length, char *data)
{
register unsigned int cs = 0;
switch (chip) {
case 0:
#ifdef MRAMS_LED0_PORT
TRIS_CLR(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
LAT_SET(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
#endif
break;
case 1:
#ifdef MRAMS_LED1_PORT
TRIS_CLR(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
LAT_SET(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
#endif
break;
case 2:
#ifdef MRAMS_LED2_PORT
TRIS_CLR(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
LAT_SET(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
#endif
break;
case 3:
#ifdef MRAMS_LED3_PORT
TRIS_CLR(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
LAT_SET(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
#endif
break;
}
spi_select(fd[chip]);
spi_transfer(fd[chip], MRAM_READ);
spi_transfer(fd[chip], address>>16);
spi_transfer(fd[chip], address>>8);
spi_transfer(fd[chip], address);
// If the length is a multiple of 32 bits, then do a 32 bit transfer
#if 0
if ((length & 3) == 0)
spi_bulk_read_32(fd[chip],length,data);
else if ((length & 1) == 0)
spi_bulk_read_16(fd[chip],length,data);
else
#endif
spi_bulk_read(fd[chip],length,(unsigned char *)data);
spi_deselect(fd[chip]);
switch (chip) {
case 0:
#ifdef MRAMS_LED0_PORT
LAT_CLR(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
#endif
break;
case 1:
#ifdef MRAMS_LED1_PORT
LAT_CLR(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
#endif
break;
case 2:
#ifdef MRAMS_LED2_PORT
LAT_CLR(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
#endif
break;
case 3:
#ifdef MRAMS_LED3_PORT
LAT_CLR(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
#endif
break;
}
return cs;
}
int mrams_read(int unit, unsigned int offset, char *data, unsigned int bcount)
{
register unsigned int chip;
register unsigned int toread;
register unsigned int address;
register unsigned int pass = 0;
while (bcount > 0) {
pass++;
toread = bcount;
if (toread > MRBSIZE)
toread = MRBSIZE;
chip = offset / MRAMS_CHIPSIZE;
address = (offset<<10) - (chip * (MRAMS_CHIPSIZE*1024));
if (chip >= MRAMS_CHIPS) {
printf("!!!EIO\n");
return EIO;
}
mr_read_block(chip, address, toread, data);
bcount -= toread;
offset += (toread>>MRBLOG2);
data += toread;
}
return 1;
}
unsigned int mr_write_block(unsigned int chip, unsigned int address, unsigned int length, char *data)
{
register unsigned int cs = 0;
char blank __attribute__((unused));
switch (chip) {
case 0:
#ifdef MRAMS_LED0_PORT
TRIS_CLR(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
LAT_SET(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
#endif
break;
case 1:
#ifdef MRAMS_LED1_PORT
TRIS_CLR(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
LAT_SET(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
#endif
break;
case 2:
#ifdef MRAMS_LED2_PORT
TRIS_CLR(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
LAT_SET(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
#endif
break;
case 3:
#ifdef MRAMS_LED3_PORT
TRIS_CLR(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
LAT_SET(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
#endif
break;
}
spi_select(fd[chip]);
spi_transfer(fd[chip], MRAM_WRITE);
spi_transfer(fd[chip], address>>16);
spi_transfer(fd[chip], address>>8);
spi_transfer(fd[chip], address);
#if 0
if ((length & 3) == 0)
spi_bulk_write_32(fd[chip],length,data);
else if ((length & 1) == 0)
spi_bulk_write_16(fd[chip],length,data);
else
#endif
spi_bulk_write(fd[chip],length,(unsigned char *)data);
spi_deselect(fd[chip]);
switch (chip) {
case 0:
#ifdef MRAMS_LED0_PORT
LAT_CLR(MRAMS_LED0_PORT) = 1<<MRAMS_LED0_PIN;
#endif
break;
case 1:
#ifdef MRAMS_LED1_PORT
LAT_CLR(MRAMS_LED1_PORT) = 1<<MRAMS_LED1_PIN;
#endif
break;
case 2:
#ifdef MRAMS_LED2_PORT
LAT_CLR(MRAMS_LED2_PORT) = 1<<MRAMS_LED2_PIN;
#endif
break;
case 3:
#ifdef MRAMS_LED3_PORT
LAT_CLR(MRAMS_LED3_PORT) = 1<<MRAMS_LED3_PIN;
#endif
break;
}
return cs;
}
int mrams_write (int unit, unsigned int offset, char *data, unsigned bcount)
{
register unsigned int chip;
register unsigned int address;
register unsigned int towrite;
register unsigned int pass = 0;
while (bcount > 0) {
pass++;
towrite = bcount;
if (towrite > MRBSIZE)
towrite = MRBSIZE;
chip = offset / MRAMS_CHIPSIZE;
address = (offset<<10) - (chip * (MRAMS_CHIPSIZE*MRBSIZE));
if (chip >= MRAMS_CHIPS) {
printf("!!!EIO\n");
return EIO;
}
mr_write_block(chip, address, towrite, data);
bcount -= towrite;
offset += (towrite>>MRBLOG2);
data += towrite;
}
return 1;
}
void mrams_preinit (int unit)
{
struct buf *bp;
if (unit >= 1)
return;
/* Initialize hardware. */
fd[0] = spi_open(MRAMS_PORT,(unsigned int *)&MRAMS_CS0_PORT,MRAMS_CS0_PIN);
if (fd[0] == -1)
return;
spi_brg(fd[0],MRAMS_MHZ * 1000);
spi_set(fd[0],PIC32_SPICON_CKE);
spi_select(fd[0]);
spi_transfer(fd[0],MRAM_WREN);
spi_deselect(fd[0]);
#ifdef MRAMS_CS1_PORT
fd[1] = spi_open(MRAMS_PORT,(unsigned int *)&MRAMS_CS1_PORT,MRAMS_CS1_PIN);
spi_brg(fd[1],MRAMS_MHZ * 1000);
spi_set(fd[1],PIC32_SPICON_CKE);
spi_select(fd[1]);
spi_transfer(fd[1],MRAM_WREN);
spi_deselect(fd[1]);
#endif
#ifdef MRAMS_CS2_PORT
fd[2] = spi_open(MRAMS_PORT,(unsigned int *)&MRAMS_CS2_PORT,MRAMS_CS2_PIN);
spi_brg(fd[2],MRAMS_MHZ * 1000);
spi_set(fd[2],PIC32_SPICON_CKE);
spi_select(fd[2]);
spi_transfer(fd[2],MRAM_WREN);
spi_deselect(fd[2]);
#endif
#ifdef MRAMS_CS3_PORT
fd[3] = spi_open(MRAMS_PORT,(unsigned int *)&MRAMS_CS3_PORT,MRAMS_CS3_PIN);
spi_brg(fd[3],MRAMS_MHZ * 1000);
spi_set(fd[3],PIC32_SPICON_CKE);
spi_select(fd[3]);
spi_transfer(fd[3],MRAM_WREN);
spi_deselect(fd[3]);
#endif
printf("mrams0: port %s, size %dKB, speed %d Mbit/sec\n",
spi_name(MRAMS_PORT),MRAMS_CHIPS * MRAMS_CHIPSIZE,
spi_get_brg(fd[0]) / 1000);
bp = prepartition_device("mrams0");
if (bp) {
mrams_write (0, 0, bp->b_addr, 512);
brelse(bp);
}
}